Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc Zeller committed Sep 26, 2023
1 parent 0ce7b46 commit 9cd495b
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
title: "Aave treasury RWA Allocation Part I"
author: "Marc Zeller - Aave-Chan Initiative"
discussions: "https://governance.aave.com/t/arfc-aave-treasury-rwa-allocation/14790"
---

## Simple Summary

This proposal is the first part of the Aave treasury RWA allocation. It proposes to allocate 50k USDC & 500 AAVE to Centrifuge.

## Motivation

Aave has long been a contributor and supporter of RWA initiatives. Since the first announcement of GHO, the Aave community has consistently expressed its interest in expanding into this area. Treasury Management at Aave has historically been focused on strategic crypto assets, ignoring the returns and liquidity available in offchain markets for various reasons.

Today, with roughly 17% of the treasury in stablecoins (~13m USD), the Aave DAO is overlooking the 5% available interest in the risk-free rate of overnight financing of US treasury assets. This can offer $250,000 of recurring revenue a year at just 5m USD of investment. These markets can immediately become some of the highest earning revenue streams for the DAO.

Beyond just economics, this proposal would allow the Aave DAO to establish and begin developing the internal RWA expertise necessary to engage with these markets. Centrifuge Prime is purpose-built for DeFi native organizations, offering the critical services and infrastructure necessary to onboard a diverse portfolio of RWA through a single interface.

Centrifuge has a long track record of working with DAOs to bring RWA on as collateral, and pioneered the first Aave deployment into RWA with the joint development of the RWA Market. Onboarding Aave to Centrifuge Prime for liquid investment strategies is an optimal approach for scaling RWA with the Aave community. It will develop the legal and technical infrastructure necessary to interface with RWAs safely and efficiently, while allowing the Aave community to get comfortable and familiar with the processes and thinking around RWA. This will put Aave in a significantly improved position to be able to leverage RWA collateral for GHO in the long term, either to improve liquidity or develop additional revenue streams.

## Specification

This proposal withdraw 50k aUSDC from the Aave COLLECTOR contract and convert them to USDC before transferring them to the Centrifuge Treasury.
This proposal also create a 500 AAVE stream for a period of two years to the Centrifuge Treasury.

## References

- Implementation: [Ethereum](https://github.com/bgd-labs/aave-proposals/blob/main/src/20230925_AaveV2_Eth_AaveTreasuryRWAAllocationPartI/AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925.sol)
- Tests: [Ethereum](https://github.com/bgd-labs/aave-proposals/blob/main/src/20230925_AaveV2_Eth_AaveTreasuryRWAAllocationPartI/AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925.t.sol)
- [Snapshot](https://snapshot.org/#/aave.eth/proposal/0x71db494e4b49e7533c5ccaa566686b2d045b0761cb3296a2d77af4b500566eb0)
- [Discussion](https://governance.aave.com/t/arfc-aave-treasury-rwa-allocation/14790)

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

import {GovHelpers} from 'aave-helpers/GovHelpers.sol';
import {EthereumScript} from 'aave-helpers/ScriptUtils.sol';
import {AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925} from './AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925.sol';

/**
* @dev Deploy AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925
* command: make deploy-ledger contract=src/20230925_AaveV2_Eth_AaveTreasuryRWAAllocationPartI/AaveV2_AaveTreasuryRWAAllocationPartI_20230925.s.sol:DeployEthereum chain=mainnet
*/
contract DeployEthereum is EthereumScript {
function run() external broadcast {
new AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925();
}
}

/**
* @dev Create Proposal
* command: make deploy-ledger contract=src/20230925_AaveV2_Eth_AaveTreasuryRWAAllocationPartI/AaveV2_AaveTreasuryRWAAllocationPartI_20230925.s.sol:CreateProposal chain=mainnet
*/
contract CreateProposal is EthereumScript {
function run() external broadcast {
GovHelpers.Payload[] memory payloads = new GovHelpers.Payload[](1);
payloads[0] = GovHelpers.buildMainnet(address(0));
GovHelpers.createProposal(
payloads,
GovHelpers.ipfsHashFile(
vm,
'src/20230925_AaveV2_Eth_AaveTreasuryRWAAllocationPartI/AaveTreasuryRWAAllocationPartI.md'
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {AaveMisc} from 'aave-address-book/AaveMisc.sol';
import {AaveV2Ethereum, AaveV2EthereumAssets} from 'aave-address-book/AaveV2Ethereum.sol';
import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol';
import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol';

/**
* @title Aave treasury RWA Allocation Part I
* @author Marc Zeller - Aave-Chan Initiative
* - Snapshot: https://snapshot.org/#/aave.eth/proposal/0x71db494e4b49e7533c5ccaa566686b2d045b0761cb3296a2d77af4b500566eb0
* - Discussion: https://governance.aave.com/t/arfc-aave-treasury-rwa-allocation/14790
*/
contract AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925 {
using SafeERC20 for IERC20;

address public constant CENTRIFUGE = 0x9c489E4efba90A67299C1097a8628e233C33BB7B; // Placeholder until address is confirmed, DO NOT MERGE
uint256 public constant STREAM_AMOUNT = 500e18;
uint256 public constant STREAM_DURATION = 720 days;
uint256 public constant ACTUAL_STREAM_AMOUNT_AAVE =
(STREAM_AMOUNT / STREAM_DURATION) * STREAM_DURATION;
uint256 public constant USDC_AMOUNT = 50_000e6;

function execute() external {
AaveV2Ethereum.COLLECTOR.transfer(
AaveV2EthereumAssets.USDC_A_TOKEN,
address(this),
USDC_AMOUNT
);

// I needed to approve the transfer of USDC to CENTRIFUGE why?

IERC20(AaveV2EthereumAssets.USDC_UNDERLYING).approve(address(this), USDC_AMOUNT);


// withdraw aUSDC and convert it to USDC

AaveV2Ethereum.POOL.withdraw(
AaveV2EthereumAssets.USDC_UNDERLYING,
type(uint256).max,
address(this)
);

// transfer USDC to CENTRIFUGE

IERC20(AaveV2EthereumAssets.USDC_UNDERLYING).safeTransferFrom(
address(this),
CENTRIFUGE,
USDC_AMOUNT);

// send back USDC dust to COLLECTOR

IERC20(AaveV2EthereumAssets.USDC_UNDERLYING).approve(address(this), IERC20(AaveV2EthereumAssets.USDC_UNDERLYING).balanceOf(address(this)));


IERC20(AaveV2EthereumAssets.USDC_UNDERLYING).safeTransferFrom(
address(this),
address(AaveV2Ethereum.COLLECTOR),
IERC20(AaveV2EthereumAssets.USDC_UNDERLYING).balanceOf(address(this))
);

// create AAVE stream for CENTRIFUGE
AaveMisc.AAVE_ECOSYSTEM_RESERVE_CONTROLLER.createStream(
AaveMisc.ECOSYSTEM_RESERVE,
CENTRIFUGE,
ACTUAL_STREAM_AMOUNT_AAVE,
AaveV2EthereumAssets.AAVE_UNDERLYING,
block.timestamp,
block.timestamp + STREAM_DURATION
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import 'forge-std/Test.sol';
import {GovHelpers} from 'aave-helpers/GovHelpers.sol';
import {AaveGovernanceV2} from 'aave-address-book/AaveGovernanceV2.sol';
import {AaveMisc, IStreamable} from 'aave-address-book/AaveMisc.sol';
import {AaveV2Ethereum, AaveV2EthereumAssets} from 'aave-address-book/AaveV2Ethereum.sol';
import {ProtocolV2TestBase, ReserveConfig} from 'aave-helpers/ProtocolV2TestBase.sol';
import {AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925} from './AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925.sol';
import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol';

/**
* @dev Test for AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925
* command: make test-contract filter=AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925
*/
contract AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925_Test is ProtocolV2TestBase {
AaveV2_Ethereum_AaveTreasuryRWAAllocationPartI_20230925 internal proposal;

address public constant CENTRIFUGE = 0x9c489E4efba90A67299C1097a8628e233C33BB7B; // Placeholder until address is confirmed, DO NOT MERGE
address public constant USDC = AaveV2EthereumAssets.USDC_UNDERLYING;
address public constant AAVE = AaveV2EthereumAssets.AAVE_UNDERLYING;
address public constant AAVE_ECOSYSTEM_RESERVE = AaveMisc.ECOSYSTEM_RESERVE;
IStreamable public constant STREAMABLE_AAVE_ECOSYSTEM_RESERVE =
IStreamable(AAVE_ECOSYSTEM_RESERVE);
uint256 public constant STREAM_AMOUNT = 500e18;
uint256 public constant STREAM_DURATION = 720 days;
uint256 public constant ACTUAL_STREAM_AMOUNT_AAVE =
(STREAM_AMOUNT / STREAM_DURATION) * STREAM_DURATION;
uint256 public constant USDC_AMOUNT = 50_000e6;

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

function testProposalExecution() public {
uint256 balanceBeforeStable = IERC20(USDC).balanceOf(CENTRIFUGE);

uint256 balanceBeforeAave = IERC20(AAVE).balanceOf(CENTRIFUGE);

uint256 nextEcosystemReserveStreamID = STREAMABLE_AAVE_ECOSYSTEM_RESERVE.getNextStreamId();

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

uint256 balanceAfterStable = IERC20(USDC).balanceOf(CENTRIFUGE);

assertApproxEqAbs(balanceAfterStable, balanceBeforeStable + USDC_AMOUNT, 1 ether);

(
address senderAave,
address recipientAave,
uint256 depositAave,
address tokenAddressAave,
uint256 startTimeAave,
uint256 stopTimeAave,
uint256 remainingBalanceAave,

) = STREAMABLE_AAVE_ECOSYSTEM_RESERVE.getStream(nextEcosystemReserveStreamID);

assertEq(senderAave, AAVE_ECOSYSTEM_RESERVE);
assertEq(recipientAave, CENTRIFUGE);
assertEq(depositAave, ACTUAL_STREAM_AMOUNT_AAVE);
assertEq(tokenAddressAave, address(AAVE));
assertEq(stopTimeAave - startTimeAave, STREAM_DURATION);
assertEq(remainingBalanceAave, ACTUAL_STREAM_AMOUNT_AAVE);

vm.startPrank(CENTRIFUGE);
vm.warp(block.timestamp + STREAM_DURATION + 1 days);

uint256 currentAaveCENTRIFUGEStreamBalance = STREAMABLE_AAVE_ECOSYSTEM_RESERVE.balanceOf(
nextEcosystemReserveStreamID,
CENTRIFUGE
);

STREAMABLE_AAVE_ECOSYSTEM_RESERVE.withdrawFromStream(
nextEcosystemReserveStreamID,
currentAaveCENTRIFUGEStreamBalance
);

assertEq(
IERC20(AAVE).balanceOf(CENTRIFUGE) >= balanceBeforeAave + ACTUAL_STREAM_AMOUNT_AAVE,
true
);

vm.stopPrank();
}
}

0 comments on commit 9cd495b

Please sign in to comment.