forked from bgd-labs/aave-proposals-v3
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'bgd-labs:main' into main
- Loading branch information
Showing
10 changed files
with
661 additions
and
0 deletions.
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
...StewardUpdate_20240602_before_AaveV3Ethereum_GhoStewardUpdate_20240602_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 | ||
{} | ||
``` |
68 changes: 68 additions & 0 deletions
68
src/20240602_AaveV3Ethereum_GhoStewardUpdate/AaveV3Ethereum_GhoStewardUpdate_20240602.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,68 @@ | ||
// 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 Gho Steward Update | ||
* @author ACI | ||
* - Discussion: https://governance.aave.com/t/arfc-gho-stewards/16466/11 | ||
*/ | ||
contract AaveV3Ethereum_GhoStewardUpdate_20240602 is IProposalGenericExecutor { | ||
address public constant OLD_GHO_STEWARD = 0x8F2411a538381aae2b464499005F0211e867d84f; | ||
address public constant GHO_STEWARD = 0xb9481a29f0f996BCAc759aB201FB3844c81866c4; | ||
|
||
function execute() external { | ||
// Remove Pool admin role to the old steward | ||
AaveV3Ethereum.ACL_MANAGER.removePoolAdmin(OLD_GHO_STEWARD); | ||
|
||
// Revoke old steward's bucket manager role | ||
|
||
IGhoToken(MiscEthereum.GHO_TOKEN).revokeRole( | ||
IGhoToken(MiscEthereum.GHO_TOKEN).BUCKET_MANAGER_ROLE(), | ||
OLD_GHO_STEWARD | ||
); | ||
|
||
// Revoke old steward's configurator role on usdc, usdt gsm | ||
|
||
IGsm(MiscEthereum.GSM_USDC).revokeRole( | ||
IGsm(MiscEthereum.GSM_USDC).CONFIGURATOR_ROLE(), | ||
OLD_GHO_STEWARD | ||
); | ||
|
||
IGsm(MiscEthereum.GSM_USDT).revokeRole( | ||
IGsm(MiscEthereum.GSM_USDT).CONFIGURATOR_ROLE(), | ||
OLD_GHO_STEWARD | ||
); | ||
|
||
// 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(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 | ||
); | ||
} | ||
} |
287 changes: 287 additions & 0 deletions
287
src/20240602_AaveV3Ethereum_GhoStewardUpdate/AaveV3Ethereum_GhoStewardUpdate_20240602.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,287 @@ | ||
// 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_GhoStewardUpdate_20240602} from './AaveV3Ethereum_GhoStewardUpdate_20240602.sol'; | ||
|
||
/** | ||
* @dev Test for AaveV3Ethereum_GhoStewardUpdate_20240602 | ||
* command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20240602_AaveV3Ethereum_GhoStewardUpdate/AaveV3Ethereum_GhoStewardUpdate_20240602.t.sol | ||
-vv | ||
*/ | ||
contract AaveV3Ethereum_GhoStewardUpdate_20240602_Test is ProtocolV3TestBase { | ||
AaveV3Ethereum_GhoStewardUpdate_20240602 internal proposal; | ||
address public RISK_COUNCIL; | ||
|
||
function setUp() public { | ||
vm.createSelectFork(vm.rpcUrl('mainnet'), 20017052); | ||
proposal = new AaveV3Ethereum_GhoStewardUpdate_20240602(); | ||
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_GhoStewardUpdate_20240602', AaveV3Ethereum.POOL, address(proposal)); | ||
} | ||
|
||
function test_adminPermissions() public { | ||
executePayload(vm, address(proposal)); | ||
|
||
// Check that the old steward has been removed from roles | ||
|
||
assertFalse(AaveV3Ethereum.ACL_MANAGER.isPoolAdmin(proposal.OLD_GHO_STEWARD())); | ||
|
||
assertFalse( | ||
IGhoToken(MiscEthereum.GHO_TOKEN).hasRole( | ||
IGhoToken(MiscEthereum.GHO_TOKEN).BUCKET_MANAGER_ROLE(), | ||
proposal.OLD_GHO_STEWARD() | ||
) | ||
); | ||
|
||
assertFalse( | ||
IGsm(MiscEthereum.GSM_USDT).hasRole( | ||
IGsm(MiscEthereum.GSM_USDT).CONFIGURATOR_ROLE(), | ||
proposal.OLD_GHO_STEWARD() | ||
) | ||
); | ||
|
||
assertFalse( | ||
IGsm(MiscEthereum.GSM_USDC).hasRole( | ||
IGsm(MiscEthereum.GSM_USDC).CONFIGURATOR_ROLE(), | ||
proposal.OLD_GHO_STEWARD() | ||
) | ||
); | ||
|
||
assertTrue(AaveV3Ethereum.ACL_MANAGER.isRiskAdmin(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 testLowerGhoBorrowRate() 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 testLowerGhoBorrowCap() 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 testLowerGsmExposureCap() 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 testLowerGsmBuySellFeesBuyFee() 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(); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
src/20240602_AaveV3Ethereum_GhoStewardUpdate/GhoStewardUpdate.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,33 @@ | ||
--- | ||
title: "Gho Steward Update" | ||
author: "ACI" | ||
discussions: "https://governance.aave.com/t/arfc-gho-stewards/16466/11" | ||
--- | ||
|
||
## Simple Summary | ||
|
||
This proposal seeks to update the GHO steward to an more efficient version, allowing more granular control over GHO to increase it’s efficiency | ||
|
||
## Motivation | ||
|
||
The GHO peg is strong, and supply is growing. As GHO matures, new strategies can now be implemented to make it more liquid, resilient and help it grow larger. For example, a strong GSM is expected to allow larger cap increases, allowing faster growth of the supply. Also, in dynamic markets, tighter control on borrow rates is expected to improve asset efficiency. | ||
|
||
## Specification | ||
|
||
The upgraded Gho Steward can be found on the [gho-core github](https://github.com/aave/gho-core/blob/main/src/contracts/misc/GhoStewardV2.sol) | ||
|
||
Changes: | ||
|
||
- GSM fee strategy can now be updated by 50 bps both ways | ||
- GHO Borrow cap can now be updated both ways | ||
- GHO exposure cap can now be updated both ways | ||
|
||
## References | ||
|
||
- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/a39a86866b72f8f8edb187b8ec453fc895faf9c3/src/20240602_AaveV3Ethereum_GhoStewardUpdate/AaveV3Ethereum_GhoStewardUpdate_20240602.sol) | ||
- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/a39a86866b72f8f8edb187b8ec453fc895faf9c3/src/20240602_AaveV3Ethereum_GhoStewardUpdate/AaveV3Ethereum_GhoStewardUpdate_20240602.t.sol) | ||
- [Discussion](https://governance.aave.com/t/arfc-gho-stewards/16466/11) | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
Oops, something went wrong.