Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: v2 stable offboarding #295

Merged
merged 1 commit into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Raw diff

```json
{
"poolConfig": {
"poolImpl": {
"from": "0x085E34722e04567Df9E6d2c32e82fd74f3342e79",
"to": "0x02D84abD89Ee9DB409572f19B6e1596c301F3c81"
}
}
}
```
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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/).
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {GovV3Helpers, IPayloadsControllerCore, PayloadsControllerUtils} from 'aave-helpers/GovV3Helpers.sol';
import {EthereumScript} from 'aave-helpers/ScriptUtils.sol';
import {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'
)
);
}
}
14 changes: 14 additions & 0 deletions src/20240416_AaveV2Ethereum_V2StableDebtOffboarding/config.ts
Original file line number Diff line number Diff line change
@@ -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}}},
};
Loading