From 3a3b572c027cde84476049b51f97075989823b4c Mon Sep 17 00:00:00 2001 From: sakulstra Date: Tue, 16 Apr 2024 15:34:06 +0200 Subject: [PATCH] feat: v2 stable offboarding --- ..._V2StableDebtOffboarding_20240416_after.md | 12 ++++ ...ereum_V2StableDebtOffboarding_20240416.sol | 18 +++++ ...eum_V2StableDebtOffboarding_20240416.t.sol | 71 +++++++++++++++++++ .../V2StableDebtOffboarding.md | 38 ++++++++++ .../V2StableDebtOffboarding_20240416.s.sol | 58 +++++++++++++++ .../config.ts | 14 ++++ 6 files changed, 211 insertions(+) create mode 100644 diffs/AaveV2Ethereum_V2StableDebtOffboarding_20240416_before_AaveV2Ethereum_V2StableDebtOffboarding_20240416_after.md create mode 100644 src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.sol create mode 100644 src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.t.sol create mode 100644 src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding.md create mode 100644 src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/V2StableDebtOffboarding_20240416.s.sol create mode 100644 src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/config.ts 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/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..bfc1dac71 --- /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/main/src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/AaveV2Ethereum_V2StableDebtOffboarding_20240416.sol) +- Tests: [AaveV2Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/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}}}, +};