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

update #3

Merged
merged 6 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .assets/a2ff7054b21a6d938826bbea32b5e589c6a0c8f7.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions .assets/c73865a243e2110291617da971e6614d404cd2c5.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
## Reserve changes

### Reserves added

#### USDe ([0x4c9EDD5852cd905f086C759E8383e09bff1E68B3](https://etherscan.io/address/0x4c9EDD5852cd905f086C759E8383e09bff1E68B3))

| description | value |
| --- | --- |
| decimals | 18 |
| isActive | true |
| isFrozen | false |
| supplyCap | 80,000,000 USDe |
| borrowCap | 72,000,000 USDe |
| debtCeiling | 40,000,000 $ |
| isSiloed | false |
| isFlashloanable | true |
| eModeCategory | 0 |
| oracle | [0x55B6C4D3E8A27b8A1F5a263321b602e0fdEEcC17](https://etherscan.io/address/0x55B6C4D3E8A27b8A1F5a263321b602e0fdEEcC17) |
| oracleDecimals | 8 |
| oracleDescription | Capped USDe / USD |
| oracleLatestAnswer | 1.00079999 |
| usageAsCollateralEnabled | true |
| ltv | 72 % |
| liquidationThreshold | 75 % |
| liquidationBonus | 8.5 % |
| liquidationProtocolFee | 10 % |
| reserveFactor | 25 % |
| aToken | [0x4F5923Fc5FD4a93352581b38B7cD26943012DECF](https://etherscan.io/address/0x4F5923Fc5FD4a93352581b38B7cD26943012DECF) |
| aTokenImpl | [0x7EfFD7b47Bfd17e52fB7559d3f924201b9DbfF3d](https://etherscan.io/address/0x7EfFD7b47Bfd17e52fB7559d3f924201b9DbfF3d) |
| variableDebtToken | [0x015396E1F286289aE23a762088E863b3ec465145](https://etherscan.io/address/0x015396E1F286289aE23a762088E863b3ec465145) |
| variableDebtTokenImpl | [0xaC725CB59D16C81061BDeA61041a8A5e73DA9EC6](https://etherscan.io/address/0xaC725CB59D16C81061BDeA61041a8A5e73DA9EC6) |
| stableDebtToken | [0x43Cc8AD0c223b38D9c04802bB184A2D97e497D38](https://etherscan.io/address/0x43Cc8AD0c223b38D9c04802bB184A2D97e497D38) |
| stableDebtTokenImpl | [0x15C5620dfFaC7c7366EED66C20Ad222DDbB1eD57](https://etherscan.io/address/0x15C5620dfFaC7c7366EED66C20Ad222DDbB1eD57) |
| borrowingEnabled | true |
| stableBorrowRateEnabled | false |
| isBorrowableInIsolation | true |
| interestRateStrategy | [0x4011fcd421b9E90f131B164EC1d162DBE269621C](https://etherscan.io/address/0x4011fcd421b9E90f131B164EC1d162DBE269621C) |
| liquidityIndex | 1 |
| variableBorrowIndex | 1 |
| aTokenName | Aave Ethereum USDe |
| aTokenSymbol | aEthUSDe |
| currentLiquidityRate | 0 % |
| currentVariableBorrowRate | 0 % |
| isPaused | false |
| stableDebtTokenName | Aave Ethereum Stable Debt USDe |
| stableDebtTokenSymbol | stableDebtEthUSDe |
| variableDebtTokenName | Aave Ethereum Variable Debt USDe |
| variableDebtTokenSymbol | variableDebtEthUSDe |
| optimalUsageRatio | 80 % |
| maxExcessStableToTotalDebtRatio | 100 % |
| maxExcessUsageRatio | 20 % |
| optimalStableToTotalDebtRatio | 0 % |
| baseVariableBorrowRate | 0 % |
| variableRateSlope1 | 9 % |
| variableRateSlope2 | 75 % |
| baseStableBorrowRate | 9 % |
| stableRateSlope1 | 9 % |
| stableRateSlope2 | 75 % |
| interestRate | ![ir](/.assets/a2ff7054b21a6d938826bbea32b5e589c6a0c8f7.svg) |


## Raw diff

```json
{
"reserves": {
"0x4c9EDD5852cd905f086C759E8383e09bff1E68B3": {
"from": null,
"to": {
"aToken": "0x4F5923Fc5FD4a93352581b38B7cD26943012DECF",
"aTokenImpl": "0x7EfFD7b47Bfd17e52fB7559d3f924201b9DbfF3d",
"aTokenName": "Aave Ethereum USDe",
"aTokenSymbol": "aEthUSDe",
"borrowCap": 72000000,
"borrowingEnabled": true,
"currentLiquidityRate": 0,
"currentVariableBorrowRate": 0,
"debtCeiling": 4000000000,
"decimals": 18,
"eModeCategory": 0,
"interestRateStrategy": "0x4011fcd421b9E90f131B164EC1d162DBE269621C",
"isActive": true,
"isBorrowableInIsolation": true,
"isFlashloanable": true,
"isFrozen": false,
"isPaused": false,
"isSiloed": false,
"liquidationBonus": 10850,
"liquidationProtocolFee": 1000,
"liquidationThreshold": 7500,
"liquidityIndex": "1000000000000000000000000000",
"ltv": 7200,
"oracle": "0x55B6C4D3E8A27b8A1F5a263321b602e0fdEEcC17",
"oracleDecimals": 8,
"oracleDescription": "Capped USDe / USD",
"oracleLatestAnswer": 100079999,
"reserveFactor": 2500,
"stableBorrowRateEnabled": false,
"stableDebtToken": "0x43Cc8AD0c223b38D9c04802bB184A2D97e497D38",
"stableDebtTokenImpl": "0x15C5620dfFaC7c7366EED66C20Ad222DDbB1eD57",
"stableDebtTokenName": "Aave Ethereum Stable Debt USDe",
"stableDebtTokenSymbol": "stableDebtEthUSDe",
"supplyCap": 80000000,
"symbol": "USDe",
"underlying": "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3",
"usageAsCollateralEnabled": true,
"variableBorrowIndex": "1000000000000000000000000000",
"variableDebtToken": "0x015396E1F286289aE23a762088E863b3ec465145",
"variableDebtTokenImpl": "0xaC725CB59D16C81061BDeA61041a8A5e73DA9EC6",
"variableDebtTokenName": "Aave Ethereum Variable Debt USDe",
"variableDebtTokenSymbol": "variableDebtEthUSDe"
}
}
},
"strategies": {
"0x4c9EDD5852cd905f086C759E8383e09bff1E68B3": {
"from": null,
"to": {
"address": "0x4011fcd421b9E90f131B164EC1d162DBE269621C",
"baseStableBorrowRate": "90000000000000000000000000",
"baseVariableBorrowRate": 0,
"maxExcessStableToTotalDebtRatio": "1000000000000000000000000000",
"maxExcessUsageRatio": "200000000000000000000000000",
"optimalStableToTotalDebtRatio": 0,
"optimalUsageRatio": "800000000000000000000000000",
"stableRateSlope1": "90000000000000000000000000",
"stableRateSlope2": "750000000000000000000000000",
"variableRateSlope1": "90000000000000000000000000",
"variableRateSlope2": "750000000000000000000000000"
}
}
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
## Reserve changes

### Reserves altered

#### sUSD ([0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9](https://optimistic.etherscan.io/address/0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9))

| description | value before | value after |
| --- | --- | --- |
| isFrozen | true | false |
| supplyCap | 20,000,000 sUSD | 7,000,000 sUSD |
| borrowCap | 13,000,000 sUSD | 5,600,000 sUSD |
| ltv | 0 % | 60 % |
| liquidationThreshold | 75 % | 70 % |


## Raw diff

```json
{
"eModes": {
"1": {
"liquidationThreshold": {
"from": 9500,
"to": 9300
},
"ltv": {
"from": 9300,
"to": 9000
}
}
},
"reserves": {
"0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9": {
"borrowCap": {
"from": 13000000,
"to": 5600000
},
"isFrozen": {
"from": true,
"to": false
},
"liquidationThreshold": {
"from": 7500,
"to": 7000
},
"ltv": {
"from": 0,
"to": 6000
},
"supplyCap": {
"from": 20000000,
"to": 7000000
}
}
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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 Renewal
* @author Aave Chan Initiative
* - Snapshot: "https://snapshot.org/#/aave.eth/proposal/0x4a10e2a8ca95024d7cf0791aa82ed262c816ff0ee78bc2f3ab3487e70d731361"
* - Discussion: https://governance.aave.com/t/arfc-orbit-program-renewal-may-2024/17683
*/
contract AaveV3Ethereum_OrbitProgramRenewal_20240513 is IProposalGenericExecutor {
error EthTransferFailed(address account);
function execute() external {
// custom code goes here
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.createStream(
orbitAddresses[i],
actualStreamAmount,
AaveV3EthereumAssets.GHO_UNDERLYING,
block.timestamp,
block.timestamp + OrbitProgramData.STREAM_DURATION
);
}
}
receive() external payable {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// 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 'forge-std/Test.sol';
import {ProtocolV3TestBase, ReserveConfig} from 'aave-helpers/ProtocolV3TestBase.sol';
import {AaveV3Ethereum_OrbitProgramRenewal_20240513} from './AaveV3Ethereum_OrbitProgramRenewal_20240513.sol';

import {OrbitProgramData} from './OrbitProgramData.sol';
/**
* @dev Test for AaveV3Ethereum_OrbitProgramRenewal_20240513
* command: FOUNDRY_PROFILE=mainnet forge test --match-path=src/20240513_AaveV3Ethereum_OrbitProgramRenewal/AaveV3Ethereum_OrbitProgramRenewal_20240513.t.sol -vv
*/
contract AaveV3Ethereum_OrbitProgramRenewal_20240513_Test is ProtocolV3TestBase {
AaveV3Ethereum_OrbitProgramRenewal_20240513 internal proposal;

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

/**
* @dev executes the generic test suite including e2e and config snapshots
*/
function test_defaultProposalExecution() public {
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.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],
'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] + 1
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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 STREAM_AMOUNT = 15_000 ether;
uint256 public constant TOTAL_WETH_REBATE = 3.381 ether;
address public constant EZREAL = 0x8659D0BB123Da6D16D9394C7838BA286c2207d0E;
address public constant STABLE_LABS = 0xECC2a9240268BC7a26386ecB49E1Befca2706AC9;
address public constant SAUCY_BLOCK = 0x08651EeE3b78254653062BA89035b8F8AdF924CE;
address public constant ARETA = 0x8b37a5Af68D315cf5A64097D96621F64b5502a22;

address public constant ACI = 0x57ab7ee15cE5ECacB1aB84EE42D5A9d0d8112922;
address public constant TOKEN_LOGIC = 0x2cc1ADE245020FC5AAE66Ad443e1F66e01c54Df1;

function getGasUsageData() internal pure returns (GasUsage[] memory) {
GasUsage[] memory usage = new GasUsage[](2);
usage[0] = GasUsage(ACI, 2.74 ether);
usage[1] = GasUsage(TOKEN_LOGIC, 0.641 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] = SAUCY_BLOCK;
streamAddresses[3] = ARETA;

return streamAddresses;
}
}
Loading
Loading