diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..548c6302 --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +# include .env file and export its env vars +# (-include to ignore error if it does not exist) +-include .env + +# Deploy GHO Stewards V2 +deploy-gho-stewards :; forge script src/script/DeployGhoStewardsV2.s.sol:DeployGhoStewardsV2 --rpc-url mainnet --broadcast --ledger --mnemonic-indexes ${MNEMONIC_INDEX} --sender ${LEDGER_SENDER} --etherscan-api-key ${ETHERSCAN_API_KEY_MAINNET} --gas-estimate-multiplier 125 --verify -vvvv \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index 35991f55..18a1b1eb 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,10 +6,15 @@ script = 'src/script' cache_path = 'cache_forge' libs = ['node_modules', 'lib'] - solc_version = "0.8.10" extra_output_files = ["metadata"] optimizer = true optimizer_runs = 200 +[rpc_endpoints] +mainnet = "${RPC_MAINNET}" + +[etherscan] +mainnet={key="${ETHERSCAN_API_KEY_MAINNET}",chainId=1} + # See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file diff --git a/lib/aave-address-book b/lib/aave-address-book index e65e63ce..5c08f2b7 160000 --- a/lib/aave-address-book +++ b/lib/aave-address-book @@ -1 +1 @@ -Subproject commit e65e63cec1dd61e7a21ed0db34795a708577a503 +Subproject commit 5c08f2b7475f3af24d8f29f35a707d18716ebb93 diff --git a/remappings.txt b/remappings.txt index e7ac529f..1c35a199 100644 --- a/remappings.txt +++ b/remappings.txt @@ -2,6 +2,7 @@ @aave/periphery-v3/=lib/aave-v3-periphery/ @aave/=lib/aave-token/ @openzeppelin/=lib/openzeppelin-contracts/ +@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ aave-stk-v1-5/=lib/aave-stk-v1-5/ ds-test/=lib/forge-std/lib/ds-test/src/ eth-gas-reporter/=node_modules/eth-gas-reporter/ @@ -15,3 +16,4 @@ aave-v3-periphery/=lib/aave-address-book/lib/aave-v3-periphery/ erc4626-tests/=lib/aave-stk-v1-5/lib/openzeppelin-contracts/lib/erc4626-tests/ openzeppelin-contracts/=lib/aave-stk-v1-5/lib/openzeppelin-contracts/ solidity-utils/=lib/solidity-utils/src/ +aave-v3-origin/=lib/aave-address-book/lib/aave-v3-origin/src/ \ No newline at end of file diff --git a/src/contracts/misc/GhoStewardV2.sol b/src/contracts/misc/GhoStewardV2.sol index 40311ed4..8e79534a 100644 --- a/src/contracts/misc/GhoStewardV2.sol +++ b/src/contracts/misc/GhoStewardV2.sol @@ -3,18 +3,18 @@ pragma solidity ^0.8.10; import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol'; import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; -import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol'; -import {IPoolConfigurator} from '@aave/core-v3/contracts/interfaces/IPoolConfigurator.sol'; -import {IPool} from '@aave/core-v3/contracts/interfaces/IPool.sol'; -import {DataTypes} from '@aave/core-v3/contracts/protocol/libraries/types/DataTypes.sol'; -import {ReserveConfiguration} from '@aave/core-v3/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; -import {GhoInterestRateStrategy} from '../facilitators/aave/interestStrategy/GhoInterestRateStrategy.sol'; -import {IFixedRateStrategyFactory} from '../facilitators/aave/interestStrategy/interfaces/IFixedRateStrategyFactory.sol'; +import {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol'; +import {IPoolAddressesProvider} from 'aave-v3-origin/core/contracts/interfaces/IPoolAddressesProvider.sol'; +import {IPoolConfigurator} from 'aave-v3-origin/core/contracts/interfaces/IPoolConfigurator.sol'; +import {IPool} from 'aave-v3-origin/core/contracts/interfaces/IPool.sol'; +import {DataTypes} from 'aave-v3-origin/core/contracts/protocol/libraries/types/DataTypes.sol'; +import {ReserveConfiguration} from 'aave-v3-origin/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; import {FixedFeeStrategy} from '../facilitators/gsm/feeStrategy/FixedFeeStrategy.sol'; import {IGsm} from '../facilitators/gsm/interfaces/IGsm.sol'; import {IGsmFeeStrategy} from '../facilitators/gsm/feeStrategy/interfaces/IGsmFeeStrategy.sol'; import {IGhoToken} from '../gho/interfaces/IGhoToken.sol'; import {IGhoStewardV2} from './interfaces/IGhoStewardV2.sol'; +import {IDefaultInterestRateStrategyV2} from 'aave-v3-origin/core/contracts/interfaces/IDefaultInterestRateStrategyV2.sol'; /** * @title GhoStewardV2 @@ -25,17 +25,17 @@ import {IGhoStewardV2} from './interfaces/IGhoStewardV2.sol'; * @dev Only the Aave DAO is able add or remove approved GSMs. * @dev When updating GSM fee strategy the method assumes that the current strategy is FixedFeeStrategy for enforcing parameters * @dev FixedFeeStrategy is used when creating a new strategy for GSM - * @dev FixedRateStrategyFactory is used when creating a new borrow rate strategy for GHO */ contract GhoStewardV2 is Ownable, IGhoStewardV2 { using EnumerableSet for EnumerableSet.AddressSet; using ReserveConfiguration for DataTypes.ReserveConfigurationMap; + using SafeCast for uint256; /// @inheritdoc IGhoStewardV2 - uint256 public constant GHO_BORROW_RATE_MAX = 0.2500e27; // 25.00% + uint256 public constant GHO_BORROW_RATE_MAX = 0.2500e4; // 25.00% /// @inheritdoc IGhoStewardV2 - uint256 public constant GHO_BORROW_RATE_CHANGE_MAX = 0.0500e27; // 5.00% + uint256 public constant GHO_BORROW_RATE_CHANGE_MAX = 0.0500e4; // 5.00% /// @inheritdoc IGhoStewardV2 uint256 public constant GSM_FEE_RATE_CHANGE_MAX = 0.0050e4; // 0.50% @@ -49,9 +49,6 @@ contract GhoStewardV2 is Ownable, IGhoStewardV2 { /// @inheritdoc IGhoStewardV2 address public immutable GHO_TOKEN; - /// @inheritdoc IGhoStewardV2 - address public immutable FIXED_RATE_STRATEGY_FACTORY; - /// @inheritdoc IGhoStewardV2 address public immutable RISK_COUNCIL; @@ -86,25 +83,16 @@ contract GhoStewardV2 is Ownable, IGhoStewardV2 { * @param owner The address of the owner of the contract * @param addressesProvider The address of the PoolAddressesProvider of Aave V3 Ethereum Pool * @param ghoToken The address of the GhoToken - * @param fixedRateStrategyFactory The address of the FixedRateStrategyFactory * @param riskCouncil The address of the risk council */ - constructor( - address owner, - address addressesProvider, - address ghoToken, - address fixedRateStrategyFactory, - address riskCouncil - ) { + constructor(address owner, address addressesProvider, address ghoToken, address riskCouncil) { require(owner != address(0), 'INVALID_OWNER'); require(addressesProvider != address(0), 'INVALID_ADDRESSES_PROVIDER'); require(ghoToken != address(0), 'INVALID_GHO_TOKEN'); - require(fixedRateStrategyFactory != address(0), 'INVALID_FIXED_RATE_STRATEGY_FACTORY'); require(riskCouncil != address(0), 'INVALID_RISK_COUNCIL'); POOL_ADDRESSES_PROVIDER = addressesProvider; GHO_TOKEN = ghoToken; - FIXED_RATE_STRATEGY_FACTORY = fixedRateStrategyFactory; RISK_COUNCIL = riskCouncil; _transferOwnership(owner); @@ -150,33 +138,33 @@ contract GhoStewardV2 is Ownable, IGhoStewardV2 { function updateGhoBorrowRate( uint256 newBorrowRate ) external onlyRiskCouncil notTimelocked(_ghoTimelocks.ghoBorrowRateLastUpdate) { - DataTypes.ReserveData memory ghoReserveData = IPool( + DataTypes.ReserveDataLegacy memory ghoReserveData = IPool( IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER).getPool() ).getReserveData(GHO_TOKEN); require( ghoReserveData.interestRateStrategyAddress != address(0), 'GHO_INTEREST_RATE_STRATEGY_NOT_FOUND' ); - - uint256 currentBorrowRate = GhoInterestRateStrategy(ghoReserveData.interestRateStrategyAddress) - .getBaseVariableBorrowRate(); require(newBorrowRate <= GHO_BORROW_RATE_MAX, 'BORROW_RATE_HIGHER_THAN_MAX'); + + IDefaultInterestRateStrategyV2.InterestRateData + memory interestRateData = IDefaultInterestRateStrategyV2( + ghoReserveData.interestRateStrategyAddress + ).getInterestRateDataBps(GHO_TOKEN); + require( - _isDifferenceLowerThanMax(currentBorrowRate, newBorrowRate, GHO_BORROW_RATE_CHANGE_MAX), + _isDifferenceLowerThanMax( + interestRateData.baseVariableBorrowRate, + newBorrowRate, + GHO_BORROW_RATE_CHANGE_MAX + ), 'INVALID_BORROW_RATE_UPDATE' ); - - IFixedRateStrategyFactory strategyFactory = IFixedRateStrategyFactory( - FIXED_RATE_STRATEGY_FACTORY - ); - uint256[] memory borrowRateList = new uint256[](1); - borrowRateList[0] = newBorrowRate; - address strategy = strategyFactory.createStrategies(borrowRateList)[0]; - _ghoTimelocks.ghoBorrowRateLastUpdate = uint40(block.timestamp); + interestRateData.baseVariableBorrowRate = newBorrowRate.toUint32(); IPoolConfigurator(IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER).getPoolConfigurator()) - .setReserveInterestRateStrategyAddress(GHO_TOKEN, strategy); + .setReserveInterestRateData(GHO_TOKEN, abi.encode(interestRateData)); } /// @inheritdoc IGhoStewardV2 diff --git a/src/contracts/misc/interfaces/IGhoStewardV2.sol b/src/contracts/misc/interfaces/IGhoStewardV2.sol index 2b0138da..fac80f95 100644 --- a/src/contracts/misc/interfaces/IGhoStewardV2.sol +++ b/src/contracts/misc/interfaces/IGhoStewardV2.sol @@ -43,7 +43,7 @@ interface IGhoStewardV2 { * - the update changes up to `GHO_BORROW_RATE_CHANGE_MAX` upwards or downwards * - the update is lower than `GHO_BORROW_RATE_MAX` * @dev Only callable by Risk Council - * @param newBorrowRate The new variable borrow rate (expressed in ray) (e.g. 0.0150e27 results in 1.50%) + * @param newBorrowRate The new variable borrow rate (expressed in bps) (e.g. 0.0150e4 results in 1.50%) */ function updateGhoBorrowRate(uint256 newBorrowRate) external; @@ -78,19 +78,19 @@ interface IGhoStewardV2 { /** * @notice Returns the maximum increase/decrease for GHO borrow rate updates. - * @return The maximum increase change for borrow rate updates in ray (e.g. 0.010e27 results in 1.00%) + * @return The maximum increase change for borrow rate updates in bps (e.g. 0.0100e4 results in 1.00%) */ function GHO_BORROW_RATE_CHANGE_MAX() external view returns (uint256); /** - * @notice Returns the maximum increase for GSM fee rates (buy or sell). + * @notice Returns the maximum increase for GSM fee rates (buy or sell). 0010 * @return The maximum increase change for GSM fee rates updates in bps (e.g. 0.010e4 results in 1.00%) */ function GSM_FEE_RATE_CHANGE_MAX() external view returns (uint256); /** * @notice Returns maximum value that can be assigned to GHO borrow rate. - * @return The maximum value that can be assigned to GHO borrow rate in ray (e.g. 0.01e27 results in 1.0%) + * @return The maximum value that can be assigned to GHO borrow rate in bps (e.g. 0.0100e4 results in 1.00%) */ function GHO_BORROW_RATE_MAX() external view returns (uint256); @@ -112,12 +112,6 @@ interface IGhoStewardV2 { */ function GHO_TOKEN() external view returns (address); - /** - * @notice Returns the address of the fixed rate strategy factory - * @return The address of the FixedRateStrategyFactory - */ - function FIXED_RATE_STRATEGY_FACTORY() external view returns (address); - /** * @notice Returns the address of the risk council * @return The address of the RiskCouncil diff --git a/src/script/DeployGhoStewardsV2.s.sol b/src/script/DeployGhoStewardsV2.s.sol new file mode 100644 index 00000000..4af518ce --- /dev/null +++ b/src/script/DeployGhoStewardsV2.s.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Script, console2} from 'forge-std/Script.sol'; +import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; +import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {GhoStewardV2} from '../contracts/misc/GhoStewardV2.sol'; + +contract DeployGhoStewardsV2 is Script { + address public constant RISK_COUNCIL = 0x8513e6F37dBc52De87b166980Fa3F50639694B60; + + function run() external { + vm.startBroadcast(); + _deploy(); + vm.stopBroadcast(); + } + + function _deploy() internal { + GhoStewardV2 ghoSteward = new GhoStewardV2( + GovernanceV3Ethereum.EXECUTOR_LVL_1, // owner + address(AaveV3Ethereum.POOL_ADDRESSES_PROVIDER), + MiscEthereum.GHO_TOKEN, + RISK_COUNCIL + ); + console2.log('Gho Steward V2: ', address(ghoSteward)); + } +} diff --git a/src/test/TestGhoBase.t.sol b/src/test/TestGhoBase.t.sol index e85097cc..5579d96d 100644 --- a/src/test/TestGhoBase.t.sol +++ b/src/test/TestGhoBase.t.sol @@ -50,6 +50,7 @@ import {ERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts import {StakedAaveV3} from 'aave-stk-v1-5/src/contracts/StakedAaveV3.sol'; import {ReserveConfiguration} from '@aave/core-v3/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {DefaultReserveInterestRateStrategyV2, IDefaultInterestRateStrategyV2} from 'aave-v3-origin/core/contracts/protocol/pool/DefaultReserveInterestRateStrategyV2.sol'; // GHO contracts import {GhoAToken} from '../contracts/facilitators/aave/tokens/GhoAToken.sol'; @@ -296,7 +297,6 @@ contract TestGhoBase is Test, Constants, Events { SHORT_EXECUTOR, address(PROVIDER), address(GHO_TOKEN), - address(FIXED_RATE_STRATEGY_FACTORY), RISK_COUNCIL ); GHO_TOKEN.grantRole(GHO_TOKEN_BUCKET_MANAGER_ROLE, address(GHO_STEWARD_V2)); diff --git a/src/test/TestGhoStewardV2.t.sol b/src/test/TestGhoStewardV2.t.sol index 801fc373..9139229a 100644 --- a/src/test/TestGhoStewardV2.t.sol +++ b/src/test/TestGhoStewardV2.t.sol @@ -5,10 +5,31 @@ import './TestGhoBase.t.sol'; contract TestGhoStewardV2 is TestGhoBase { using ReserveConfiguration for DataTypes.ReserveConfigurationMap; + using SafeCast for uint256; function setUp() public { /// @dev Since block.timestamp starts at 0 this is a necessary condition (block.timestamp > `MINIMUM_DELAY`) for the timelocked contract methods to work. vm.warp(GHO_STEWARD_V2.MINIMUM_DELAY() + 1); + + // set the interest rate strategy as per v3.1 new interest rate strategy contract + DefaultReserveInterestRateStrategyV2 defaultInterestRateStrategy = new DefaultReserveInterestRateStrategyV2( + address(PROVIDER) + ); + vm.startPrank(address(CONFIGURATOR)); + POOL.setReserveInterestRateStrategyAddress( + address(GHO_TOKEN), + address(defaultInterestRateStrategy) + ); + defaultInterestRateStrategy.setInterestRateParams( + address(GHO_TOKEN), + IDefaultInterestRateStrategyV2.InterestRateData({ + optimalUsageRatio: 99_00, + baseVariableBorrowRate: 6_00, + variableRateSlope1: 0, + variableRateSlope2: 0 + }) + ); + vm.stopPrank(); } function testConstructor() public { @@ -20,7 +41,6 @@ contract TestGhoStewardV2 is TestGhoBase { assertEq(GHO_STEWARD.owner(), SHORT_EXECUTOR); assertEq(GHO_STEWARD_V2.POOL_ADDRESSES_PROVIDER(), address(PROVIDER)); assertEq(GHO_STEWARD_V2.GHO_TOKEN(), address(GHO_TOKEN)); - assertEq(GHO_STEWARD_V2.FIXED_RATE_STRATEGY_FACTORY(), address(FIXED_RATE_STRATEGY_FACTORY)); assertEq(GHO_STEWARD_V2.RISK_COUNCIL(), RISK_COUNCIL); IGhoStewardV2.GhoDebounce memory ghoTimelocks = GHO_STEWARD_V2.getGhoTimelocks(); @@ -41,27 +61,22 @@ contract TestGhoStewardV2 is TestGhoBase { function testRevertConstructorInvalidExecutor() public { vm.expectRevert('INVALID_OWNER'); - new GhoStewardV2(address(0), address(0x002), address(0x003), address(0x004), address(0x005)); + new GhoStewardV2(address(0), address(0x002), address(0x003), address(0x005)); } function testRevertConstructorInvalidAddressesProvider() public { vm.expectRevert('INVALID_ADDRESSES_PROVIDER'); - new GhoStewardV2(address(0x001), address(0), address(0x003), address(0x004), address(0x005)); + new GhoStewardV2(address(0x001), address(0), address(0x003), address(0x005)); } function testRevertConstructorInvalidGhoToken() public { vm.expectRevert('INVALID_GHO_TOKEN'); - new GhoStewardV2(address(0x001), address(0x002), address(0), address(0x004), address(0x005)); - } - - function testRevertConstructorInvalidFixedRateStrategyFactory() public { - vm.expectRevert('INVALID_FIXED_RATE_STRATEGY_FACTORY'); - new GhoStewardV2(address(0x001), address(0x002), address(0x003), address(0), address(0x005)); + new GhoStewardV2(address(0x001), address(0x002), address(0), address(0x005)); } function testRevertConstructorInvalidRiskCouncil() public { vm.expectRevert('INVALID_RISK_COUNCIL'); - new GhoStewardV2(address(0x001), address(0x002), address(0x003), address(0x005), address(0)); + new GhoStewardV2(address(0x001), address(0x002), address(0x003), address(0)); } function testUpdateFacilitatorBucketCapacity() public { @@ -256,7 +271,7 @@ contract TestGhoStewardV2 is TestGhoBase { function testUpdateGhoBorrowRateMaxValue() public { uint256 ghoBorrowRateMax = GHO_STEWARD_V2.GHO_BORROW_RATE_MAX(); - (, uint256 oldBorrowRate) = _setGhoBorrowRateViaConfigurator(ghoBorrowRateMax - 1); + uint256 oldBorrowRate = _setGhoBorrowRateViaConfigurator(ghoBorrowRateMax - 1); vm.prank(RISK_COUNCIL); GHO_STEWARD_V2.updateGhoBorrowRate(ghoBorrowRateMax); uint256 currentBorrowRate = _getGhoBorrowRate(); @@ -324,11 +339,13 @@ contract TestGhoStewardV2 is TestGhoBase { } function testRevertUpdateGhoBorrowRateIfUpdatedTooSoon() public { - address oldInterestStrategy = POOL.getReserveInterestRateStrategyAddress(address(GHO_TOKEN)); - uint256 oldBorrowRate = GhoInterestRateStrategy(oldInterestStrategy) - .getBaseVariableBorrowRate(); + address interestRateStrategy = POOL.getReserveInterestRateStrategyAddress(address(GHO_TOKEN)); + IDefaultInterestRateStrategyV2.InterestRateData + memory interestRateData = IDefaultInterestRateStrategyV2(interestRateStrategy) + .getInterestRateDataBps(address(GHO_TOKEN)); + vm.prank(RISK_COUNCIL); - uint256 newBorrowRate = oldBorrowRate + 1; + uint256 newBorrowRate = interestRateData.baseVariableBorrowRate + 1; GHO_STEWARD_V2.updateGhoBorrowRate(newBorrowRate); vm.prank(RISK_COUNCIL); vm.expectRevert('DEBOUNCE_NOT_RESPECTED'); @@ -821,32 +838,27 @@ contract TestGhoStewardV2 is TestGhoBase { CONFIGURATOR.setBorrowCap(address(GHO_TOKEN), newBorrowCap); } - function _setGhoBorrowRateViaConfigurator( - uint256 newBorrowRate - ) internal returns (GhoInterestRateStrategy, uint256) { - GhoInterestRateStrategy newRateStrategy = new GhoInterestRateStrategy( - address(PROVIDER), - newBorrowRate - ); - CONFIGURATOR.setReserveInterestRateStrategyAddress( + function _setGhoBorrowRateViaConfigurator(uint256 newBorrowRate) internal returns (uint256) { + address interestRateStrategy = POOL.getReserveInterestRateStrategyAddress(address(GHO_TOKEN)); + IDefaultInterestRateStrategyV2.InterestRateData + memory interestRateData = IDefaultInterestRateStrategyV2(interestRateStrategy) + .getInterestRateDataBps(address(GHO_TOKEN)); + interestRateData.baseVariableBorrowRate = newBorrowRate.toUint32(); + + vm.prank(address(CONFIGURATOR)); + IDefaultInterestRateStrategyV2(interestRateStrategy).setInterestRateParams( address(GHO_TOKEN), - address(newRateStrategy) - ); - address currentInterestRateStrategy = POOL.getReserveInterestRateStrategyAddress( - address(GHO_TOKEN) + interestRateData ); - uint256 currentBorrowRate = GhoInterestRateStrategy(currentInterestRateStrategy) - .getBaseVariableBorrowRate(); - assertEq(currentInterestRateStrategy, address(newRateStrategy)); - assertEq(currentBorrowRate, newBorrowRate); - return (newRateStrategy, newBorrowRate); + return newBorrowRate; } function _getGhoBorrowRate() internal view returns (uint256) { - address currentInterestRateStrategy = POOL.getReserveInterestRateStrategyAddress( - address(GHO_TOKEN) - ); - return GhoInterestRateStrategy(currentInterestRateStrategy).getBaseVariableBorrowRate(); + address interestRateStrategy = POOL.getReserveInterestRateStrategyAddress(address(GHO_TOKEN)); + IDefaultInterestRateStrategyV2.InterestRateData + memory interestRateData = IDefaultInterestRateStrategyV2(interestRateStrategy) + .getInterestRateDataBps(address(GHO_TOKEN)); + return interestRateData.baseVariableBorrowRate; } function _getGhoBorrowCap() internal view returns (uint256) { diff --git a/src/test/helpers/Constants.sol b/src/test/helpers/Constants.sol index 68952b7b..6d0f726e 100644 --- a/src/test/helpers/Constants.sol +++ b/src/test/helpers/Constants.sol @@ -55,9 +55,9 @@ contract Constants { uint40 constant STEWARD_LIFESPAN = 90 days; // GhoStewardV2 - uint256 constant GHO_BORROW_RATE_CHANGE_MAX = 0.0500e27; + uint256 constant GHO_BORROW_RATE_CHANGE_MAX = 0.0500e4; uint256 constant GSM_FEE_RATE_CHANGE_MAX = 0.0050e4; - uint256 constant GHO_BORROW_RATE_MAX = 0.2500e27; + uint256 constant GHO_BORROW_RATE_MAX = 0.2500e4; uint256 constant MINIMUM_DELAY_V2 = 2 days; uint256 constant FIXED_RATE_STRATEGY_FACTORY_REVISION = 1; diff --git a/src/test/mocks/MockConfigurator.sol b/src/test/mocks/MockConfigurator.sol index c7f6d2e1..bc7e8d7b 100644 --- a/src/test/mocks/MockConfigurator.sol +++ b/src/test/mocks/MockConfigurator.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import {IPool} from '@aave/core-v3/contracts/interfaces/IPool.sol'; import {DataTypes} from '@aave/core-v3/contracts/protocol/libraries/types/DataTypes.sol'; import {ReserveConfiguration} from '@aave/core-v3/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; +import {IDefaultInterestRateStrategyV2} from 'aave-v3-origin/core/contracts/interfaces/IDefaultInterestRateStrategyV2.sol'; contract MockConfigurator { using ReserveConfiguration for DataTypes.ReserveConfigurationMap; @@ -18,6 +19,8 @@ contract MockConfigurator { event BorrowCapChanged(address indexed asset, uint256 oldBorrowCap, uint256 newBorrowCap); + event ReserveInterestRateDataChanged(address indexed asset, address indexed strategy, bytes data); + constructor(IPool pool) { _pool = pool; } @@ -37,6 +40,23 @@ contract MockConfigurator { emit ReserveInterestRateStrategyChanged(asset, oldRateStrategyAddress, newRateStrategyAddress); } + function setReserveInterestRateStrategyAddress( + address asset, + address rateStrategyAddress, + bytes calldata rateData + ) external { + DataTypes.ReserveData memory reserve = _pool.getReserveData(asset); + _updateInterestRateStrategy(asset, reserve, rateStrategyAddress, rateData); + } + + function setReserveInterestRateData( + address asset, + bytes calldata rateData + ) external { + DataTypes.ReserveData memory reserve = _pool.getReserveData(asset); + _updateInterestRateStrategy(asset, reserve, reserve.interestRateStrategyAddress, rateData); + } + function setBorrowCap(address asset, uint256 newBorrowCap) external { DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); uint256 oldBorrowCap = currentConfig.getBorrowCap(); @@ -44,4 +64,25 @@ contract MockConfigurator { _pool.setConfiguration(asset, currentConfig); emit BorrowCapChanged(asset, oldBorrowCap, newBorrowCap); } + + function _updateInterestRateStrategy( + address asset, + DataTypes.ReserveData memory reserve, + address newRateStrategyAddress, + bytes calldata rateData + ) internal { + address oldRateStrategyAddress = reserve.interestRateStrategyAddress; + + IDefaultInterestRateStrategyV2(newRateStrategyAddress).setInterestRateParams(asset, rateData); + emit ReserveInterestRateDataChanged(asset, newRateStrategyAddress, rateData); + + if (oldRateStrategyAddress != newRateStrategyAddress) { + _pool.setReserveInterestRateStrategyAddress(asset, newRateStrategyAddress); + emit ReserveInterestRateStrategyChanged( + asset, + oldRateStrategyAddress, + newRateStrategyAddress + ); + } + } }