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

Aave Funding Updates #33

Merged
merged 20 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/20231102_Multi_AaveFundingUpdates/AaveFundingUpdates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: "Aave Funding Updates"
author: "TokenLogic"
discussions: "https://governance.aave.com/t/arfc-aave-funding-update/15194"
---

## Simple Summary

This AIP aims to consolidate Aave DAO's stablecoin holdings. It is divided into different parts that are detailed below. Part one is depositing DAI into aEthDAI, part two is migrating aDAI and aUSDT into aEthDAI and aEthUSDT, part three bridges assets from Polygon to Mainnet and part four swaps some holdings into GHO.

## Motivation

This proposal intends to ensure the DAO is well capitalised. A separate DAO budget publication will be shared during Q4 2023.

The DAO has sufficient USDC, DAI and USDT deposited across the various instances of Aave Protocol to support existing streams and the AURA purchase 3.

However, with the emergence of new service provider proposal expected, the DAO needs to adjust its stable coin holdings. This publication supports transferring additional funds from Polygon to Mainnet and acquiring GHO on the market to ensure the DAO is well capitalised for the next 6 months. It also aims to move assets from the old V2 to the newer V3 aToken.

## Specification

- Deposit 1M units of DAI from Treasury into Aave v3
- Migrate all aDAI from Aave v2 to v3

- Redeem and transfer 1.7M USDC to Ethereum Treasury
- Redeem and transfer 0.5M DAI to Ethereum Treasury
- Redeem and transfer 0.75M USDT to Ethereum Treasury

Swap the following asset holdings to GHO:
Zer0dot marked this conversation as resolved.
Show resolved Hide resolved

- All available aTUSD that can be redeemed (57,373.85 units at time of writing)
sakulstra marked this conversation as resolved.
Show resolved Hide resolved
- 500k units of DAI held in Treasury (received from Polygon bridge)

Swap the following asset holdings to USDC (there is no GHO / ETH oracle thus these tokens cannot be swapped to GHO directly):

- All GUSD (18,464.03 units at time of writing)
sakulstra marked this conversation as resolved.
Show resolved Hide resolved
- All UST (893,257.63 units at time of writing)
sakulstra marked this conversation as resolved.
Show resolved Hide resolved

## References

- Implementation: [AaveV2Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20231102_Multi_AaveFundingUpdates/AaveV2Ethereum_AaveFundingUpdates_20231102.sol), [AaveV2Polygon](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20231102_Multi_AaveFundingUpdates/AaveV2Polygon_AaveFundingUpdates_20231102.sol), [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20231102_Multi_AaveFundingUpdates/AaveV3Ethereum_AaveFundingUpdates_20231102.sol)
- Tests: [AaveV2Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20231102_Multi_AaveFundingUpdates/AaveV2Ethereum_AaveFundingUpdates_20231102.t.sol), [AaveV2Polygon](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20231102_Multi_AaveFundingUpdates/AaveV2Polygon_AaveFundingUpdates_20231102.t.sol), [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20231102_Multi_AaveFundingUpdates/AaveV3Ethereum_AaveFundingUpdates_20231102.t.sol)
- [Snapshot](https://snapshot.org/#/aave.eth/proposal/0x099f88e1728760952be26fcb8fc99b26c29336e6a109820b391751b108399ee5)
- [Discussion](https://governance.aave.com/t/arfc-aave-funding-update/15194)

## 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,74 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {GovV3Helpers, IPayloadsControllerCore, PayloadsControllerUtils} from 'aave-helpers/GovV3Helpers.sol';
import {EthereumScript, PolygonScript} from 'aave-helpers/ScriptUtils.sol';
import {AaveV2Polygon_AaveFundingUpdates_20231102} from './AaveV2Polygon_AaveFundingUpdates_20231102.sol';
import {AaveV3Ethereum_AaveFundingUpdates_20231102} from './AaveV3Ethereum_AaveFundingUpdates_20231102.sol';

/**
* @dev Deploy Ethereum
* command: make deploy-ledger contract=src/20231102_Multi_AaveFundingUpdates/AaveFundingUpdates_20231102.s.sol:DeployEthereum chain=mainnet
*/
contract DeployEthereum is EthereumScript {
function run() external broadcast {
// deploy payloads
AaveV3Ethereum_AaveFundingUpdates_20231102 payload0 = new AaveV3Ethereum_AaveFundingUpdates_20231102();

// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(address(payload0));

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Deploy Polygon
* command: make deploy-ledger contract=src/20231102_Multi_AaveFundingUpdates/AaveFundingUpdates_20231102.s.sol:DeployPolygon chain=polygon
*/
contract DeployPolygon is PolygonScript {
function run() external broadcast {
// deploy payloads
AaveV2Polygon_AaveFundingUpdates_20231102 payload0 = new AaveV2Polygon_AaveFundingUpdates_20231102();

// compose action
IPayloadsControllerCore.ExecutionAction[]
memory actions = new IPayloadsControllerCore.ExecutionAction[](1);
actions[0] = GovV3Helpers.buildAction(address(payload0));

// register action at payloadsController
GovV3Helpers.createPayload(actions);
}
}

/**
* @dev Create Proposal
* command: make deploy-ledger contract=src/20231102_Multi_AaveFundingUpdates/AaveFundingUpdates_20231102.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(address(0));
payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum);

IPayloadsControllerCore.ExecutionAction[]
memory actionsPolygon = new IPayloadsControllerCore.ExecutionAction[](1);
actionsPolygon[0] = GovV3Helpers.buildAction(address(0));
payloads[1] = GovV3Helpers.buildPolygonPayload(vm, actionsPolygon);

// create proposal
vm.startBroadcast();
GovV3Helpers.createProposal2_5(
sakulstra marked this conversation as resolved.
Show resolved Hide resolved
payloads,
GovV3Helpers.ipfsHashFile(vm, 'src/20231102_Multi_AaveFundingUpdates/AaveFundingUpdates.md')
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol';
import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol';
import {AaveV2EthereumArc} from 'aave-address-book/AaveV2EthereumArc.sol';
import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol';
import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol';
import {AaveSwapper} from 'aave-helpers/swaps/AaveSwapper.sol';
import {IProposalGenericExecutor} from 'aave-helpers/interfaces/IProposalGenericExecutor.sol';

/**
* @title Aave Funding Updates
* @author efecarranza.eth
* - Snapshot: https://snapshot.org/#/aave.eth/proposal/0x099f88e1728760952be26fcb8fc99b26c29336e6a109820b391751b108399ee5
* - Discussion: https://governance.aave.com/t/arfc-aave-funding-update/15194
*/
contract AaveV2Ethereum_AaveFundingUpdates_20231102 is IProposalGenericExecutor {
using SafeERC20 for IERC20;

AaveSwapper public constant SWAPPER = AaveSwapper(MiscEthereum.AAVE_SWAPPER);

address public constant MILKMAN = 0x11C76AD590ABDFFCD980afEC9ad951B160F02797;
address public constant PRICE_CHECKER = 0xe80a1C615F75AFF7Ed8F08c9F21f9d00982D666c;
address public constant ARC_USDC = 0xd35f648C3C7f17cd1Ba92e5eac991E3EfcD4566d;

function execute() external {
AaveV3Ethereum.COLLECTOR.transfer(
ARC_USDC,
address(this),
IERC20(ARC_USDC).balanceOf(address(AaveV3Ethereum.COLLECTOR))
);

AaveV2EthereumArc.POOL.withdraw(
AaveV3EthereumAssets.USDC_UNDERLYING,
type(uint256).max,
address(SWAPPER)
);

SWAPPER.swap(
MILKMAN,
PRICE_CHECKER,
AaveV3EthereumAssets.USDC_UNDERLYING,
AaveV3EthereumAssets.GHO_UNDERLYING,
AaveV3EthereumAssets.USDC_ORACLE,
AaveV3EthereumAssets.GHO_ORACLE,
address(AaveV3Ethereum.COLLECTOR),
IERC20(AaveV3EthereumAssets.USDC_UNDERLYING).balanceOf(address(SWAPPER)),
300
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {GovHelpers} from 'aave-helpers/GovHelpers.sol';
import {AaveGovernanceV2} from 'aave-address-book/AaveGovernanceV2.sol';
import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol';
import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol';
import {AaveV2EthereumArc} from 'aave-address-book/AaveV2EthereumArc.sol';
import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol';
import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/ProtocolV3TestBase.sol';

import {AaveV2Ethereum_AaveFundingUpdates_20231102} from './AaveV2Ethereum_AaveFundingUpdates_20231102.sol';

/**
* @dev Test for AaveV3Ethereum_AaveFundingUpdates_20231102
* command: make test-contract filter=AaveV2Ethereum_AaveFundingUpdates_20231102
*/
contract AaveV2Ethereum_AaveFundingUpdates_20231102_Test is ProtocolV3TestBase {
event SwapRequested(
address milkman,
address indexed fromToken,
address indexed toToken,
address fromOracle,
address toOracle,
uint256 amount,
address indexed recipient,
uint256 slippage
);

AaveV2Ethereum_AaveFundingUpdates_20231102 internal proposal;

function setUp() public {
vm.createSelectFork(vm.rpcUrl('mainnet'), 18486934);
proposal = new AaveV2Ethereum_AaveFundingUpdates_20231102();
}

function test_execute() public {
uint256 balanceArcUSDCBefore = IERC20(proposal.ARC_USDC()).balanceOf(
address(AaveV3Ethereum.COLLECTOR)
);

assertGt(balanceArcUSDCBefore, 0);

vm.expectEmit(true, true, false, false, MiscEthereum.AAVE_SWAPPER);
emit SwapRequested(
proposal.MILKMAN(),
AaveV3EthereumAssets.USDC_UNDERLYING,
AaveV3EthereumAssets.GHO_UNDERLYING,
AaveV3EthereumAssets.USDC_ORACLE,
AaveV3EthereumAssets.GHO_ORACLE,
IERC20(proposal.ARC_USDC()).balanceOf(address(AaveV3Ethereum.COLLECTOR)),
address(AaveV3Ethereum.COLLECTOR),
100
);

GovHelpers.executePayload(vm, address(proposal), AaveGovernanceV2.ARC_TIMELOCK);

assertLt(
sakulstra marked this conversation as resolved.
Show resolved Hide resolved
IERC20(proposal.ARC_USDC()).balanceOf(address(AaveV3Ethereum.COLLECTOR)),
balanceArcUSDCBefore
);

assertEq(IERC20(proposal.ARC_USDC()).balanceOf(address(proposal.SWAPPER())), 0);
sakulstra marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {AaveV2Polygon, AaveV2PolygonAssets} from 'aave-address-book/AaveV2Polygon.sol';
import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol';
import {MiscPolygon} from 'aave-address-book/MiscPolygon.sol';
import {IProposalGenericExecutor} from 'aave-helpers/interfaces/IProposalGenericExecutor.sol';

interface IAavePolEthERC20Bridge {
function bridge(address token, uint256 amount) external;
}

/**
* @title Aave Funding Updates
* @author efecarranza.eth
* - Snapshot: https://snapshot.org/#/aave.eth/proposal/0x099f88e1728760952be26fcb8fc99b26c29336e6a109820b391751b108399ee5
* - Discussion: https://governance.aave.com/t/arfc-aave-funding-update/15194
*/
contract AaveV2Polygon_AaveFundingUpdates_20231102 is IProposalGenericExecutor {
IAavePolEthERC20Bridge public constant bridge =
IAavePolEthERC20Bridge(MiscPolygon.AAVE_POL_ETH_BRIDGE);
uint256 public constant USDC_TO_WITHDRAW = 1_700_000e6;
uint256 public constant USDT_TO_WITHDRAW = 750_000e6;
uint256 public constant DAI_TO_WITHDRAW = 500_000e18;

function execute() external {
AaveV2Polygon.COLLECTOR.transfer(
AaveV2PolygonAssets.USDC_A_TOKEN,
address(this),
USDC_TO_WITHDRAW
);
AaveV2Polygon.COLLECTOR.transfer(
AaveV2PolygonAssets.USDT_A_TOKEN,
address(this),
USDT_TO_WITHDRAW
);
AaveV2Polygon.COLLECTOR.transfer(
AaveV2PolygonAssets.DAI_A_TOKEN,
address(this),
DAI_TO_WITHDRAW
);

uint256 usdcWithdrawn = AaveV2Polygon.POOL.withdraw(
AaveV2PolygonAssets.USDC_UNDERLYING,
type(uint256).max,
MiscPolygon.AAVE_POL_ETH_BRIDGE
);
uint256 usdtWithdrawn = AaveV2Polygon.POOL.withdraw(
AaveV2PolygonAssets.USDT_UNDERLYING,
type(uint256).max,
MiscPolygon.AAVE_POL_ETH_BRIDGE
);
uint256 daiWithdrawn = AaveV2Polygon.POOL.withdraw(
AaveV2PolygonAssets.DAI_UNDERLYING,
type(uint256).max,
MiscPolygon.AAVE_POL_ETH_BRIDGE
);

bridge.bridge(AaveV2PolygonAssets.USDC_UNDERLYING, usdcWithdrawn);
bridge.bridge(AaveV2PolygonAssets.USDT_UNDERLYING, usdtWithdrawn);
bridge.bridge(AaveV2PolygonAssets.DAI_UNDERLYING, daiWithdrawn);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol';
import {GovHelpers} from 'aave-helpers/GovHelpers.sol';
import {GovernanceV3Polygon} from 'aave-address-book/GovernanceV3Polygon.sol';
import {AaveV2Polygon, AaveV2PolygonAssets} from 'aave-address-book/AaveV2Polygon.sol';
import {MiscPolygon} from 'aave-address-book/MiscPolygon.sol';
import {ProtocolV2TestBase, ReserveConfig} from 'aave-helpers/ProtocolV2TestBase.sol';
import {AaveV2Polygon_AaveFundingUpdates_20231102} from './AaveV2Polygon_AaveFundingUpdates_20231102.sol';

/**
* @dev Test for AaveV2Polygon_AaveFundingUpdates_20231102
* command: make test-contract filter=AaveV2Polygon_AaveFundingUpdates_20231102
*/
contract AaveV2Polygon_AaveFundingUpdates_20231102_Test is ProtocolV2TestBase {
event Bridge(address token, uint256 amount);

AaveV2Polygon_AaveFundingUpdates_20231102 internal proposal;

function setUp() public {
vm.createSelectFork(vm.rpcUrl('polygon'), 49475560);
proposal = new AaveV2Polygon_AaveFundingUpdates_20231102();
}

function test_execute() public {
uint256 usdcBalanceBefore = IERC20(AaveV2PolygonAssets.USDC_A_TOKEN).balanceOf(
address(AaveV2Polygon.COLLECTOR)
);
uint256 usdtBalanceBefore = IERC20(AaveV2PolygonAssets.USDT_A_TOKEN).balanceOf(
address(AaveV2Polygon.COLLECTOR)
);
uint256 daiBalanceBefore = IERC20(AaveV2PolygonAssets.DAI_A_TOKEN).balanceOf(
address(AaveV2Polygon.COLLECTOR)
);

vm.expectEmit(true, true, false, false, MiscPolygon.AAVE_POL_ETH_BRIDGE);
emit Bridge(AaveV2PolygonAssets.USDC_UNDERLYING, proposal.USDC_TO_WITHDRAW());

vm.expectEmit(true, true, false, false, MiscPolygon.AAVE_POL_ETH_BRIDGE);
emit Bridge(AaveV2PolygonAssets.USDT_UNDERLYING, proposal.USDT_TO_WITHDRAW());

vm.expectEmit(true, true, false, false, MiscPolygon.AAVE_POL_ETH_BRIDGE);
emit Bridge(AaveV2PolygonAssets.DAI_UNDERLYING, proposal.DAI_TO_WITHDRAW());

GovHelpers.executePayload(vm, address(proposal), GovernanceV3Polygon.EXECUTOR_LVL_1);

assertApproxEqRel(
IERC20(AaveV2PolygonAssets.USDC_A_TOKEN).balanceOf(address(AaveV2Polygon.COLLECTOR)),
usdcBalanceBefore - proposal.USDC_TO_WITHDRAW(),
0.001e18
);
assertApproxEqRel(
IERC20(AaveV2PolygonAssets.USDT_A_TOKEN).balanceOf(address(AaveV2Polygon.COLLECTOR)),
usdtBalanceBefore - proposal.USDT_TO_WITHDRAW(),
0.001e18
);
assertApproxEqRel(
IERC20(AaveV2PolygonAssets.DAI_A_TOKEN).balanceOf(address(AaveV2Polygon.COLLECTOR)),
daiBalanceBefore - proposal.DAI_TO_WITHDRAW(),
0.001e18
);
}
}