Skip to content

Commit 828bb38

Browse files
feat: caps injector (aave-dao#29)
* refactor: edgeRiskStewardRates * feat: add edgeRiskStewardCaps * refactor: abstract rates injector and fix tests * chore: fix comment * feat: caps injector * test: aave steward cap injector * feat: add pause to base injector * test: AaveStewardsInjectorCaps * fix: remove size and test max checkUpkeep gas limit * chore: fix lint * chore: some cleanup * fix: ownableWithGuardian * feat: change market to aToken and change decoding for cap value * feat: use decimals to consume from risk oracle * chore: fix lint * fix: use calldata and add deploy scripts
1 parent be012de commit 828bb38

20 files changed

+1435
-425
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Some assets/oracles can also be restricted on the RiskStewards by calling the `s
7070

7171
With the introduction of Edge Risk Oracles by Chaos Labs, which leverages advanced off-chain infrastructure to deliver real-time risk updates to the Aave protocol via the Risk Oracle, the risk updates for the Aave protocol can be automated in a constrained manner. This can be done by combining the Edge Risk Oracle with the Aave Risk Steward, using a middleware contract `AaveStewardsInjector`.
7272

73-
The Aave Risk Steward contract used for automated updates (called now [EdgeRiskSteward](./src/contracts/EdgeRiskSteward.sol)), has been slightly modified to only allow Interest Rates Updates on the protocol initially as a matter of extra security considerations.
73+
The Aave Risk Steward contract used for automated updates (called now [EdgeRiskStewardRates](./src/contracts/EdgeRiskStewardRates.sol)), has been slightly modified to only allow Interest Rates Updates on the protocol initially as a matter of extra security considerations.
7474

7575
The following is a simple diagram of how the system works as a whole:
7676

scripts/RiskStewardsBase.s.sol

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@ abstract contract RiskStewardsBase is ProtocolV3TestBase {
125125
vm.warp(block.timestamp + uint256(maxTimelock) + 1);
126126
}
127127

128-
if (generateDiffReport)
129-
createConfigurationSnapshot(pre, POOL, true, true, false, false);
128+
if (generateDiffReport) createConfigurationSnapshot(pre, POOL, true, true, false, false);
130129

131130
if (capUpdates.length != 0) {
132131
callDatas[txCount] = abi.encodeWithSelector(IRiskSteward.updateCaps.selector, capUpdates);
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
import 'solidity-utils/contracts/utils/ScriptUtils.sol';
5+
import {MiscArbitrum} from 'aave-address-book/MiscArbitrum.sol';
6+
import {AaveV3Arbitrum, AaveV3ArbitrumAssets} from 'aave-address-book/AaveV3Arbitrum.sol';
7+
import {GovernanceV3Arbitrum} from 'aave-address-book/GovernanceV3Arbitrum.sol';
8+
import {ICreate3Factory} from 'solidity-utils/contracts/create3/interfaces/ICreate3Factory.sol';
9+
import {IOwnable} from 'aave-address-book/common/IOwnable.sol';
10+
import {EdgeRiskStewardCaps, IRiskSteward, IPoolDataProvider, IEngine} from '../../src/contracts/EdgeRiskStewardCaps.sol';
11+
import {AaveStewardInjectorCaps} from '../../src/contracts/AaveStewardInjectorCaps.sol';
12+
13+
library DeployStewardContracts {
14+
address constant EDGE_RISK_ORACLE = 0x861eeAdB55E41f161F31Acb1BFD4c70E3a964Aed;
15+
16+
function _deployRiskStewards(
17+
address poolDataProvider,
18+
address configEngine,
19+
address riskCouncil,
20+
address governance
21+
) internal returns (address) {
22+
address riskSteward = address(
23+
new EdgeRiskStewardCaps(
24+
IPoolDataProvider(poolDataProvider),
25+
IEngine(configEngine),
26+
riskCouncil,
27+
_getRiskConfig()
28+
)
29+
);
30+
IOwnable(riskSteward).transferOwnership(governance);
31+
return riskSteward;
32+
}
33+
34+
function _deployCapsStewardInjector(
35+
bytes32 salt,
36+
address riskSteward,
37+
address owner,
38+
address guardian,
39+
address[] memory whitelistedMarkets
40+
) internal returns (address) {
41+
address stewardInjector = ICreate3Factory(MiscArbitrum.CREATE_3_FACTORY).create(
42+
salt,
43+
abi.encodePacked(
44+
type(AaveStewardInjectorCaps).creationCode,
45+
abi.encode(EDGE_RISK_ORACLE, riskSteward, msg.sender, guardian)
46+
)
47+
);
48+
AaveStewardInjectorCaps(stewardInjector).addMarkets(whitelistedMarkets);
49+
AaveStewardInjectorCaps(stewardInjector).transferOwnership(owner);
50+
return stewardInjector;
51+
}
52+
53+
function _getRiskConfig() internal pure returns (IRiskSteward.Config memory) {
54+
return
55+
IRiskSteward.Config({
56+
ltv: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 25}),
57+
liquidationThreshold: IRiskSteward.RiskParamConfig({
58+
minDelay: 3 days,
59+
maxPercentChange: 25
60+
}),
61+
liquidationBonus: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 50}),
62+
supplyCap: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 30_00}),
63+
borrowCap: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 30_00}),
64+
debtCeiling: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 20_00}),
65+
baseVariableBorrowRate: IRiskSteward.RiskParamConfig({
66+
minDelay: 3 days,
67+
maxPercentChange: 50
68+
}),
69+
variableRateSlope1: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 50}),
70+
variableRateSlope2: IRiskSteward.RiskParamConfig({
71+
minDelay: 3 days,
72+
maxPercentChange: 5_00
73+
}),
74+
optimalUsageRatio: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 3_00}),
75+
priceCapLst: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 5_00}),
76+
priceCapStable: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 50})
77+
});
78+
}
79+
}
80+
81+
// make deploy-ledger contract=scripts/deploy/DeployCapInjector.s.sol:DeployArbitrum chain=arbitrum
82+
contract DeployArbitrum is ArbitrumScript {
83+
address constant GUARDIAN = 0x87dFb794364f2B117C8dbaE29EA622938b3Ce465;
84+
85+
function run() external {
86+
vm.startBroadcast();
87+
bytes32 salt = 'CapsStewardInjector';
88+
address predictedStewardsInjector = ICreate3Factory(MiscArbitrum.CREATE_3_FACTORY)
89+
.predictAddress(msg.sender, salt);
90+
91+
address riskSteward = DeployStewardContracts._deployRiskStewards(
92+
address(AaveV3Arbitrum.AAVE_PROTOCOL_DATA_PROVIDER),
93+
AaveV3Arbitrum.CONFIG_ENGINE,
94+
predictedStewardsInjector,
95+
GovernanceV3Arbitrum.EXECUTOR_LVL_1
96+
);
97+
98+
address[] memory whitelistedMarkets = new address[](15);
99+
whitelistedMarkets[0] = AaveV3ArbitrumAssets.WETH_A_TOKEN;
100+
whitelistedMarkets[1] = AaveV3ArbitrumAssets.USDC_A_TOKEN;
101+
whitelistedMarkets[2] = AaveV3ArbitrumAssets.USDT_A_TOKEN;
102+
whitelistedMarkets[3] = AaveV3ArbitrumAssets.WBTC_A_TOKEN;
103+
whitelistedMarkets[4] = AaveV3ArbitrumAssets.DAI_A_TOKEN;
104+
whitelistedMarkets[5] = AaveV3ArbitrumAssets.weETH_A_TOKEN;
105+
whitelistedMarkets[6] = AaveV3ArbitrumAssets.ARB_A_TOKEN;
106+
whitelistedMarkets[7] = AaveV3ArbitrumAssets.USDCn_A_TOKEN;
107+
whitelistedMarkets[8] = AaveV3ArbitrumAssets.GHO_A_TOKEN;
108+
whitelistedMarkets[9] = AaveV3ArbitrumAssets.LINK_A_TOKEN;
109+
whitelistedMarkets[10] = AaveV3ArbitrumAssets.wstETH_A_TOKEN;
110+
whitelistedMarkets[11] = AaveV3ArbitrumAssets.LUSD_A_TOKEN;
111+
whitelistedMarkets[12] = AaveV3ArbitrumAssets.FRAX_A_TOKEN;
112+
whitelistedMarkets[13] = AaveV3ArbitrumAssets.rETH_A_TOKEN;
113+
whitelistedMarkets[14] = AaveV3ArbitrumAssets.AAVE_A_TOKEN;
114+
115+
DeployStewardContracts._deployCapsStewardInjector(
116+
salt,
117+
riskSteward,
118+
GovernanceV3Arbitrum.EXECUTOR_LVL_1,
119+
GUARDIAN,
120+
whitelistedMarkets
121+
);
122+
vm.stopBroadcast();
123+
}
124+
}

scripts/deploy/DeployInjector.s.sol

Lines changed: 0 additions & 90 deletions
This file was deleted.
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
import 'solidity-utils/contracts/utils/ScriptUtils.sol';
5+
import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol';
6+
import {AaveV3EthereumLido, AaveV3EthereumLidoAssets} from 'aave-address-book/AaveV3EthereumLido.sol';
7+
import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol';
8+
import {ICreate3Factory} from 'solidity-utils/contracts/create3/interfaces/ICreate3Factory.sol';
9+
import {IOwnable} from 'aave-address-book/common/IOwnable.sol';
10+
import {EdgeRiskStewardRates, IRiskSteward, IPoolDataProvider, IEngine} from '../../src/contracts/EdgeRiskStewardRates.sol';
11+
import {AaveStewardInjectorRates} from '../../src/contracts/AaveStewardInjectorRates.sol';
12+
13+
library DeployStewardContracts {
14+
address constant EDGE_RISK_ORACLE = 0x7ABB46C690C52E919687D19ebF89C81A6136C1F2;
15+
16+
function _deployRiskStewards(
17+
address poolDataProvider,
18+
address configEngine,
19+
address riskCouncil,
20+
address governance
21+
) internal returns (address) {
22+
address riskSteward = address(
23+
new EdgeRiskStewardRates(
24+
IPoolDataProvider(poolDataProvider),
25+
IEngine(configEngine),
26+
riskCouncil,
27+
_getRiskConfig()
28+
)
29+
);
30+
IOwnable(riskSteward).transferOwnership(governance);
31+
return riskSteward;
32+
}
33+
34+
function _deployRatesStewardInjector(
35+
bytes32 salt,
36+
address riskSteward,
37+
address owner,
38+
address guardian,
39+
address whitelistedAsset
40+
) internal returns (address) {
41+
address stewardInjector = ICreate3Factory(MiscEthereum.CREATE_3_FACTORY).create(
42+
salt,
43+
abi.encodePacked(
44+
type(AaveStewardInjectorRates).creationCode,
45+
abi.encode(EDGE_RISK_ORACLE, riskSteward, owner, guardian, whitelistedAsset)
46+
)
47+
);
48+
return stewardInjector;
49+
}
50+
51+
function _getRiskConfig() internal pure returns (IRiskSteward.Config memory) {
52+
return
53+
IRiskSteward.Config({
54+
ltv: IRiskSteward.RiskParamConfig({minDelay: 1 days, maxPercentChange: 25}),
55+
liquidationThreshold: IRiskSteward.RiskParamConfig({
56+
minDelay: 1 days,
57+
maxPercentChange: 25
58+
}),
59+
liquidationBonus: IRiskSteward.RiskParamConfig({minDelay: 1 days, maxPercentChange: 50}),
60+
supplyCap: IRiskSteward.RiskParamConfig({minDelay: 1 days, maxPercentChange: 100_00}),
61+
borrowCap: IRiskSteward.RiskParamConfig({minDelay: 1 days, maxPercentChange: 100_00}),
62+
debtCeiling: IRiskSteward.RiskParamConfig({minDelay: 1 days, maxPercentChange: 20_00}),
63+
baseVariableBorrowRate: IRiskSteward.RiskParamConfig({
64+
minDelay: 1 days,
65+
maxPercentChange: 50
66+
}),
67+
variableRateSlope1: IRiskSteward.RiskParamConfig({minDelay: 1 days, maxPercentChange: 50}),
68+
variableRateSlope2: IRiskSteward.RiskParamConfig({
69+
minDelay: 1 days,
70+
maxPercentChange: 5_00
71+
}),
72+
optimalUsageRatio: IRiskSteward.RiskParamConfig({minDelay: 1 days, maxPercentChange: 3_00}),
73+
priceCapLst: IRiskSteward.RiskParamConfig({minDelay: 1 days, maxPercentChange: 5_00}),
74+
priceCapStable: IRiskSteward.RiskParamConfig({minDelay: 1 days, maxPercentChange: 50})
75+
});
76+
}
77+
}
78+
79+
// make deploy-ledger contract=scripts/deploy/DeployRateInjector.s.sol:DeployEthereumLido chain=mainnet
80+
contract DeployEthereumLido is EthereumScript {
81+
address constant GUARDIAN = 0xff37939808EcF199A2D599ef91D699Fb13dab7F7;
82+
83+
function run() external {
84+
vm.startBroadcast();
85+
bytes32 salt = 'StewardInjector';
86+
address predictedStewardsInjector = ICreate3Factory(MiscEthereum.CREATE_3_FACTORY)
87+
.predictAddress(msg.sender, salt);
88+
89+
address riskSteward = DeployStewardContracts._deployRiskStewards(
90+
address(AaveV3EthereumLido.AAVE_PROTOCOL_DATA_PROVIDER),
91+
AaveV3EthereumLido.CONFIG_ENGINE,
92+
predictedStewardsInjector,
93+
GovernanceV3Ethereum.EXECUTOR_LVL_1
94+
);
95+
96+
DeployStewardContracts._deployRatesStewardInjector(
97+
salt,
98+
riskSteward,
99+
GovernanceV3Ethereum.EXECUTOR_LVL_1,
100+
GUARDIAN,
101+
AaveV3EthereumLidoAssets.WETH_UNDERLYING
102+
);
103+
vm.stopBroadcast();
104+
}
105+
}

0 commit comments

Comments
 (0)