@@ -10,6 +10,8 @@ import {IScaledBalanceToken} from '../../../interfaces/IScaledBalanceToken.sol';
10
10
import {IPriceOracleGetter} from '../../../interfaces/IPriceOracleGetter.sol ' ;
11
11
import {IAToken} from '../../../interfaces/IAToken.sol ' ;
12
12
import {IPriceOracleSentinel} from '../../../interfaces/IPriceOracleSentinel.sol ' ;
13
+ import {IPoolAddressesProvider} from '../../../interfaces/IPoolAddressesProvider.sol ' ;
14
+ import {IAccessControl} from '../../../dependencies/openzeppelin/contracts/IAccessControl.sol ' ;
13
15
import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol ' ;
14
16
import {UserConfiguration} from '../configuration/UserConfiguration.sol ' ;
15
17
import {Errors} from '../helpers/Errors.sol ' ;
@@ -19,6 +21,7 @@ import {DataTypes} from '../types/DataTypes.sol';
19
21
import {ReserveLogic} from './ReserveLogic.sol ' ;
20
22
import {GenericLogic} from './GenericLogic.sol ' ;
21
23
import {SafeCast} from '../../../dependencies/openzeppelin/contracts/SafeCast.sol ' ;
24
+ import {IncentivizedERC20} from '../../tokenization/base/IncentivizedERC20.sol ' ;
22
25
23
26
/**
24
27
* @title ReserveLogic library
@@ -49,6 +52,12 @@ library ValidationLogic {
49
52
*/
50
53
uint256 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1e18 ;
51
54
55
+ /**
56
+ * @dev Role identifier for the role allowed to supply isolated reserves as collateral
57
+ */
58
+ bytes32 public constant ISOLATED_COLLATERAL_SUPPLIER_ROLE =
59
+ keccak256 ('ISOLATED_COLLATERAL_SUPPLIER ' );
60
+
52
61
/**
53
62
* @notice Validates a supply action.
54
63
* @param reserveCache The cached data of the reserve
@@ -664,7 +673,7 @@ library ValidationLogic {
664
673
Errors.INCONSISTENT_EMODE_CATEGORY
665
674
);
666
675
667
- //eMode can always be enabled if the user hasn't supplied anything
676
+ // eMode can always be enabled if the user hasn't supplied anything
668
677
if (userConfig.isEmpty ()) {
669
678
return ;
670
679
}
@@ -688,10 +697,8 @@ library ValidationLogic {
688
697
}
689
698
690
699
/**
691
- * @notice Validates if an asset can be activated as collateral in the following actions: supply, transfer,
692
- * set as collateral, mint unbacked, and liquidate
693
- * @dev This is used to ensure that the constraints for isolated assets are respected by all the actions that
694
- * generate transfers of aTokens
700
+ * @notice Validates the action of activating the asset as collateral.
701
+ * @dev Only possible if the asset has non-zero LTV and the user is not in isolation mode
695
702
* @param reservesData The state of all the reserves
696
703
* @param reservesList The addresses of all the active reserves
697
704
* @param userConfig the user configuration
@@ -704,11 +711,46 @@ library ValidationLogic {
704
711
DataTypes.UserConfigurationMap storage userConfig ,
705
712
DataTypes.ReserveConfigurationMap memory reserveConfig
706
713
) internal view returns (bool ) {
714
+ if (reserveConfig.getLtv () == 0 ) {
715
+ return false ;
716
+ }
707
717
if (! userConfig.isUsingAsCollateralAny ()) {
708
718
return true ;
709
719
}
710
720
(bool isolationModeActive , , ) = userConfig.getIsolationModeState (reservesData, reservesList);
711
721
712
722
return (! isolationModeActive && reserveConfig.getDebtCeiling () == 0 );
713
723
}
724
+
725
+ /**
726
+ * @notice Validates if an asset should be automatically activated as collateral in the following actions: supply,
727
+ * transfer, mint unbacked, and liquidate
728
+ * @dev This is used to ensure that isolated assets are not enabled as collateral automatically
729
+ * @param reservesData The state of all the reserves
730
+ * @param reservesList The addresses of all the active reserves
731
+ * @param userConfig the user configuration
732
+ * @param reserveConfig The reserve configuration
733
+ * @return True if the asset can be activated as collateral, false otherwise
734
+ */
735
+ function validateAutomaticUseAsCollateral (
736
+ mapping (address => DataTypes.ReserveData) storage reservesData ,
737
+ mapping (uint256 => address ) storage reservesList ,
738
+ DataTypes.UserConfigurationMap storage userConfig ,
739
+ DataTypes.ReserveConfigurationMap memory reserveConfig ,
740
+ address aTokenAddress
741
+ ) internal view returns (bool ) {
742
+ if (reserveConfig.getDebtCeiling () != 0 ) {
743
+ // ensures only the ISOLATED_COLLATERAL_SUPPLIER_ROLE can enable collateral as side-effect of an action
744
+ IPoolAddressesProvider addressesProvider = IncentivizedERC20 (aTokenAddress)
745
+ .POOL ()
746
+ .ADDRESSES_PROVIDER ();
747
+ if (
748
+ ! IAccessControl (addressesProvider.getACLManager ()).hasRole (
749
+ ISOLATED_COLLATERAL_SUPPLIER_ROLE,
750
+ msg .sender
751
+ )
752
+ ) return false ;
753
+ }
754
+ return validateUseAsCollateral (reservesData, reservesList, userConfig, reserveConfig);
755
+ }
714
756
}
0 commit comments