diff --git a/diffs/AaveV2Avalanche_ReserveFactorUpgrades_20240411_before_AaveV2Avalanche_ReserveFactorUpgrades_20240411_after.md b/diffs/AaveV2Avalanche_ReserveFactorUpgrades_20240411_before_AaveV2Avalanche_ReserveFactorUpgrades_20240411_after.md new file mode 100644 index 000000000..f93e7d463 --- /dev/null +++ b/diffs/AaveV2Avalanche_ReserveFactorUpgrades_20240411_before_AaveV2Avalanche_ReserveFactorUpgrades_20240411_after.md @@ -0,0 +1,90 @@ +## Reserve changes + +### Reserve altered + +#### WETH.e ([0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB](https://snowscan.xyz/address/0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 35 % | 40 % | + + +#### WBTC.e ([0x50b7545627a5162F82A992c33b87aDc75187B218](https://snowscan.xyz/address/0x50b7545627a5162F82A992c33b87aDc75187B218)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 40 % | 45 % | + + +#### USDC.e ([0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664](https://snowscan.xyz/address/0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 35 % | 40 % | + + +#### WAVAX ([0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7](https://snowscan.xyz/address/0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 35 % | 40 % | + + +#### USDT.e ([0xc7198437980c041c805A1EDcbA50c1Ce5db95118](https://snowscan.xyz/address/0xc7198437980c041c805A1EDcbA50c1Ce5db95118)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 35 % | 40 % | + + +#### DAI.e ([0xd586E7F844cEa2F87f50152665BCbc2C279D8d70](https://snowscan.xyz/address/0xd586E7F844cEa2F87f50152665BCbc2C279D8d70)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 35 % | 40 % | + + +## Raw diff + +```json +{ + "reserves": { + "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB": { + "reserveFactor": { + "from": 3500, + "to": 4000 + } + }, + "0x50b7545627a5162F82A992c33b87aDc75187B218": { + "reserveFactor": { + "from": 4000, + "to": 4500 + } + }, + "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664": { + "reserveFactor": { + "from": 3500, + "to": 4000 + } + }, + "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7": { + "reserveFactor": { + "from": 3500, + "to": 4000 + } + }, + "0xc7198437980c041c805A1EDcbA50c1Ce5db95118": { + "reserveFactor": { + "from": 3500, + "to": 4000 + } + }, + "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70": { + "reserveFactor": { + "from": 3500, + "to": 4000 + } + } + } +} +``` \ No newline at end of file diff --git a/diffs/AaveV2Ethereum_ReserveFactorUpgrades_20240411_before_AaveV2Ethereum_ReserveFactorUpgrades_20240411_after.md b/diffs/AaveV2Ethereum_ReserveFactorUpgrades_20240411_before_AaveV2Ethereum_ReserveFactorUpgrades_20240411_after.md new file mode 100644 index 000000000..d3c5716e2 --- /dev/null +++ b/diffs/AaveV2Ethereum_ReserveFactorUpgrades_20240411_before_AaveV2Ethereum_ReserveFactorUpgrades_20240411_after.md @@ -0,0 +1,155 @@ +## Reserve changes + +### Reserve altered + +#### GUSD ([0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd](https://etherscan.io/address/0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 35 % | 40 % | + + +#### WBTC ([0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599](https://etherscan.io/address/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 45 % | 50 % | + + +#### LINK ([0x514910771AF9Ca656af840dff83E8264EcF986CA](https://etherscan.io/address/0x514910771AF9Ca656af840dff83E8264EcF986CA)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 45 % | 50 % | + + +#### sUSD ([0x57Ab1ec28D129707052df4dF418D58a2D46d5f51](https://etherscan.io/address/0x57Ab1ec28D129707052df4dF418D58a2D46d5f51)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 45 % | 50 % | + + +#### LUSD ([0x5f98805A4E8be255a32880FDeC7F6728C6568bA0](https://etherscan.io/address/0x5f98805A4E8be255a32880FDeC7F6728C6568bA0)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 40 % | 45 % | + + +#### DAI ([0x6B175474E89094C44Da98b954EedeAC495271d0F](https://etherscan.io/address/0x6B175474E89094C44Da98b954EedeAC495271d0F)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 40 % | 45 % | + + +#### FRAX ([0x853d955aCEf822Db058eb8505911ED77F175b99e](https://etherscan.io/address/0x853d955aCEf822Db058eb8505911ED77F175b99e)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 45 % | 50 % | + + +#### USDP ([0x8E870D67F660D95d5be530380D0eC0bd388289E1](https://etherscan.io/address/0x8E870D67F660D95d5be530380D0eC0bd388289E1)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 35 % | 40 % | + + +#### USDC ([0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48](https://etherscan.io/address/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 40 % | 45 % | + + +#### WETH ([0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2](https://etherscan.io/address/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 40 % | 45 % | + + +#### USDT ([0xdAC17F958D2ee523a2206206994597C13D831ec7](https://etherscan.io/address/0xdAC17F958D2ee523a2206206994597C13D831ec7)) + +| description | value before | value after | +| --- | --- | --- | +| reserveFactor | 40 % | 45 % | + + +## Raw diff + +```json +{ + "reserves": { + "0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd": { + "reserveFactor": { + "from": 3500, + "to": 4000 + } + }, + "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599": { + "reserveFactor": { + "from": 4500, + "to": 5000 + } + }, + "0x514910771AF9Ca656af840dff83E8264EcF986CA": { + "reserveFactor": { + "from": 4500, + "to": 5000 + } + }, + "0x57Ab1ec28D129707052df4dF418D58a2D46d5f51": { + "reserveFactor": { + "from": 4500, + "to": 5000 + } + }, + "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0": { + "reserveFactor": { + "from": 4000, + "to": 4500 + } + }, + "0x6B175474E89094C44Da98b954EedeAC495271d0F": { + "reserveFactor": { + "from": 4000, + "to": 4500 + } + }, + "0x853d955aCEf822Db058eb8505911ED77F175b99e": { + "reserveFactor": { + "from": 4500, + "to": 5000 + } + }, + "0x8E870D67F660D95d5be530380D0eC0bd388289E1": { + "reserveFactor": { + "from": 3500, + "to": 4000 + } + }, + "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48": { + "reserveFactor": { + "from": 4000, + "to": 4500 + } + }, + "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2": { + "reserveFactor": { + "from": 4000, + "to": 4500 + } + }, + "0xdAC17F958D2ee523a2206206994597C13D831ec7": { + "reserveFactor": { + "from": 4000, + "to": 4500 + } + } + } +} +``` \ No newline at end of file diff --git a/diffs/AaveV2Ethereum_V2StableDebtOffboarding_20240416_before_AaveV2Ethereum_V2StableDebtOffboarding_20240416_after.md b/diffs/AaveV2Ethereum_V2StableDebtOffboarding_20240416_before_AaveV2Ethereum_V2StableDebtOffboarding_20240416_after.md new file mode 100644 index 000000000..bf7693eed --- /dev/null +++ b/diffs/AaveV2Ethereum_V2StableDebtOffboarding_20240416_before_AaveV2Ethereum_V2StableDebtOffboarding_20240416_after.md @@ -0,0 +1,12 @@ +## Raw diff + +```json +{ + "poolConfig": { + "poolImpl": { + "from": "0x085E34722e04567Df9E6d2c32e82fd74f3342e79", + "to": "0x02D84abD89Ee9DB409572f19B6e1596c301F3c81" + } + } +} +``` \ No newline at end of file diff --git a/diffs/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312_before_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312_after.md b/diffs/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312_before_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312_after.md new file mode 100644 index 000000000..c15d3e2bc --- /dev/null +++ b/diffs/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312_before_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312_after.md @@ -0,0 +1,5 @@ +## Raw diff + +```json +{} +``` \ No newline at end of file diff --git a/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312.sol b/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312.sol new file mode 100644 index 000000000..4b879258f --- /dev/null +++ b/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {IProposalGenericExecutor} from 'aave-helpers/interfaces/IProposalGenericExecutor.sol'; +import {IEmissionManager} from 'aave-v3-periphery/contracts/rewards/interfaces/IEmissionManager.sol'; + +/** + * @title Mainnet PYUSD Emissions Admin + * @author Aave Chan Initiative + * - Snapshot: https://snapshot.org/#/aave.eth/proposal/0xac80b6d5488c4949e30013d8ed88189ed48b64cb47580bee46921b28e3899bb7 + * - Discussion: https://governance.aave.com/t/arfc-set-aave-chan-initiative-as-emission-manager-for-pyusd-on-aave-v3-ethereum-market/16837 + */ +contract AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312 is IProposalGenericExecutor { + address public constant PYUSD_EMISSION_ADMIN = 0xac140648435d03f784879cd789130F22Ef588Fcd; + + function execute() external { + IEmissionManager(AaveV3Ethereum.EMISSION_MANAGER).setEmissionAdmin( + AaveV3EthereumAssets.PYUSD_UNDERLYING, + PYUSD_EMISSION_ADMIN + ); + } +} diff --git a/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312.t.sol b/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312.t.sol new file mode 100644 index 000000000..ebc253714 --- /dev/null +++ b/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312.t.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {GovV3Helpers} from 'aave-helpers/GovV3Helpers.sol'; +import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {IEmissionManager} from 'aave-v3-periphery/contracts/rewards/interfaces/IEmissionManager.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/ProtocolV3TestBase.sol'; +import {AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312} from './AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312.sol'; + +/** + * @dev Test for AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312 + * command: make test-contract filter=AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312 + */ +contract AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312_Test is ProtocolV3TestBase { + AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312 internal proposal; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 19421865); + proposal = new AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312', + AaveV3Ethereum.POOL, + address(proposal) + ); + } + + function test_isEmmissionAdmin() external { + GovV3Helpers.executePayload(vm, address(proposal)); + assertEq( + IEmissionManager(AaveV3Ethereum.EMISSION_MANAGER).getEmissionAdmin( + AaveV3EthereumAssets.PYUSD_UNDERLYING + ), + 0xac140648435d03f784879cd789130F22Ef588Fcd + ); + } +} diff --git a/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/MainnetPYUSDEmissionsAdmin.md b/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/MainnetPYUSDEmissionsAdmin.md new file mode 100644 index 000000000..3bbb343c5 --- /dev/null +++ b/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/MainnetPYUSDEmissionsAdmin.md @@ -0,0 +1,43 @@ +--- +title: "Mainnet PYUSD Emissions Admin" +author: "Aave Chan Initiative" +discussions: "https://governance.aave.com/t/arfc-set-aave-chan-initiative-as-emission-manager-for-pyusd-on-aave-v3-ethereum-market/16837" +snapshot: "https://snapshot.org/#/aave.eth/proposal/0xac80b6d5488c4949e30013d8ed88189ed48b64cb47580bee46921b28e3899bb7" +--- + +## Simple Summary + +This AIP proposes to set the Aave Chan Initiative (ACI) wallet as the emission manager for the PYUSD token on Aave V3 Ethereum Market. This will enable the ACI to enact incentive programs funded by ecosystem partners for all PYUSD markets, promoting growth and expanding the user base of Aave. + +## Motivation + +The Aave Chan Initiative (ACI) has been in discussion with various parties that have a desire to actively contribute to the growth and development of the Aave V3 on the Ethereum Network. + +Recently, governance approved the [addition of PYUSD to Aave V3 Ethereum Market](https://governance.aave.com/t/arfc-add-pyusd-to-aave-v3-ethereum-market/16218). As a result, onboarding PYUSD into Aave has: + +- Built synergies between Aave and PYUSD. +- Offered Aave users an additional stablecoin option. +- Strengthened the relationship between the PYUSD & the GHO stablecoin. + +In order to facilitate emissions by various stakeholders, ACI proposes becoming the emissions manager for PYUSD on Aave V3 Ethereum Market. Emission incentives will be sent to ACI multisig and distributed as agreed on with partners. By setting the multisig as the emission manager for the PYUSD token, the ACI will be able to directly manage incentive programs that can attract more users to the pool and stimulate activity. This aligns with the broader goals of the Aave community to foster active and engaged markets on the Ethereum Chain. + +## Specification + +The Aave Chan Initiative (ACI) multisig address [0xac140648435d03f784879cd789130F22Ef588Fcd](https://app.safe.global/home?safe=eth:0xac140648435d03f784879cd789130F22Ef588Fcd) will be set as Emissions manager. + +The call to the setEmissionAdmin() method in the emission_manager contract will be as follows: + +`EMISSION_MANAGER.setEmissionAdmin(pyUSD,0xac140648435d03f784879cd789130F22Ef588Fcd);` + +This method will set the Aave Chan Initiative (ACI) wallet as the emission admin for the PYUSD token on Aave V3 Ethereum Market. + +## References + +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/154a6473412cab8fcd2a0f81f3230ac54cdbbcb2/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/154a6473412cab8fcd2a0f81f3230ac54cdbbcb2/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312.t.sol) +- [Snapshot](https://snapshot.org/#/aave.eth/proposal/0xac80b6d5488c4949e30013d8ed88189ed48b64cb47580bee46921b28e3899bb7) +- [Discussion](https://governance.aave.com/t/arfc-set-aave-chan-initiative-as-emission-manager-for-pyusd-on-aave-v3-ethereum-market/16837) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/MainnetPYUSDEmissionsAdmin_20240312.s.sol b/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/MainnetPYUSDEmissionsAdmin_20240312.s.sol new file mode 100644 index 000000000..80eeea713 --- /dev/null +++ b/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/MainnetPYUSDEmissionsAdmin_20240312.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_MainnetPYUSDEmissionsAdmin_20240312} from './AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312.sol'; + +/** + * @dev Deploy Ethereum + * deploy-command: make deploy-ledger contract=src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/MainnetPYUSDEmissionsAdmin_20240312.s.sol:DeployEthereum chain=mainnet + * verify-command: npx catapulta-verify -b broadcast/MainnetPYUSDEmissionsAdmin_20240312.s.sol/1/run-latest.json + */ +contract DeployEthereum is EthereumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Ethereum_MainnetPYUSDEmissionsAdmin_20240312).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/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/MainnetPYUSDEmissionsAdmin_20240312.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_MainnetPYUSDEmissionsAdmin_20240312).creationCode + ); + payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal( + vm, + payloads, + GovV3Helpers.ipfsHashFile( + vm, + 'src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/MainnetPYUSDEmissionsAdmin.md' + ) + ); + } +} diff --git a/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/config.ts b/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/config.ts new file mode 100644 index 000000000..c0bc2e958 --- /dev/null +++ b/src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/config.ts @@ -0,0 +1,23 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + configFile: 'src/20240312_AaveV3Ethereum_MainnetPYUSDEmissionsAdmin/config.ts', + author: 'Aave Chan Initiative', + pools: ['AaveV3Ethereum'], + title: 'Mainnet PYUSD Emissions Admin', + shortName: 'MainnetPYUSDEmissionsAdmin', + date: '20240312', + discussion: + 'https://governance.aave.com/t/arfc-set-aave-chan-initiative-as-emission-manager-for-pyusd-on-aave-v3-ethereum-market/16837', + snapshot: + 'https://snapshot.org/#/aave.eth/proposal/0xac80b6d5488c4949e30013d8ed88189ed48b64cb47580bee46921b28e3899bb7', + }, + poolOptions: { + AaveV3Ethereum: { + configs: { + EMISSION_MANAGER: [{asset: 'PYUSD', admin: '0xac140648435d03f784879cd789130F22Ef588Fcd'}], + }, + cache: {blockNumber: 19421865}, + }, + }, +}; diff --git a/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Avalanche_ReserveFactorUpgrades_20240411.sol b/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Avalanche_ReserveFactorUpgrades_20240411.sol new file mode 100644 index 000000000..dc2b79bdc --- /dev/null +++ b/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Avalanche_ReserveFactorUpgrades_20240411.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +/* + _ ΞΞΞΞ _ + /_;-.__ / _\ _.-;_\ + `-._`'`_/'`.-' + `\ /` + | / + /-.( + \_._\ + \ \`; + > |/ + / // + |// + \(\ + `` + defijesus.eth +*/ +pragma solidity ^0.8.0; + +import {IProposalGenericExecutor} from 'aave-helpers/interfaces/IProposalGenericExecutor.sol'; +import {AaveV2Avalanche, AaveV2AvalancheAssets, ILendingPoolConfigurator} from 'aave-address-book/AaveV2Avalanche.sol'; + +/** + * @title Reserve Factor Upgrades + * @author karpatkey_TokenLogic + * - Snapshot: https://snapshot.org/#/aave.eth/proposal/0x770ff4e02634c77aaa09952345551168920f7878b32ab03fcef92763a5fb70ab + * - Discussion: https://governance.aave.com/t/arfc-avalanche-v2-reserve-factor-adjustment/17040/2 + */ +contract AaveV2Avalanche_ReserveFactorUpgrades_20240411 is IProposalGenericExecutor { + ILendingPoolConfigurator public constant POOL_CONFIGURATOR = + ILendingPoolConfigurator(AaveV2Avalanche.POOL_CONFIGURATOR); + + uint256 public constant DAIe_RF = 40_00; + uint256 public constant USDCe_RF = 40_00; + uint256 public constant USDTe_RF = 40_00; + uint256 public constant WAVAX_RF = 40_00; + uint256 public constant WBTCe_RF = 45_00; + uint256 public constant WETHe_RF = 40_00; + + function execute() external { + POOL_CONFIGURATOR.setReserveFactor(AaveV2AvalancheAssets.DAIe_UNDERLYING, DAIe_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2AvalancheAssets.USDCe_UNDERLYING, USDCe_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2AvalancheAssets.USDTe_UNDERLYING, USDTe_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2AvalancheAssets.WAVAX_UNDERLYING, WAVAX_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2AvalancheAssets.WBTCe_UNDERLYING, WBTCe_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2AvalancheAssets.WETHe_UNDERLYING, WETHe_RF); + } +} diff --git a/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Avalanche_ReserveFactorUpgrades_20240411.t.sol b/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Avalanche_ReserveFactorUpgrades_20240411.t.sol new file mode 100644 index 000000000..c5c77615a --- /dev/null +++ b/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Avalanche_ReserveFactorUpgrades_20240411.t.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV2Avalanche, AaveV2AvalancheAssets} from 'aave-address-book/AaveV2Avalanche.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV2TestBase, ReserveConfig} from 'aave-helpers/ProtocolV2TestBase.sol'; +import {AaveV2Avalanche_ReserveFactorUpgrades_20240411} from './AaveV2Avalanche_ReserveFactorUpgrades_20240411.sol'; + +/** + * @dev Test for AaveV2Avalanche_ReserveFactorUpgrades_20240411 + * command: make test-contract filter=AaveV2Avalanche_ReserveFactorUpgrades_20240411 + */ +contract AaveV2Avalanche_ReserveFactorUpgrades_20240411_Test is ProtocolV2TestBase { + AaveV2Avalanche_ReserveFactorUpgrades_20240411 internal proposal; + + struct Changes { + address asset; + uint256 reserveFactor; + } + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('avalanche'), 44280713); + proposal = new AaveV2Avalanche_ReserveFactorUpgrades_20240411(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + (ReserveConfig[] memory allConfigsBefore, ReserveConfig[] memory allConfigsAfter) = defaultTest( + 'AaveV2Avalanche_ReserveFactorUpgrades_20240411', + AaveV2Avalanche.POOL, + address(proposal) + ); + + address[] memory assetsChanged = new address[](6); + assetsChanged[0] = AaveV2AvalancheAssets.DAIe_UNDERLYING; + assetsChanged[1] = AaveV2AvalancheAssets.USDCe_UNDERLYING; + assetsChanged[2] = AaveV2AvalancheAssets.USDTe_UNDERLYING; + assetsChanged[3] = AaveV2AvalancheAssets.WAVAX_UNDERLYING; + assetsChanged[4] = AaveV2AvalancheAssets.WBTCe_UNDERLYING; + assetsChanged[5] = AaveV2AvalancheAssets.WETHe_UNDERLYING; + + Changes[] memory assetChanges = new Changes[](6); + assetChanges[0] = Changes({ + asset: AaveV2AvalancheAssets.DAIe_UNDERLYING, + reserveFactor: proposal.DAIe_RF() + }); + assetChanges[1] = Changes({ + asset: AaveV2AvalancheAssets.USDCe_UNDERLYING, + reserveFactor: proposal.USDCe_RF() + }); + assetChanges[2] = Changes({ + asset: AaveV2AvalancheAssets.USDTe_UNDERLYING, + reserveFactor: proposal.USDTe_RF() + }); + assetChanges[3] = Changes({ + asset: AaveV2AvalancheAssets.WAVAX_UNDERLYING, + reserveFactor: proposal.WAVAX_RF() + }); + assetChanges[4] = Changes({ + asset: AaveV2AvalancheAssets.WBTCe_UNDERLYING, + reserveFactor: proposal.WBTCe_RF() + }); + assetChanges[5] = Changes({ + asset: AaveV2AvalancheAssets.WETHe_UNDERLYING, + reserveFactor: proposal.WETHe_RF() + }); + + _noReservesConfigsChangesApartFrom(allConfigsBefore, allConfigsAfter, assetsChanged); + + for (uint i = 0; i < assetChanges.length; i++) { + ReserveConfig memory cfg = _findReserveConfig(allConfigsAfter, assetChanges[i].asset); + assertEq(cfg.reserveFactor, assetChanges[i].reserveFactor); + } + } +} diff --git a/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Ethereum_ReserveFactorUpgrades_20240411.sol b/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Ethereum_ReserveFactorUpgrades_20240411.sol new file mode 100644 index 000000000..b05434086 --- /dev/null +++ b/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Ethereum_ReserveFactorUpgrades_20240411.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +/* + _ ΞΞΞΞ _ + /_;-.__ / _\ _.-;_\ + `-._`'`_/'`.-' + `\ /` + | / + /-.( + \_._\ + \ \`; + > |/ + / // + |// + \(\ + `` + defijesus.eth +*/ +pragma solidity ^0.8.0; + +import {IProposalGenericExecutor} from 'aave-helpers/interfaces/IProposalGenericExecutor.sol'; +import {AaveV2Ethereum, AaveV2EthereumAssets, ILendingPoolConfigurator} from 'aave-address-book/AaveV2Ethereum.sol'; + +/** + * @title Reserve Factor Upgrades + * @author karpatkey_TokenLogic + * - Snapshot: https://snapshot.org/#/aave.eth/proposal/0x26a03c08359c340f63b78b0c3e96d37aa0adeda65814643b0886d4719048ea7e + * - Discussion: https://governance.aave.com/t/arfc-ethereum-v2-reserve-factor-adjustment/16764/7 + */ +contract AaveV2Ethereum_ReserveFactorUpgrades_20240411 is IProposalGenericExecutor { + ILendingPoolConfigurator public constant POOL_CONFIGURATOR = + ILendingPoolConfigurator(AaveV2Ethereum.POOL_CONFIGURATOR); + + uint256 public constant DAI_RF = 45_00; + uint256 public constant FRAX_RF = 50_00; + uint256 public constant GUSD_RF = 40_00; + uint256 public constant LINK_RF = 50_00; + uint256 public constant LUSD_RF = 45_00; + uint256 public constant sUSD_RF = 50_00; + uint256 public constant USDC_RF = 45_00; + uint256 public constant USDP_RF = 40_00; + uint256 public constant USDT_RF = 45_00; + uint256 public constant WBTC_RF = 50_00; + uint256 public constant WETH_RF = 45_00; + + function execute() external { + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.DAI_UNDERLYING, DAI_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.FRAX_UNDERLYING, FRAX_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.GUSD_UNDERLYING, GUSD_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.LINK_UNDERLYING, LINK_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.LUSD_UNDERLYING, LUSD_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.sUSD_UNDERLYING, sUSD_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.USDC_UNDERLYING, USDC_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.USDP_UNDERLYING, USDP_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.USDT_UNDERLYING, USDT_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.WBTC_UNDERLYING, WBTC_RF); + POOL_CONFIGURATOR.setReserveFactor(AaveV2EthereumAssets.WETH_UNDERLYING, WETH_RF); + } +} diff --git a/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Ethereum_ReserveFactorUpgrades_20240411.t.sol b/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Ethereum_ReserveFactorUpgrades_20240411.t.sol new file mode 100644 index 000000000..b46008153 --- /dev/null +++ b/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Ethereum_ReserveFactorUpgrades_20240411.t.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV2Ethereum, AaveV2EthereumAssets} from 'aave-address-book/AaveV2Ethereum.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV2TestBase, ReserveConfig} from 'aave-helpers/ProtocolV2TestBase.sol'; +import {AaveV2Ethereum_ReserveFactorUpgrades_20240411} from './AaveV2Ethereum_ReserveFactorUpgrades_20240411.sol'; + +/** + * @dev Test for AaveV2Ethereum_ReserveFactorUpgrades_20240411 + * command: make test-contract filter=AaveV2Ethereum_ReserveFactorUpgrades_20240411 + */ +contract AaveV2Ethereum_ReserveFactorUpgrades_20240411_Test is ProtocolV2TestBase { + AaveV2Ethereum_ReserveFactorUpgrades_20240411 internal proposal; + + struct Changes { + address asset; + uint256 reserveFactor; + } + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 19668943); + proposal = new AaveV2Ethereum_ReserveFactorUpgrades_20240411(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + (ReserveConfig[] memory allConfigsBefore, ReserveConfig[] memory allConfigsAfter) = defaultTest( + 'AaveV2Ethereum_ReserveFactorUpgrades_20240411', + AaveV2Ethereum.POOL, + address(proposal) + ); + + address[] memory assetsChanged = new address[](11); + assetsChanged[0] = AaveV2EthereumAssets.DAI_UNDERLYING; + assetsChanged[1] = AaveV2EthereumAssets.FRAX_UNDERLYING; + assetsChanged[2] = AaveV2EthereumAssets.GUSD_UNDERLYING; + assetsChanged[3] = AaveV2EthereumAssets.LINK_UNDERLYING; + assetsChanged[4] = AaveV2EthereumAssets.LUSD_UNDERLYING; + assetsChanged[5] = AaveV2EthereumAssets.sUSD_UNDERLYING; + assetsChanged[6] = AaveV2EthereumAssets.USDC_UNDERLYING; + assetsChanged[7] = AaveV2EthereumAssets.USDP_UNDERLYING; + assetsChanged[8] = AaveV2EthereumAssets.USDT_UNDERLYING; + assetsChanged[9] = AaveV2EthereumAssets.WBTC_UNDERLYING; + assetsChanged[10] = AaveV2EthereumAssets.WETH_UNDERLYING; + + Changes[] memory assetChanges = new Changes[](11); + assetChanges[0] = Changes({ + asset: AaveV2EthereumAssets.DAI_UNDERLYING, + reserveFactor: proposal.DAI_RF() + }); + assetChanges[1] = Changes({ + asset: AaveV2EthereumAssets.FRAX_UNDERLYING, + reserveFactor: proposal.FRAX_RF() + }); + assetChanges[2] = Changes({ + asset: AaveV2EthereumAssets.GUSD_UNDERLYING, + reserveFactor: proposal.GUSD_RF() + }); + assetChanges[3] = Changes({ + asset: AaveV2EthereumAssets.LINK_UNDERLYING, + reserveFactor: proposal.LINK_RF() + }); + assetChanges[4] = Changes({ + asset: AaveV2EthereumAssets.LUSD_UNDERLYING, + reserveFactor: proposal.LUSD_RF() + }); + assetChanges[5] = Changes({ + asset: AaveV2EthereumAssets.sUSD_UNDERLYING, + reserveFactor: proposal.sUSD_RF() + }); + assetChanges[6] = Changes({ + asset: AaveV2EthereumAssets.USDC_UNDERLYING, + reserveFactor: proposal.USDC_RF() + }); + assetChanges[7] = Changes({ + asset: AaveV2EthereumAssets.USDP_UNDERLYING, + reserveFactor: proposal.USDP_RF() + }); + assetChanges[8] = Changes({ + asset: AaveV2EthereumAssets.USDT_UNDERLYING, + reserveFactor: proposal.USDT_RF() + }); + assetChanges[9] = Changes({ + asset: AaveV2EthereumAssets.WBTC_UNDERLYING, + reserveFactor: proposal.WBTC_RF() + }); + assetChanges[10] = Changes({ + asset: AaveV2EthereumAssets.WETH_UNDERLYING, + reserveFactor: proposal.WETH_RF() + }); + + _noReservesConfigsChangesApartFrom(allConfigsBefore, allConfigsAfter, assetsChanged); + + for (uint i = 0; i < assetChanges.length; i++) { + ReserveConfig memory cfg = _findReserveConfig(allConfigsAfter, assetChanges[i].asset); + assertEq(cfg.reserveFactor, assetChanges[i].reserveFactor); + } + } +} diff --git a/src/20240411_Multi_ReserveFactorUpgrades/ReserveFactorUpgrades.md b/src/20240411_Multi_ReserveFactorUpgrades/ReserveFactorUpgrades.md new file mode 100644 index 000000000..568dbf848 --- /dev/null +++ b/src/20240411_Multi_ReserveFactorUpgrades/ReserveFactorUpgrades.md @@ -0,0 +1,61 @@ +--- +title: "Reserve Factor Updates" +author: "karpatkey_TokenLogic" +discussions: "https://governance.aave.com/t/arfc-ethereum-v2-reserve-factor-adjustment/16764/7" +snapshot: "https://snapshot.org/#/aave.eth/proposal/0x26a03c08359c340f63b78b0c3e96d37aa0adeda65814643b0886d4719048ea7e" +--- + +## Simple Summary + +This AIP is composed of two actions: (1) a continuation of proposal 73 on Governance V3 that increases the Reserve Factor (RF) for assets on Ethereum V2 by 5.00%, up to a maximum of 99.99%; and (2) to start periodically increasing the RF across Avalanche V2. + +## Motivation + +This AIP will reduce deposit yield for assets on Ethereum & Avalanche V2 by increasing the RF. With this upgrade being passed, users will be further encouraged to migrate from Ethereum V2 to V3. + +Increasing the RF routes a larger portion of the interest paid by users to Aave DAO's Treasury. User's funds are not at risk of liquidation and the borrowing rate remains unchanged. + +Of the assets with an RF set at 99.99%, there is no change. All other asset reserves will have the RF increased by up to 5.00%. + +## Specification + +For Ethereum V2, the following parameters are to be updated as follows: + +| Asset | Previous Reserve Factor | New Reserve Factor | +| :---: | :---------------------: | :----------------: | +| DAI | 40.00% | 45.00% | +| FRAX | 45.00% | 50.00% | +| GUSD | 35.00% | 40.00% | +| LINK | 45.00% | 50.00% | +| LUSD | 40.00% | 45.00% | +| sUSD | 45.00% | 50.00% | +| USDC | 40.00% | 45.00% | +| USDP | 35.00% | 40.00% | +| USDT | 40.00% | 45.00% | +| WBTC | 45.00% | 50.00% | +| WETH | 40.00% | 45.00% | + +For Avalanche V2, the following parameters are to be updated as follows: + +| Asset | Previous Reserve Factor | New Reserve Factor | +| :---: | :---------------------: | :----------------: | +| DAIe | 35.00% | 40.00% | +| USDCe | 35.00% | 40.00% | +| USDTe | 35.00% | 40.00% | +| WAVAX | 35.00% | 40.00% | +| WBTCe | 40.00% | 45.00% | +| WETHe | 35.00% | 40.00% | + +## References + +- Implementation: [AaveV2Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/a08db8acff5c6f1398bc4a2b75fce2ab983351c6/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Ethereum_ReserveFactorUpgrades_20240411.sol), [AaveV2Avalanche](https://github.com/bgd-labs/aave-proposals-v3/blob/a08db8acff5c6f1398bc4a2b75fce2ab983351c6/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Avalanche_ReserveFactorUpgrades_20240411.sol) +- Tests: [AaveV2Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/a08db8acff5c6f1398bc4a2b75fce2ab983351c6/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Ethereum_ReserveFactorUpgrades_20240411.t.sol), [AaveV2Avalanche](https://github.com/bgd-labs/aave-proposals-v3/blob/a08db8acff5c6f1398bc4a2b75fce2ab983351c6/src/20240411_Multi_ReserveFactorUpgrades/AaveV2Avalanche_ReserveFactorUpgrades_20240411.t.sol) +- [Snapshot](https://snapshot.org/#/aave.eth/proposal/0x26a03c08359c340f63b78b0c3e96d37aa0adeda65814643b0886d4719048ea7e) +- [Discussion for Ethereum Reserve Factor Updates](https://governance.aave.com/t/arfc-ethereum-v2-reserve-factor-adjustment/16764/7) +- [Snapshot for Ethereum Reserve Factor Updates](https://snapshot.org/#/aave.eth/proposal/0x26a03c08359c340f63b78b0c3e96d37aa0adeda65814643b0886d4719048ea7e) +- [Discussion for Avalanche Reserve Factor Updates](https://governance.aave.com/t/arfc-avalanche-v2-reserve-factor-adjustment/17040/3) +- [Snapshot for Avalanche Reserve Factor Updates](https://snapshot.org/#/aave.eth/proposal/0x770ff4e02634c77aaa09952345551168920f7878b32ab03fcef92763a5fb70ab) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20240411_Multi_ReserveFactorUpgrades/ReserveFactorUpgrades_20240411.s.sol b/src/20240411_Multi_ReserveFactorUpgrades/ReserveFactorUpgrades_20240411.s.sol new file mode 100644 index 000000000..1b555300e --- /dev/null +++ b/src/20240411_Multi_ReserveFactorUpgrades/ReserveFactorUpgrades_20240411.s.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {GovV3Helpers, IPayloadsControllerCore, PayloadsControllerUtils} from 'aave-helpers/GovV3Helpers.sol'; +import {EthereumScript, AvalancheScript} from 'aave-helpers/ScriptUtils.sol'; +import {AaveV2Ethereum_ReserveFactorUpgrades_20240411} from './AaveV2Ethereum_ReserveFactorUpgrades_20240411.sol'; +import {AaveV2Avalanche_ReserveFactorUpgrades_20240411} from './AaveV2Avalanche_ReserveFactorUpgrades_20240411.sol'; + +/** + * @dev Deploy Ethereum + * deploy-command: make deploy-ledger contract=src/20240411_Multi_ReserveFactorUpgrades/ReserveFactorUpgrades_20240411.s.sol:DeployEthereum chain=mainnet + * verify-command: npx catapulta-verify -b broadcast/ReserveFactorUpgrades_20240411.s.sol/1/run-latest.json + */ +contract DeployEthereum is EthereumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV2Ethereum_ReserveFactorUpgrades_20240411).creationCode + ); + + // compose action + IPayloadsControllerCore.ExecutionAction[] + memory actions = new IPayloadsControllerCore.ExecutionAction[](1); + actions[0] = GovV3Helpers.buildAction(payload0); + + // register action at payloadsController + GovV3Helpers.createPayload(actions); + } +} + +/** + * @dev Deploy Avalanche + * deploy-command: make deploy-ledger contract=src/20240411_Multi_ReserveFactorUpgrades/ReserveFactorUpgrades_20240411.s.sol:DeployAvalanche chain=avalanche + * verify-command: npx catapulta-verify -b broadcast/ReserveFactorUpgrades_20240411.s.sol/43114/run-latest.json + */ +contract DeployAvalanche is AvalancheScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV2Avalanche_ReserveFactorUpgrades_20240411).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/20240411_Multi_ReserveFactorUpgrades/ReserveFactorUpgrades_20240411.s.sol:CreateProposal chain=mainnet + */ +contract CreateProposal is EthereumScript { + function run() external { + // create payloads + PayloadsControllerUtils.Payload[] memory payloads = new PayloadsControllerUtils.Payload[](2); + + // compose actions for validation + IPayloadsControllerCore.ExecutionAction[] + memory actionsEthereum = new IPayloadsControllerCore.ExecutionAction[](1); + actionsEthereum[0] = GovV3Helpers.buildAction( + type(AaveV2Ethereum_ReserveFactorUpgrades_20240411).creationCode + ); + payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); + + IPayloadsControllerCore.ExecutionAction[] + memory actionsAvalanche = new IPayloadsControllerCore.ExecutionAction[](1); + actionsAvalanche[0] = GovV3Helpers.buildAction( + type(AaveV2Avalanche_ReserveFactorUpgrades_20240411).creationCode + ); + payloads[1] = GovV3Helpers.buildAvalanchePayload(vm, actionsAvalanche); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal( + vm, + payloads, + GovV3Helpers.ipfsHashFile( + vm, + 'src/20240411_Multi_ReserveFactorUpgrades/ReserveFactorUpgrades.md' + ) + ); + } +} diff --git a/src/20240411_Multi_ReserveFactorUpgrades/config.ts b/src/20240411_Multi_ReserveFactorUpgrades/config.ts new file mode 100644 index 000000000..a912f9597 --- /dev/null +++ b/src/20240411_Multi_ReserveFactorUpgrades/config.ts @@ -0,0 +1,17 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + pools: ['AaveV2Ethereum', 'AaveV2Avalanche'], + title: 'Reserve Factor Upgrades', + shortName: 'ReserveFactorUpgrades', + date: '20240411', + author: 'karpatkey_TokenLogic', + discussion: 'https://governance.aave.com/t/arfc-ethereum-v2-reserve-factor-adjustment/16764/7', + snapshot: + 'https://snapshot.org/#/aave.eth/proposal/0x26a03c08359c340f63b78b0c3e96d37aa0adeda65814643b0886d4719048ea7e', + }, + poolOptions: { + AaveV2Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 19668943}}, + AaveV2Avalanche: {configs: {OTHERS: {}}, cache: {blockNumber: 44280713}}, + }, +}; diff --git a/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.sol b/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.sol new file mode 100644 index 000000000..3d80c5341 --- /dev/null +++ b/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV2Ethereum} from 'aave-address-book/AaveV2Ethereum.sol'; +import {IProposalGenericExecutor} from 'aave-helpers/interfaces/IProposalGenericExecutor.sol'; +/** + * @title V2 Stable Debt Offboarding + * @author BGD Labs @bgdlabs + * - Snapshot: https://snapshot.org/#/aave.eth/proposal/0xb58ef33b4b7f4c35b7a6834b24f11b282d713b5e9f527f29d782aef04886c189 + * - Discussion: https://governance.aave.com/t/bgd-full-deprecation-of-stable-rate/16473 + */ +contract AaveV2Ethereum_V2StableDebtOffboarding_20240416 is IProposalGenericExecutor { + address public constant LENDING_POOL_IMPL = 0x02D84abD89Ee9DB409572f19B6e1596c301F3c81; + + function execute() external { + AaveV2Ethereum.POOL_ADDRESSES_PROVIDER.setLendingPoolImpl(LENDING_POOL_IMPL); + } +} diff --git a/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.t.sol b/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.t.sol new file mode 100644 index 000000000..11876375b --- /dev/null +++ b/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.t.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV2Ethereum, AaveV2EthereumAssets} from 'aave-address-book/AaveV2Ethereum.sol'; +import {DataTypes} from 'aave-address-book/AaveV2.sol'; +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; + +import 'forge-std/Test.sol'; +import {ProtocolV2TestBase, ReserveConfig} from 'aave-helpers/ProtocolV2TestBase.sol'; +import {AaveV2Ethereum_V2StableDebtOffboarding_20240416} from './AaveV2Ethereum_V2StableDebtOffboarding_20240416.sol'; + +interface IUpdatedLendingPool { + function swapToVariable(address asset, address user) external; +} + +/** + * @dev Test for AaveV2Ethereum_V2StableDebtOffboarding_20240416 + * command: make test-contract filter=AaveV2Ethereum_V2StableDebtOffboarding_20240416 + */ +contract AaveV2Ethereum_V2StableDebtOffboarding_20240416_Test is ProtocolV2TestBase { + AaveV2Ethereum_V2StableDebtOffboarding_20240416 internal proposal; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 19668247); + proposal = new AaveV2Ethereum_V2StableDebtOffboarding_20240416(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + defaultTest( + 'AaveV2Ethereum_V2StableDebtOffboarding_20240416', + AaveV2Ethereum.POOL, + address(proposal) + ); + } + + function test_rateSwap() public { + executePayload(vm, address(proposal)); + DataTypes.ReserveData memory reserveData = AaveV2Ethereum.POOL.getReserveData( + AaveV2EthereumAssets.DAI_UNDERLYING + ); + address[] memory users = _getsDaiUsers(); + for (uint256 i = 0; i < users.length; i++) { + uint256 stableDebtBefore = IERC20(reserveData.stableDebtTokenAddress).balanceOf(users[i]); + uint256 variableDebtBefore = IERC20(reserveData.variableDebtTokenAddress).balanceOf(users[i]); + + IUpdatedLendingPool(address(AaveV2Ethereum.POOL)).swapToVariable( + AaveV2EthereumAssets.DAI_UNDERLYING, + users[i] + ); + + uint256 stableDebtAfter = IERC20(reserveData.stableDebtTokenAddress).balanceOf(users[i]); + uint256 variableDebtAfter = IERC20(reserveData.variableDebtTokenAddress).balanceOf(users[i]); + assertEq(stableDebtAfter, 0); + assertApproxEqAbs(variableDebtAfter, variableDebtBefore + stableDebtBefore, 1); + } + } + + function _getsDaiUsers() internal returns (address[] memory) { + address[] memory users = new address[](5); + users[0] = 0x1047DC58a642AEd18B1DC04C11f02C622b42cf21; + users[1] = 0xeb7AE9d125442A5b4ed57FE7C4Cbc87512B02ADA; + users[2] = 0xC28AC4b691cFd8d27B7e1c6fc757FE2cBa10604A; + users[3] = 0xe59d885CEc9Fb8A79E4ee30EDabd250E470E757A; + users[4] = 0x9CD6658537dDBB63F075ec3E92e53Ef3E723b195; + + return users; + } +} diff --git a/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding.md b/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding.md new file mode 100644 index 000000000..5c015ea41 --- /dev/null +++ b/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding.md @@ -0,0 +1,38 @@ +--- +title: "V2 Stable Debt Offboarding" +author: "BGD Labs @bgdlabs" +discussions: "https://governance.aave.com/t/bgd-full-deprecation-of-stable-rate/16473" +snapshot: "https://snapshot.org/#/aave.eth/proposal/0xb58ef33b4b7f4c35b7a6834b24f11b282d713b5e9f527f29d782aef04886c189" +--- + +## Simple Summary + +Introduce a new method `swapToVariable(address asset, address user)` that allows permissionless swapping from stable to variable debt. + +## Motivation + +On the 4th of November 2023 10, a report was received via the Aave <> Immunefi bug bounty program about a critical bug related to the stable borrow rate. + +Only certain assets were affected due to their configuration, but given the nature of the bug, together with the progressive deprecation of stable rate that started before (not enabled in Aave v3 Ethereum, the main instance of Aave at the moment, or any other afterwards), the fix involved a full deprecation of minting mechanisms of stable debt: halting new borrowings in that mode and also halting rebalancing and swapping from variable to stable. + +Even if with the halting of minting of stable rate we are fully confident that there is no further vector, the current situation is extremely asymmetric, and creating really important technical overhead, for example when doing security evaluations/reviews of the protocol: there are user positions at stable, which factually have fixed rate until they decide to close it, without any kind of rebalancing applicable. + +Therefore, after evaluating the scenario for some time, we think the better solution is to progress on the deprecation of stable rate, by migrating all user positions from stable to variable. + +## Specification + +On execution this proposal will call: + +- `AaveV2Ethereum.POOL_ADDRESSES_PROVIDER.setLendingPoolImpl(LENDING_POOL_IMPL)` to update the pool implementation + +## References + +- Implementation: [AaveV2Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/c897b15496a26fd9f30aff69e3a66b22321a1576/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.sol) +- Tests: [AaveV2Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/c897b15496a26fd9f30aff69e3a66b22321a1576/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.t.sol) +- [Snapshot](https://snapshot.org/#/aave.eth/proposal/0xb58ef33b4b7f4c35b7a6834b24f11b282d713b5e9f527f29d782aef04886c189) +- [Discussion](https://governance.aave.com/t/bgd-full-deprecation-of-stable-rate/16473) +- [Diff](https://github.com/bgd-labs/v2-stable-debt-offboarding/blob/d9862450d82930a6c9c9fe67e84894c7c467514e/diffs/diff.md) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding_20240416.s.sol b/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding_20240416.s.sol new file mode 100644 index 000000000..cee6fdddc --- /dev/null +++ b/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding_20240416.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 {AaveV2Ethereum_V2StableDebtOffboarding_20240416} from './AaveV2Ethereum_V2StableDebtOffboarding_20240416.sol'; + +/** + * @dev Deploy Ethereum + * deploy-command: make deploy-ledger contract=src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding_20240416.s.sol:DeployEthereum chain=mainnet + * verify-command: npx catapulta-verify -b broadcast/V2StableDebtOffboarding_20240416.s.sol/1/run-latest.json + */ +contract DeployEthereum is EthereumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV2Ethereum_V2StableDebtOffboarding_20240416).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/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding_20240416.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(AaveV2Ethereum_V2StableDebtOffboarding_20240416).creationCode + ); + payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal( + vm, + payloads, + GovV3Helpers.ipfsHashFile( + vm, + 'src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding.md' + ) + ); + } +} diff --git a/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/config.ts b/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/config.ts new file mode 100644 index 000000000..a0bc21fa4 --- /dev/null +++ b/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/config.ts @@ -0,0 +1,14 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + author: 'BGD Labs @bgdlabs', + pools: ['AaveV2Ethereum'], + title: 'V2 Stable Debt Offboarding', + shortName: 'V2StableDebtOffboarding', + date: '20240416', + discussion: 'https://governance.aave.com/t/bgd-full-deprecation-of-stable-rate/16473', + snapshot: + 'https://snapshot.org/#/aave.eth/proposal/0xb58ef33b4b7f4c35b7a6834b24f11b282d713b5e9f527f29d782aef04886c189', + }, + poolOptions: {AaveV2Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 19668247}}}, +};