Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: gho stewards v2 #418

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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
7 changes: 6 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion lib/aave-address-book
Submodule aave-address-book updated 280 files
2 changes: 2 additions & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand All @@ -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/
62 changes: 25 additions & 37 deletions src/contracts/misc/GhoStewardV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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%
Expand All @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
14 changes: 4 additions & 10 deletions src/contracts/misc/interfaces/IGhoStewardV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);

Expand All @@ -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
Expand Down
28 changes: 28 additions & 0 deletions src/script/DeployGhoStewardsV2.s.sol
Original file line number Diff line number Diff line change
@@ -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));
}
}
2 changes: 1 addition & 1 deletion src/test/TestGhoBase.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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));
Expand Down
Loading