Skip to content

Commit

Permalink
Merge pull request #832 from aave/feat/3.0.2
Browse files Browse the repository at this point in the history
3.0.2 Upgrade
  • Loading branch information
miguelmtzinf authored Jun 26, 2023
2 parents 29ff9b9 + 9a22701 commit 65c9b32
Show file tree
Hide file tree
Showing 25 changed files with 751 additions and 81 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/certora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
with: { java-version: '11', java-package: jre }

- name: Install certora cli
run: pip install certora-cli
run: pip install certora-cli==3.6.8.post3

- name: Install solc
run: |
Expand Down
Binary file added audits/19-04-2023_SigmaPrime_AaveV3-0-2.pdf
Binary file not shown.
Binary file modified audits/27-01-2022_SigmaPrime_AaveV3.pdf
Binary file not shown.
Binary file added certora/Aave_V3.0.2_PR_820_Report_Mar2023.pdf
Binary file not shown.
2 changes: 1 addition & 1 deletion certora/scripts/verifyAToken.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ certoraRun certora/harness/SimpleERC20.sol \
--link ATokenHarness:_underlyingAsset=SimpleERC20 \
--optimistic_loop \
--solc solc8.10 \
--cloud master \
--cloud \
--msg "aToken spec - all rules"
2 changes: 1 addition & 1 deletion certora/scripts/verifyPool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ certoraRun certora/harness/PoolHarness.sol \
--settings -mediumTimeout=700,-depth=40 \
--optimistic_loop \
--solc solc8.10 \
--cloud master \
--cloud \
--rules $1 \
--msg "Pool"
2 changes: 1 addition & 1 deletion certora/scripts/verifyReserveConfiguration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ certoraRun certora/harness/ReserveConfigurationHarness.sol \
--settings -useBitVectorTheory \
--optimistic_loop \
--solc solc8.10 \
--cloud master \
--cloud \
--msg "ReserveConfiguration"
2 changes: 1 addition & 1 deletion certora/scripts/verifyStableTokenCLI.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ certoraRun certora/harness/StableDebtTokenHarness.sol:StableDebtTokenHarness \
--settings -assumeUnwindCond,-b=4 \
--cache StableToken \
--solc solc8.10 \
--cloud master \
--cloud \
--msg "stableTokenCLI"
2 changes: 1 addition & 1 deletion certora/scripts/verifyUserConfigCLI.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ certoraRun certora/harness/UserConfigurationHarness.sol \
--settings -useBitVectorTheory \
--optimistic_loop \
--solc solc8.10 \
--cloud master \
--cloud \
--msg "UserConfiguration All spec"
2 changes: 1 addition & 1 deletion certora/scripts/verifyVariableTokenCLI.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ certoraRun certora/harness/VariableDebtTokenHarness.sol \
--verify VariableDebtTokenHarness:certora/specs/VariableDebtToken.spec \
--optimistic_loop \
--solc solc8.10 \
--cloud master \
--cloud \
--msg "variable debt token"
3 changes: 2 additions & 1 deletion contracts/interfaces/IL2Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ interface IL2Pool {
* @dev the shortenedAmount is cast to 256 bits at decode time, if type(uint128).max the value will be expanded to
* type(uint256).max
* @dev assetId is the index of the asset in the reservesList.
* @return The final amount withdrawn
*/
function withdraw(bytes32 args) external;
function withdraw(bytes32 args) external returns (uint256);

/**
* @notice Calldata efficient wrapper of the borrow function, borrowing on behalf of the caller
Expand Down
105 changes: 105 additions & 0 deletions contracts/misc/ZeroReserveInterestRateStrategy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
import {IDefaultInterestRateStrategy} from '../interfaces/IDefaultInterestRateStrategy.sol';
import {IReserveInterestRateStrategy} from '../interfaces/IReserveInterestRateStrategy.sol';
import {IPoolAddressesProvider} from '../interfaces/IPoolAddressesProvider.sol';

/**
* @title ZeroReserveInterestRateStrategy contract
* @author Aave
* @notice Interest Rate Strategy contract, with all parameters zeroed.
* @dev It returns zero liquidity and borrow rate.
*/
contract ZeroReserveInterestRateStrategy is IDefaultInterestRateStrategy {
/// @inheritdoc IDefaultInterestRateStrategy
uint256 public constant OPTIMAL_USAGE_RATIO = 0;

/// @inheritdoc IDefaultInterestRateStrategy
uint256 public constant OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO = 0;

/// @inheritdoc IDefaultInterestRateStrategy
uint256 public constant MAX_EXCESS_USAGE_RATIO = 0;

/// @inheritdoc IDefaultInterestRateStrategy
uint256 public constant MAX_EXCESS_STABLE_TO_TOTAL_DEBT_RATIO = 0;

IPoolAddressesProvider public immutable ADDRESSES_PROVIDER;

// Base variable borrow rate when usage rate = 0. Expressed in ray
uint256 internal constant _baseVariableBorrowRate = 0;

// Slope of the variable interest curve when usage ratio > 0 and <= OPTIMAL_USAGE_RATIO. Expressed in ray
uint256 internal constant _variableRateSlope1 = 0;

// Slope of the variable interest curve when usage ratio > OPTIMAL_USAGE_RATIO. Expressed in ray
uint256 internal constant _variableRateSlope2 = 0;

// Slope of the stable interest curve when usage ratio > 0 and <= OPTIMAL_USAGE_RATIO. Expressed in ray
uint256 internal constant _stableRateSlope1 = 0;

// Slope of the stable interest curve when usage ratio > OPTIMAL_USAGE_RATIO. Expressed in ray
uint256 internal constant _stableRateSlope2 = 0;

// Premium on top of `_variableRateSlope1` for base stable borrowing rate
uint256 internal constant _baseStableRateOffset = 0;

// Additional premium applied to stable rate when stable debt surpass `OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO`
uint256 internal constant _stableRateExcessOffset = 0;

/**
* @dev Constructor.
* @param provider The address of the PoolAddressesProvider contract
*/
constructor(IPoolAddressesProvider provider) {
ADDRESSES_PROVIDER = provider;
}

/// @inheritdoc IDefaultInterestRateStrategy
function getVariableRateSlope1() external pure returns (uint256) {
return _variableRateSlope1;
}

/// @inheritdoc IDefaultInterestRateStrategy
function getVariableRateSlope2() external pure returns (uint256) {
return _variableRateSlope2;
}

/// @inheritdoc IDefaultInterestRateStrategy
function getStableRateSlope1() external pure returns (uint256) {
return _stableRateSlope1;
}

/// @inheritdoc IDefaultInterestRateStrategy
function getStableRateSlope2() external pure returns (uint256) {
return _stableRateSlope2;
}

/// @inheritdoc IDefaultInterestRateStrategy
function getStableRateExcessOffset() external pure returns (uint256) {
return _stableRateExcessOffset;
}

/// @inheritdoc IDefaultInterestRateStrategy
function getBaseStableBorrowRate() public pure returns (uint256) {
return _variableRateSlope1 + _baseStableRateOffset;
}

/// @inheritdoc IDefaultInterestRateStrategy
function getBaseVariableBorrowRate() external pure override returns (uint256) {
return _baseVariableBorrowRate;
}

/// @inheritdoc IDefaultInterestRateStrategy
function getMaxVariableBorrowRate() external pure override returns (uint256) {
return _baseVariableBorrowRate + _variableRateSlope1 + _variableRateSlope2;
}

/// @inheritdoc IReserveInterestRateStrategy
function calculateInterestRates(
DataTypes.CalculateInterestRatesParams memory
) public pure override returns (uint256, uint256, uint256) {
return (0, 0, 0);
}
}
2 changes: 1 addition & 1 deletion contracts/protocol/libraries/helpers/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ library Errors {
string public constant PRICE_ORACLE_SENTINEL_CHECK_FAILED = '59'; // 'Price oracle sentinel validation failed'
string public constant ASSET_NOT_BORROWABLE_IN_ISOLATION = '60'; // 'Asset is not borrowable in isolation mode'
string public constant RESERVE_ALREADY_INITIALIZED = '61'; // 'Reserve has already been initialized'
string public constant USER_IN_ISOLATION_MODE = '62'; // 'User is in isolation mode'
string public constant USER_IN_ISOLATION_MODE_OR_LTV_ZERO = '62'; // 'User is in isolation mode or ltv is zero'
string public constant INVALID_LTV = '63'; // 'Invalid ltv parameter for the reserve'
string public constant INVALID_LIQ_THRESHOLD = '64'; // 'Invalid liquidity threshold parameter for the reserve'
string public constant INVALID_LIQ_BONUS = '65'; // 'Invalid liquidity bonus parameter for the reserve'
Expand Down
5 changes: 3 additions & 2 deletions contracts/protocol/libraries/logic/BridgeLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,12 @@ library BridgeLogic {

if (isFirstSupply) {
if (
ValidationLogic.validateUseAsCollateral(
ValidationLogic.validateAutomaticUseAsCollateral(
reservesData,
reservesList,
userConfig,
reserveCache.reserveConfiguration
reserveCache.reserveConfiguration,
reserveCache.aTokenAddress
)
) {
userConfig.setUsingAsCollateral(reserve.id, true);
Expand Down
5 changes: 4 additions & 1 deletion contracts/protocol/libraries/logic/FlashLoanLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ library FlashLoanLogic {

for (vars.i = 0; vars.i < params.assets.length; vars.i++) {
vars.currentAmount = params.amounts[vars.i];
vars.totalPremiums[vars.i] = vars.currentAmount.percentMul(vars.flashloanPremiumTotal);
vars.totalPremiums[vars.i] = DataTypes.InterestRateMode(params.interestRateModes[vars.i]) ==
DataTypes.InterestRateMode.NONE
? vars.currentAmount.percentMul(vars.flashloanPremiumTotal)
: 0;
IAToken(reservesData[params.assets[vars.i]].aTokenAddress).transferUnderlyingTo(
params.receiverAddress,
vars.currentAmount
Expand Down
5 changes: 3 additions & 2 deletions contracts/protocol/libraries/logic/LiquidationLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,12 @@ library LiquidationLogic {
if (liquidatorPreviousATokenBalance == 0) {
DataTypes.UserConfigurationMap storage liquidatorConfig = usersConfig[msg.sender];
if (
ValidationLogic.validateUseAsCollateral(
ValidationLogic.validateAutomaticUseAsCollateral(
reservesData,
reservesList,
liquidatorConfig,
collateralReserve.configuration
collateralReserve.configuration,
collateralReserve.aTokenAddress
)
) {
liquidatorConfig.setUsingAsCollateral(collateralReserve.id, true);
Expand Down
12 changes: 7 additions & 5 deletions contracts/protocol/libraries/logic/SupplyLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,12 @@ library SupplyLogic {

if (isFirstSupply) {
if (
ValidationLogic.validateUseAsCollateral(
ValidationLogic.validateAutomaticUseAsCollateral(
reservesData,
reservesList,
userConfig,
reserveCache.reserveConfiguration
reserveCache.reserveConfiguration,
reserveCache.aTokenAddress
)
) {
userConfig.setUsingAsCollateral(reserve.id, true);
Expand Down Expand Up @@ -212,11 +213,12 @@ library SupplyLogic {
if (params.balanceToBefore == 0) {
DataTypes.UserConfigurationMap storage toConfig = usersConfig[params.to];
if (
ValidationLogic.validateUseAsCollateral(
ValidationLogic.validateAutomaticUseAsCollateral(
reservesData,
reservesList,
toConfig,
reserve.configuration
reserve.configuration,
reserve.aTokenAddress
)
) {
toConfig.setUsingAsCollateral(reserveId, true);
Expand Down Expand Up @@ -270,7 +272,7 @@ library SupplyLogic {
userConfig,
reserveCache.reserveConfiguration
),
Errors.USER_IN_ISOLATION_MODE
Errors.USER_IN_ISOLATION_MODE_OR_LTV_ZERO
);

userConfig.setUsingAsCollateral(reserve.id, true);
Expand Down
52 changes: 47 additions & 5 deletions contracts/protocol/libraries/logic/ValidationLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {IScaledBalanceToken} from '../../../interfaces/IScaledBalanceToken.sol';
import {IPriceOracleGetter} from '../../../interfaces/IPriceOracleGetter.sol';
import {IAToken} from '../../../interfaces/IAToken.sol';
import {IPriceOracleSentinel} from '../../../interfaces/IPriceOracleSentinel.sol';
import {IPoolAddressesProvider} from '../../../interfaces/IPoolAddressesProvider.sol';
import {IAccessControl} from '../../../dependencies/openzeppelin/contracts/IAccessControl.sol';
import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../configuration/UserConfiguration.sol';
import {Errors} from '../helpers/Errors.sol';
Expand All @@ -19,6 +21,7 @@ import {DataTypes} from '../types/DataTypes.sol';
import {ReserveLogic} from './ReserveLogic.sol';
import {GenericLogic} from './GenericLogic.sol';
import {SafeCast} from '../../../dependencies/openzeppelin/contracts/SafeCast.sol';
import {IncentivizedERC20} from '../../tokenization/base/IncentivizedERC20.sol';

/**
* @title ReserveLogic library
Expand Down Expand Up @@ -49,6 +52,12 @@ library ValidationLogic {
*/
uint256 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1e18;

/**
* @dev Role identifier for the role allowed to supply isolated reserves as collateral
*/
bytes32 public constant ISOLATED_COLLATERAL_SUPPLIER_ROLE =
keccak256('ISOLATED_COLLATERAL_SUPPLIER');

/**
* @notice Validates a supply action.
* @param reserveCache The cached data of the reserve
Expand Down Expand Up @@ -664,7 +673,7 @@ library ValidationLogic {
Errors.INCONSISTENT_EMODE_CATEGORY
);

//eMode can always be enabled if the user hasn't supplied anything
// eMode can always be enabled if the user hasn't supplied anything
if (userConfig.isEmpty()) {
return;
}
Expand All @@ -688,10 +697,8 @@ library ValidationLogic {
}

/**
* @notice Validates if an asset can be activated as collateral in the following actions: supply, transfer,
* set as collateral, mint unbacked, and liquidate
* @dev This is used to ensure that the constraints for isolated assets are respected by all the actions that
* generate transfers of aTokens
* @notice Validates the action of activating the asset as collateral.
* @dev Only possible if the asset has non-zero LTV and the user is not in isolation mode
* @param reservesData The state of all the reserves
* @param reservesList The addresses of all the active reserves
* @param userConfig the user configuration
Expand All @@ -704,11 +711,46 @@ library ValidationLogic {
DataTypes.UserConfigurationMap storage userConfig,
DataTypes.ReserveConfigurationMap memory reserveConfig
) internal view returns (bool) {
if (reserveConfig.getLtv() == 0) {
return false;
}
if (!userConfig.isUsingAsCollateralAny()) {
return true;
}
(bool isolationModeActive, , ) = userConfig.getIsolationModeState(reservesData, reservesList);

return (!isolationModeActive && reserveConfig.getDebtCeiling() == 0);
}

/**
* @notice Validates if an asset should be automatically activated as collateral in the following actions: supply,
* transfer, mint unbacked, and liquidate
* @dev This is used to ensure that isolated assets are not enabled as collateral automatically
* @param reservesData The state of all the reserves
* @param reservesList The addresses of all the active reserves
* @param userConfig the user configuration
* @param reserveConfig The reserve configuration
* @return True if the asset can be activated as collateral, false otherwise
*/
function validateAutomaticUseAsCollateral(
mapping(address => DataTypes.ReserveData) storage reservesData,
mapping(uint256 => address) storage reservesList,
DataTypes.UserConfigurationMap storage userConfig,
DataTypes.ReserveConfigurationMap memory reserveConfig,
address aTokenAddress
) internal view returns (bool) {
if (reserveConfig.getDebtCeiling() != 0) {
// ensures only the ISOLATED_COLLATERAL_SUPPLIER_ROLE can enable collateral as side-effect of an action
IPoolAddressesProvider addressesProvider = IncentivizedERC20(aTokenAddress)
.POOL()
.ADDRESSES_PROVIDER();
if (
!IAccessControl(addressesProvider.getACLManager()).hasRole(
ISOLATED_COLLATERAL_SUPPLIER_ROLE,
msg.sender
)
) return false;
}
return validateUseAsCollateral(reservesData, reservesList, userConfig, reserveConfig);
}
}
6 changes: 1 addition & 5 deletions contracts/protocol/libraries/types/DataTypes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,7 @@ library DataTypes {
string label;
}

enum InterestRateMode {
NONE,
STABLE,
VARIABLE
}
enum InterestRateMode {NONE, STABLE, VARIABLE}

struct ReserveCache {
uint256 currScaledVariableDebt;
Expand Down
4 changes: 2 additions & 2 deletions contracts/protocol/pool/L2Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ contract L2Pool is Pool, IL2Pool {
}

/// @inheritdoc IL2Pool
function withdraw(bytes32 args) external override {
function withdraw(bytes32 args) external override returns (uint256) {
(address asset, uint256 amount) = CalldataLogic.decodeWithdrawParams(_reservesList, args);

withdraw(asset, amount, msg.sender);
return withdraw(asset, amount, msg.sender);
}

/// @inheritdoc IL2Pool
Expand Down
2 changes: 1 addition & 1 deletion helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export enum ProtocolErrors {
PRICE_ORACLE_SENTINEL_CHECK_FAILED = '59', // 'Price oracle sentinel validation failed'
ASSET_NOT_BORROWABLE_IN_ISOLATION = '60', // 'Asset is not borrowable in isolation mode'
RESERVE_ALREADY_INITIALIZED = '61', // 'Reserve has already been initialized'
USER_IN_ISOLATION_MODE = '62', // 'User is in isolation mode'
USER_IN_ISOLATION_MODE_OR_LTV_ZERO = '62', // 'User is in isolation mode or ltv is zero'
INVALID_LTV = '63', // 'Invalid ltv parameter for the reserve'
INVALID_LIQ_THRESHOLD = '64', // 'Invalid liquidity threshold parameter for the reserve'
INVALID_LIQ_BONUS = '65', // 'Invalid liquidity bonus parameter for the reserve'
Expand Down
Loading

0 comments on commit 65c9b32

Please sign in to comment.