diff --git a/diffs/AaveV3Ethereum_ActivateGhoStewards_20240326_before_AaveV3Ethereum_ActivateGhoStewards_20240326_after.md b/diffs/AaveV3Ethereum_ActivateGhoStewards_20240326_before_AaveV3Ethereum_ActivateGhoStewards_20240326_after.md new file mode 100644 index 000000000..c15d3e2bc --- /dev/null +++ b/diffs/AaveV3Ethereum_ActivateGhoStewards_20240326_before_AaveV3Ethereum_ActivateGhoStewards_20240326_after.md @@ -0,0 +1,5 @@ +## Raw diff + +```json +{} +``` \ No newline at end of file diff --git a/src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.sol b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.sol new file mode 100644 index 000000000..fc5c1bb41 --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IProposalGenericExecutor} from 'aave-helpers/interfaces/IProposalGenericExecutor.sol'; +import {IGhoStewardV2} from './interfaces/IGhoStewardV2.sol'; +import {IGhoToken} from './interfaces/IGho.sol'; +import {IGsm} from './interfaces/IGsm.sol'; +import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; + +/** + * @title Activate Gho Stewards + * @author Aave Chan Initiative + * - Snapshot: https://snapshot.org/#/aave.eth/proposal/0x29f63b24638ee822f88632572ca4b061774771c0cc6d0ae5ccdeb538177232cd + * - Discussion: https://governance.aave.com/t/arfc-gho-stewards-borrow-rate-update/16956 + */ +contract AaveV3Ethereum_ActivateGhoStewards_20240326 is IProposalGenericExecutor { + address public constant GHO_STEWARD = 0x8F2411a538381aae2b464499005F0211e867d84f; + + function execute() external { + // Give pool admin role to the steward + AaveV3Ethereum.ACL_MANAGER.addPoolAdmin(GHO_STEWARD); + + // Give bucket manager role to the steward + IGhoToken(MiscEthereum.GHO_TOKEN).grantRole( + IGhoToken(MiscEthereum.GHO_TOKEN).BUCKET_MANAGER_ROLE(), + GHO_STEWARD + ); + + // Give configurator role on usdc, usdt gsm to the stewards + IGsm(MiscEthereum.GSM_USDC).grantRole( + IGsm(MiscEthereum.GSM_USDC).CONFIGURATOR_ROLE(), + GHO_STEWARD + ); + IGsm(MiscEthereum.GSM_USDT).grantRole( + IGsm(MiscEthereum.GSM_USDT).CONFIGURATOR_ROLE(), + GHO_STEWARD + ); + + // Whitelist all the facilitators on the stewards, including: GhoAToken, GhoFlashMinter, GSM USDC, GSM USDT + IGhoStewardV2(GHO_STEWARD).setControlledFacilitator( + IGhoToken(MiscEthereum.GHO_TOKEN).getFacilitatorsList(), + true + ); + } +} diff --git a/src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.t.sol b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.t.sol new file mode 100644 index 000000000..57ca8f464 --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.t.sol @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IGhoStewardV2} from './interfaces/IGhoStewardV2.sol'; +import {IGhoToken} from './interfaces/IGho.sol'; +import {IGsmFeeStrategy} from './interfaces/IGsmFeeStrategy.sol'; +import {IGsm} from './interfaces/IGsm.sol'; +import {IDefaultInterestRateStrategy} from 'aave-v3-core/contracts/interfaces/IDefaultInterestRateStrategy.sol'; +import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {ProtocolV3TestBase} from 'aave-helpers/ProtocolV3TestBase.sol'; +import {AaveV3Ethereum_ActivateGhoStewards_20240326} from './AaveV3Ethereum_ActivateGhoStewards_20240326.sol'; + +/** + * @dev Test for AaveV3Ethereum_ActivateGhoStewards_20240326 + * command: make test-contract filter=AaveV3Ethereum_ActivateGhoStewards_20240326 + */ +contract AaveV3Ethereum_ActivateGhoStewards_20240326_Test is ProtocolV3TestBase { + AaveV3Ethereum_ActivateGhoStewards_20240326 internal proposal; + address public RISK_COUNCIL; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 19519644); + proposal = new AaveV3Ethereum_ActivateGhoStewards_20240326(); + RISK_COUNCIL = IGhoStewardV2(proposal.GHO_STEWARD()).RISK_COUNCIL(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV3Ethereum_ActivateGhoStewards_20240326', + AaveV3Ethereum.POOL, + address(proposal) + ); + } + + function test_adminPermissions() public { + executePayload(vm, address(proposal)); + + assertTrue(AaveV3Ethereum.ACL_MANAGER.isPoolAdmin(proposal.GHO_STEWARD())); + assertTrue( + IGhoToken(MiscEthereum.GHO_TOKEN).hasRole( + IGhoToken(MiscEthereum.GHO_TOKEN).BUCKET_MANAGER_ROLE(), + proposal.GHO_STEWARD() + ) + ); + assertTrue( + IGsm(MiscEthereum.GSM_USDT).hasRole( + IGsm(MiscEthereum.GSM_USDT).CONFIGURATOR_ROLE(), + proposal.GHO_STEWARD() + ) + ); + assertTrue( + IGsm(MiscEthereum.GSM_USDC).hasRole( + IGsm(MiscEthereum.GSM_USDC).CONFIGURATOR_ROLE(), + proposal.GHO_STEWARD() + ) + ); + + address[] memory controlledFacilitatorsList = IGhoStewardV2(proposal.GHO_STEWARD()) + .getControlledFacilitators(); + address[] memory ghoFacilitatorList = IGhoToken(MiscEthereum.GHO_TOKEN).getFacilitatorsList(); + assertEq(controlledFacilitatorsList.length, ghoFacilitatorList.length); + + for (uint256 i = 0; i < controlledFacilitatorsList.length; i++) { + assertEq(controlledFacilitatorsList[i], ghoFacilitatorList[i]); + } + } + + function testUpdateGhoBorrowRate() public { + executePayload(vm, address(proposal)); + + uint256 oldBorrowRate = _getGhoBorrowRate(); + uint256 newBorrowRate = oldBorrowRate + 1; + + vm.startPrank(RISK_COUNCIL); + IGhoStewardV2(proposal.GHO_STEWARD()).updateGhoBorrowRate(newBorrowRate); + vm.stopPrank(); + + uint256 currentBorrowRate = _getGhoBorrowRate(); + assertEq(currentBorrowRate, newBorrowRate); + } + + function testUpdateGhoBorrowCap() public { + executePayload(vm, address(proposal)); + + (uint256 oldBorrowCap, ) = AaveV3Ethereum.AAVE_PROTOCOL_DATA_PROVIDER.getReserveCaps( + MiscEthereum.GHO_TOKEN + ); + uint256 newBorrowCap = oldBorrowCap + 1; + + vm.startPrank(RISK_COUNCIL); + IGhoStewardV2(proposal.GHO_STEWARD()).updateGhoBorrowCap(newBorrowCap); + vm.stopPrank(); + + (uint256 updatedBorrowCap, ) = AaveV3Ethereum.AAVE_PROTOCOL_DATA_PROVIDER.getReserveCaps( + MiscEthereum.GHO_TOKEN + ); + assertEq(newBorrowCap, updatedBorrowCap); + } + + function testUpdateFacilitatorBucketCapacity() public { + executePayload(vm, address(proposal)); + address[] memory ghoFacilitatorList = IGhoToken(MiscEthereum.GHO_TOKEN).getFacilitatorsList(); + + for (uint256 i = 0; i < ghoFacilitatorList.length; i++) { + address ghoFacilitator = ghoFacilitatorList[i]; + (uint256 currentBucketCapacity, ) = IGhoToken(MiscEthereum.GHO_TOKEN).getFacilitatorBucket( + ghoFacilitator + ); + uint128 newBucketCapacity = uint128(currentBucketCapacity) + 1; + + vm.startPrank(RISK_COUNCIL); + IGhoStewardV2(proposal.GHO_STEWARD()).updateFacilitatorBucketCapacity( + ghoFacilitator, + newBucketCapacity + ); + vm.stopPrank(); + + (uint256 updatedCapacity, ) = IGhoToken(MiscEthereum.GHO_TOKEN).getFacilitatorBucket( + ghoFacilitator + ); + assertEq(newBucketCapacity, updatedCapacity); + } + } + + function testUpdateGsmExposureCap() public { + executePayload(vm, address(proposal)); + + address[2] memory gsmList; + gsmList[0] = MiscEthereum.GSM_USDC; + gsmList[1] = MiscEthereum.GSM_USDT; + + for (uint256 i = 0; i < gsmList.length; i++) { + address gsm = gsmList[i]; + + uint128 oldExposureCap = IGsm(gsm).getExposureCap(); + uint128 newExposureCap = oldExposureCap + 1; + + vm.startPrank(RISK_COUNCIL); + IGhoStewardV2(proposal.GHO_STEWARD()).updateGsmExposureCap(gsm, newExposureCap); + vm.stopPrank(); + + uint128 currentExposureCap = IGsm(gsm).getExposureCap(); + assertEq(currentExposureCap, newExposureCap); + } + } + + function testUpdateGsmBuySellFeesBuyFee() public { + executePayload(vm, address(proposal)); + + address[2] memory gsmList; + gsmList[0] = MiscEthereum.GSM_USDC; + gsmList[1] = MiscEthereum.GSM_USDT; + + for (uint256 i = 0; i < gsmList.length; i++) { + address gsm = gsmList[i]; + + address feeStrategy = IGsm(gsm).getFeeStrategy(); + uint256 buyFee = IGsmFeeStrategy(feeStrategy).getBuyFee(1e4); + uint256 sellFee = IGsmFeeStrategy(feeStrategy).getSellFee(1e4); + + vm.startPrank(RISK_COUNCIL); + IGhoStewardV2(proposal.GHO_STEWARD()).updateGsmBuySellFees(gsm, buyFee + 1, sellFee + 1); + vm.stopPrank(); + + address newStrategy = IGsm(gsm).getFeeStrategy(); + uint256 newBuyFee = IGsmFeeStrategy(newStrategy).getBuyFee(1e4); + uint256 newSellFee = IGsmFeeStrategy(newStrategy).getSellFee(1e4); + + assertEq(newBuyFee, buyFee + 1); + assertEq(newSellFee, sellFee + 1); + } + } + + function _getGhoBorrowRate() internal view returns (uint256) { + address currentInterestRateStrategy = AaveV3Ethereum + .AAVE_PROTOCOL_DATA_PROVIDER + .getInterestRateStrategyAddress(address(MiscEthereum.GHO_TOKEN)); + return IDefaultInterestRateStrategy(currentInterestRateStrategy).getBaseVariableBorrowRate(); + } +} diff --git a/src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards.md b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards.md new file mode 100644 index 000000000..0b913932a --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards.md @@ -0,0 +1,54 @@ +--- +title: "Activate Gho Stewards" +author: "Aave Chan Initiative" +discussions: "https://governance.aave.com/t/arfc-gho-stewards-borrow-rate-update/16956" +snapshot: "https://snapshot.org/#/aave.eth/proposal/0x29f63b24638ee822f88632572ca4b061774771c0cc6d0ae5ccdeb538177232cd" +--- + +## Simple Summary + +This proposal activates GHO steward V2 for the Aave DAO, allowing better management of the GHO stablecoin by Risk, Growth & Finance Aave DAO service providers + +## Motivation + +This publication proposes to creating the GHO Stewards and granting the GHO Stewards permission to adjust the following parameters: + +- GHO Borrow Cap +- GHO Borrow Rate +- GSM Exposure Cap +- GSM Bucket Capacity +- GSM Fee Strategy + +GHO Stewards consists of members from Growth (ACI), Risk (ChaosLabs) and Finance (TokenLogic + Karpatkey) Service Providers and utilize a 3 of 4 multi-sig. + +## Specification + +The proposal gives the following admin roles: + +- Grant GHO Steward the Pool Admin role via the [ACL_MANAGER](https://etherscan.io/address/0xc2aaCf6553D20d1e9d78E365AAba8032af9c85b0) contract. +- Grant GHO Steward the Bucket Manager role on the [GHO token](https://etherscan.io/address/0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f). +- Grant GHO Steward the Configurator role on [GSM_USDC](https://etherscan.io/address/0x0d8eFfC11dF3F229AA1EA0509BC9DFa632A13578) and [GSM_USDT](https://etherscan.io/address/0x686F8D21520f4ecEc7ba577be08354F4d1EB8262). +- Whitelists all the facilitators on the GHO Stewards, including: [GHO_AToken](https://etherscan.io/address/0x00907f9921424583e7ffBfEdf84F92B7B2Be4977), [GHO_FlashMinter](https://etherscan.io/address/0xb639D208Bcf0589D54FaC24E655C79EC529762B8), [GSM_USDC](https://etherscan.io/address/0x0d8eFfC11dF3F229AA1EA0509BC9DFa632A13578), [GSM_USDT](https://etherscan.io/address/0x686F8D21520f4ecEc7ba577be08354F4d1EB8262) - so that the steward has the permissions to update the bucket capacity. + +The GHO Stewards parameters are set as follow: + +- GHO Aave Bucket Capacity: 100% increase +- GHO Borrow Rate: 5% change +- GSM Exposure Cap: 100% increase +- GSM Bucket Capacity: 100% increase +- GHO Borrow Cap: 100% increase +- GSM Fee Strategy: +0.5% + +## References + +- GHO Steward SAFE address: [0x8513e6F37dBc52De87b166980Fa3F50639694B60](https://etherscan.io/address/0x8513e6F37dBc52De87b166980Fa3F50639694B60) +- GHO Steward V2 address: [0x8F2411a538381aae2b464499005F0211e867d84f](https://etherscan.io/address/0x8F2411a538381aae2b464499005F0211e867d84f) +- GHO Steward Repo: [GhoStewardV2.sol](https://github.com/aave/gho-core/blob/f02f87482de7ccbd30ba76b40939fb016dbb2fea/src/contracts/misc/GhoStewardV2.sol) +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.t.sol) +- [Snapshot](https://snapshot.org/#/aave.eth/proposal/0x29f63b24638ee822f88632572ca4b061774771c0cc6d0ae5ccdeb538177232cd) +- [Discussion](https://governance.aave.com/t/arfc-gho-stewards-borrow-rate-update/16956) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards_20240326.s.sol b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards_20240326.s.sol new file mode 100644 index 000000000..a2f0b5ecb --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards_20240326.s.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {GovV3Helpers, IPayloadsControllerCore, PayloadsControllerUtils} from 'aave-helpers/GovV3Helpers.sol'; +import {EthereumScript} from 'aave-helpers/ScriptUtils.sol'; +import {AaveV3Ethereum_ActivateGhoStewards_20240326} from './AaveV3Ethereum_ActivateGhoStewards_20240326.sol'; + +/** + * @dev Deploy Ethereum + * deploy-command: make deploy-ledger contract=src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards_20240326.s.sol:DeployEthereum chain=mainnet + * verify-command: npx catapulta-verify -b broadcast/ActivateGhoStewards_20240326.s.sol/1/run-latest.json + */ +contract DeployEthereum is EthereumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Ethereum_ActivateGhoStewards_20240326).creationCode + ); + + // compose action + IPayloadsControllerCore.ExecutionAction[] + memory actions = new IPayloadsControllerCore.ExecutionAction[](1); + actions[0] = GovV3Helpers.buildAction(payload0); + + // register action at payloadsController + GovV3Helpers.createPayload(actions); + } +} + +/** + * @dev Create Proposal + * command: make deploy-ledger contract=src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards_20240326.s.sol:CreateProposal chain=mainnet + */ +contract CreateProposal is EthereumScript { + function run() external { + // create payloads + PayloadsControllerUtils.Payload[] memory payloads = new PayloadsControllerUtils.Payload[](1); + + // compose actions for validation + IPayloadsControllerCore.ExecutionAction[] + memory actionsEthereum = new IPayloadsControllerCore.ExecutionAction[](1); + actionsEthereum[0] = GovV3Helpers.buildAction( + type(AaveV3Ethereum_ActivateGhoStewards_20240326).creationCode + ); + payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal( + vm, + payloads, + GovV3Helpers.ipfsHashFile( + vm, + 'src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards.md' + ) + ); + } +} diff --git a/src/20240326_AaveV3Ethereum_ActivateGhoStewards/config.ts b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/config.ts new file mode 100644 index 000000000..cd1fff2dc --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/config.ts @@ -0,0 +1,14 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + pools: ['AaveV3Ethereum'], + title: 'Activate Gho Stewards', + shortName: 'ActivateGhoStewards', + date: '20240326', + author: 'Aave Chan Initiative', + discussion: 'https://governance.aave.com/t/arfc-gho-stewards-borrow-rate-update/16956', + snapshot: + 'https://snapshot.org/#/aave.eth/proposal/0x29f63b24638ee822f88632572ca4b061774771c0cc6d0ae5ccdeb538177232cd', + }, + poolOptions: {AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 19519644}}}, +}; diff --git a/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGho.sol b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGho.sol new file mode 100644 index 000000000..e7b88cd52 --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGho.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IAccessControl} from 'aave-v3-core/contracts/dependencies/openzeppelin/contracts/IAccessControl.sol'; + +interface IGhoToken is IAccessControl { + function BUCKET_MANAGER_ROLE() external pure returns (bytes32); + + function getFacilitatorsList() external view returns (address[] memory); + + function getFacilitatorBucket(address facilitator) external view returns (uint256, uint256); +} diff --git a/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGhoStewardV2.sol b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGhoStewardV2.sol new file mode 100644 index 000000000..5f3aa7a87 --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGhoStewardV2.sol @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.10; + +/** + * @title IGhoStewardV2 + * @author Aave Labs + * @notice Defines the basic interface of the GhoStewardV2 + */ +interface IGhoStewardV2 { + struct GhoDebounce { + uint40 ghoBorrowCapLastUpdate; + uint40 ghoBorrowRateLastUpdate; + } + + struct GsmDebounce { + uint40 gsmExposureCapLastUpdated; + uint40 gsmFeeStrategyLastUpdated; + } + + /** + * @notice Updates the bucket capacity of facilitator, only if: + * - respects `MINIMUM_DELAY`, the minimum time delay between updates + * - the update changes up to 100% upwards + * - the facilitator is controlled + * @dev Only callable by Risk Council + * @param facilitator The facilitator address + * @param newBucketCapacity The new facilitator bucket capacity + */ + function updateFacilitatorBucketCapacity(address facilitator, uint128 newBucketCapacity) external; + + /** + * @notice Updates the GHO borrow cap, only if: + * - respects `MINIMUM_DELAY`, the minimum time delay between updates + * - the update changes up to 100% upwards + * @dev Only callable by Risk Council + * @param newBorrowCap The new borrow cap (in whole tokens) + */ + function updateGhoBorrowCap(uint256 newBorrowCap) external; + + /** + * @notice Updates the borrow rate of GHO, only if: + * - respects `MINIMUM_DELAY`, the minimum time delay between updates + * - 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%) + */ + function updateGhoBorrowRate(uint256 newBorrowRate) external; + + /** + * @notice Updates the exposure cap of the GSM, only if: + * - respects `MINIMUM_DELAY`, the minimum time delay between updates + * - the update changes up to 100% upwards + * @dev Only callable by Risk Council + * @param gsm The gsm address to update + * @param newExposureCap The new exposure cap (in underlying asset terms) + */ + function updateGsmExposureCap(address gsm, uint128 newExposureCap) external; + + /** + * @notice Updates the fixed percent fees of the GSM, only if: + * - respects `MINIMUM_DELAY`, the minimum time delay between updates + * - the update changes up to `GSM_FEE_RATE_CHANGE_MAX` upwards (for both buy and sell individually); + * @dev Only callable by Risk Council + * @param gsm The gsm address to update + * @param buyFee The new buy fee (expressed in bps) (e.g. 0.0150e4 results in 1.50%) + * @param sellFee The new sell fee (expressed in bps) (e.g. 0.0150e4 results in 1.50%) + */ + function updateGsmBuySellFees(address gsm, uint256 buyFee, uint256 sellFee) external; + + /** + * @notice Adds/Removes controlled facilitators + * @dev Only callable by owner + * @param facilitatorList A list of facilitators addresses to add to control + * @param approve True to add as controlled facilitators, false to remove + */ + function setControlledFacilitator(address[] memory facilitatorList, bool approve) external; + + /** + * @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%) + */ + function GHO_BORROW_RATE_CHANGE_MAX() external view returns (uint256); + + /** + * @notice Returns the maximum increase for GSM fee rates (buy or sell). + * @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%) + */ + function GHO_BORROW_RATE_MAX() external view returns (uint256); + + /** + * @notice Returns the minimum delay that must be respected between parameters update. + * @return The minimum delay between parameter updates (in seconds) + */ + function MINIMUM_DELAY() external view returns (uint256); + + /** + * @notice Returns the address of the Pool Addresses Provider of the Aave V3 Ethereum Pool + * @return The address of the PoolAddressesProvider of Aave V3 Ethereum Pool + */ + function POOL_ADDRESSES_PROVIDER() external view returns (address); + + /** + * @notice Returns the address of the Gho Token + * @return The address of the GhoToken + */ + 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 + */ + function RISK_COUNCIL() external view returns (address); + + /** + * @notice Returns the list of controlled facilitators by this steward. + * @return An array of facilitator addresses + */ + function getControlledFacilitators() external view returns (address[] memory); + + /** + * @notice Returns timestamp of the last update of GHO parameters + * @return The GhoDebounce struct describing the last update of GHO parameters + */ + function getGhoTimelocks() external view returns (GhoDebounce memory); + + /** + * @notice Returns timestamp of the last update of Gsm parameters + * @param gsm The GSM address + * @return The GsmDebounce struct describing the last update of GSM parameters + */ + function getGsmTimelocks(address gsm) external view returns (GsmDebounce memory); + + /** + * @notice Returns timestamp of the facilitators last bucket capacity update + * @param facilitator The facilitator address + * @return The unix time of the last bucket capacity (in seconds). + */ + function getFacilitatorBucketCapacityTimelock(address facilitator) external view returns (uint40); + + /** + * @notice Returns the list of Fixed Fee Strategies for GSM + * @return An array of FixedFeeStrategy addresses + */ + function getGsmFeeStrategies() external view returns (address[] memory); +} diff --git a/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGsm.sol b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGsm.sol new file mode 100644 index 000000000..596740394 --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGsm.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IAccessControl} from 'aave-v3-core/contracts/dependencies/openzeppelin/contracts/IAccessControl.sol'; + +interface IGsm is IAccessControl { + function CONFIGURATOR_ROLE() external pure returns (bytes32); + + function getExposureCap() external view returns (uint128); + + function getFeeStrategy() external view returns (address); +} diff --git a/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGsmFeeStrategy.sol b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGsmFeeStrategy.sol new file mode 100644 index 000000000..8c0dc8acf --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGsmFeeStrategy.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IGsmFeeStrategy { + function getBuyFee(uint256 grossAmount) external view returns (uint256); + + function getSellFee(uint256 grossAmount) external view returns (uint256); + + function getGrossAmountFromTotalBought(uint256 totalAmount) external view returns (uint256); + + function getGrossAmountFromTotalSold(uint256 totalAmount) external view returns (uint256); +}