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

Treasury Management - Aave Funding Update #43

Merged
merged 14 commits into from
Jan 11, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: "Aave Funding Updates (part 2)"
author: "TokenLogic, efecarranza.eth"
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. This is part two and it consists of depositing USDC into Aave v3 Ethereum, as well as migrating the v2 position to v3 in Ethereum. Also depositing USDT into Aave v2 Ethereum and swapping DAI for GHO.
efecarranza marked this conversation as resolved.
Show resolved Hide resolved

## Motivation

This proposal intends to ensure the DAO is well capitalised.

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.
efecarranza marked this conversation as resolved.
Show resolved Hide resolved

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 1.7M units of USDC from Treasury into Aave v3 Ethereum (received from Polygon bridge)
- Deposit 750k units of USDT from Treasury into Aave v3 Ethereum (received from Polygon bridge)
- Withdraw 900k units of USDC from Aave v2 Ethereum Pool into USDC
efecarranza marked this conversation as resolved.
Show resolved Hide resolved
- Deposit 900k of USDC into Aave v3 Ethereum Pool (withdrawn in previous step)
efecarranza marked this conversation as resolved.
Show resolved Hide resolved

Swap the following asset holdings to GHO:

- 500k units of DAI held in Treasury (received from Polygon bridge)

efecarranza marked this conversation as resolved.
Show resolved Hide resolved
## References

- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20231106_AaveV3Ethereum_AaveFundingUpdates/AaveV3Ethereum_AaveFundingUpdates_20231106.sol)
- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20231106_AaveV3Ethereum_AaveFundingUpdates/AaveV3Ethereum_AaveFundingUpdates_20231106.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,53 @@
// 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_AaveFundingUpdates_20231106} from './AaveV3Ethereum_AaveFundingUpdates_20231106.sol';

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

// 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/20231106_AaveV3Ethereum_AaveFundingUpdates/AaveFundingUpdates_20231106.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
sendra marked this conversation as resolved.
Show resolved Hide resolved
IPayloadsControllerCore.ExecutionAction[]
memory actionsEthereum = new IPayloadsControllerCore.ExecutionAction[](1);
actionsEthereum[0] = GovV3Helpers.buildAction(address(0));
payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum);

// create proposal
vm.startBroadcast();
GovV3Helpers.createProposal2_5(
vm,
payloads,
GovV3Helpers.ipfsHashFile(
vm,
'src/20231106_AaveV3Ethereum_AaveFundingUpdates/AaveFundingUpdates.md'
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;

import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol';
import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol';
import {AaveV2Ethereum, AaveV2EthereumAssets} from 'aave-address-book/AaveV2Ethereum.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 AaveV3Ethereum_AaveFundingUpdates_20231106 is IProposalGenericExecutor {
using SafeERC20 for IERC20;

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

uint256 public constant USDC_TO_DEPOSIT = 1_700_000e6;
uint256 public constant USDT_TO_DEPOSIT = 750_000e6;
uint256 public constant DAI_TO_SWAP = 500_000e18;
uint256 public constant USDC_TO_MIGRATE = 900_000e6;

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

// https://etherscan.io/address/0x3f12643D3f6f874d39C2a4c9f2Cd6f2DbAC877FC
address public constant GHO_ORACLE = 0x3f12643D3f6f874d39C2a4c9f2Cd6f2DbAC877FC;

function execute() external {
AaveV3Ethereum.COLLECTOR.transfer(
AaveV2EthereumAssets.USDC_A_TOKEN,
address(this),
USDC_TO_MIGRATE
);

AaveV2Ethereum.POOL.withdraw(
AaveV2EthereumAssets.USDC_UNDERLYING,
type(uint256).max,
sendra marked this conversation as resolved.
Show resolved Hide resolved
address(this)
);

IERC20(AaveV2EthereumAssets.USDC_UNDERLYING).forceApprove(
address(AaveV3Ethereum.POOL),
IERC20(AaveV2EthereumAssets.USDC_UNDERLYING).balanceOf(address(this))
);

AaveV3Ethereum.POOL.deposit(
AaveV2EthereumAssets.USDC_UNDERLYING,
IERC20(AaveV2EthereumAssets.USDC_UNDERLYING).balanceOf(address(this)),
address(AaveV3Ethereum.COLLECTOR),
0
);

AaveV3Ethereum.COLLECTOR.transfer(
AaveV3EthereumAssets.DAI_UNDERLYING,
address(SWAPPER),
DAI_TO_SWAP
);

// Deposit into V3

AaveV3Ethereum.COLLECTOR.transfer(
AaveV3EthereumAssets.USDC_UNDERLYING,
address(this),
USDC_TO_DEPOSIT
);
IERC20(AaveV3EthereumAssets.USDC_UNDERLYING).forceApprove(
address(AaveV3Ethereum.POOL),
USDC_TO_DEPOSIT
);
AaveV3Ethereum.POOL.deposit(
AaveV3EthereumAssets.USDC_UNDERLYING,
USDC_TO_DEPOSIT,
address(AaveV3Ethereum.COLLECTOR),
0
);

AaveV3Ethereum.COLLECTOR.transfer(
AaveV3EthereumAssets.USDT_UNDERLYING,
address(this),
USDT_TO_DEPOSIT
);
IERC20(AaveV3EthereumAssets.USDT_UNDERLYING).forceApprove(
address(AaveV2Ethereum.POOL),
USDT_TO_DEPOSIT
);
AaveV2Ethereum.POOL.deposit(
AaveV3EthereumAssets.USDT_UNDERLYING,
USDT_TO_DEPOSIT,
address(AaveV3Ethereum.COLLECTOR),
0
);

// Swaps

SWAPPER.swap(
MILKMAN,
PRICE_CHECKER,
AaveV3EthereumAssets.DAI_UNDERLYING,
AaveV3EthereumAssets.GHO_UNDERLYING,
AaveV3EthereumAssets.DAI_ORACLE,
GHO_ORACLE,
address(AaveV3Ethereum.COLLECTOR),
DAI_TO_SWAP,
100
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;

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

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

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

AaveV3Ethereum_AaveFundingUpdates_20231106 internal proposal;

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

function test_execute() public {
uint256 balanceUsdcBefore = IERC20(AaveV3EthereumAssets.USDC_UNDERLYING).balanceOf(
address(AaveV3Ethereum.COLLECTOR)
);

uint256 balanceUsdtBefore = IERC20(AaveV3EthereumAssets.USDT_UNDERLYING).balanceOf(
address(AaveV3Ethereum.COLLECTOR)
);

uint256 balanceDaiBefore = IERC20(AaveV3EthereumAssets.DAI_UNDERLYING).balanceOf(
address(AaveV3Ethereum.COLLECTOR)
);

uint256 balanceAUsdcV2Before = IERC20(AaveV2EthereumAssets.USDC_A_TOKEN).balanceOf(
address(AaveV3Ethereum.COLLECTOR)
);

uint256 balanceAUsdcV3Before = IERC20(AaveV3EthereumAssets.USDC_A_TOKEN).balanceOf(
address(AaveV3Ethereum.COLLECTOR)
);

uint256 balanceAUsdtBefore = IERC20(AaveV2EthereumAssets.USDT_A_TOKEN).balanceOf(
address(AaveV3Ethereum.COLLECTOR)
);

assertGt(balanceUsdcBefore, proposal.USDC_TO_DEPOSIT());

assertEq(balanceUsdtBefore, proposal.USDT_TO_DEPOSIT());

vm.expectEmit(true, true, true, true, MiscEthereum.AAVE_SWAPPER);
emit SwapRequested(
proposal.MILKMAN(),
AaveV3EthereumAssets.DAI_UNDERLYING,
AaveV3EthereumAssets.GHO_UNDERLYING,
AaveV3EthereumAssets.DAI_ORACLE,
proposal.GHO_ORACLE(),
proposal.DAI_TO_SWAP(),
address(AaveV3Ethereum.COLLECTOR),
100
);

executePayload(vm, address(proposal));

assertEq(IERC20(AaveV3EthereumAssets.DAI_UNDERLYING).balanceOf(address(proposal.SWAPPER())), 0);

assertEq(
IERC20(AaveV3EthereumAssets.USDC_UNDERLYING).balanceOf(address(AaveV3Ethereum.COLLECTOR)),
balanceUsdcBefore - proposal.USDC_TO_DEPOSIT()
);

assertApproxEqAbs(
IERC20(AaveV2EthereumAssets.USDC_A_TOKEN).balanceOf(address(AaveV3Ethereum.COLLECTOR)),
balanceAUsdcV2Before - proposal.USDC_TO_MIGRATE(),
150e6
);

assertEq(
IERC20(AaveV3EthereumAssets.USDT_UNDERLYING).balanceOf(address(AaveV3Ethereum.COLLECTOR)),
balanceUsdtBefore - proposal.USDT_TO_DEPOSIT()
);

assertEq(
IERC20(AaveV3EthereumAssets.DAI_UNDERLYING).balanceOf(address(AaveV3Ethereum.COLLECTOR)),
balanceDaiBefore - proposal.DAI_TO_SWAP()
);

assertGt(
IERC20(AaveV3EthereumAssets.USDC_A_TOKEN).balanceOf(address(AaveV3Ethereum.COLLECTOR)),
balanceAUsdcV3Before
);

assertGt(
IERC20(AaveV2EthereumAssets.USDT_A_TOKEN).balanceOf(address(AaveV3Ethereum.COLLECTOR)),
balanceAUsdtBefore
);
}
}
19 changes: 19 additions & 0 deletions src/20231106_AaveV3Ethereum_AaveFundingUpdates/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"rootOptions": {
"pools": ["AaveV3Ethereum"],
"title": "Aave Funding Updates",
"shortName": "AaveFundingUpdates",
"date": "20231106",
"author": "TokenLogic",
"discussion": "https://governance.aave.com/t/arfc-aave-funding-update/15194",
"snapshot": "https://snapshot.org/#/aave.eth/proposal/0x099f88e1728760952be26fcb8fc99b26c29336e6a109820b391751b108399ee5"
},
"poolOptions": {
"AaveV3Ethereum": {
"configs": {
"OTHERS": {}
},
"features": ["OTHERS"]
}
}
}