diff --git a/scripts/deploy/DeployDiscountRateInjector.s.sol b/scripts/deploy/DeployDiscountRateInjector.s.sol index 67ffc7c..e732d7e 100644 --- a/scripts/deploy/DeployDiscountRateInjector.s.sol +++ b/scripts/deploy/DeployDiscountRateInjector.s.sol @@ -10,6 +10,7 @@ import {GovernanceV3Plasma} from 'aave-address-book/GovernanceV3Plasma.sol'; import {ICreate3Factory} from 'solidity-utils/contracts/create3/interfaces/ICreate3Factory.sol'; import {EdgeRiskStewardDiscountRate, IRiskSteward} from '../../src/contracts/EdgeRiskStewardDiscountRate.sol'; import {AaveStewardInjectorDiscountRate} from '../../src/contracts/AaveStewardInjectorDiscountRate.sol'; +import {GelatoAaveStewardInjectorDiscountRate} from '../../src/contracts/gelato/GelatoAaveStewardInjectorDiscountRate.sol'; library DeployStewardContracts { struct DeployStewardInput { @@ -28,6 +29,7 @@ library DeployStewardContracts { address owner; address guardian; address[] whitelistedMarkets; + bool isGelatoInjector; } function _deployRiskStewards( @@ -42,10 +44,13 @@ library DeployStewardContracts { function _deployDiscountRateStewardInjector( DeployInjectorInput memory input ) internal returns (address) { + bytes memory injectorCode = input.isGelatoInjector ? + type(GelatoAaveStewardInjectorDiscountRate).creationCode : type(AaveStewardInjectorDiscountRate).creationCode; + address stewardInjector = ICreate3Factory(input.create3Factory).create( input.salt, abi.encodePacked( - type(AaveStewardInjectorDiscountRate).creationCode, + injectorCode, abi.encode(input.aaveOracle, input.edgeRiskOracle, input.riskSteward, input.whitelistedMarkets, input.owner, input.guardian) ) ); @@ -97,7 +102,8 @@ contract DeployEthereum is EthereumScript { edgeRiskOracle: EDGE_RISK_ORACLE, owner: GovernanceV3Ethereum.EXECUTOR_LVL_1, guardian: GUARDIAN, - whitelistedMarkets: whitelistedPendleAssets + whitelistedMarkets: whitelistedPendleAssets, + isGelatoInjector: false }) ); vm.stopBroadcast(); @@ -112,7 +118,7 @@ contract DeployPlasma is PlasmaScript { function run() external { vm.startBroadcast(); - bytes32 salt = 'DiscountRateStewardInjector'; + bytes32 salt = 'DiscountRateStewardInjectorV2'; address predictedStewardsInjector = ICreate3Factory(CREATE_3_FACTORY) .predictAddress(msg.sender, salt); @@ -134,7 +140,8 @@ contract DeployPlasma is PlasmaScript { edgeRiskOracle: EDGE_RISK_ORACLE, owner: GovernanceV3Plasma.EXECUTOR_LVL_1, guardian: GUARDIAN, - whitelistedMarkets: new address[](0) + whitelistedMarkets: new address[](0), + isGelatoInjector: true }) ); vm.stopBroadcast(); diff --git a/scripts/deploy/DeployEModeInjector.s.sol b/scripts/deploy/DeployEModeInjector.s.sol index 878ef6a..fa50a43 100644 --- a/scripts/deploy/DeployEModeInjector.s.sol +++ b/scripts/deploy/DeployEModeInjector.s.sol @@ -11,6 +11,7 @@ import {GovernanceV3Plasma} from 'aave-address-book/GovernanceV3Plasma.sol'; import {ICreate3Factory} from 'solidity-utils/contracts/create3/interfaces/ICreate3Factory.sol'; import {EdgeRiskStewardEMode, IRiskSteward} from '../../src/contracts/EdgeRiskStewardEMode.sol'; import {AaveStewardInjectorEMode} from '../../src/contracts/AaveStewardInjectorEMode.sol'; +import {GelatoAaveStewardInjectorEMode} from '../../src/contracts/gelato/GelatoAaveStewardInjectorEMode.sol'; library DeployStewardContracts { function _deployRiskStewards( @@ -32,17 +33,21 @@ library DeployStewardContracts { address edgeRiskOracle, address owner, address guardian, - uint8[] memory whitelistedEModes + uint8[] memory whitelistedEModes, + bool isGelatoInjector ) internal returns (address) { address[] memory whitelistedMarkets = new address[](whitelistedEModes.length); for (uint256 i = 0; i < whitelistedEModes.length; i++) { whitelistedMarkets[i] = address(uint160(whitelistedEModes[i])); } + bytes memory injectorCode = isGelatoInjector ? + type(GelatoAaveStewardInjectorEMode).creationCode : type(AaveStewardInjectorEMode).creationCode; + address stewardInjector = ICreate3Factory(create3Factory).create( salt, abi.encodePacked( - type(AaveStewardInjectorEMode).creationCode, + injectorCode, abi.encode(edgeRiskOracle, riskSteward, whitelistedMarkets, owner, guardian) ) ); @@ -131,7 +136,8 @@ contract DeployEthereum is EthereumScript { EDGE_RISK_ORACLE, GovernanceV3Ethereum.EXECUTOR_LVL_1, GUARDIAN, - whitelistedEModes + whitelistedEModes, + false ); vm.stopBroadcast(); } @@ -145,7 +151,7 @@ contract DeployPlasma is PlasmaScript { function run() external { vm.startBroadcast(); - bytes32 salt = 'EModeStewardInjector'; + bytes32 salt = 'EModeStewardInjectorV2'; address predictedStewardsInjector = ICreate3Factory(CREATE_3_FACTORY) .predictAddress(msg.sender, salt); @@ -165,7 +171,8 @@ contract DeployPlasma is PlasmaScript { EDGE_RISK_ORACLE, GovernanceV3Plasma.EXECUTOR_LVL_1, GUARDIAN, - whitelistedEModes + whitelistedEModes, + true ); vm.stopBroadcast(); } diff --git a/scripts/deploy/DeployRateInjector.s.sol b/scripts/deploy/DeployRateInjector.s.sol index 89cde0c..ac2bd4e 100644 --- a/scripts/deploy/DeployRateInjector.s.sol +++ b/scripts/deploy/DeployRateInjector.s.sol @@ -3,11 +3,16 @@ pragma solidity ^0.8.0; import 'solidity-utils/contracts/utils/ScriptUtils.sol'; import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {MiscLinea} from 'aave-address-book/MiscLinea.sol'; import {AaveV3EthereumLido, AaveV3EthereumLidoAssets} from 'aave-address-book/AaveV3EthereumLido.sol'; +import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; +import {AaveV3Linea, AaveV3LineaAssets} from 'aave-address-book/AaveV3Linea.sol'; import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; +import {GovernanceV3Linea} from 'aave-address-book/GovernanceV3Linea.sol'; import {ICreate3Factory} from 'solidity-utils/contracts/create3/interfaces/ICreate3Factory.sol'; import {EdgeRiskStewardRates, IRiskSteward} from '../../src/contracts/EdgeRiskStewardRates.sol'; import {AaveStewardInjectorRates} from '../../src/contracts/AaveStewardInjectorRates.sol'; +import {GelatoAaveStewardInjectorRates} from '../../src/contracts/gelato/GelatoAaveStewardInjectorRates.sol'; library DeployStewardContracts { function _deployRiskStewards( @@ -22,7 +27,7 @@ library DeployStewardContracts { configEngine, riskCouncil, governance, - _getRiskConfig() + _getSlope2RiskConfig() ) ); return riskSteward; @@ -35,21 +40,29 @@ library DeployStewardContracts { address edgeRiskOracle, address owner, address guardian, - address whitelistedAsset + address[] memory markets, + bool isGelatoInjector ) internal returns (address) { - address[] memory markets = new address[](1); - markets[0] = whitelistedAsset; + bytes memory injectorCode = isGelatoInjector ? + type(GelatoAaveStewardInjectorRates).creationCode : type(AaveStewardInjectorRates).creationCode; address stewardInjector = ICreate3Factory(create3Factory).create( salt, abi.encodePacked( - type(AaveStewardInjectorRates).creationCode, + injectorCode, abi.encode(edgeRiskOracle, riskSteward, markets, owner, guardian) ) ); return stewardInjector; } + function _getSlope2RiskConfig() internal pure returns (IRiskSteward.Config memory) { + IRiskSteward.Config memory config; + config.rateConfig.variableRateSlope2 = IRiskSteward.RiskParamConfig({minDelay: 8 hours, maxPercentChange: 4_00}); + + return config; + } + function _getRiskConfig() internal pure returns (IRiskSteward.Config memory) { return IRiskSteward.Config({ @@ -101,6 +114,47 @@ contract DeployEthereumLido is EthereumScript { GovernanceV3Ethereum.EXECUTOR_LVL_1 ); + address[] memory whitelistedAssets = new address[](1); + whitelistedAssets[0] = AaveV3EthereumLidoAssets.WETH_UNDERLYING; + + DeployStewardContracts._deployRatesStewardInjector( + MiscEthereum.CREATE_3_FACTORY, + salt, + riskSteward, + EDGE_RISK_ORACLE, + GovernanceV3Ethereum.EXECUTOR_LVL_1, + GUARDIAN, + whitelistedAssets, + false + ); + vm.stopBroadcast(); + } +} + +// make deploy-ledger contract=scripts/deploy/DeployRateInjector.s.sol:DeployEthereum chain=mainnet +contract DeployEthereum is EthereumScript { + address constant GUARDIAN = 0xff37939808EcF199A2D599ef91D699Fb13dab7F7; + address constant EDGE_RISK_ORACLE = 0x7ABB46C690C52E919687D19ebF89C81A6136C1F2; + + function run() external { + vm.startBroadcast(); + bytes32 salt = 'StewardInjectorCoreV1'; + address predictedStewardsInjector = ICreate3Factory(MiscEthereum.CREATE_3_FACTORY) + .predictAddress(msg.sender, salt); + + address riskSteward = DeployStewardContracts._deployRiskStewards( + address(AaveV3Ethereum.POOL), + AaveV3Ethereum.CONFIG_ENGINE, + predictedStewardsInjector, + GovernanceV3Ethereum.EXECUTOR_LVL_1 + ); + + address[] memory whitelistedAssets = new address[](4); + whitelistedAssets[0] = AaveV3EthereumAssets.WETH_UNDERLYING; + whitelistedAssets[1] = AaveV3EthereumAssets.USDC_UNDERLYING; + whitelistedAssets[2] = AaveV3EthereumAssets.USDT_UNDERLYING; + whitelistedAssets[3] = AaveV3EthereumAssets.USDe_UNDERLYING; + DeployStewardContracts._deployRatesStewardInjector( MiscEthereum.CREATE_3_FACTORY, salt, @@ -108,7 +162,46 @@ contract DeployEthereumLido is EthereumScript { EDGE_RISK_ORACLE, GovernanceV3Ethereum.EXECUTOR_LVL_1, GUARDIAN, - AaveV3EthereumLidoAssets.WETH_UNDERLYING + whitelistedAssets, + false + ); + vm.stopBroadcast(); + } +} + +// make deploy-ledger contract=scripts/deploy/DeployRateInjector.s.sol:DeployLinea chain=linea +contract DeployLinea is LineaScript { + address constant GUARDIAN = 0x0c28C535CE08345851F150dFC9c737978d726aEc; + address constant EDGE_RISK_ORACLE = 0xa6C229d3a1D4D31708B16C0ad2f14337aE4E7893; + address constant CREATE_3_FACTORY = 0x194a5828Fddf8782e6570149f0B2d31F8a1B89b6; + + function run() external { + vm.startBroadcast(); + bytes32 salt = 'StewardInjectorV3'; + address predictedStewardsInjector = ICreate3Factory(CREATE_3_FACTORY) + .predictAddress(msg.sender, salt); + + address riskSteward = DeployStewardContracts._deployRiskStewards( + address(AaveV3Linea.POOL), + AaveV3Linea.CONFIG_ENGINE, + predictedStewardsInjector, + GovernanceV3Linea.EXECUTOR_LVL_1 + ); + + address[] memory whitelistedAssets = new address[](3); + whitelistedAssets[0] = AaveV3LineaAssets.WETH_UNDERLYING; + whitelistedAssets[1] = AaveV3LineaAssets.USDC_UNDERLYING; + whitelistedAssets[2] = AaveV3LineaAssets.USDT_UNDERLYING; + + DeployStewardContracts._deployRatesStewardInjector( + CREATE_3_FACTORY, + salt, + riskSteward, + EDGE_RISK_ORACLE, + GovernanceV3Linea.EXECUTOR_LVL_1, + GUARDIAN, + whitelistedAssets, + true ); vm.stopBroadcast(); } diff --git a/src/contracts/gelato/GelatoAaveStewardInjectorDiscountRate.sol b/src/contracts/gelato/GelatoAaveStewardInjectorDiscountRate.sol new file mode 100644 index 0000000..841b0bc --- /dev/null +++ b/src/contracts/gelato/GelatoAaveStewardInjectorDiscountRate.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {AaveStewardInjectorDiscountRate, AaveStewardInjectorBase} from '../AaveStewardInjectorDiscountRate.sol'; + +/** + * @title GelatoAaveStewardInjectorDiscountRate + * @author BGD Labs + * @notice Contract to perform pendle discountRate update automation using Gelato. + */ +contract GelatoAaveStewardInjectorDiscountRate is AaveStewardInjectorDiscountRate { + /** + * @param aaveOracle address of the aave oracle of the instance. + * @param riskOracle address of the edge risk oracle contract. + * @param riskSteward address of the risk steward contract. + * @param markets list of market addresses to allow. + * @param owner address of the owner of the stewards injector. + * @param guardian address of the guardian of the stewards injector. + */ + constructor( + address aaveOracle, + address riskOracle, + address riskSteward, + address[] memory markets, + address owner, + address guardian + ) AaveStewardInjectorDiscountRate(aaveOracle, riskOracle, riskSteward, markets, owner, guardian) {} + + /** + * @inheritdoc AaveStewardInjectorBase + * @dev the returned bytes is specific to gelato and is encoded with the function selector. + */ + function checkUpkeep(bytes memory) public view override returns (bool, bytes memory) { + (bool upkeepNeeded, bytes memory encodedActionDataToExecute) = super.checkUpkeep(''); + return (upkeepNeeded, abi.encodeCall(this.performUpkeep, encodedActionDataToExecute)); + } +} diff --git a/src/contracts/gelato/GelatoAaveStewardInjectorEMode.sol b/src/contracts/gelato/GelatoAaveStewardInjectorEMode.sol new file mode 100644 index 0000000..3787445 --- /dev/null +++ b/src/contracts/gelato/GelatoAaveStewardInjectorEMode.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {AaveStewardInjectorEMode, AaveStewardInjectorBase} from '../AaveStewardInjectorEMode.sol'; + +/** + * @title GelatoAaveStewardInjectorEMode + * @author BGD Labs + * @notice Contract to perform EMode category update automation using Gelato. + */ +contract GelatoAaveStewardInjectorEMode is AaveStewardInjectorEMode { + /** + * @param riskOracle address of the edge risk oracle contract. + * @param riskSteward address of the risk steward contract. + * @param markets list of market addresses to allow. + * @param owner address of the owner of the stewards injector. + * @param guardian address of the guardian of the stewards injector. + */ + constructor( + address riskOracle, + address riskSteward, + address[] memory markets, + address owner, + address guardian + ) AaveStewardInjectorEMode(riskOracle, riskSteward, markets, owner, guardian) {} + + /** + * @inheritdoc AaveStewardInjectorBase + * @dev the returned bytes is specific to gelato and is encoded with the function selector. + */ + function checkUpkeep(bytes memory) public view override returns (bool, bytes memory) { + (bool upkeepNeeded, bytes memory encodedActionDataToExecute) = super.checkUpkeep(''); + return (upkeepNeeded, abi.encodeCall(this.performUpkeep, encodedActionDataToExecute)); + } +} diff --git a/src/contracts/gelato/GelatoAaveStewardInjectorRates.sol b/src/contracts/gelato/GelatoAaveStewardInjectorRates.sol new file mode 100644 index 0000000..1726336 --- /dev/null +++ b/src/contracts/gelato/GelatoAaveStewardInjectorRates.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {AaveStewardInjectorRates, AaveStewardInjectorBase} from '../AaveStewardInjectorRates.sol'; + +/** + * @title GelatoAaveStewardInjectorRates + * @author BGD Labs + * @notice Contract to perform interest rate update automation using Gelato. + */ +contract GelatoAaveStewardInjectorRates is AaveStewardInjectorRates { + /** + * @param riskOracle address of the edge risk oracle contract. + * @param riskSteward address of the risk steward contract. + * @param markets list of market addresses to allow. + * @param owner address of the owner of the stewards injector. + * @param guardian address of the guardian of the stewards injector. + */ + constructor( + address riskOracle, + address riskSteward, + address[] memory markets, + address owner, + address guardian + ) AaveStewardInjectorRates(riskOracle, riskSteward, markets, owner, guardian) {} + + /** + * @inheritdoc AaveStewardInjectorBase + * @dev the returned bytes is specific to gelato and is encoded with the function selector. + */ + function checkUpkeep(bytes memory) public view override returns (bool, bytes memory) { + (bool upkeepNeeded, bytes memory encodedActionDataToExecute) = super.checkUpkeep(''); + return (upkeepNeeded, abi.encodeCall(this.performUpkeep, encodedActionDataToExecute)); + } +} diff --git a/tests/AaveStewardInjectorDiscountRate.t.sol b/tests/AaveStewardInjectorDiscountRate.t.sol index 6279b51..e45bf39 100644 --- a/tests/AaveStewardInjectorDiscountRate.t.sol +++ b/tests/AaveStewardInjectorDiscountRate.t.sol @@ -9,12 +9,12 @@ import {EngineFlags} from 'aave-v3-origin/src/contracts/extensions/v3-config-eng import './AaveStewardsInjectorBase.t.sol'; contract AaveStewardsInjectorDiscountRate_Test is AaveStewardsInjectorBaseTest { - string internal _updateType = 'PendleDiscountRateUpdate_Core'; + string internal _updateType = 'PendleDiscountRateUpdate'; address internal _pendlePTAssetOne; address internal _pendlePTAssetTwo; - function setUp() public override { + function setUp() public virtual override { super.setUp(); IRiskSteward.Config memory config; diff --git a/tests/AaveStewardInjectorEMode.t.sol b/tests/AaveStewardInjectorEMode.t.sol index 6bc3a7f..83c898f 100644 --- a/tests/AaveStewardInjectorEMode.t.sol +++ b/tests/AaveStewardInjectorEMode.t.sol @@ -14,9 +14,9 @@ contract AaveStewardsInjectorEMode_Test is AaveStewardsInjectorBaseTest { uint8 internal _eModeIdOne = 1; uint8 internal _eModeIdTwo = 2; uint8 internal _eModeIdThree = 3; - string internal _updateType = 'EModeCategoryUpdate_Core'; + string internal _updateType = 'EModeCategoryUpdate'; - function setUp() public override { + function setUp() public virtual override { super.setUp(); IRiskSteward.RiskParamConfig memory defaultRiskParamConfig = IRiskSteward.RiskParamConfig({ diff --git a/tests/AaveStewardsInjectorRates.t.sol b/tests/AaveStewardsInjectorRates.t.sol index c68552b..5c55f3e 100644 --- a/tests/AaveStewardsInjectorRates.t.sol +++ b/tests/AaveStewardsInjectorRates.t.sol @@ -6,7 +6,7 @@ import {EdgeRiskStewardRates} from '../src/contracts/EdgeRiskStewardRates.sol'; import './AaveStewardsInjectorBase.t.sol'; contract AaveStewardsInjectorRates_Test is AaveStewardsInjectorBaseTest { - function setUp() public override { + function setUp() public virtual override { super.setUp(); IRiskSteward.RiskParamConfig memory defaultRiskParamConfig = IRiskSteward.RiskParamConfig({ diff --git a/tests/GelatoAaveStewardInjectorDiscountRate.t.sol b/tests/GelatoAaveStewardInjectorDiscountRate.t.sol new file mode 100644 index 0000000..4dfa8d4 --- /dev/null +++ b/tests/GelatoAaveStewardInjectorDiscountRate.t.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {Address} from 'openzeppelin-contracts/contracts/utils/Address.sol'; +import {GelatoAaveStewardInjectorDiscountRate} from '../src/contracts/gelato/GelatoAaveStewardInjectorDiscountRate.sol'; +import './AaveStewardInjectorDiscountRate.t.sol'; + +contract GelatoAaveStewardsInjectorDiscountRate_Test is AaveStewardsInjectorDiscountRate_Test { + using Address for address; + + function setUp() public override { + super.setUp(); + + IRiskSteward.Config memory config; + config.priceCapConfig.discountRatePendle = IRiskSteward.RiskParamConfig({ + minDelay: 2 days, + maxPercentChange: 0.01e18 // 1% change allowed + }); + + address[] memory pendlePTAssets = new address[](2); + pendlePTAssets[0] = _pendlePTAssetOne; + pendlePTAssets[1] = _pendlePTAssetTwo; + + // setup steward injector + vm.startPrank(_stewardsInjectorOwner); + + address computedRiskStewardAddress = vm.computeCreateAddress( + _stewardsInjectorOwner, + vm.getNonce(_stewardsInjectorOwner) + 1 + ); + + _stewardInjector = new GelatoAaveStewardInjectorDiscountRate( + report.aaveOracle, + address(_riskOracle), + address(computedRiskStewardAddress), + pendlePTAssets, + _stewardsInjectorOwner, + _stewardsInjectorGuardian + ); + + // setup risk steward + _riskSteward = new EdgeRiskStewardDiscountRate( + address(contracts.poolProxy), + report.configEngine, + address(_stewardInjector), + address(this), + config + ); + vm.stopPrank(); + + vm.prank(poolAdmin); + contracts.aclManager.addRiskAdmin(address(_riskSteward)); + } + + function _checkAndPerformAutomation() internal virtual override returns (bool) { + (bool shouldRunKeeper, bytes memory encodedPerformData) = _stewardInjector.checkUpkeep(''); + if (shouldRunKeeper) { + address(_stewardInjector).functionCall(encodedPerformData); + } + return shouldRunKeeper; + } + + function _performAutomation(bytes memory encodedCalldata) internal override { + address(_stewardInjector).functionCall(encodedCalldata); + } +} diff --git a/tests/GelatoAaveStewardInjectorEMode.t.sol b/tests/GelatoAaveStewardInjectorEMode.t.sol new file mode 100644 index 0000000..be048c7 --- /dev/null +++ b/tests/GelatoAaveStewardInjectorEMode.t.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {Address} from 'openzeppelin-contracts/contracts/utils/Address.sol'; +import {GelatoAaveStewardInjectorEMode} from '../src/contracts/gelato/GelatoAaveStewardInjectorEMode.sol'; +import './AaveStewardInjectorEMode.t.sol'; + +contract GelatoAaveStewardsInjectorEMode_Test is AaveStewardsInjectorEMode_Test { + using Address for address; + + function setUp() public override { + super.setUp(); + + IRiskSteward.RiskParamConfig memory defaultRiskParamConfig = IRiskSteward.RiskParamConfig({ + minDelay: 1 days, + maxPercentChange: 25 // 0.25% change allowed + }); + IRiskSteward.Config memory riskConfig; + riskConfig.eModeConfig.ltv = defaultRiskParamConfig; + riskConfig.eModeConfig.liquidationThreshold = defaultRiskParamConfig; + riskConfig.eModeConfig.liquidationBonus = defaultRiskParamConfig; + + // setup steward injector + vm.startPrank(_stewardsInjectorOwner); + + address computedRiskStewardAddress = vm.computeCreateAddress( + _stewardsInjectorOwner, + vm.getNonce(_stewardsInjectorOwner) + 1 + ); + + address[] memory markets = new address[](1); + markets[0] = _encodeUintToAddress(_eModeIdOne); + + _stewardInjector = new GelatoAaveStewardInjectorEMode( + address(_riskOracle), + address(computedRiskStewardAddress), + markets, + _stewardsInjectorOwner, + _stewardsInjectorGuardian + ); + + // setup risk steward + _riskSteward = new EdgeRiskStewardEMode( + address(contracts.poolProxy), + report.configEngine, + address(_stewardInjector), + address(this), + riskConfig + ); + vm.stopPrank(); + + vm.prank(poolAdmin); + contracts.aclManager.addRiskAdmin(address(_riskSteward)); + } + + function _checkAndPerformAutomation() internal virtual override returns (bool) { + (bool shouldRunKeeper, bytes memory encodedPerformData) = _stewardInjector.checkUpkeep(''); + if (shouldRunKeeper) { + address(_stewardInjector).functionCall(encodedPerformData); + } + return shouldRunKeeper; + } + + function _performAutomation(bytes memory encodedCalldata) internal override { + address(_stewardInjector).functionCall(encodedCalldata); + } +} diff --git a/tests/GelatoAaveStewardInjectorRates.t.sol b/tests/GelatoAaveStewardInjectorRates.t.sol new file mode 100644 index 0000000..a840048 --- /dev/null +++ b/tests/GelatoAaveStewardInjectorRates.t.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {Address} from 'openzeppelin-contracts/contracts/utils/Address.sol'; +import {GelatoAaveStewardInjectorRates} from '../src/contracts/gelato/GelatoAaveStewardInjectorRates.sol'; +import './AaveStewardsInjectorRates.t.sol'; + +contract GelatoAaveStewardsInjectorRates_Test is AaveStewardsInjectorRates_Test { + using Address for address; + + function setUp() public override { + super.setUp(); + + IRiskSteward.RiskParamConfig memory defaultRiskParamConfig = IRiskSteward.RiskParamConfig({ + minDelay: 3 days, + maxPercentChange: 5_00 // 5% + }); + IRiskSteward.Config memory riskConfig; + riskConfig.rateConfig.baseVariableBorrowRate = defaultRiskParamConfig; + riskConfig.rateConfig.variableRateSlope1 = defaultRiskParamConfig; + riskConfig.rateConfig.variableRateSlope2 = defaultRiskParamConfig; + riskConfig.rateConfig.optimalUsageRatio = defaultRiskParamConfig; + + // setup steward injector + vm.startPrank(_stewardsInjectorOwner); + + address computedRiskStewardAddress = vm.computeCreateAddress( + _stewardsInjectorOwner, + vm.getNonce(_stewardsInjectorOwner) + 1 + ); + address[] memory validMarkets = new address[](1); + validMarkets[0] = address(weth); + + _stewardInjector = new GelatoAaveStewardInjectorRates( + address(_riskOracle), + address(computedRiskStewardAddress), + validMarkets, + _stewardsInjectorOwner, + _stewardsInjectorGuardian + ); + + // setup risk steward + _riskSteward = new EdgeRiskStewardRates( + address(contracts.poolProxy), + report.configEngine, + address(_stewardInjector), + address(this), + riskConfig + ); + vm.stopPrank(); + + vm.startPrank(poolAdmin); + contracts.aclManager.addRiskAdmin(address(_riskSteward)); + vm.stopPrank(); + } + + function _checkAndPerformAutomation() internal virtual override returns (bool) { + (bool shouldRunKeeper, bytes memory encodedPerformData) = _stewardInjector.checkUpkeep(''); + if (shouldRunKeeper) { + address(_stewardInjector).functionCall(encodedPerformData); + } + return shouldRunKeeper; + } + + function _performAutomation(bytes memory encodedCalldata) internal override { + address(_stewardInjector).functionCall(encodedCalldata); + } +}