From b976c0bffb5ca13fb8147674b914af5348722618 Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Tue, 26 Mar 2024 22:36:31 +0530 Subject: [PATCH] feat: gho stewards activation payload --- ...reum_ActivateGhoStewards_20240326_after.md | 5 + ...3Ethereum_ActivateGhoStewards_20240326.sol | 42 +++++ ...thereum_ActivateGhoStewards_20240326.t.sol | 32 ++++ .../ActivateGhoStewards.md | 23 +++ .../ActivateGhoStewards_20240326.s.sol | 58 +++++++ .../config.ts | 14 ++ .../interfaces/IGho.sol | 10 ++ .../interfaces/IGhoStewardV2.sol | 158 ++++++++++++++++++ .../interfaces/IGsm.sol | 8 + 9 files changed, 350 insertions(+) create mode 100644 diffs/AaveV3Ethereum_ActivateGhoStewards_20240326_before_AaveV3Ethereum_ActivateGhoStewards_20240326_after.md create mode 100644 src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.sol create mode 100644 src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.t.sol create mode 100644 src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards.md create mode 100644 src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards_20240326.s.sol create mode 100644 src/20240326_AaveV3Ethereum_ActivateGhoStewards/config.ts create mode 100644 src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGho.sol create mode 100644 src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGhoStewardV2.sol create mode 100644 src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGsm.sol 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..eae030e68 --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.sol @@ -0,0 +1,42 @@ +// 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/16466 + */ +contract AaveV3Ethereum_ActivateGhoStewards_20240326 is IProposalGenericExecutor { + address public constant GHO_STEWARD = 0x8F2411a538381aae2b464499005F0211e867d84f; + address public constant GSM_USDC = 0x0d8eFfC11dF3F229AA1EA0509BC9DFa632A13578; + address public constant GSM_USDT = 0x686F8D21520f4ecEc7ba577be08354F4d1EB8262; + + function execute() external { + // Give risk admin role to the steward + AaveV3Ethereum.ACL_MANAGER.addRiskAdmin(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(GSM_USDC).grantRole(IGsm(GSM_USDC).CONFIGURATOR_ROLE(), GHO_STEWARD); + IGsm(GSM_USDT).grantRole(IGsm(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..8d19a2f76 --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.t.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV3TestBase, ReserveConfig} 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; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 19519644); + proposal = new AaveV3Ethereum_ActivateGhoStewards_20240326(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV3Ethereum_ActivateGhoStewards_20240326', + AaveV3Ethereum.POOL, + address(proposal) + ); + } +} diff --git a/src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards.md b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards.md new file mode 100644 index 000000000..0d94ce64b --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards.md @@ -0,0 +1,23 @@ +--- +title: "Activate Gho Stewards" +author: "Aave Chan Initiative" +discussions: "https://governance.aave.com/t/arfc-gho-stewards/16466" +snapshot: "https://snapshot.org/#/aave.eth/proposal/0x29f63b24638ee822f88632572ca4b061774771c0cc6d0ae5ccdeb538177232cd" +--- + +## Simple Summary + +## Motivation + +## Specification + +## References + +- 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/16466) + +## 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..b65a4aefe --- /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/16466', + 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..ffb3ac57d --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGho.sol @@ -0,0 +1,10 @@ +// 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); +} 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..58891b743 --- /dev/null +++ b/src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGsm.sol @@ -0,0 +1,8 @@ +// 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); +}