generated from bgd-labs/bgd-forge-template
-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: gho stewards activation (#276)
* feat: gho stewards activation payload * test: added stewards tests * chore: add writeup * fix: writeup * fix: oops * fix: writeup * chore: update suggestion * fix: give pool admin role just to be consistent with the deployed stewards
- Loading branch information
1 parent
5c4add2
commit f14e412
Showing
10 changed files
with
555 additions
and
0 deletions.
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
...hoStewards_20240326_before_AaveV3Ethereum_ActivateGhoStewards_20240326_after.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## Raw diff | ||
|
||
```json | ||
{} | ||
``` |
46 changes: 46 additions & 0 deletions
46
...240326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
); | ||
} | ||
} |
184 changes: 184 additions & 0 deletions
184
...0326_AaveV3Ethereum_ActivateGhoStewards/AaveV3Ethereum_ActivateGhoStewards_20240326.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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/). |
58 changes: 58 additions & 0 deletions
58
src/20240326_AaveV3Ethereum_ActivateGhoStewards/ActivateGhoStewards_20240326.s.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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' | ||
) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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}}}, | ||
}; |
12 changes: 12 additions & 0 deletions
12
src/20240326_AaveV3Ethereum_ActivateGhoStewards/interfaces/IGho.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
Oops, something went wrong.
f14e412
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Foundry report
Build log
Test success 🌈