From e4eb777378bbb5be0e2b85b294f0ff0554a11432 Mon Sep 17 00:00:00 2001 From: efecarranza Date: Mon, 24 Feb 2025 18:48:53 -0300 Subject: [PATCH] feat: add more tests and gsm stewards --- ...m_GSMsMigrationToGSM4626_20250114_after.md | 16 +++ ...hereum_GSMsMigrationToGSM4626_20250114.sol | 22 +++- ...reum_GSMsMigrationToGSM4626_20250114.t.sol | 112 ++++++++++++++---- 3 files changed, 128 insertions(+), 22 deletions(-) diff --git a/diffs/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_before_AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_after.md b/diffs/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_before_AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_after.md index 21bfbc213..d5f302e59 100644 --- a/diffs/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_before_AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_after.md +++ b/diffs/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_before_AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_after.md @@ -85,6 +85,10 @@ "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" }, + "0x54aa8ce151e8da021b9dde749b7107b580f1ed706eedfb4b672c505e334672f7": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, "0x96beb32a9f918673c243821111bf0d7eb1d8bbd6dd12a369f2a5588b5051db40": { "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" @@ -443,6 +447,10 @@ "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" }, + "0x54aa8ce151e8da021b9dde749b7107b580f1ed706eedfb4b672c505e334672f7": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, "0xa5871918c6346c7bd648c060659e3180d091571857cea690f38eb10724ec2109": { "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" @@ -615,6 +623,10 @@ "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" }, + "0x54aa8ce151e8da021b9dde749b7107b580f1ed706eedfb4b672c505e334672f7": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, "0x96beb32a9f918673c243821111bf0d7eb1d8bbd6dd12a369f2a5588b5051db40": { "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" @@ -867,6 +879,10 @@ "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" }, + "0x54aa8ce151e8da021b9dde749b7107b580f1ed706eedfb4b672c505e334672f7": { + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, "0x54c6c721cb1093982dfbdba080db2ecfb4ccb77ae6e3bc08aac8e1988da4bb1a": { "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001" diff --git a/src/20250114_AaveV3Ethereum_GSMsMigrationToGSM4626/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114.sol b/src/20250114_AaveV3Ethereum_GSMsMigrationToGSM4626/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114.sol index d88120b2f..0eb4614f5 100644 --- a/src/20250114_AaveV3Ethereum_GSMsMigrationToGSM4626/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114.sol +++ b/src/20250114_AaveV3Ethereum_GSMsMigrationToGSM4626/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114.sol @@ -18,7 +18,7 @@ import {IGsmRegistry} from 'src/interfaces/IGsmRegistry.sol'; import {IAaveCLRobotOperator} from './IAaveCLRobotOperator.sol'; /** - * @title GSMs Migration to GSM4626 + * @title GSMs Migration to stataGSM4626 * @author TokenLogic * - Snapshot: https://snapshot.box/#/s:aave.eth/proposal/0x82d3ad8b8d43b12d3c08344c9b3aadfa6da03b358aa92915d0046f19344a7faa * - Discussion: https://governance.aave.com/t/arfc-deploy-statausdc-and-statausdt-gsms-on-ethereum/20682 @@ -113,6 +113,16 @@ contract AaveV3Ethereum_GSMsMigrationToGSM4626_20250114 is IProposalGenericExecu // Add GSMs to GSM Registry IGsmRegistry(GhoEthereum.GSM_REGISTRY).addGsm(NEW_GSM_USDC); IGsmRegistry(GhoEthereum.GSM_REGISTRY).addGsm(NEW_GSM_USDT); + + // GHO GSM Steward + IGsm(NEW_GSM_USDC).grantRole( + IGsm(NEW_GSM_USDC).CONFIGURATOR_ROLE(), + GhoEthereum.GHO_GSM_STEWARD + ); + IGsm(NEW_GSM_USDT).grantRole( + IGsm(NEW_GSM_USDT).CONFIGURATOR_ROLE(), + GhoEthereum.GHO_GSM_STEWARD + ); } function _updateFeeStrategy() internal { @@ -242,6 +252,16 @@ contract AaveV3Ethereum_GSMsMigrationToGSM4626_20250114 is IProposalGenericExecu IGsm(GhoEthereum.GSM_USDC).revokeRole(SWAP_FREEZER_ROLE, GovernanceV3Ethereum.EXECUTOR_LVL_1); IGsm(GhoEthereum.GSM_USDT).revokeRole(SWAP_FREEZER_ROLE, GovernanceV3Ethereum.EXECUTOR_LVL_1); + // GHO GSM Steward + IGsm(GhoEthereum.GSM_USDC).revokeRole( + IGsm(GhoEthereum.GSM_USDC).CONFIGURATOR_ROLE(), + GhoEthereum.GHO_GSM_STEWARD + ); + IGsm(GhoEthereum.GSM_USDT).revokeRole( + IGsm(GhoEthereum.GSM_USDT).CONFIGURATOR_ROLE(), + GhoEthereum.GHO_GSM_STEWARD + ); + // Cancel existing keepers IAaveCLRobotOperator(MiscEthereum.AAVE_CL_ROBOT_OPERATOR).cancel( EXISTING_ORACLE_SWAP_FREEZER_USDC diff --git a/src/20250114_AaveV3Ethereum_GSMsMigrationToGSM4626/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114.t.sol b/src/20250114_AaveV3Ethereum_GSMsMigrationToGSM4626/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114.t.sol index 58b1cc266..fa08bd539 100644 --- a/src/20250114_AaveV3Ethereum_GSMsMigrationToGSM4626/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114.t.sol +++ b/src/20250114_AaveV3Ethereum_GSMsMigrationToGSM4626/AaveV3Ethereum_GSMsMigrationToGSM4626_20250114.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import {IERC20} from 'openzeppelin-contracts/contracts/token/ERC20/IERC20.sol'; +import {IERC4626} from 'openzeppelin-contracts/contracts/interfaces/IERC4626.sol'; import {IAaveOracle} from 'aave-address-book/AaveV2.sol'; import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; @@ -163,6 +164,18 @@ contract AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_Test is ProtocolV3TestBa GovernanceV3Ethereum.EXECUTOR_LVL_1 ) ); + assertFalse( + IGsm(GhoEthereum.GSM_USDC).hasRole( + IGsm(GhoEthereum.GSM_USDC).CONFIGURATOR_ROLE(), + GhoEthereum.GHO_GSM_STEWARD + ) + ); + assertFalse( + IGsm(GhoEthereum.GSM_USDT).hasRole( + IGsm(GhoEthereum.GSM_USDT).CONFIGURATOR_ROLE(), + GhoEthereum.GHO_GSM_STEWARD + ) + ); } function test_oracleSwapFreezers() public { @@ -272,14 +285,9 @@ contract AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_Test is ProtocolV3TestBa _checkRolesConfig(IGsm(proposal.NEW_GSM_USDT())); } - function test_gsmIsOperational() public { + function test_oldGsmsAreSeized() public { executePayload(vm, address(proposal)); - deal(AaveV3EthereumAssets.USDC_UNDERLYING, address(this), 1_000e6); - deal(AaveV3EthereumAssets.USDT_UNDERLYING, address(this), 1_000e6); - deal(AaveV3EthereumAssets.USDC_STATA_TOKEN, address(this), 1_000e6); - deal(AaveV3EthereumAssets.USDT_STATA_TOKEN, address(this), 1_000e6); - // Old GSMs are seized vm.expectRevert(bytes('GSM_SEIZED')); IGsm(GhoEthereum.GSM_USDC).buyAsset(1000e6, address(this)); @@ -289,45 +297,95 @@ contract AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_Test is ProtocolV3TestBa IGsm(GhoEthereum.GSM_USDC).sellAsset(1000e6, address(this)); vm.expectRevert(bytes('GSM_SEIZED')); IGsm(GhoEthereum.GSM_USDT).sellAsset(1000e6, address(this)); + } + + function test_gsmUsdcIsOperational() public { + executePayload(vm, address(proposal)); + + deal(AaveV3EthereumAssets.USDC_STATA_TOKEN, address(this), 1_000e6); // New GSMs are operational IERC20(AaveV3EthereumAssets.USDC_STATA_TOKEN).approve(proposal.NEW_GSM_USDC(), 1_000e6); - IERC20(AaveV3EthereumAssets.USDT_STATA_TOKEN).approve(proposal.NEW_GSM_USDT(), 1_000e6); IERC20(AaveV3EthereumAssets.GHO_UNDERLYING).approve(proposal.NEW_GSM_USDC(), 1_200 ether); - IERC20(AaveV3EthereumAssets.GHO_UNDERLYING).approve(proposal.NEW_GSM_USDT(), 1_200 ether); uint256 amountUnderlying = 1_000e6; uint256 balanceBeforeUsdcGsm = IERC20(AaveV3EthereumAssets.USDC_STATA_TOKEN).balanceOf( proposal.NEW_GSM_USDC() ); - uint256 balanceBeforeUsdtGsm = IERC20(AaveV3EthereumAssets.USDT_STATA_TOKEN).balanceOf( - proposal.NEW_GSM_USDT() - ); + uint256 balanceGhoBefore = IGhoToken(GhoEthereum.GHO_TOKEN).balanceOf(address(this)); - IGsm(proposal.NEW_GSM_USDC()).sellAsset(amountUnderlying, address(this)); - IGsm(proposal.NEW_GSM_USDT()).sellAsset(amountUnderlying, address(this)); + (, uint256 ghoBought) = IGsm(proposal.NEW_GSM_USDC()).sellAsset( + amountUnderlying, + address(this) + ); assertEq( IERC20(AaveV3EthereumAssets.USDC_STATA_TOKEN).balanceOf(proposal.NEW_GSM_USDC()), balanceBeforeUsdcGsm + amountUnderlying, 'amounts USDC after sellAsset not equal' ); + assertEq( + IGhoToken(GhoEthereum.GHO_TOKEN).balanceOf(address(this)), + balanceGhoBefore + ghoBought, + 'GHO balance after sellAsset not equal' + ); + + (, uint256 ghoSold) = IGsm(proposal.NEW_GSM_USDC()).buyAsset(500e6, address(this)); + + assertEq( + IERC20(AaveV3EthereumAssets.USDC_STATA_TOKEN).balanceOf(proposal.NEW_GSM_USDC()), + balanceBeforeUsdcGsm + amountUnderlying - 500e6, + 'stataUSDC balance after buyAsset not equal' + ); + assertEq( + IGhoToken(GhoEthereum.GHO_TOKEN).balanceOf(address(this)), + balanceGhoBefore + ghoBought - ghoSold, + 'GHO balance after buyAsset not equal' + ); + } + + function test_gsmUsdtIsOperational() public { + executePayload(vm, address(proposal)); + + deal(AaveV3EthereumAssets.USDT_STATA_TOKEN, address(this), 1_000e6); + + // New GSMs are operational + IERC20(AaveV3EthereumAssets.USDT_STATA_TOKEN).approve(proposal.NEW_GSM_USDT(), 1_000e6); + IERC20(AaveV3EthereumAssets.GHO_UNDERLYING).approve(proposal.NEW_GSM_USDT(), 1_200 ether); + + uint256 amountUnderlying = 1_000e6; + uint256 balanceBeforeUsdtGsm = IERC20(AaveV3EthereumAssets.USDT_STATA_TOKEN).balanceOf( + proposal.NEW_GSM_USDT() + ); + uint256 balanceGhoBefore = IGhoToken(GhoEthereum.GHO_TOKEN).balanceOf(address(this)); + + (, uint256 ghoBought) = IGsm(proposal.NEW_GSM_USDT()).sellAsset( + amountUnderlying, + address(this) + ); + assertEq( IERC20(AaveV3EthereumAssets.USDT_STATA_TOKEN).balanceOf(proposal.NEW_GSM_USDT()), balanceBeforeUsdtGsm + amountUnderlying, 'amounts USDT after sellAsset not equal' ); + assertEq( + IGhoToken(GhoEthereum.GHO_TOKEN).balanceOf(address(this)), + balanceGhoBefore + ghoBought, + 'GHO balance after sellAsset not equal' + ); - IGsm(proposal.NEW_GSM_USDC()).buyAsset(500e6, address(this)); - IGsm(proposal.NEW_GSM_USDT()).buyAsset(500e6, address(this)); + (, uint256 ghoSold) = IGsm(proposal.NEW_GSM_USDT()).buyAsset(500e6, address(this)); assertEq( - IERC20(AaveV3EthereumAssets.USDC_STATA_TOKEN).balanceOf(proposal.NEW_GSM_USDC()), - balanceBeforeUsdcGsm + amountUnderlying - 500e6 + IERC20(AaveV3EthereumAssets.USDT_STATA_TOKEN).balanceOf(proposal.NEW_GSM_USDT()), + balanceBeforeUsdtGsm + amountUnderlying - 500e6, + 'stataUSDT balance after buyAsset not equal' ); assertEq( - IERC20(AaveV3EthereumAssets.USDT_STATA_TOKEN).balanceOf(proposal.NEW_GSM_USDT()), - balanceBeforeUsdtGsm + amountUnderlying - 500e6 + IGhoToken(GhoEthereum.GHO_TOKEN).balanceOf(address(this)), + balanceGhoBefore + ghoBought - ghoSold, + 'GHO balance after buyAsset not equal' ); } @@ -359,6 +417,12 @@ contract AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_Test is ProtocolV3TestBa gsm.hasRole(gsm.TOKEN_RESCUER_ROLE(), deployer), 'Deployer cannot be token rescuer' ); + + // GHO Steward + assertTrue( + gsm.hasRole(gsm.CONFIGURATOR_ROLE(), GhoEthereum.GHO_GSM_STEWARD), + 'Gho Steward not configured' + ); } function _mockAssetPrice(address priceOracle, address asset, uint256 price) internal { @@ -400,8 +464,14 @@ contract AaveV3Ethereum_GSMsMigrationToGSM4626_20250114_Test is ProtocolV3TestBa // Price Strategy IFixedPriceStrategy4626 priceStrategy = IFixedPriceStrategy4626(gsm.PRICE_STRATEGY()); - assertApproxEqAbs(priceStrategy.getAssetPriceInGho(1e6, true), 1 ether, 0.15 ether); - assertApproxEqAbs(priceStrategy.getGhoPriceInAsset(1 ether, true), 1e6, 0.15e6); + assertEq( + IERC4626(underlying).previewMint(1e6) * 10 ** 12, + priceStrategy.getAssetPriceInGho(1e6, true) + ); + assertEq( + IERC4626(underlying).previewWithdraw(1 ether) / 10 ** 12, + priceStrategy.getGhoPriceInAsset(1 ether, false) + ); assertEq(gsm.getGhoTreasury(), address(AaveV3Ethereum.COLLECTOR));