Skip to content
This repository was archived by the owner on Dec 9, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from 2 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
94 changes: 94 additions & 0 deletions scripts/deploy/DeployHorizonStewards.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import 'solidity-utils/contracts/utils/ScriptUtils.sol';
import {AaveV3Ethereum} from 'aave-address-book/AaveV3Ethereum.sol';
import {RiskSteward, IRiskSteward} from '../../src/contracts/RiskSteward.sol';

library DeployHorizonRiskStewards {
function _deployRiskStewards(
address pool,
address configEngine,
address riskCouncil,
address governance
) internal returns (address) {
address riskSteward = address(
new RiskSteward(pool, configEngine, riskCouncil, governance, _getRiskConfig())
);
return riskSteward;
}

function _getRiskConfig() internal pure returns (IRiskSteward.Config memory) {
// only collateralConfig will be applied; other config changes will be reverted by the CollateralRiskSteward
return
IRiskSteward.Config({
collateralConfig: IRiskSteward.CollateralConfig({
ltv: IRiskSteward.RiskParamConfig({minDelay: 0, maxPercentChange: type(uint256).max}),
liquidationThreshold: IRiskSteward.RiskParamConfig({
minDelay: 0,
maxPercentChange: type(uint256).max
}),
liquidationBonus: IRiskSteward.RiskParamConfig({
minDelay: 0,
maxPercentChange: type(uint256).max
}),
debtCeiling: IRiskSteward.RiskParamConfig({
minDelay: 0,
maxPercentChange: type(uint256).max
})
}),
eModeConfig: IRiskSteward.EmodeConfig({
ltv: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 50}),
liquidationThreshold: IRiskSteward.RiskParamConfig({
minDelay: 3 days,
maxPercentChange: 10
}),
liquidationBonus: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 50})
}),
rateConfig: IRiskSteward.RateConfig({
baseVariableBorrowRate: IRiskSteward.RiskParamConfig({
minDelay: 3 days,
maxPercentChange: 1_00
}),
variableRateSlope1: IRiskSteward.RiskParamConfig({
minDelay: 3 days,
maxPercentChange: 1_00
}),
variableRateSlope2: IRiskSteward.RiskParamConfig({
minDelay: 3 days,
maxPercentChange: 20_00
}),
optimalUsageRatio: IRiskSteward.RiskParamConfig({
minDelay: 3 days,
maxPercentChange: 3_00
})
}),
capConfig: IRiskSteward.CapConfig({
supplyCap: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 100_00}),
borrowCap: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 100_00})
}),
priceCapConfig: IRiskSteward.PriceCapConfig({
priceCapLst: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 5_00}),
priceCapStable: IRiskSteward.RiskParamConfig({minDelay: 3 days, maxPercentChange: 50}),
discountRatePendle: IRiskSteward.RiskParamConfig({
minDelay: 2 days,
maxPercentChange: 0.025e18
})
})
});
}
}

// make deploy-ledger contract=scripts/deploy/DeployStewards.s.sol:DeployEthereum chain=mainnet
contract DeployEthereum is EthereumScript {
function run() external {
vm.startBroadcast();
DeployHorizonRiskStewards._deployRiskStewards(
address(AaveV3Ethereum.POOL),
AaveV3Ethereum.CONFIG_ENGINE,
address(1), // TODO: advanced multisig
address(1) // TODO: advanced multisig
);
vm.stopBroadcast();
}
}
79 changes: 79 additions & 0 deletions src/contracts/CollateralRiskSteward.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import {IAaveV3ConfigEngine as IEngine} from 'aave-v3-origin/src/contracts/extensions/v3-config-engine/IAaveV3ConfigEngine.sol';
import {IRiskSteward, RiskSteward} from './RiskSteward.sol';

/**
* @title CollateralRiskSteward
* @author Aave labs
* @notice Contract to manage the risk params without bounds on Horizon aave v3 pool:
* This contract can update the following risk params: ltv, liqThreshold, liqBonus, debtCeiling.
*/
contract CollateralRiskSteward is RiskSteward {
/**
* @param pool The aave pool to be controlled by the steward
* @param engine the config engine to be used by the steward
* @param riskCouncil the safe address of the council being able to interact with the steward
* @param owner the owner of the risk steward being able to set configs and mark items as restricted
* @param riskConfig the risk configuration to setup for each individual risk param
*/
constructor(
address pool,
address engine,
address riskCouncil,
address owner,
Config memory riskConfig
) RiskSteward(pool, engine, riskCouncil, owner, riskConfig) {}

/// @inheritdoc IRiskSteward
function updateCaps(
IEngine.CapsUpdate[] calldata capsUpdate
) external virtual override onlyRiskCouncil {
revert UpdateNotAllowed();
}

/// @inheritdoc IRiskSteward
function updateRates(
IEngine.RateStrategyUpdate[] calldata ratesUpdate
) external virtual override onlyRiskCouncil {
revert UpdateNotAllowed();
}

/// @inheritdoc IRiskSteward
function updateEModeCategories(
IEngine.EModeCategoryUpdate[] calldata eModeCategoryUpdates
) external virtual override onlyRiskCouncil {
revert UpdateNotAllowed();
}

/// @inheritdoc IRiskSteward
function updateLstPriceCaps(
PriceCapLstUpdate[] calldata priceCapUpdates
) external virtual override onlyRiskCouncil {
revert UpdateNotAllowed();
}

/// @inheritdoc IRiskSteward
function updateStablePriceCaps(
PriceCapStableUpdate[] calldata priceCapUpdates
) external virtual override onlyRiskCouncil {
revert UpdateNotAllowed();
}

/// @inheritdoc IRiskSteward
function updatePendleDiscountRates(
DiscountRatePendleUpdate[] calldata discountRateUpdates
) external virtual override onlyRiskCouncil {
revert UpdateNotAllowed();
}

function _updateWithinAllowedRange(
uint256 from,
uint256 to,
uint256 maxPercentChange,
bool isChangeRelative
) internal pure virtual override returns (bool) {
return true;
}
}
18 changes: 13 additions & 5 deletions src/contracts/RiskSteward.sol
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,9 @@ contract RiskSteward is Ownable, IRiskSteward {
eModeCategoryUpdates[i].liqBonus == 0
) revert InvalidUpdateToZero();

DataTypes.CollateralConfig memory currentEmodeConfig = POOL.getEModeCategoryCollateralConfig(eModeId);
DataTypes.CollateralConfig memory currentEmodeConfig = POOL.getEModeCategoryCollateralConfig(
eModeId
);

_validateParamUpdate(
ParamUpdateValidationInput({
Expand Down Expand Up @@ -595,7 +597,9 @@ contract RiskSteward is Ownable, IRiskSteward {
* @notice method to update the eMode category params using the config engine and updates the debounce
* @param eModeCategoryUpdates list containing the new eMode category params of the eMode category id
*/
function _updateEModeCategories(IEngine.EModeCategoryUpdate[] calldata eModeCategoryUpdates) internal {
function _updateEModeCategories(
IEngine.EModeCategoryUpdate[] calldata eModeCategoryUpdates
) internal {
for (uint256 i = 0; i < eModeCategoryUpdates.length; i++) {
uint8 eModeId = eModeCategoryUpdates[i].eModeCategory;

Expand Down Expand Up @@ -651,13 +655,17 @@ contract RiskSteward is Ownable, IRiskSteward {
* @notice method to update the pendle oracle discount rate
* @param discountRateUpdate list containing the new discount rate values for the pendle oracles
*/
function _updatePendleDiscountRates(DiscountRatePendleUpdate[] calldata discountRateUpdate) internal {
function _updatePendleDiscountRates(
DiscountRatePendleUpdate[] calldata discountRateUpdate
) internal {
for (uint256 i = 0; i < discountRateUpdate.length; i++) {
address oracle = discountRateUpdate[i].oracle;

_timelocks[oracle].priceCapLastUpdated = uint40(block.timestamp);

IPendlePriceCapAdapter(oracle).setDiscountRatePerYear(discountRateUpdate[i].discountRate.toUint64());
IPendlePriceCapAdapter(oracle).setDiscountRatePerYear(
discountRateUpdate[i].discountRate.toUint64()
);
}
}

Expand Down Expand Up @@ -707,7 +715,7 @@ contract RiskSteward is Ownable, IRiskSteward {
uint256 to,
uint256 maxPercentChange,
bool isChangeRelative
) internal pure returns (bool) {
) internal pure virtual returns (bool) {
// diff denotes the difference between the from and to values, ensuring it is a positive value always
uint256 diff = from > to ? from - to : to - from;

Expand Down
Loading
Loading