diff --git a/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015.sol b/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015.sol new file mode 100644 index 00000000..5c2d658f --- /dev/null +++ b/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {AaveV2Ethereum} from 'aave-address-book/AaveV2Ethereum.sol'; + +/** + * @title TokenLogic Hohmann Transfer + * @author Marc Zeller - Aave-Chan Initiative + * - Snapshot: https://snapshot.org/#/aave.eth/proposal/0x89c3286743dc99b961d40d948c9507fe1005bc6fedf7e34ffb3d1265e0bc4bff + * - Discussion: https://governance.aave.com/t/arfc-tokenlogic-hohmann-transfer/15051 + */ +contract AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015 { + address public constant TOKEN_LOGIC = 0x3e4A9f478C0c13A15137Fc81e9d8269F127b4B40; + address public constant GHO = AaveV3EthereumAssets.GHO_UNDERLYING; + uint256 public constant STREAM_AMOUNT = 15000e18; + uint256 public constant STREAM_DURATION = 90 days; + uint256 public constant ACTUAL_STREAM_AMOUNT_GHO = + (STREAM_AMOUNT / STREAM_DURATION) * STREAM_DURATION; + + function execute() external { + AaveV2Ethereum.COLLECTOR.createStream( + TOKEN_LOGIC, + ACTUAL_STREAM_AMOUNT_GHO, + GHO, + block.timestamp, + block.timestamp + STREAM_DURATION + ); + } +} diff --git a/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015.t.sol b/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015.t.sol new file mode 100644 index 00000000..05c57d4c --- /dev/null +++ b/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015.t.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity ^0.8.16; + +// testing libraries +import 'forge-std/Test.sol'; + +// contract dependencies +import {AaveGovernanceV2} from 'aave-address-book/AaveGovernanceV2.sol'; +import {AaveV2Ethereum, ICollector} from 'aave-address-book/AaveV2Ethereum.sol'; +import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {AaveMisc, IStreamable} from 'aave-address-book/AaveMisc.sol'; +import {AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015} from './AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015.sol'; +import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; +import {GovHelpers} from 'aave-helpers/GovHelpers.sol'; + +// make test-contract filter=AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015 + +contract AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015Test is Test { + IERC20 public constant GHO = IERC20(AaveV3EthereumAssets.GHO_UNDERLYING); + + address GHO_WHALE = 0xE831C8903de820137c13681E78A5780afDdf7697; + + ICollector public immutable AAVE_COLLECTOR = AaveV2Ethereum.COLLECTOR; + + IStreamable public immutable STREAMABLE_AAVE_COLLECTOR = + IStreamable(address(AaveV2Ethereum.COLLECTOR)); + + uint256 public constant STREAM_AMOUNT = 15_000 * 1e18; + uint256 public constant STREAM_DURATION = 90 days; + uint256 public constant actualAmountGHO = (STREAM_AMOUNT / STREAM_DURATION) * STREAM_DURATION; + + address public constant TOKEN_LOGIC = 0x3e4A9f478C0c13A15137Fc81e9d8269F127b4B40; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 18211914); + } + + function testExecute() public { + + // transfer GHO to COLLECTOR + + vm.startPrank(GHO_WHALE); + GHO.transfer(address(AAVE_COLLECTOR), 15_000 * 1e18); + vm.stopPrank(); + + // Capturing next Stream IDs before proposal is executed + uint256 nextCollectorStreamID = STREAMABLE_AAVE_COLLECTOR.getNextStreamId(); + + // execute proposal + GovHelpers.executePayload( + vm, + address(new AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015()), + AaveGovernanceV2.SHORT_EXECUTOR + ); + + uint256 initialBalance = GHO.balanceOf(TOKEN_LOGIC); + + ( + address senderGHO, + address recipientGHO, + uint256 depositGHO, + address tokenAddressGHO, + uint256 startTimeGHO, + uint256 stopTimeGHO, + uint256 remainingBalanceGHO, + uint256 rateGHO + ) = STREAMABLE_AAVE_COLLECTOR.getStream(nextCollectorStreamID); + + assertEq(senderGHO, address(AAVE_COLLECTOR)); + assertEq(recipientGHO, TOKEN_LOGIC); + assertEq(depositGHO, actualAmountGHO); + assertEq(tokenAddressGHO, address(GHO)); + assertEq(stopTimeGHO - startTimeGHO, STREAM_DURATION); + assertEq(remainingBalanceGHO, actualAmountGHO); + + uint256 expectedRateGHO = actualAmountGHO / STREAM_DURATION; + assertEq( + rateGHO, + expectedRateGHO, + 'The rate of GHO streaming does not match the expected rate.' + ); + + // Checking if the recipient can withdraw from streams + vm.startPrank(TOKEN_LOGIC); + vm.warp(block.timestamp + STREAM_DURATION + 1 days); + + STREAMABLE_AAVE_COLLECTOR.withdrawFromStream(nextCollectorStreamID, actualAmountGHO); + uint256 nextBalance = GHO.balanceOf(TOKEN_LOGIC); + assertEq(initialBalance, nextBalance - actualAmountGHO); + } +} diff --git a/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_TokenLogicHohmannTransfer_20231015.s.sol b/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_TokenLogicHohmannTransfer_20231015.s.sol new file mode 100644 index 00000000..b8cd0b31 --- /dev/null +++ b/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_TokenLogicHohmannTransfer_20231015.s.sol @@ -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 {AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015} from './AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015.sol'; + +/** + * @dev Deploy AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015 + * command: make deploy-ledger contract=src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_TokenLogicHohmannTransfer_20231015.s.sol:DeployEthereum chain=mainnet + */ +contract DeployEthereum is EthereumScript { + function run() external broadcast { + new AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015(); + } +} + +/** + * @dev Create Proposal + * command: make deploy-ledger contract=src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_TokenLogicHohmannTransfer_20231015.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(0xd446384e77B1386da0B53f3FbfC7E3E55552a89E); + GovHelpers.createProposal( + payloads, + GovHelpers.ipfsHashFile( + vm, + 'src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/TokenLogicHohmannTransfer.md' + ) + ); + } +} diff --git a/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/TokenLogicHohmannTransfer.md b/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/TokenLogicHohmannTransfer.md new file mode 100644 index 00000000..bf0c34b9 --- /dev/null +++ b/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/TokenLogicHohmannTransfer.md @@ -0,0 +1,40 @@ +--- +title: "TokenLogic Hohmann Transfer" +author: "Marc Zeller - Aave-Chan Initiative" +discussions: "https://governance.aave.com/t/arfc-tokenlogic-hohmann-transfer/15051" +--- + +## Simple Summary + +This AIP proposes the inclusion of TokenLogic in the "Orbit" delegate platform initiative for a period of 90 days, with a monthly compensation of 5k GHO and total budget of 15k GHO. + +## Motivation + +TokenLogic has been an active and valuable participant in the Aave ecosystem. While they were initially eligible and considered for the Orbit program, they opted to explore the possibility of becoming a service provider to the DAO. However, given their recent decision to re-organize internally and re-evaluate their proposed scope as a service provider, it's appropriate to reconsider their inclusion in the Orbit program. + +## Specification + +### TokenLogic Inclusion + +- TokenLogic will be recognized as an official delegate within the Orbit program for a period of 90 days. +- They will receive a monthly compensation of 5k GHO, totaling 15k GHO over the three-month period. + +### Funding and Emissions + +TokenLogic's compensation will be in line with the Orbit program's guidelines, ensuring fairness and consistency with other delegates. + +### Responsibilities and Conditions + +- TokenLogic will actively participate in Aave governance, representing their delegators and contributing to the protocol's growth. +- If TokenLogic presents and successfully passes a proposal to become a service provider to the DAO, their Orbit funding stream will be terminated to prevent double compensation. + +## References + +- Implementation: [Ethereum](https://github.com/bgd-labs/aave-proposals/blob/main/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015.sol) +- Tests: [Ethereum](https://github.com/bgd-labs/aave-proposals/blob/main/src/20231015_AaveV3_Eth_TokenLogicHohmannTransfer/AaveV3_Ethereum_TokenLogicHohmannTransfer_20231015.t.sol) +- [Snapshot](https://snapshot.org/#/aave.eth/proposal/0x89c3286743dc99b961d40d948c9507fe1005bc6fedf7e34ffb3d1265e0bc4bff) +- [Discussion](https://governance.aave.com/t/arfc-tokenlogic-hohmann-transfer/15051) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).