From 312f7338478da05b55b2104434002762238df0d3 Mon Sep 17 00:00:00 2001 From: Fermin 'Piscu' Carranza Date: Fri, 23 Feb 2024 06:38:07 -0500 Subject: [PATCH 1/6] GSM Part 2 (#208) * feat: gsm part 2 * chore: lint * feat: include orbit program in proposal * feat: update README * chore: format table * feat: optimizations - Commented operations for better readibility. - Reduced codesize of payload contract from 5788 to 5345 bytes - Optimized execution and order of operations to save 2000 gas during execution. * Update src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/OrbitProgramData.sol Co-authored-by: Marc Zeller * Update src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/OrbitProgramData.sol Co-authored-by: Marc Zeller * feat: add APE transfer * chore: add comment on lbs address update * feat: remove extra AIPs from PR * chore: update readme * Update src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2.md Co-authored-by: Harsh Pandey --------- Co-authored-by: luigy-lemon Co-authored-by: Marc Zeller Co-authored-by: Harsh Pandey --- ...gRWAStrategyPreparationsPart2_20240209.sol | 93 +++++++++++++ ...WAStrategyPreparationsPart2_20240209.t.sol | 125 ++++++++++++++++++ ...tGSMFundingRWAStrategyPreparationsPart2.md | 32 +++++ ...WAStrategyPreparationsPart2_20240209.s.sol | 60 +++++++++ .../config.ts | 15 +++ 5 files changed, 325 insertions(+) create mode 100644 src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.sol create mode 100644 src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.t.sol create mode 100644 src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2.md create mode 100644 src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.s.sol create mode 100644 src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/config.ts diff --git a/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.sol b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.sol new file mode 100644 index 000000000..dd6156cda --- /dev/null +++ b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.sol @@ -0,0 +1,93 @@ +// 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 {AaveSwapper} from 'aave-helpers/swaps/AaveSwapper.sol'; +import {DepositV3SwapPayload} from 'aave-helpers/swaps/DepositV3SwapPayload.sol'; +import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; + +/** + * @title Treasury Management - GSM Funding & RWA Strategy Preparations (Part 2) + * @author karpatkey_TokenLogic + * - Snapshot: https://snapshot.org/#/aave.eth/proposal/0xb39537e468eef8c212c67a539cdc6d802cd857f186a4f66aefd44faaadd6ba19 + * - Discussion: https://governance.aave.com/t/arfc-treasury-management-gsm-funding-rwa-strategy-preparations/16128 + */ +contract AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209 is + DepositV3SwapPayload +{ + using SafeERC20 for IERC20; + + uint256 public constant USDC_TO_SWAP = 700_000e6; + AaveSwapper public constant SWAPPER = AaveSwapper(MiscEthereum.AAVE_SWAPPER); + address public constant MILKMAN = 0x11C76AD590ABDFFCD980afEC9ad951B160F02797; + address public constant PRICE_CHECKER = 0xe80a1C615F75AFF7Ed8F08c9F21f9d00982D666c; + + function execute() external { + // Transfer 700k USDC from Collector to Swapper + AaveV3Ethereum.COLLECTOR.transfer( + AaveV3EthereumAssets.USDC_UNDERLYING, + address(SWAPPER), + USDC_TO_SWAP + ); + + // Deposit all remaining USDC from collector into Aave v3. + uint256 usdcBalance = IERC20(AaveV3EthereumAssets.USDC_UNDERLYING).balanceOf( + address(AaveV3Ethereum.COLLECTOR) + ); + + AaveV3Ethereum.COLLECTOR.transfer( + AaveV3EthereumAssets.USDC_UNDERLYING, + address(this), + usdcBalance + ); + + _deposit(AaveV3EthereumAssets.USDC_UNDERLYING, usdcBalance); + + // Transfer the whole DAI balance of the collector into the Swapper + uint256 daiBalance = IERC20(AaveV3EthereumAssets.DAI_UNDERLYING).balanceOf( + address(AaveV3Ethereum.COLLECTOR) + ); + + AaveV3Ethereum.COLLECTOR.transfer( + AaveV3EthereumAssets.DAI_UNDERLYING, + address(SWAPPER), + daiBalance + ); + + // Swap DAI into USDT with receiver being this contract + SWAPPER.swap( + MILKMAN, + PRICE_CHECKER, + AaveV3EthereumAssets.DAI_UNDERLYING, + AaveV3EthereumAssets.USDT_UNDERLYING, + AaveV3EthereumAssets.DAI_ORACLE, + AaveV3EthereumAssets.USDT_ORACLE, + SELF, + daiBalance, + 50 + ); + + // Swap USDC into USDT with receiver being this contract + SWAPPER.swap( + MILKMAN, + PRICE_CHECKER, + AaveV3EthereumAssets.USDC_UNDERLYING, + AaveV3EthereumAssets.USDT_UNDERLYING, + AaveV3EthereumAssets.USDC_ORACLE, + AaveV3EthereumAssets.USDT_ORACLE, + SELF, + USDC_TO_SWAP, + 50 + ); + } + + /** + * @dev To be used after the async swap takes place to deposit USDT in AAVE v3 + */ + function deposit(address token, uint256 amount) external { + _deposit(token, amount); + } +} diff --git a/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.t.sol b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.t.sol new file mode 100644 index 000000000..8e03f2b63 --- /dev/null +++ b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.t.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {ProtocolV3TestBase} from 'aave-helpers/ProtocolV3TestBase.sol'; + +import {AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209} from './AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.sol'; + +/** + * @dev Test for AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209 + * command: make test-contract filter=AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209 + */ +contract AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209_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_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209 + internal proposal; + + address public constant swapProxyDai = 0xa59c5fE2c0A09069bD1fD31a71031d9b8D3FaE93; + address public constant swapProxyUsdc = 0x16b97c7a2870edCA71e4Ed837b3a0Ec93Af328E9; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 19215132); + proposal = new AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + uint256 collectorDaiBalanceBefore = IERC20(AaveV3EthereumAssets.DAI_UNDERLYING).balanceOf( + address(AaveV3Ethereum.COLLECTOR) + ); + + uint256 aUsdcBalanceBefore = IERC20(AaveV3EthereumAssets.USDC_A_TOKEN).balanceOf( + address(AaveV3Ethereum.COLLECTOR) + ); + + vm.expectEmit(true, true, true, true, MiscEthereum.AAVE_SWAPPER); + emit SwapRequested( + proposal.MILKMAN(), + AaveV3EthereumAssets.DAI_UNDERLYING, + AaveV3EthereumAssets.USDT_UNDERLYING, + AaveV3EthereumAssets.DAI_ORACLE, + AaveV3EthereumAssets.USDT_ORACLE, + IERC20(AaveV3EthereumAssets.DAI_UNDERLYING).balanceOf(address(AaveV3Ethereum.COLLECTOR)), + address(proposal), + 50 + ); + + vm.expectEmit(true, true, true, true, MiscEthereum.AAVE_SWAPPER); + emit SwapRequested( + proposal.MILKMAN(), + AaveV3EthereumAssets.USDC_UNDERLYING, + AaveV3EthereumAssets.USDT_UNDERLYING, + AaveV3EthereumAssets.USDC_ORACLE, + AaveV3EthereumAssets.USDT_ORACLE, + proposal.USDC_TO_SWAP(), + address(proposal), + 50 + ); + + executePayload(vm, address(proposal)); + + assertEq( + IERC20(AaveV3EthereumAssets.DAI_UNDERLYING).balanceOf(address(AaveV3Ethereum.COLLECTOR)), + 0, + 'DAI balance of Collector is not zero' + ); + assertEq( + IERC20(AaveV3EthereumAssets.DAI_UNDERLYING).balanceOf(swapProxyDai), + collectorDaiBalanceBefore, + 'DAI balance of proxy is not equal to Collector balance before' + ); + + assertEq( + IERC20(AaveV3EthereumAssets.USDC_UNDERLYING).balanceOf(address(AaveV3Ethereum.COLLECTOR)), + 0, + 'USDC balance of Collector is not zero' + ); + assertEq( + IERC20(AaveV3EthereumAssets.USDC_UNDERLYING).balanceOf(swapProxyUsdc), + proposal.USDC_TO_SWAP(), + 'USDC balance of proxy is not equal to USDC_TO_SWAP amount' + ); + + assertGt( + IERC20(AaveV3EthereumAssets.USDC_A_TOKEN).balanceOf(address(AaveV3Ethereum.COLLECTOR)), + aUsdcBalanceBefore, + 'aUSDC balance of Collector is not greater than before' + ); + } + + function test_depositsToV3() public { + uint256 collectorAUsdtBalanceBefore = IERC20(AaveV3EthereumAssets.USDT_A_TOKEN).balanceOf( + address(AaveV3Ethereum.COLLECTOR) + ); + + uint256 toWithdraw = 1_000e6; + + deal(AaveV3EthereumAssets.USDT_UNDERLYING, address(proposal), toWithdraw); + + proposal.deposit(AaveV3EthereumAssets.USDT_UNDERLYING, toWithdraw); + + assertApproxEqAbs( + IERC20(AaveV3EthereumAssets.USDT_A_TOKEN).balanceOf(address(AaveV3Ethereum.COLLECTOR)), + collectorAUsdtBalanceBefore + toWithdraw, + 1 + ); + } +} diff --git a/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2.md b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2.md new file mode 100644 index 000000000..0cfaafdda --- /dev/null +++ b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2.md @@ -0,0 +1,32 @@ +--- +title: "Treasury Management - GSM Funding & RWA Strategy Preparations (Part 2)" +author: "karpatkey_TokenLogic" +discussions: "https://governance.aave.com/t/arfc-treasury-management-gsm-funding-rwa-strategy-preparations/16128" +snapshot: "https://snapshot.org/#/aave.eth/proposal/0xb39537e468eef8c212c67a539cdc6d802cd857f186a4f66aefd44faaadd6ba19" +--- + +## Simple Summary + +In preparation for potentially funding the GHO Stability Module (GSM) and the $1M RWA strategy with Centrifuge, this publication seeks to make available the necessary amount of USDC, USDT and DAI on Ethereum. + +## Motivation + +The GSM was deployed in a previous proposal and the current stable coin holdings on Ethereum are insufficient to support both the GSM, RWA strategy and Service Provider (SP) commitments. Additional funds are needed on Ethereum to support the GSM. + +## Specification + +- Swap all DAI to USDT +- Swap 0.70M USDC to USDT +- Deposit USDT into Aave v3 +- Deposit USDC minus 0.70M into Aave v3 + +## References + +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.t.sol) +- [Snapshot](https://snapshot.org/#/aave.eth/proposal/0xb39537e468eef8c212c67a539cdc6d802cd857f186a4f66aefd44faaadd6ba19) +- [Discussion](https://governance.aave.com/t/arfc-treasury-management-gsm-funding-rwa-strategy-preparations/16128) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.s.sol b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.s.sol new file mode 100644 index 000000000..c54decff1 --- /dev/null +++ b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.s.sol @@ -0,0 +1,60 @@ +// 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_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209} from './AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.sol'; + +/** + * @dev Deploy Ethereum + * deploy-command: make deploy-ledger contract=src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.s.sol:DeployEthereum chain=mainnet + * verify-command: npx catapulta-verify -b broadcast/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.s.sol/1/run-latest.json + */ +contract DeployEthereum is EthereumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209) + .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/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.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(AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209) + .creationCode + ); + payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal( + vm, + payloads, + GovV3Helpers.ipfsHashFile( + vm, + 'src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2.md' + ) + ); + } +} diff --git a/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/config.ts b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/config.ts new file mode 100644 index 000000000..1c1ef90d9 --- /dev/null +++ b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/config.ts @@ -0,0 +1,15 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + pools: ['AaveV3Ethereum'], + title: 'Treasury Management - GSM Funding & RWA Strategy Preparations (Part 2)', + shortName: 'TreasuryManagementGSMFundingRWAStrategyPreparationsPart2', + date: '20240209', + author: 'karpatkey_TokenLogic', + discussion: + 'https://governance.aave.com/t/arfc-treasury-management-gsm-funding-rwa-strategy-preparations/16128', + snapshot: + 'https://snapshot.org/#/aave.eth/proposal/0xb39537e468eef8c212c67a539cdc6d802cd857f186a4f66aefd44faaadd6ba19', + }, + poolOptions: {AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 19191027}}}, +}; From 4c5418c68391550f3aa1186f8eb3ae3ec25ef870 Mon Sep 17 00:00:00 2001 From: Cache bot Date: Fri, 23 Feb 2024 11:38:37 +0000 Subject: [PATCH 2/6] fix(cache): automated cache update [skip ci] --- ...reasuryManagementGSMFundingRWAStrategyPreparationsPart2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2.md b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2.md index 0cfaafdda..fe724ad7b 100644 --- a/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2.md +++ b/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/TreasuryManagementGSMFundingRWAStrategyPreparationsPart2.md @@ -22,8 +22,8 @@ The GSM was deployed in a previous proposal and the current stable coin holdings ## References -- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.sol) -- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.t.sol) +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/312f7338478da05b55b2104434002762238df0d3/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/312f7338478da05b55b2104434002762238df0d3/src/20240209_AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2/AaveV3Ethereum_TreasuryManagementGSMFundingRWAStrategyPreparationsPart2_20240209.t.sol) - [Snapshot](https://snapshot.org/#/aave.eth/proposal/0xb39537e468eef8c212c67a539cdc6d802cd857f186a4f66aefd44faaadd6ba19) - [Discussion](https://governance.aave.com/t/arfc-treasury-management-gsm-funding-rwa-strategy-preparations/16128) From 4c487a2f49adf301e08c80313dc3f946709c29f3 Mon Sep 17 00:00:00 2001 From: Fermin 'Piscu' Carranza Date: Fri, 23 Feb 2024 06:48:32 -0500 Subject: [PATCH 3/6] Orbit Program Renewal (#221) * feat: orbit program * chore: update readme * chore: validate result of transfer --- .../AaveV3Ethereum_OrbitProgram_20240220.sol | 64 +++++++++++++ ...AaveV3Ethereum_OrbitProgram_20240220.t.sol | 94 +++++++++++++++++++ .../OrbitProgram.md | 56 +++++++++++ .../OrbitProgramData.sol | 45 +++++++++ .../OrbitProgram_20240220.s.sol | 55 +++++++++++ .../config.ts | 14 +++ 6 files changed, 328 insertions(+) create mode 100644 src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.sol create mode 100644 src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.t.sol create mode 100644 src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram.md create mode 100644 src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgramData.sol create mode 100644 src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram_20240220.s.sol create mode 100644 src/20240220_AaveV3Ethereum_OrbitProgram/config.ts diff --git a/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.sol b/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.sol new file mode 100644 index 000000000..cddddbf46 --- /dev/null +++ b/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.sol @@ -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 {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; + +import {OrbitProgramData} from './OrbitProgramData.sol'; + +import {IProposalGenericExecutor} from 'aave-helpers/interfaces/IProposalGenericExecutor.sol'; + +/// Helper interface to withdraw ETH +interface IWETH { + function withdraw(uint256) external; +} + +/** + * @title Orbit Program + * @author karpatkey_TokenLogic_ACI + * - Snapshot: https://snapshot.org/#/aave.eth/proposal/0x412b38c7a0cf1840b102e28ea7ef0373e3ab4b9544873e8cc1544972b777d9a1 + * - Discussion: https://governance.aave.com/t/arfc-orbit-program-renewal/16550 + */ +contract AaveV3Ethereum_OrbitProgram_20240220 is IProposalGenericExecutor { + error EthTransferFailed(address account); + + function execute() external { + AaveV3Ethereum.COLLECTOR.transfer( + AaveV3EthereumAssets.WETH_UNDERLYING, + address(this), + OrbitProgramData.TOTAL_WETH_REBATE + ); + + IWETH(AaveV3EthereumAssets.WETH_UNDERLYING).withdraw(OrbitProgramData.TOTAL_WETH_REBATE); + + OrbitProgramData.GasUsage[] memory usage = OrbitProgramData.getGasUsageData(); + uint256 usageLength = usage.length; + for (uint256 i = 0; i < usageLength; i++) { + (bool ok, ) = usage[i].account.call{value: usage[i].usage}(''); + if (!ok) revert EthTransferFailed(usage[i].account); + } + + uint256 actualStreamAmount = (OrbitProgramData.STREAM_AMOUNT / + OrbitProgramData.STREAM_DURATION) * OrbitProgramData.STREAM_DURATION; + + address[] memory orbitAddresses = OrbitProgramData.getOrbitAddresses(); + uint256 orbitAddressesLength = orbitAddresses.length; + for (uint256 i = 0; i < orbitAddressesLength; i++) { + AaveV3Ethereum.COLLECTOR.transfer( + AaveV3EthereumAssets.GHO_UNDERLYING, + orbitAddresses[i], + OrbitProgramData.RETRO_PAYMENT + ); + + AaveV3Ethereum.COLLECTOR.createStream( + orbitAddresses[i], + actualStreamAmount, + AaveV3EthereumAssets.GHO_UNDERLYING, + block.timestamp, + block.timestamp + OrbitProgramData.STREAM_DURATION + ); + } + } + + receive() external payable {} +} diff --git a/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.t.sol b/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.t.sol new file mode 100644 index 000000000..3f3e6198a --- /dev/null +++ b/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.t.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; + +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; +import {ProtocolV3TestBase} from 'aave-helpers/ProtocolV3TestBase.sol'; + +import {AaveV3Ethereum_OrbitProgram_20240220} from './AaveV3Ethereum_OrbitProgram_20240220.sol'; +import {OrbitProgramData} from './OrbitProgramData.sol'; + +/** + * @dev Test for AaveV3Ethereum_OrbitProgram_20240220 + * command: make test-contract filter=AaveV3Ethereum_OrbitProgram_20240220 + */ +contract AaveV3Ethereum_OrbitProgram_20240220_Test is ProtocolV3TestBase { + uint256 public constant TOTAL_GHO_WITHDRAWN = 20_000 ether; + + AaveV3Ethereum_OrbitProgram_20240220 internal proposal; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 19215132); + proposal = new AaveV3Ethereum_OrbitProgram_20240220(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + uint256 collectorGhoBalanceBefore = IERC20(AaveV3EthereumAssets.GHO_UNDERLYING).balanceOf( + address(AaveV3Ethereum.COLLECTOR) + ); + uint256 collectorWethBalanceBefore = IERC20(AaveV3EthereumAssets.WETH_UNDERLYING).balanceOf( + address(AaveV3Ethereum.COLLECTOR) + ); + + uint256[] memory ethBalancesBeforeUsers = new uint256[](7); + OrbitProgramData.GasUsage[] memory usage = OrbitProgramData.getGasUsageData(); + for (uint256 i = 0; i < usage.length; i++) { + ethBalancesBeforeUsers[i] = usage[i].account.balance; + } + + uint256[] memory ghoBalancesBeforeUsers = new uint256[](4); + address[] memory ghoPaymentAddresses = OrbitProgramData.getOrbitAddresses(); + for (uint256 i = 0; i < ghoPaymentAddresses.length; i++) { + ghoBalancesBeforeUsers[i] = IERC20(AaveV3EthereumAssets.GHO_UNDERLYING).balanceOf( + ghoPaymentAddresses[i] + ); + } + + uint256 nextStreamId = AaveV3Ethereum.COLLECTOR.getNextStreamId(); + vm.expectRevert(); + AaveV3Ethereum.COLLECTOR.getStream(nextStreamId); + + executePayload(vm, address(proposal)); + + assertEq( + IERC20(AaveV3EthereumAssets.GHO_UNDERLYING).balanceOf(address(AaveV3Ethereum.COLLECTOR)), + collectorGhoBalanceBefore - TOTAL_GHO_WITHDRAWN, + 'GHO balance of Collector is not equal to previous minus to withdraw' + ); + assertEq( + IERC20(AaveV3EthereumAssets.WETH_UNDERLYING).balanceOf(address(AaveV3Ethereum.COLLECTOR)), + collectorWethBalanceBefore - OrbitProgramData.TOTAL_WETH_REBATE, + 'WETH balance of Collector is not equal to previous minus to withdraw' + ); + + for (uint256 i = 0; i < usage.length; i++) { + assertGt( + usage[i].account.balance, + ethBalancesBeforeUsers[i], + 'REBATE recipient balance is not greater than before' + ); + } + + vm.warp(block.timestamp + 7 days); + + /// Their GHO balance has increased and call also withdraw from stream as it now exists + for (uint256 i = 0; i < ghoPaymentAddresses.length; i++) { + assertEq( + IERC20(AaveV3EthereumAssets.GHO_UNDERLYING).balanceOf(ghoPaymentAddresses[i]), + ghoBalancesBeforeUsers[i] + OrbitProgramData.RETRO_PAYMENT, + 'GHO balance of Orbit recipient is not greater than before' + ); + + vm.prank(ghoPaymentAddresses[i]); + AaveV3Ethereum.COLLECTOR.withdrawFromStream(nextStreamId + i, 1); + assertEq( + IERC20(AaveV3EthereumAssets.GHO_UNDERLYING).balanceOf(ghoPaymentAddresses[i]), + ghoBalancesBeforeUsers[i] + OrbitProgramData.RETRO_PAYMENT + 1 + ); + } + } +} diff --git a/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram.md b/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram.md new file mode 100644 index 000000000..991a672f3 --- /dev/null +++ b/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram.md @@ -0,0 +1,56 @@ +--- +title: "Orbit Program" +author: "karpatkey_TokenLogic_ACI" +discussions: "https://governance.aave.com/t/arfc-orbit-program-renewal/16550" +snapshot: "https://snapshot.org/#/aave.eth/proposal/0x412b38c7a0cf1840b102e28ea7ef0373e3ab4b9544873e8cc1544972b777d9a1" +--- + +## Simple Summary + +This proposal includes the renewal of the Orbit program for recognized delegates. Compensating them with GHO and ETH reimbursement of Gas costs associated with their governance activity. + +## Motivation + +The Orbit program Snapshot and discussion can be found [here](https://snapshot.org/#/aave.eth/proposal/0x412b38c7a0cf1840b102e28ea7ef0373e3ab4b9544873e8cc1544972b777d9a1) and [here](https://governance.aave.com/t/arfc-orbit-program-renewal/16550) respectively. +LBS updated their address [here](https://governance.aave.com/t/arfc-orbit-program-renewal/16550/5?u=lbsblockchain). + +The following table outlines the proposed compensation for eligible delegates matching the requirements: + +| Delegate Platform | Retro-Payment (GHO) | New Stream (GHO) | +| ----------------- | ------------------- | ---------------- | +| EzR3al | 5000 | 15000 | +| Stable Labs | 5000 | 15000 | +| LBS Blockchain | 5000 | 15000 | +| Michigan | 5000 | 15000 | + +In terms of gas rebate, we included Gov V2 reimbursement & payload-related activity in the following table: + +| Delegate / Service Provider | Gas Used (ETH) | +| --------------------------- | -------------- | +| ACI | 3.365 | +| Tokenlogic | 0.586 | +| Michigan | 0.276 | +| Wintermute | 0.2518 | +| LBS | 0.031 | +| StableLabs | 0.0342 | +| ezr3al | 0.3833 | +| Total | 4.9273 | + +Note Michigan has rebranded as Arana as can be seen in the forum [here](https://governance.aave.com/t/arfc-orbit-program-renewal/16550/6). + +## Specification + +- Create GHO streams for Orbit participants of 15,000 GHO for 90 days as detailed in the table above +- Transfer GHO for Orbit participants of 5,000 as retroactive payment as detailed in the table above +- Transfer ETH to delegates/service providers as detailed in the table above + +## References + +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.t.sol) +- [Snapshot](https://snapshot.org/#/aave.eth/proposal/0x412b38c7a0cf1840b102e28ea7ef0373e3ab4b9544873e8cc1544972b777d9a1) +- [Discussion](https://governance.aave.com/t/arfc-orbit-program-renewal/16550) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgramData.sol b/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgramData.sol new file mode 100644 index 000000000..822741a64 --- /dev/null +++ b/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgramData.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +library OrbitProgramData { + struct GasUsage { + address account; + uint256 usage; + } + + uint256 public constant STREAM_DURATION = 90 days; + uint256 public constant RETRO_PAYMENT = 5_000 ether; + uint256 public constant STREAM_AMOUNT = 15_000 ether; + uint256 public constant TOTAL_WETH_REBATE = 4.9273 ether; + address public constant EZREAL = 0x8659D0BB123Da6D16D9394C7838BA286c2207d0E; + address public constant STABLE_LABS = 0xECC2a9240268BC7a26386ecB49E1Befca2706AC9; + address public constant LBS = 0x8b37a5Af68D315cf5A64097D96621F64b5502a22; + address public constant MICHIGAN = 0x0579A616689f7ed748dC07692A3F150D44b0CA09; + address public constant ACI = 0x57ab7ee15cE5ECacB1aB84EE42D5A9d0d8112922; + address public constant TOKEN_LOGIC = 0x2cc1ADE245020FC5AAE66Ad443e1F66e01c54Df1; + address public constant WINTERMUTE = 0xB933AEe47C438f22DE0747D57fc239FE37878Dd1; + + function getGasUsageData() internal pure returns (GasUsage[] memory) { + GasUsage[] memory usage = new GasUsage[](7); + usage[0] = GasUsage(ACI, 3.365 ether); + usage[1] = GasUsage(TOKEN_LOGIC, 0.586 ether); + usage[2] = GasUsage(MICHIGAN, 0.276 ether); + usage[3] = GasUsage(WINTERMUTE, 0.2518 ether); + usage[4] = GasUsage(LBS, 0.031 ether); + usage[5] = GasUsage(STABLE_LABS, 0.0342 ether); + usage[6] = GasUsage(EZREAL, 0.3833 ether); + + return usage; + } + + function getOrbitAddresses() internal pure returns (address[] memory) { + address[] memory streamAddresses = new address[](4); + streamAddresses[0] = EZREAL; + streamAddresses[1] = STABLE_LABS; + streamAddresses[2] = MICHIGAN; + streamAddresses[3] = LBS; + + return streamAddresses; + } +} diff --git a/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram_20240220.s.sol b/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram_20240220.s.sol new file mode 100644 index 000000000..e785b0d07 --- /dev/null +++ b/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram_20240220.s.sol @@ -0,0 +1,55 @@ +// 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_OrbitProgram_20240220} from './AaveV3Ethereum_OrbitProgram_20240220.sol'; + +/** + * @dev Deploy Ethereum + * deploy-command: make deploy-ledger contract=src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram_20240220.s.sol:DeployEthereum chain=mainnet + * verify-command: npx catapulta-verify -b broadcast/OrbitProgram_20240220.s.sol/1/run-latest.json + */ +contract DeployEthereum is EthereumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Ethereum_OrbitProgram_20240220).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/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram_20240220.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(AaveV3Ethereum_OrbitProgram_20240220).creationCode + ); + payloads[0] = GovV3Helpers.buildMainnetPayload(vm, actionsEthereum); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal( + vm, + payloads, + GovV3Helpers.ipfsHashFile(vm, 'src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram.md') + ); + } +} diff --git a/src/20240220_AaveV3Ethereum_OrbitProgram/config.ts b/src/20240220_AaveV3Ethereum_OrbitProgram/config.ts new file mode 100644 index 000000000..ed4736014 --- /dev/null +++ b/src/20240220_AaveV3Ethereum_OrbitProgram/config.ts @@ -0,0 +1,14 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + pools: ['AaveV3Ethereum'], + title: 'Orbit Program', + shortName: 'OrbitProgram', + date: '20240220', + author: 'karpatkey_TokenLogic_ACI', + discussion: 'https://governance.aave.com/t/arfc-orbit-program-renewal/16550', + snapshot: + 'https://snapshot.org/#/aave.eth/proposal/0x412b38c7a0cf1840b102e28ea7ef0373e3ab4b9544873e8cc1544972b777d9a1', + }, + poolOptions: {AaveV3Ethereum: {configs: {OTHERS: {}}, cache: {blockNumber: 19273121}}}, +}; From 8a97e46366b36efccbe0e5e81d90e036de70b7ec Mon Sep 17 00:00:00 2001 From: Cache bot Date: Fri, 23 Feb 2024 11:49:00 +0000 Subject: [PATCH 4/6] fix(cache): automated cache update [skip ci] --- src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram.md b/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram.md index 991a672f3..f8f19c6ad 100644 --- a/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram.md +++ b/src/20240220_AaveV3Ethereum_OrbitProgram/OrbitProgram.md @@ -46,8 +46,8 @@ Note Michigan has rebranded as Arana as can be seen in the forum [here](https:// ## References -- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.sol) -- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.t.sol) +- Implementation: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/4c487a2f49adf301e08c80313dc3f946709c29f3/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.sol) +- Tests: [AaveV3Ethereum](https://github.com/bgd-labs/aave-proposals-v3/blob/4c487a2f49adf301e08c80313dc3f946709c29f3/src/20240220_AaveV3Ethereum_OrbitProgram/AaveV3Ethereum_OrbitProgram_20240220.t.sol) - [Snapshot](https://snapshot.org/#/aave.eth/proposal/0x412b38c7a0cf1840b102e28ea7ef0373e3ab4b9544873e8cc1544972b777d9a1) - [Discussion](https://governance.aave.com/t/arfc-orbit-program-renewal/16550) From 1b85d9fb8fd2175b49da486fc6db3f8b752349cc Mon Sep 17 00:00:00 2001 From: Fermin 'Piscu' Carranza Date: Fri, 23 Feb 2024 06:53:33 -0500 Subject: [PATCH 5/6] Aave Protocol Embassy ARB Token Transfer (#220) * feat: add APE payload * chore: update readme * Update src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy.md Co-authored-by: Harsh Pandey --------- Co-authored-by: Harsh Pandey --- .../AaveProtocolEmbassy.md | 33 +++++++++++ .../AaveProtocolEmbassy_20240220.s.sol | 58 +++++++++++++++++++ ...3Arbitrum_AaveProtocolEmbassy_20240220.sol | 25 ++++++++ ...rbitrum_AaveProtocolEmbassy_20240220.t.sol | 46 +++++++++++++++ .../config.ts | 14 +++++ 5 files changed, 176 insertions(+) create mode 100644 src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy.md create mode 100644 src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy_20240220.s.sol create mode 100644 src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.sol create mode 100644 src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.t.sol create mode 100644 src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/config.ts diff --git a/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy.md b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy.md new file mode 100644 index 000000000..7f8856776 --- /dev/null +++ b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy.md @@ -0,0 +1,33 @@ +--- +title: "Aave Protocol Embassy" +author: "karpatkey_TokenLogic_ACI" +discussions: "https://governance.aave.com/t/arfc-establishing-the-aave-protocol-embassy-ape/16445" +snapshot: "https://snapshot.org/#/aave.eth/proposal/0xe9da0e50526a98a55aae743f44afc21a86076a12184a6c6c9022aa63dcb0be73" +--- + +## Simple Summary + +Transfer all available ARB on Aave V3 Arbitrum to the Aave Protocol Embassy multi-sig. + +## Motivation + +The Aave DAO possesses significant voting power in various governance tokens. However, the current structure of the collector contract hinders direct participation in other DAOs' governance. To effectively leverage this power and actively participate in pivotal governance decisions, such as LTIPs on Arbitrum, the creation of APE is essential. + +This will allow the Aave DAO to have a meta-governance embassy represented by Aave DAO service providers and significant delegates. + +## Specification + +The multi-sig address was commented [here](https://governance.aave.com/t/arfc-establishing-the-aave-protocol-embassy-ape/16445/9). + +- Transfer all available ARB on the Collector on Arbitrum to SAFE Multi-sig 0xa9e777D56C0Ad861f6a03967E080e767ad8D39b6 + +## References + +- Implementation: [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.sol) +- Tests: [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.t.sol) +- [Snapshot](https://snapshot.org/#/aave.eth/proposal/0xe9da0e50526a98a55aae743f44afc21a86076a12184a6c6c9022aa63dcb0be73) +- [Discussion](https://governance.aave.com/t/arfc-establishing-the-aave-protocol-embassy-ape/16445) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy_20240220.s.sol b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy_20240220.s.sol new file mode 100644 index 000000000..7381110f4 --- /dev/null +++ b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy_20240220.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, ArbitrumScript} from 'aave-helpers/ScriptUtils.sol'; +import {AaveV3Arbitrum_AaveProtocolEmbassy_20240220} from './AaveV3Arbitrum_AaveProtocolEmbassy_20240220.sol'; + +/** + * @dev Deploy Arbitrum + * deploy-command: make deploy-ledger contract=src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy_20240220.s.sol:DeployArbitrum chain=arbitrum + * verify-command: npx catapulta-verify -b broadcast/AaveProtocolEmbassy_20240220.s.sol/42161/run-latest.json + */ +contract DeployArbitrum is ArbitrumScript { + function run() external broadcast { + // deploy payloads + address payload0 = GovV3Helpers.deployDeterministic( + type(AaveV3Arbitrum_AaveProtocolEmbassy_20240220).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/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy_20240220.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 actionsArbitrum = new IPayloadsControllerCore.ExecutionAction[](1); + actionsArbitrum[0] = GovV3Helpers.buildAction( + type(AaveV3Arbitrum_AaveProtocolEmbassy_20240220).creationCode + ); + payloads[0] = GovV3Helpers.buildArbitrumPayload(vm, actionsArbitrum); + + // create proposal + vm.startBroadcast(); + GovV3Helpers.createProposal( + vm, + payloads, + GovV3Helpers.ipfsHashFile( + vm, + 'src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy.md' + ) + ); + } +} diff --git a/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.sol b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.sol new file mode 100644 index 000000000..446c5bdd9 --- /dev/null +++ b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; +import {AaveV3Arbitrum, AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {IProposalGenericExecutor} from 'aave-helpers/interfaces/IProposalGenericExecutor.sol'; + +/** + * @title Aave Protocol Embassy + * @author karpatkey_TokenLogic_ACI + * - Snapshot: https://snapshot.org/#/aave.eth/proposal/0xe9da0e50526a98a55aae743f44afc21a86076a12184a6c6c9022aa63dcb0be73 + * - Discussion: https://governance.aave.com/t/arfc-establishing-the-aave-protocol-embassy-ape/16445 + */ +contract AaveV3Arbitrum_AaveProtocolEmbassy_20240220 is IProposalGenericExecutor { + address public constant SAFE = 0xa9e777D56C0Ad861f6a03967E080e767ad8D39b6; + + function execute() external { + AaveV3Arbitrum.COLLECTOR.transfer( + AaveV3ArbitrumAssets.ARB_UNDERLYING, + SAFE, + IERC20(AaveV3ArbitrumAssets.ARB_UNDERLYING).balanceOf(address(AaveV3Arbitrum.COLLECTOR)) + ); + } +} diff --git a/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.t.sol b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.t.sol new file mode 100644 index 000000000..12d49c418 --- /dev/null +++ b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.t.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; + +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; +import {AaveV3Arbitrum, AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol'; +import {ProtocolV3TestBase} from 'aave-helpers/ProtocolV3TestBase.sol'; + +import {AaveV3Arbitrum_AaveProtocolEmbassy_20240220} from './AaveV3Arbitrum_AaveProtocolEmbassy_20240220.sol'; + +/** + * @dev Test for AaveV3Arbitrum_AaveProtocolEmbassy_20240220 + * command: make test-contract filter=AaveV3Arbitrum_AaveProtocolEmbassy_20240220 + */ +contract AaveV3Arbitrum_AaveProtocolEmbassy_20240220_Test is ProtocolV3TestBase { + AaveV3Arbitrum_AaveProtocolEmbassy_20240220 internal proposal; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('arbitrum'), 182366085); + proposal = new AaveV3Arbitrum_AaveProtocolEmbassy_20240220(); + } + + /** + * @dev executes the generic test suite including e2e and config snapshots + */ + function test_defaultProposalExecution() public { + uint256 balanceCollectorBefore = IERC20(AaveV3ArbitrumAssets.ARB_UNDERLYING).balanceOf( + address(AaveV3Arbitrum.COLLECTOR) + ); + + assertEq(IERC20(AaveV3ArbitrumAssets.ARB_UNDERLYING).balanceOf(proposal.SAFE()), 0); + + executePayload(vm, address(proposal)); + + assertEq( + IERC20(AaveV3ArbitrumAssets.ARB_UNDERLYING).balanceOf(address(AaveV3Arbitrum.COLLECTOR)), + 0 + ); + assertEq( + IERC20(AaveV3ArbitrumAssets.ARB_UNDERLYING).balanceOf(proposal.SAFE()), + balanceCollectorBefore + ); + } +} diff --git a/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/config.ts b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/config.ts new file mode 100644 index 000000000..48405f590 --- /dev/null +++ b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/config.ts @@ -0,0 +1,14 @@ +import {ConfigFile} from '../../generator/types'; +export const config: ConfigFile = { + rootOptions: { + pools: ['AaveV3Arbitrum'], + title: 'Aave Protocol Embassy', + shortName: 'AaveProtocolEmbassy', + date: '20240220', + author: 'karpatkey_TokenLogic_ACI', + discussion: + 'https://governance.aave.com/t/arfc-establishing-the-aave-protocol-embassy-ape/16445', + snapshot: 'https://governance.aave.com/t/arfc-establishing-the-aave-protocol-embassy-ape/16445', + }, + poolOptions: {AaveV3Arbitrum: {configs: {OTHERS: {}}, cache: {blockNumber: 182860683}}}, +}; From 113ba40d09cf396e22d625d88a816d36bcf48269 Mon Sep 17 00:00:00 2001 From: Cache bot Date: Fri, 23 Feb 2024 11:54:04 +0000 Subject: [PATCH 6/6] fix(cache): automated cache update [skip ci] --- .../AaveProtocolEmbassy.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy.md b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy.md index 7f8856776..2ba2b12a2 100644 --- a/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy.md +++ b/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveProtocolEmbassy.md @@ -23,8 +23,8 @@ The multi-sig address was commented [here](https://governance.aave.com/t/arfc-es ## References -- Implementation: [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.sol) -- Tests: [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/main/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.t.sol) +- Implementation: [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/1b85d9fb8fd2175b49da486fc6db3f8b752349cc/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.sol) +- Tests: [AaveV3Arbitrum](https://github.com/bgd-labs/aave-proposals-v3/blob/1b85d9fb8fd2175b49da486fc6db3f8b752349cc/src/20240220_AaveV3Arbitrum_AaveProtocolEmbassy/AaveV3Arbitrum_AaveProtocolEmbassy_20240220.t.sol) - [Snapshot](https://snapshot.org/#/aave.eth/proposal/0xe9da0e50526a98a55aae743f44afc21a86076a12184a6c6c9022aa63dcb0be73) - [Discussion](https://governance.aave.com/t/arfc-establishing-the-aave-protocol-embassy-ape/16445)