diff --git a/contracts/credit/CreditFacade.sol b/contracts/credit/CreditFacade.sol index 7485bf30..9605ec07 100644 --- a/contracts/credit/CreditFacade.sol +++ b/contracts/credit/CreditFacade.sol @@ -17,6 +17,7 @@ import {QuotaUpdate} from "../interfaces/IPoolQuotaKeeper.sol"; import {ICreditFacade, ICreditFacadeExtended, FullCheckParams} from "../interfaces/ICreditFacade.sol"; import {ICreditManagerV2, ClosureAction} from "../interfaces/ICreditManagerV2.sol"; import {IPriceOracleV2} from "@gearbox-protocol/core-v2/contracts/interfaces/IPriceOracle.sol"; +import {IPoolQuotaKeeper, TokenLT} from "../interfaces/IPoolQuotaKeeper.sol"; import {IDegenNFT} from "@gearbox-protocol/core-v2/contracts/interfaces/IDegenNFT.sol"; import {IWETH} from "@gearbox-protocol/core-v2/contracts/interfaces/external/IWETH.sol"; import {IWETHGateway} from "../interfaces/IWETHGateway.sol"; @@ -1125,8 +1126,20 @@ contract CreditFacade is ICreditFacade, ReentrancyGuard { view returns (uint256 totalUSD, uint256 twvUSD) { - uint256 tokenMask = 1; uint256 enabledTokensMask = creditManager.enabledTokensMap(creditAccount); // F:[FA-41] + uint256 limitedTokenMask = creditManager.limitedTokenMask(); + + if (creditManager.supportsQuotas()) { + TokenLT[] memory tokens = creditManager.getLimitedTokens(creditAccount); + + if (tokens.length > 0) { + (twvUSD,) = creditManager.poolQuotaKeeper().computeQuotedCollateralUSD( + address(creditManager), creditAccount, address(priceOracle), tokens + ); + } + } + + uint256 tokenMask = 1; while (tokenMask <= enabledTokensMask) { if (enabledTokensMask & tokenMask != 0) { @@ -1139,7 +1152,10 @@ contract CreditFacade is ICreditFacade, ReentrancyGuard { unchecked { totalUSD += value; // F:[FA-41] } - twvUSD += value * liquidationThreshold; // F:[FA-41] + + if (tokenMask & limitedTokenMask == 0) { + twvUSD += value * liquidationThreshold; // F:[FA-41] + } } } // T:[FA-41] diff --git a/contracts/credit/CreditManager.sol b/contracts/credit/CreditManager.sol index b39c14ce..b3210ed8 100644 --- a/contracts/credit/CreditManager.sol +++ b/contracts/credit/CreditManager.sol @@ -145,10 +145,10 @@ contract CreditManager is ICreditManagerV2, ACLNonReentrantTrait { /// QUOTA-RELATED PARAMS /// @dev Whether the CM supports quota-related logic - bool public immutable supportsQuotas; + bool public immutable override supportsQuotas; /// @dev Mask of tokens to apply quotas for - uint256 public limitedTokenMask; + uint256 public override limitedTokenMask; /// @dev Previously accrued and unrepaid interest on quotas. /// This does not always represent the most actual quota interest, @@ -885,6 +885,7 @@ contract CreditManager is ICreditManagerV2, ACLNonReentrantTrait { } } + /// @dev Returns the array of quoted tokens that are enabled on the account function getLimitedTokens(address creditAccount) public view returns (TokenLT[] memory tokens) { uint256 limitMask = enabledTokensMap[creditAccount] & limitedTokenMask; diff --git a/contracts/interfaces/ICreditManagerV2.sol b/contracts/interfaces/ICreditManagerV2.sol index fdec0983..1cd53e51 100644 --- a/contracts/interfaces/ICreditManagerV2.sol +++ b/contracts/interfaces/ICreditManagerV2.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.10; import {IPriceOracleV2} from "@gearbox-protocol/core-v2/contracts/interfaces/IPriceOracle.sol"; -import {QuotaUpdate} from "./IPoolQuotaKeeper.sol"; +import {IPoolQuotaKeeper, QuotaUpdate, TokenLT} from "./IPoolQuotaKeeper.sol"; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; enum ClosureAction { @@ -191,22 +191,6 @@ interface ICreditManagerV2 is ICreditManagerV2Events, ICreditManagerV2Exceptions /// @param token Address of the token to enable function checkAndEnableToken(address token) external; - // /// @dev Performs a full health check on an account, summing up - // /// value of all enabled collateral tokens - // /// @param creditAccount Address of the Credit Account to check - // function fullCollateralCheck(address creditAccount) external; - - // /// @dev Performs a full health check on an account with a custom - // /// order of evaluated tokens - // /// @param creditAccount Address of the Credit Account to check - // /// @param collateralHints Array of token masks in the desired order of evaluation - // /// @notice Full collateral check with hints will first evaluate limited tokens as normal (this is done in PoolQuotaKeeper), - // /// then evaluate the hinted tokens in the order of hints, and then will move on to other tokens if the check is still not satisfied - // function fullCollateralCheck( - // address creditAccount, - // uint256[] memory collateralHints - // ) external; - /// @dev Performs a full health check on an account with a custom order of evaluated tokens and /// a custom minimal health factor /// @param creditAccount Address of the Credit Account to check @@ -244,16 +228,6 @@ interface ICreditManagerV2 is ICreditManagerV2Events, ICreditManagerV2Exceptions // QUOTAS MANAGEMENT // - // /// @dev Updates credit account's quota for given token - // /// @param creditAccount Address of credit account - // /// @param token Address of the token to change the quota for - // /// @param quotaChange Requested quota change in pool's underlying asset units - // function updateQuota( - // address creditAccount, - // address token, - // int96 quotaChange - // ) external; - /// @dev Updates credit account's quotas for multiple tokens /// @param creditAccount Address of credit account /// @param quotaUpdates Requested quota updates, see `QuotaUpdate` @@ -314,6 +288,9 @@ interface ICreditManagerV2 is ICreditManagerV2Events, ICreditManagerV2Exceptions view returns (address token, uint16 liquidationThreshold); + /// @dev Returns the array of quoted tokens that are enabled on the account + function getLimitedTokens(address creditAccount) external view returns (TokenLT[] memory tokens); + /// @dev Total number of known collateral tokens. function collateralTokensCount() external view returns (uint256); @@ -324,6 +301,9 @@ interface ICreditManagerV2 is ICreditManagerV2Events, ICreditManagerV2Exceptions /// @dev Bit mask encoding a set of forbidden tokens function forbiddenTokenMask() external view returns (uint256); + /// @dev Mask of tokens to apply quotas for + function limitedTokenMask() external view returns (uint256); + /// @dev Maps allowed adapters to their respective target contracts. function adapterToContract(address adapter) external view returns (address); @@ -340,6 +320,12 @@ interface ICreditManagerV2 is ICreditManagerV2Events, ICreditManagerV2Exceptions /// @notice [DEPRECATED]: use pool() instead. function poolService() external view returns (address); + /// @dev Returns the current pool quota keeper connected to the pool + function poolQuotaKeeper() external view returns (IPoolQuotaKeeper); + + /// @dev Whether the Credit Manager supports quotas + function supportsQuotas() external view returns (bool); + /// @dev A map from borrower addresses to Credit Account addresses function creditAccounts(address borrower) external view returns (address);