From 8bafe86bc72419234528cef7ec028c96219b13e1 Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Mon, 3 Nov 2025 15:53:38 +0100 Subject: [PATCH 01/62] feat : procedures to deploy contracts --- foundry.toml | 6 +++++- .../AaveV4AaveOraclerDeployProcedure.sol | 16 ++++++++++++++++ .../AaveV4AccessManagerDeployProcedure.sol | 12 ++++++++++++ .../AaveV4HubConfiguratorDeployProcedure.sol | 12 ++++++++++++ .../procedures/AaveV4HubDeployProcedure.sol | 12 ++++++++++++ ...AaveV4InterestRateStrategyDeployProcedure.sol | 12 ++++++++++++ .../AaveV4NativeTokenGatewayDeployProcedure.sol | 15 +++++++++++++++ .../AaveV4SignatureGatewayDeployProcedure.sol | 12 ++++++++++++ .../AaveV4SpokeConfiguratorDeployProcedure.sol | 12 ++++++++++++ .../AaveV4SpokeInstanceDeployProcedure.sol | 12 ++++++++++++ ...ransparentUpgradeableProxyDeployProcedure.sol | 16 ++++++++++++++++ .../AaveV4TreasurySpokeDeployProcedure.sol | 12 ++++++++++++ 12 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/deployments/procedures/AaveV4AaveOraclerDeployProcedure.sol create mode 100644 src/deployments/procedures/AaveV4AccessManagerDeployProcedure.sol create mode 100644 src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol create mode 100644 src/deployments/procedures/AaveV4HubDeployProcedure.sol create mode 100644 src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol create mode 100644 src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol create mode 100644 src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol create mode 100644 src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol create mode 100644 src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol create mode 100644 src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol create mode 100644 src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol diff --git a/foundry.toml b/foundry.toml index 4ffc6999c..c62704edc 100644 --- a/foundry.toml +++ b/foundry.toml @@ -4,7 +4,11 @@ test = 'tests' script = 'scripts' out = 'out' libs = ['lib'] -fs_permissions = [{ access = "read", path = "tests/mocks/JsonBindings.sol" }] +fs_permissions = [ + { access = "read", path = "tests/mocks/JsonBindings.sol" }, + { access = "read", path = "./config" }, + { access = "read-write", path = "./output" } +] solc_version = "0.8.28" evm_version = "cancun" optimizer = true diff --git a/src/deployments/procedures/AaveV4AaveOraclerDeployProcedure.sol b/src/deployments/procedures/AaveV4AaveOraclerDeployProcedure.sol new file mode 100644 index 000000000..4ca76a304 --- /dev/null +++ b/src/deployments/procedures/AaveV4AaveOraclerDeployProcedure.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveOracle} from 'src/contracts/spoke/AaveOracle.sol'; + +contract AaveV4AaveOracleDeployProcedure { + function _deployAaveOracle( + address spoke_, + uint8 decimals_, + string memory description_ + ) internal returns (address) { + address oracle = address(new AaveOracle(spoke_, decimals_, description_)); + + return oracle; + } +} diff --git a/src/deployments/procedures/AaveV4AccessManagerDeployProcedure.sol b/src/deployments/procedures/AaveV4AccessManagerDeployProcedure.sol new file mode 100644 index 000000000..cf4ef1595 --- /dev/null +++ b/src/deployments/procedures/AaveV4AccessManagerDeployProcedure.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AccessManager} from 'src/dependencies/openzeppelin/AccessManager.sol'; + +contract AaveV4AccessManagerDeployProcedure { + function _deployAccessManager(address admin_) internal returns (address) { + address accessManager = address(new AccessManager(admin_)); + + return accessManager; + } +} diff --git a/src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol new file mode 100644 index 000000000..32280fa38 --- /dev/null +++ b/src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {HubConfigurator} from 'src/contracts/hub/HubConfigurator.sol'; + +contract AaveV4HubConfiguratorDeployProcedure { + function _deployHubConfigurator(address owner_) internal returns (address) { + address hubConfigurator = address(new HubConfigurator(owner_)); + + return hubConfigurator; + } +} diff --git a/src/deployments/procedures/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/AaveV4HubDeployProcedure.sol new file mode 100644 index 000000000..830d58f4a --- /dev/null +++ b/src/deployments/procedures/AaveV4HubDeployProcedure.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Hub} from 'src/contracts/hub/Hub.sol'; + +contract AaveV4HubDeployProcedure { + function _deployHub(address accessManager_) internal returns (address) { + address hub = address(new Hub(accessManager_)); + + return hub; + } +} diff --git a/src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol b/src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol new file mode 100644 index 000000000..1a3d73554 --- /dev/null +++ b/src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AssetInterestRateStrategy} from 'src/contracts/hub/AssetInterestRateStrategy.sol'; + +contract AaveV4InterestRateStrategyDeployProcedure { + function _deployInterestRateStrategy(address hub_) internal returns (address) { + address interestRateStrategy = address(new AssetInterestRateStrategy(hub_)); + + return interestRateStrategy; + } +} diff --git a/src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol new file mode 100644 index 000000000..f1df0eaeb --- /dev/null +++ b/src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {NativeTokenGateway} from 'src/contracts/position-manager/NativeTokenGateway.sol'; + +contract AaveV4NativeTokenGatewayDeployProcedure { + function _deployNativeTokenGateway( + address nativeWrapper_, + address owner_ + ) internal returns (address) { + address nativeTokenGateway = address(new NativeTokenGateway(nativeWrapper_, owner_)); + + return nativeTokenGateway; + } +} diff --git a/src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol new file mode 100644 index 000000000..25412afd2 --- /dev/null +++ b/src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SignatureGateway} from 'src/contracts/position-manager/SignatureGateway.sol'; + +contract AaveV4SignatureGatewayDeployProcedure { + function _deploySignatureGateway(address owner_) internal returns (address) { + address signatureGateway = address(new SignatureGateway(owner_)); + + return signatureGateway; + } +} diff --git a/src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol new file mode 100644 index 000000000..ae52798e0 --- /dev/null +++ b/src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SpokeConfigurator} from 'src/contracts/spoke/SpokeConfigurator.sol'; + +contract AaveV4SpokeConfiguratorDeployProcedure { + function _deploySpokeConfigurator(address owner_) internal returns (address) { + address spokeConfigurator = address(new SpokeConfigurator(owner_)); + + return spokeConfigurator; + } +} diff --git a/src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol b/src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol new file mode 100644 index 000000000..9bbd14454 --- /dev/null +++ b/src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SpokeInstance} from 'src/contracts/spoke/instances/SpokeInstance.sol'; + +contract AaveV4SpokeInstanceDeployProcedure { + function _deploySpokeInstance(address oracle_) internal returns (address) { + address spokeInstance = address(new SpokeInstance(oracle_)); + + return spokeInstance; + } +} diff --git a/src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol b/src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol new file mode 100644 index 000000000..b1a16b00e --- /dev/null +++ b/src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {TransparentUpgradeableProxy} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; + +contract AaveV4TransparentUpgradeableProxyDeployProcedure { + function _deployTransparentUpgradeableProxy( + address logic_, + address initialOwner_, + bytes memory data_ + ) internal returns (address) { + address proxy = address(new TransparentUpgradeableProxy(logic_, initialOwner_, data_)); + + return proxy; + } +} diff --git a/src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol b/src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol new file mode 100644 index 000000000..0e8fd0296 --- /dev/null +++ b/src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {TreasurySpoke} from 'src/contracts/spoke/TreasurySpoke.sol'; + +contract AaveV4TreasurySpokeDeployProcedure { + function _deployTreasurySpoke(address owner_, address hub_) internal returns (address) { + address treasurySpoke = address(new TreasurySpoke(owner_, hub_)); + + return treasurySpoke; + } +} From d95101be668b490f65b35d2440a4b0c808074401 Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Wed, 5 Nov 2025 12:00:22 +0100 Subject: [PATCH 02/62] feat : add batch contracts for deploy --- src/deployments/batches/AaveV4AccessBatch.sol | 18 ++++++ .../batches/AaveV4GatewaysBatch.sol | 27 +++++++++ src/deployments/batches/AaveV4HubBatch.sol | 35 +++++++++++ .../batches/AaveV4SpokeInstanceBatch.sol | 60 +++++++++++++++++++ ...ol => AaveV4AaveOracleDeployProcedure.sol} | 2 +- .../AaveV4HubConfiguratorDeployProcedure.sol | 2 +- .../procedures/AaveV4HubDeployProcedure.sol | 2 +- ...eV4InterestRateStrategyDeployProcedure.sol | 2 +- ...aveV4NativeTokenGatewayDeployProcedure.sol | 2 +- .../AaveV4SignatureGatewayDeployProcedure.sol | 2 +- ...AaveV4SpokeConfiguratorDeployProcedure.sol | 2 +- .../AaveV4SpokeInstanceDeployProcedure.sol | 2 +- .../AaveV4TreasurySpokeDeployProcedure.sol | 2 +- src/deployments/types/BatchReports.sol | 27 +++++++++ src/deployments/utils/DeployUtils.sol | 11 ++++ 15 files changed, 187 insertions(+), 9 deletions(-) create mode 100644 src/deployments/batches/AaveV4AccessBatch.sol create mode 100644 src/deployments/batches/AaveV4GatewaysBatch.sol create mode 100644 src/deployments/batches/AaveV4HubBatch.sol create mode 100644 src/deployments/batches/AaveV4SpokeInstanceBatch.sol rename src/deployments/procedures/{AaveV4AaveOraclerDeployProcedure.sol => AaveV4AaveOracleDeployProcedure.sol} (84%) create mode 100644 src/deployments/types/BatchReports.sol create mode 100644 src/deployments/utils/DeployUtils.sol diff --git a/src/deployments/batches/AaveV4AccessBatch.sol b/src/deployments/batches/AaveV4AccessBatch.sol new file mode 100644 index 000000000..cf9d11f46 --- /dev/null +++ b/src/deployments/batches/AaveV4AccessBatch.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {AaveV4AccessManagerDeployProcedure} from 'src/deployments/procedures/AaveV4AccessManagerDeployProcedure.sol'; + +contract AaveV4AccessBatch is AaveV4AccessManagerDeployProcedure { + BatchReports.AccessBatchReport internal _report; + + constructor(address admin_) { + address accessManagerAddress = _deployAccessManager(admin_); + _report = BatchReports.AccessBatchReport({accessManagerAddress: accessManagerAddress}); + } + + function getReport() external view returns (BatchReports.AccessBatchReport memory) { + return _report; + } +} diff --git a/src/deployments/batches/AaveV4GatewaysBatch.sol b/src/deployments/batches/AaveV4GatewaysBatch.sol new file mode 100644 index 000000000..c035d8ec6 --- /dev/null +++ b/src/deployments/batches/AaveV4GatewaysBatch.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {AaveV4NativeTokenGatewayDeployProcedure} from 'src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol'; +import {AaveV4SignatureGatewayDeployProcedure} from 'src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol'; + +contract AaveV4GatewaysBatch is + AaveV4NativeTokenGatewayDeployProcedure, + AaveV4SignatureGatewayDeployProcedure +{ + BatchReports.GatewaysBatchReport internal _report; + + constructor(address nativeWrapper_, address admin_) { + address nativeGatewayAddress = _deployNativeTokenGateway(nativeWrapper_, admin_); + address signatureGatewayAddress = _deploySignatureGateway(admin_); + + _report = BatchReports.GatewaysBatchReport({ + nativeGatewayAddress: nativeGatewayAddress, + signatureGatewayAddress: signatureGatewayAddress + }); + } + + function getReport() external view returns (BatchReports.GatewaysBatchReport memory) { + return _report; + } +} diff --git a/src/deployments/batches/AaveV4HubBatch.sol b/src/deployments/batches/AaveV4HubBatch.sol new file mode 100644 index 000000000..456d554b8 --- /dev/null +++ b/src/deployments/batches/AaveV4HubBatch.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {AaveV4HubDeployProcedure} from 'src/deployments/procedures/AaveV4HubDeployProcedure.sol'; +import {AaveV4InterestRateStrategyDeployProcedure} from 'src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol'; +import {AaveV4TreasurySpokeDeployProcedure} from 'src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol'; +import {AaveV4HubConfiguratorDeployProcedure} from 'src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol'; + +contract AaveV4HubBatch is + AaveV4HubDeployProcedure, + AaveV4InterestRateStrategyDeployProcedure, + AaveV4TreasurySpokeDeployProcedure, + AaveV4HubConfiguratorDeployProcedure +{ + BatchReports.HubBatchReport internal _report; + + constructor(address admin_, address accessManagerAddress_) { + address hubAddress = _deployHub(accessManagerAddress_); + address irStrategyAddress = _deployInterestRateStrategy(hubAddress); + address treasurySpokeAddress = _deployTreasurySpoke(admin_, hubAddress); + address hubConfiguratorAddress = _deployHubConfigurator(admin_); + + _report = BatchReports.HubBatchReport({ + hubAddress: hubAddress, + irStrategyAddress: irStrategyAddress, + treasurySpokeAddress: treasurySpokeAddress, + hubConfiguratorAddress: hubConfiguratorAddress + }); + } + + function getReport() external view returns (BatchReports.HubBatchReport memory) { + return _report; + } +} diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol new file mode 100644 index 000000000..89fab42f8 --- /dev/null +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/Vm.sol'; + +import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {AaveV4SpokeInstanceDeployProcedure} from 'src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol'; +import {AaveV4TransparentUpgradeableProxyDeployProcedure} from 'src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol'; +import {AaveV4AaveOracleDeployProcedure} from 'src/deployments/procedures/AaveV4AaveOracleDeployProcedure.sol'; +import {AaveV4SpokeConfiguratorDeployProcedure} from 'src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol'; + +contract AaveV4SpokeInstanceBatch is + AaveV4SpokeInstanceDeployProcedure, + AaveV4TransparentUpgradeableProxyDeployProcedure, + AaveV4AaveOracleDeployProcedure, + AaveV4SpokeConfiguratorDeployProcedure +{ + BatchReports.SpokeInstanceBatchReport internal _report; + + constructor( + Vm vm, + address deployer, + address admin_, + address accessManagerAddress_, + uint8 oracleDecimals_, + string memory oracleDescription_ + ) { + address predictedSpokeInstanceAddress = vm.computeCreateAddress( + deployer, + vm.getNonce(deployer) + 2 + ); + + address aaveOracleAddress = _deployAaveOracle( + predictedSpokeInstanceAddress, + oracleDecimals_, + oracleDescription_ + ); + address spokeImplementationAddress = _deploySpokeInstance(aaveOracleAddress); + address spokeProxyAddress = _deployTransparentUpgradeableProxy( + spokeImplementationAddress, + admin_, + abi.encodeWithSignature('initialize(address)', accessManagerAddress_) + ); + + require(spokeProxyAddress == predictedSpokeInstanceAddress, 'SpokeInstance address mismatch'); + + address spokeConfiguratorAddress = _deploySpokeConfigurator(admin_); + + _report = BatchReports.SpokeInstanceBatchReport({ + aaveOracleAddress: aaveOracleAddress, + spokeImplementationAddress: spokeImplementationAddress, + spokeProxyAddress: spokeProxyAddress, + spokeConfiguratorAddress: spokeConfiguratorAddress + }); + } + + function getReport() external view returns (BatchReports.SpokeInstanceBatchReport memory) { + return _report; + } +} diff --git a/src/deployments/procedures/AaveV4AaveOraclerDeployProcedure.sol b/src/deployments/procedures/AaveV4AaveOracleDeployProcedure.sol similarity index 84% rename from src/deployments/procedures/AaveV4AaveOraclerDeployProcedure.sol rename to src/deployments/procedures/AaveV4AaveOracleDeployProcedure.sol index 4ca76a304..790ab8c18 100644 --- a/src/deployments/procedures/AaveV4AaveOraclerDeployProcedure.sol +++ b/src/deployments/procedures/AaveV4AaveOracleDeployProcedure.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {AaveOracle} from 'src/contracts/spoke/AaveOracle.sol'; +import {AaveOracle} from 'src/spoke/AaveOracle.sol'; contract AaveV4AaveOracleDeployProcedure { function _deployAaveOracle( diff --git a/src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol index 32280fa38..e977302f6 100644 --- a/src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {HubConfigurator} from 'src/contracts/hub/HubConfigurator.sol'; +import {HubConfigurator} from 'src/hub/HubConfigurator.sol'; contract AaveV4HubConfiguratorDeployProcedure { function _deployHubConfigurator(address owner_) internal returns (address) { diff --git a/src/deployments/procedures/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/AaveV4HubDeployProcedure.sol index 830d58f4a..fe9bb7abe 100644 --- a/src/deployments/procedures/AaveV4HubDeployProcedure.sol +++ b/src/deployments/procedures/AaveV4HubDeployProcedure.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {Hub} from 'src/contracts/hub/Hub.sol'; +import {Hub} from 'src/hub/Hub.sol'; contract AaveV4HubDeployProcedure { function _deployHub(address accessManager_) internal returns (address) { diff --git a/src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol b/src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol index 1a3d73554..80e74e1af 100644 --- a/src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol +++ b/src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {AssetInterestRateStrategy} from 'src/contracts/hub/AssetInterestRateStrategy.sol'; +import {AssetInterestRateStrategy} from 'src/hub/AssetInterestRateStrategy.sol'; contract AaveV4InterestRateStrategyDeployProcedure { function _deployInterestRateStrategy(address hub_) internal returns (address) { diff --git a/src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol index f1df0eaeb..b97e44108 100644 --- a/src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol +++ b/src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {NativeTokenGateway} from 'src/contracts/position-manager/NativeTokenGateway.sol'; +import {NativeTokenGateway} from 'src/position-manager/NativeTokenGateway.sol'; contract AaveV4NativeTokenGatewayDeployProcedure { function _deployNativeTokenGateway( diff --git a/src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol index 25412afd2..21e2e24cb 100644 --- a/src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol +++ b/src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {SignatureGateway} from 'src/contracts/position-manager/SignatureGateway.sol'; +import {SignatureGateway} from 'src/position-manager/SignatureGateway.sol'; contract AaveV4SignatureGatewayDeployProcedure { function _deploySignatureGateway(address owner_) internal returns (address) { diff --git a/src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol index ae52798e0..3b074d5fc 100644 --- a/src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {SpokeConfigurator} from 'src/contracts/spoke/SpokeConfigurator.sol'; +import {SpokeConfigurator} from 'src/spoke/SpokeConfigurator.sol'; contract AaveV4SpokeConfiguratorDeployProcedure { function _deploySpokeConfigurator(address owner_) internal returns (address) { diff --git a/src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol b/src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol index 9bbd14454..224f4fbcd 100644 --- a/src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol +++ b/src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {SpokeInstance} from 'src/contracts/spoke/instances/SpokeInstance.sol'; +import {SpokeInstance} from 'src/spoke/instances/SpokeInstance.sol'; contract AaveV4SpokeInstanceDeployProcedure { function _deploySpokeInstance(address oracle_) internal returns (address) { diff --git a/src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol b/src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol index 0e8fd0296..e79b06ffd 100644 --- a/src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol +++ b/src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {TreasurySpoke} from 'src/contracts/spoke/TreasurySpoke.sol'; +import {TreasurySpoke} from 'src/spoke/TreasurySpoke.sol'; contract AaveV4TreasurySpokeDeployProcedure { function _deployTreasurySpoke(address owner_, address hub_) internal returns (address) { diff --git a/src/deployments/types/BatchReports.sol b/src/deployments/types/BatchReports.sol new file mode 100644 index 000000000..9688b499f --- /dev/null +++ b/src/deployments/types/BatchReports.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +library BatchReports { + struct AccessBatchReport { + address accessManagerAddress; + } + + struct SpokeInstanceBatchReport { + address spokeImplementationAddress; + address spokeProxyAddress; + address aaveOracleAddress; + address spokeConfiguratorAddress; + } + + struct HubBatchReport { + address hubAddress; + address irStrategyAddress; + address treasurySpokeAddress; + address hubConfiguratorAddress; + } + + struct GatewaysBatchReport { + address signatureGatewayAddress; + address nativeGatewayAddress; + } +} diff --git a/src/deployments/utils/DeployUtils.sol b/src/deployments/utils/DeployUtils.sol new file mode 100644 index 000000000..fb8ed1d41 --- /dev/null +++ b/src/deployments/utils/DeployUtils.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/StdJson.sol'; +import 'forge-std/Vm.sol'; + +contract DeployUtils { + using stdJson for string; + + Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); +} From 00ba92a5ef38d6aff19fca420d28b9be31ec7f90 Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Wed, 5 Nov 2025 13:52:46 +0100 Subject: [PATCH 03/62] feat : add Logger for Deploy Engine --- src/deployments/utils/LogUtils.sol | 118 +++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/deployments/utils/LogUtils.sol diff --git a/src/deployments/utils/LogUtils.sol b/src/deployments/utils/LogUtils.sol new file mode 100644 index 000000000..3b79559ef --- /dev/null +++ b/src/deployments/utils/LogUtils.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/StdJson.sol'; +import 'forge-std/Vm.sol'; +import {console} from 'forge-std/console.sol'; + +contract LogUtils { + using stdJson for string; + + struct AddressEntry { + string label; + address value; + } + + struct ValueEntry { + string label; + uint256 value; + } + + Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); + + string internal _outputPath; + string internal _root; + + constructor(string memory outputPath_) { + _root = 'root'; + _outputPath = outputPath_; + } + + function log(string memory label, address value) public view { + _log(label, value); + } + + function log(string memory label, uint256 value) public view { + _log(label, value); + } + + function log(string memory value) public view { + _log(value); + } + + function write(string memory label, address value) public { + _write(label, value); + } + + function write(string memory label, uint256 value) public { + _write(label, value); + } + + function write(string memory value) public { + _write(value); + } + + function writeGroup(string memory groupLabel, AddressEntry[] memory entries) public { + _writeGroup(groupLabel, entries); + } + + function writeGroup(string memory groupLabel, ValueEntry[] memory entries) public { + _writeGroup(groupLabel, entries); + } + + function save() public { + console.log(); + console.log('Saving log to %s', _outputPath); + console.log(_root); + vm.writeJson(_root, _outputPath); + } + + function _log(string memory label, address value) internal view { + console.log('%s: %s', label, value); + } + + function _log(string memory label, uint256 value) internal view { + console.log('%s: %s', label, value); + } + + function _log(string memory value) internal view { + console.log(value); + } + + function _write(string memory label, address value) internal { + _log(label, value); + _root = vm.serializeAddress(_root, label, value); + } + + function _write(string memory label, uint256 value) internal { + _log(label, value); + _root = vm.serializeString(_root, label, vm.toString(value)); + } + + function _write(string memory value) internal { + _log(value); + _root = vm.serializeString(_root, 'message', value); + } + + function _writeGroup(string memory groupLabel, AddressEntry[] memory entries) internal { + string memory group; + _log(groupLabel); + for (uint256 i = 0; i < entries.length; i++) { + _log(entries[i].label, entries[i].value); + group = vm.serializeAddress(group, entries[i].label, entries[i].value); + } + _root = vm.serializeString(_root, groupLabel, group); + console.log(); + } + + function _writeGroup(string memory groupLabel, ValueEntry[] memory entries) internal { + string memory group; + _log(groupLabel); + for (uint256 i = 0; i < entries.length; i++) { + _log(entries[i].label, entries[i].value); + group = vm.serializeString(group, entries[i].label, vm.toString(entries[i].value)); + } + _root = vm.serializeString(_root, groupLabel, group); + console.log(); + } +} From 9f6c70ddb94bdb83ad9eb9a5de325d5cd02128ff Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Wed, 5 Nov 2025 16:01:03 +0100 Subject: [PATCH 04/62] feat : Input helper for Deploy Engine --- src/deployments/utils/InputUtils.sol | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/deployments/utils/InputUtils.sol diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol new file mode 100644 index 000000000..5221170c7 --- /dev/null +++ b/src/deployments/utils/InputUtils.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/StdJson.sol'; +import 'forge-std/Vm.sol'; + +contract InputUtils { + using stdJson for string; + + struct FullDeployInputs { + address admin; + address nativeWrapperAddress; + string[] hubLabels; + string[] spokeLabels; + } + + struct SpokeDeployInputs { + address admin; + string spokeLabel; + } + + struct HubDeployInputs { + address admin; + string hubLabel; + } + + Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); + + function loadFullDeployInputs( + string memory inputPath + ) public view returns (FullDeployInputs memory) { + string memory json = vm.readFile(inputPath); + bytes memory data = vm.parseJson(json); + FullDeployInputs memory inputs = abi.decode(data, (FullDeployInputs)); + return inputs; + } + + function loadSpokeDeployInputs( + string memory inputPath + ) public view returns (SpokeDeployInputs memory) { + string memory json = vm.readFile(inputPath); + bytes memory data = vm.parseJson(json); + SpokeDeployInputs memory inputs = abi.decode(data, (SpokeDeployInputs)); + return inputs; + } + + function loadHubDeployInputs( + string memory inputPath + ) public view returns (HubDeployInputs memory) { + string memory json = vm.readFile(inputPath); + bytes memory data = vm.parseJson(json); + HubDeployInputs memory inputs = abi.decode(data, (HubDeployInputs)); + return inputs; + } +} From cecd4f305ea33aaf68b0a1d343d835c44e2abfcd Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Fri, 7 Nov 2025 15:29:37 +0100 Subject: [PATCH 05/62] feat : add orchestration methods & 1st draft deploy payload --- foundry.toml | 3 +- scripts/deploy/AaveV4DeployBatch.s.sol | 47 +++++ .../batches/AaveV4GatewaysBatch.sol | 2 +- .../batches/AaveV4SpokeInstanceBatch.sol | 2 +- .../AaveV4DeployOrchestration.sol | 193 ++++++++++++++++++ ...sparentUpgradeableProxyDeployProcedure.sol | 2 +- src/deployments/utils/DeployUtils.sol | 3 - .../utils/{LogUtils.sol => Logger.sol} | 2 +- 8 files changed, 246 insertions(+), 8 deletions(-) create mode 100644 scripts/deploy/AaveV4DeployBatch.s.sol create mode 100644 src/deployments/orchestration/AaveV4DeployOrchestration.sol rename src/deployments/utils/{LogUtils.sol => Logger.sol} (99%) diff --git a/foundry.toml b/foundry.toml index c62704edc..78797a5a5 100644 --- a/foundry.toml +++ b/foundry.toml @@ -7,7 +7,8 @@ libs = ['lib'] fs_permissions = [ { access = "read", path = "tests/mocks/JsonBindings.sol" }, { access = "read", path = "./config" }, - { access = "read-write", path = "./output" } + { access = "read-write", path = "./output" }, + { access = "read-write", path = "./scripts/input" } ] solc_version = "0.8.28" evm_version = "cancun" diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol new file mode 100644 index 000000000..4f0695378 --- /dev/null +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Script} from 'forge-std/Script.sol'; + +import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; +import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; +import {Logger} from 'src/deployments/utils/Logger.sol'; + +import {BatchReports} from 'src/deployments/types/BatchReports.sol'; + +import {AaveV4DeployOrchestration} from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; + +contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { + string internal constant INPUT_PATH = 'scripts/deploy/input/AaveV4DeployInput.json'; + string internal constant OUTPUT_PATH = 'output/reports/deployments/AaveV4DeployBatch.json'; + + constructor() {} + + function run() external { + Logger logger = new Logger(OUTPUT_PATH); + FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); + //TODO : load roles + + address deployer = msg.sender; + + logger.log('Starting Aave V4 Batch Deployment'); + + vm.startBroadcast(); + AaveV4DeployOrchestration.FullDeploymentReport memory report = AaveV4DeployOrchestration + .deployAaveV4( + logger, + deployer, + inputs.admin, + inputs.nativeWrapperAddress, + inputs.hubLabels, + inputs.spokeLabels + ); + vm.stopBroadcast(); + + // TODO : apply roles + + logger.log('Batch Deployment Completed'); + logger.log('Saving Logs'); + logger.save(); + } +} diff --git a/src/deployments/batches/AaveV4GatewaysBatch.sol b/src/deployments/batches/AaveV4GatewaysBatch.sol index c035d8ec6..45c428f9e 100644 --- a/src/deployments/batches/AaveV4GatewaysBatch.sol +++ b/src/deployments/batches/AaveV4GatewaysBatch.sol @@ -11,7 +11,7 @@ contract AaveV4GatewaysBatch is { BatchReports.GatewaysBatchReport internal _report; - constructor(address nativeWrapper_, address admin_) { + constructor(address admin_, address nativeWrapper_) { address nativeGatewayAddress = _deployNativeTokenGateway(nativeWrapper_, admin_); address signatureGatewayAddress = _deploySignatureGateway(admin_); diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 89fab42f8..676a5d7c3 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -36,7 +36,7 @@ contract AaveV4SpokeInstanceBatch is oracleDescription_ ); address spokeImplementationAddress = _deploySpokeInstance(aaveOracleAddress); - address spokeProxyAddress = _deployTransparentUpgradeableProxy( + address spokeProxyAddress = _proxify( spokeImplementationAddress, admin_, abi.encodeWithSignature('initialize(address)', accessManagerAddress_) diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol new file mode 100644 index 000000000..701c9c887 --- /dev/null +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/Vm.sol'; + +import {Logger} from 'src/deployments/utils/Logger.sol'; +import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; +import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; +import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; +import {AaveV4GatewaysBatch} from 'src/deployments/batches/AaveV4GatewaysBatch.sol'; + +library AaveV4DeployOrchestration { + Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); + + uint8 constant ORACLE_DECIMALS = 8; + string constant ORACLE_SUFFIX = ' (USD)'; + + struct SpokeDeploymentReport { + string label; + BatchReports.SpokeInstanceBatchReport report; + } + + struct HubDeploymentReport { + string label; + BatchReports.HubBatchReport report; + } + + struct FullDeploymentReport { + BatchReports.AccessBatchReport accessBatchReport; + SpokeDeploymentReport spokeInstanceBatchReport; + HubDeploymentReport hubBatchReport; + BatchReports.GatewaysBatchReport gatewaysBatchReport; + } + + function deployAaveV4( + Logger logger, + address deployer, + address admin, + address nativeWrapper, + string[] memory hubLabels, + string[] memory spokeLabels + ) internal returns (FullDeploymentReport memory) { + FullDeploymentReport memory report; + + // Deploy Access Batch + report.accessBatchReport = _deployAccessBatch(admin); + logger.log('AccessManager', report.accessBatchReport.accessManagerAddress); + + // Deploy Hub Batches + uint256 hubCount = hubLabels.length; + Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](hubCount); + for (uint256 i; i < hubCount; i++) { + report.hubBatchReport.label = hubLabels[i]; + report.hubBatchReport.report = _deployHubBatch( + admin, + report.accessBatchReport.accessManagerAddress + ); + hubEntries[i] = Logger.AddressEntry({ + label: hubLabels[i], + value: report.hubBatchReport.report.hubAddress + }); + logger.log(string.concat(hubLabels[i], ' Hub'), report.hubBatchReport.report.hubAddress); + logger.log( + string.concat(hubLabels[i], ' InterestRateStrategy'), + report.hubBatchReport.report.irStrategyAddress + ); + logger.log( + string.concat(hubLabels[i], ' TreasurySpoke'), + report.hubBatchReport.report.treasurySpokeAddress + ); + logger.log( + string.concat(hubLabels[i], ' HubConfigurator'), + report.hubBatchReport.report.hubConfiguratorAddress + ); + } + logger.writeGroup('Hubs', hubEntries); + + // Deploy Spoke Instance Batches + uint256 spokeCount = spokeLabels.length; + Logger.AddressEntry[] memory spokeEntries = new Logger.AddressEntry[](spokeCount); + for (uint256 i; i < spokeCount; i++) { + report.spokeInstanceBatchReport.label = spokeLabels[i]; + report.spokeInstanceBatchReport.report = _deploySpokeInstanceBatch( + deployer, + admin, + report.accessBatchReport.accessManagerAddress, + spokeLabels[i] + ); + spokeEntries[i] = Logger.AddressEntry({ + label: spokeLabels[i], + value: report.spokeInstanceBatchReport.report.spokeProxyAddress + }); + logger.log( + string.concat(spokeLabels[i], ' SpokeInstance Proxy'), + report.spokeInstanceBatchReport.report.spokeProxyAddress + ); + logger.log( + string.concat(spokeLabels[i], ' SpokeInstance Implementation'), + report.spokeInstanceBatchReport.report.spokeImplementationAddress + ); + logger.log( + string.concat(spokeLabels[i], ' AaveOracle'), + report.spokeInstanceBatchReport.report.aaveOracleAddress + ); + logger.log( + string.concat(spokeLabels[i], ' SpokeConfigurator'), + report.spokeInstanceBatchReport.report.spokeConfiguratorAddress + ); + } + logger.writeGroup('SpokeInstances', spokeEntries); + + // Deploy Gateways Batch + report.gatewaysBatchReport = _deployGatewaysBatch(admin, nativeWrapper); + logger.log('NativeTokenGateway', report.gatewaysBatchReport.nativeGatewayAddress); + logger.log('SignatureGateway', report.gatewaysBatchReport.signatureGatewayAddress); + + return report; + } + + function deployHub( + Logger logger, + address admin, + address accessManagerAddress, + string memory label + ) internal returns (HubDeploymentReport memory) { + HubDeploymentReport memory hubReport; + hubReport.label = label; + hubReport.report = _deployHubBatch(admin, accessManagerAddress); + logger.write('Hub', hubReport.report.hubAddress); + logger.write('InterestRateStrategy', hubReport.report.irStrategyAddress); + logger.write('TreasurySpoke', hubReport.report.treasurySpokeAddress); + logger.write('HubConfigurator', hubReport.report.hubConfiguratorAddress); + return hubReport; + } + + function deploySpoke( + Logger logger, + address deployer, + address admin, + address accessManagerAddress, + string memory label + ) internal returns (SpokeDeploymentReport memory) { + SpokeDeploymentReport memory spokeReport; + spokeReport.label = label; + spokeReport.report = _deploySpokeInstanceBatch(deployer, admin, accessManagerAddress, label); + logger.write('SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); + logger.write('SpokeInstance Implementation', spokeReport.report.spokeImplementationAddress); + logger.write('AaveOracle', spokeReport.report.aaveOracleAddress); + logger.write('SpokeConfigurator', spokeReport.report.spokeConfiguratorAddress); + return spokeReport; + } + + function _deployAccessBatch( + address admin + ) internal returns (BatchReports.AccessBatchReport memory) { + AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin); + return accessBatch.getReport(); + } + + function _deployHubBatch( + address admin, + address accessManagerAddress + ) internal returns (BatchReports.HubBatchReport memory) { + AaveV4HubBatch hubBatch = new AaveV4HubBatch(admin, accessManagerAddress); + return hubBatch.getReport(); + } + + function _deploySpokeInstanceBatch( + address deployer, + address admin, + address accessManagerAddress, + string memory label + ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { + AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch( + vm, + deployer, + admin, + accessManagerAddress, + ORACLE_DECIMALS, + string.concat(label, ORACLE_SUFFIX) + ); + return spokeInstanceBatch.getReport(); + } + + function _deployGatewaysBatch( + address admin, + address nativeWrapper + ) internal returns (BatchReports.GatewaysBatchReport memory) { + AaveV4GatewaysBatch gatewaysBatch = new AaveV4GatewaysBatch(admin, nativeWrapper); + return gatewaysBatch.getReport(); + } +} diff --git a/src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol b/src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol index b1a16b00e..a890b6b9d 100644 --- a/src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol +++ b/src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {TransparentUpgradeableProxy} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; contract AaveV4TransparentUpgradeableProxyDeployProcedure { - function _deployTransparentUpgradeableProxy( + function _proxify( address logic_, address initialOwner_, bytes memory data_ diff --git a/src/deployments/utils/DeployUtils.sol b/src/deployments/utils/DeployUtils.sol index fb8ed1d41..87b39f6a3 100644 --- a/src/deployments/utils/DeployUtils.sol +++ b/src/deployments/utils/DeployUtils.sol @@ -1,11 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import 'forge-std/StdJson.sol'; import 'forge-std/Vm.sol'; contract DeployUtils { - using stdJson for string; - Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); } diff --git a/src/deployments/utils/LogUtils.sol b/src/deployments/utils/Logger.sol similarity index 99% rename from src/deployments/utils/LogUtils.sol rename to src/deployments/utils/Logger.sol index 3b79559ef..e5c67df25 100644 --- a/src/deployments/utils/LogUtils.sol +++ b/src/deployments/utils/Logger.sol @@ -5,7 +5,7 @@ import 'forge-std/StdJson.sol'; import 'forge-std/Vm.sol'; import {console} from 'forge-std/console.sol'; -contract LogUtils { +contract Logger { using stdJson for string; struct AddressEntry { From 460c2e0708087b950a5331a87a111aa68729b1b3 Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Mon, 10 Nov 2025 09:36:14 +0100 Subject: [PATCH 06/62] fix : separate batch for configurators --- scripts/Script.s.sol | 13 --------- .../batches/AaveV4ConfiguratorBatch.sol | 27 +++++++++++++++++++ src/deployments/batches/AaveV4HubBatch.sol | 8 ++---- .../batches/AaveV4SpokeInstanceBatch.sol | 9 ++----- .../AaveV4DeployOrchestration.sol | 24 ++++++++++------- src/deployments/types/BatchReports.sol | 7 +++-- 6 files changed, 50 insertions(+), 38 deletions(-) delete mode 100644 scripts/Script.s.sol create mode 100644 src/deployments/batches/AaveV4ConfiguratorBatch.sol diff --git a/scripts/Script.s.sol b/scripts/Script.s.sol deleted file mode 100644 index a4eb9d861..000000000 --- a/scripts/Script.s.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.0; - -// import {Script} from 'forge-std/Script.sol'; - -// contract Deploy is Script { -// function run() external { -// vm.startBroadcast(); -// TODO -// vm.stopBroadcast(); -// } -// } diff --git a/src/deployments/batches/AaveV4ConfiguratorBatch.sol b/src/deployments/batches/AaveV4ConfiguratorBatch.sol new file mode 100644 index 000000000..21fea9b00 --- /dev/null +++ b/src/deployments/batches/AaveV4ConfiguratorBatch.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {AaveV4HubConfiguratorDeployProcedure} from 'src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol'; +import {AaveV4SpokeConfiguratorDeployProcedure} from 'src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol'; + +contract AaveV4ConfiguratorBatch is + AaveV4HubConfiguratorDeployProcedure, + AaveV4SpokeConfiguratorDeployProcedure +{ + BatchReports.ConfiguratorBatchReport internal _report; + + constructor(address admin_) { + address hubConfiguratorAddress = _deployHubConfigurator(admin_); + address spokeConfiguratorAddress = _deploySpokeConfigurator(admin_); + + _report = BatchReports.ConfiguratorBatchReport({ + hubConfiguratorAddress: hubConfiguratorAddress, + spokeConfiguratorAddress: spokeConfiguratorAddress + }); + } + + function getReport() external view returns (BatchReports.ConfiguratorBatchReport memory) { + return _report; + } +} diff --git a/src/deployments/batches/AaveV4HubBatch.sol b/src/deployments/batches/AaveV4HubBatch.sol index 456d554b8..8fb8c60b0 100644 --- a/src/deployments/batches/AaveV4HubBatch.sol +++ b/src/deployments/batches/AaveV4HubBatch.sol @@ -5,13 +5,11 @@ import {BatchReports} from 'src/deployments/types/BatchReports.sol'; import {AaveV4HubDeployProcedure} from 'src/deployments/procedures/AaveV4HubDeployProcedure.sol'; import {AaveV4InterestRateStrategyDeployProcedure} from 'src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol'; import {AaveV4TreasurySpokeDeployProcedure} from 'src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol'; -import {AaveV4HubConfiguratorDeployProcedure} from 'src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol'; contract AaveV4HubBatch is AaveV4HubDeployProcedure, AaveV4InterestRateStrategyDeployProcedure, - AaveV4TreasurySpokeDeployProcedure, - AaveV4HubConfiguratorDeployProcedure + AaveV4TreasurySpokeDeployProcedure { BatchReports.HubBatchReport internal _report; @@ -19,13 +17,11 @@ contract AaveV4HubBatch is address hubAddress = _deployHub(accessManagerAddress_); address irStrategyAddress = _deployInterestRateStrategy(hubAddress); address treasurySpokeAddress = _deployTreasurySpoke(admin_, hubAddress); - address hubConfiguratorAddress = _deployHubConfigurator(admin_); _report = BatchReports.HubBatchReport({ hubAddress: hubAddress, irStrategyAddress: irStrategyAddress, - treasurySpokeAddress: treasurySpokeAddress, - hubConfiguratorAddress: hubConfiguratorAddress + treasurySpokeAddress: treasurySpokeAddress }); } diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 676a5d7c3..0e793503c 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -7,13 +7,11 @@ import {BatchReports} from 'src/deployments/types/BatchReports.sol'; import {AaveV4SpokeInstanceDeployProcedure} from 'src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol'; import {AaveV4TransparentUpgradeableProxyDeployProcedure} from 'src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol'; import {AaveV4AaveOracleDeployProcedure} from 'src/deployments/procedures/AaveV4AaveOracleDeployProcedure.sol'; -import {AaveV4SpokeConfiguratorDeployProcedure} from 'src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol'; contract AaveV4SpokeInstanceBatch is AaveV4SpokeInstanceDeployProcedure, AaveV4TransparentUpgradeableProxyDeployProcedure, - AaveV4AaveOracleDeployProcedure, - AaveV4SpokeConfiguratorDeployProcedure + AaveV4AaveOracleDeployProcedure { BatchReports.SpokeInstanceBatchReport internal _report; @@ -44,13 +42,10 @@ contract AaveV4SpokeInstanceBatch is require(spokeProxyAddress == predictedSpokeInstanceAddress, 'SpokeInstance address mismatch'); - address spokeConfiguratorAddress = _deploySpokeConfigurator(admin_); - _report = BatchReports.SpokeInstanceBatchReport({ aaveOracleAddress: aaveOracleAddress, spokeImplementationAddress: spokeImplementationAddress, - spokeProxyAddress: spokeProxyAddress, - spokeConfiguratorAddress: spokeConfiguratorAddress + spokeProxyAddress: spokeProxyAddress }); } diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 701c9c887..be0ae6b33 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -6,6 +6,7 @@ import 'forge-std/Vm.sol'; import {Logger} from 'src/deployments/utils/Logger.sol'; import {BatchReports} from 'src/deployments/types/BatchReports.sol'; import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; +import {AaveV4ConfiguratorBatch} from 'src/deployments/batches/AaveV4ConfiguratorBatch.sol'; import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; import {AaveV4GatewaysBatch} from 'src/deployments/batches/AaveV4GatewaysBatch.sol'; @@ -28,6 +29,7 @@ library AaveV4DeployOrchestration { struct FullDeploymentReport { BatchReports.AccessBatchReport accessBatchReport; + BatchReports.ConfiguratorBatchReport configuratorBatchReport; SpokeDeploymentReport spokeInstanceBatchReport; HubDeploymentReport hubBatchReport; BatchReports.GatewaysBatchReport gatewaysBatchReport; @@ -47,6 +49,11 @@ library AaveV4DeployOrchestration { report.accessBatchReport = _deployAccessBatch(admin); logger.log('AccessManager', report.accessBatchReport.accessManagerAddress); + // Deploy Configurator Batch + report.configuratorBatchReport = _deployConfiguratorBatch(admin); + logger.log('HubConfigurator', report.configuratorBatchReport.hubConfiguratorAddress); + logger.log('SpokeConfigurator', report.configuratorBatchReport.spokeConfiguratorAddress); + // Deploy Hub Batches uint256 hubCount = hubLabels.length; Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](hubCount); @@ -69,10 +76,6 @@ library AaveV4DeployOrchestration { string.concat(hubLabels[i], ' TreasurySpoke'), report.hubBatchReport.report.treasurySpokeAddress ); - logger.log( - string.concat(hubLabels[i], ' HubConfigurator'), - report.hubBatchReport.report.hubConfiguratorAddress - ); } logger.writeGroup('Hubs', hubEntries); @@ -103,10 +106,6 @@ library AaveV4DeployOrchestration { string.concat(spokeLabels[i], ' AaveOracle'), report.spokeInstanceBatchReport.report.aaveOracleAddress ); - logger.log( - string.concat(spokeLabels[i], ' SpokeConfigurator'), - report.spokeInstanceBatchReport.report.spokeConfiguratorAddress - ); } logger.writeGroup('SpokeInstances', spokeEntries); @@ -130,7 +129,6 @@ library AaveV4DeployOrchestration { logger.write('Hub', hubReport.report.hubAddress); logger.write('InterestRateStrategy', hubReport.report.irStrategyAddress); logger.write('TreasurySpoke', hubReport.report.treasurySpokeAddress); - logger.write('HubConfigurator', hubReport.report.hubConfiguratorAddress); return hubReport; } @@ -147,7 +145,6 @@ library AaveV4DeployOrchestration { logger.write('SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); logger.write('SpokeInstance Implementation', spokeReport.report.spokeImplementationAddress); logger.write('AaveOracle', spokeReport.report.aaveOracleAddress); - logger.write('SpokeConfigurator', spokeReport.report.spokeConfiguratorAddress); return spokeReport; } @@ -158,6 +155,13 @@ library AaveV4DeployOrchestration { return accessBatch.getReport(); } + function _deployConfiguratorBatch( + address admin + ) internal returns (BatchReports.ConfiguratorBatchReport memory) { + AaveV4ConfiguratorBatch configuratorBatch = new AaveV4ConfiguratorBatch(admin); + return configuratorBatch.getReport(); + } + function _deployHubBatch( address admin, address accessManagerAddress diff --git a/src/deployments/types/BatchReports.sol b/src/deployments/types/BatchReports.sol index 9688b499f..fe09353e8 100644 --- a/src/deployments/types/BatchReports.sol +++ b/src/deployments/types/BatchReports.sol @@ -6,18 +6,21 @@ library BatchReports { address accessManagerAddress; } + struct ConfiguratorBatchReport { + address hubConfiguratorAddress; + address spokeConfiguratorAddress; + } + struct SpokeInstanceBatchReport { address spokeImplementationAddress; address spokeProxyAddress; address aaveOracleAddress; - address spokeConfiguratorAddress; } struct HubBatchReport { address hubAddress; address irStrategyAddress; address treasurySpokeAddress; - address hubConfiguratorAddress; } struct GatewaysBatchReport { From 2aaeb00a9aebab1294c8e78c7fdb9477c61ba891 Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Mon, 10 Nov 2025 15:24:08 +0100 Subject: [PATCH 07/62] feat : roles procedures & small fixes --- scripts/deploy/AaveV4DeployBatch.s.sol | 21 +++-- src/deployments/batches/AaveV4AccessBatch.sol | 2 +- .../batches/AaveV4ConfiguratorBatch.sol | 4 +- .../batches/AaveV4GatewaysBatch.sol | 4 +- src/deployments/batches/AaveV4HubBatch.sol | 6 +- .../batches/AaveV4SpokeInstanceBatch.sol | 6 +- .../AaveV4DeployOrchestration.sol | 81 ++++++++++++++----- .../AaveV4AaveOracleDeployProcedure.sol | 0 .../AaveV4AccessManagerDeployProcedure.sol | 0 .../AaveV4HubConfiguratorDeployProcedure.sol | 0 .../{ => deploy}/AaveV4HubDeployProcedure.sol | 0 ...eV4InterestRateStrategyDeployProcedure.sol | 0 ...aveV4NativeTokenGatewayDeployProcedure.sol | 0 .../AaveV4SignatureGatewayDeployProcedure.sol | 0 ...AaveV4SpokeConfiguratorDeployProcedure.sol | 0 .../AaveV4SpokeInstanceDeployProcedure.sol | 0 ...sparentUpgradeableProxyDeployProcedure.sol | 0 .../AaveV4TreasurySpokeDeployProcedure.sol | 0 .../roles/AaveV4AdminRolesProcedure.sol | 21 +++++ .../roles/AaveV4HubRolesProcedure.sol | 23 ++++++ .../roles/AaveV4SpokeRolesProcedure.sol | 25 ++++++ src/deployments/utils/InputUtils.sol | 3 + src/deployments/utils/Logger.sol | 12 +-- 23 files changed, 161 insertions(+), 47 deletions(-) rename src/deployments/procedures/{ => deploy}/AaveV4AaveOracleDeployProcedure.sol (100%) rename src/deployments/procedures/{ => deploy}/AaveV4AccessManagerDeployProcedure.sol (100%) rename src/deployments/procedures/{ => deploy}/AaveV4HubConfiguratorDeployProcedure.sol (100%) rename src/deployments/procedures/{ => deploy}/AaveV4HubDeployProcedure.sol (100%) rename src/deployments/procedures/{ => deploy}/AaveV4InterestRateStrategyDeployProcedure.sol (100%) rename src/deployments/procedures/{ => deploy}/AaveV4NativeTokenGatewayDeployProcedure.sol (100%) rename src/deployments/procedures/{ => deploy}/AaveV4SignatureGatewayDeployProcedure.sol (100%) rename src/deployments/procedures/{ => deploy}/AaveV4SpokeConfiguratorDeployProcedure.sol (100%) rename src/deployments/procedures/{ => deploy}/AaveV4SpokeInstanceDeployProcedure.sol (100%) rename src/deployments/procedures/{ => deploy}/AaveV4TransparentUpgradeableProxyDeployProcedure.sol (100%) rename src/deployments/procedures/{ => deploy}/AaveV4TreasurySpokeDeployProcedure.sol (100%) create mode 100644 src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol create mode 100644 src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol create mode 100644 src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index 4f0695378..908aa0a53 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -20,26 +20,23 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { function run() external { Logger logger = new Logger(OUTPUT_PATH); FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); - //TODO : load roles address deployer = msg.sender; logger.log('Starting Aave V4 Batch Deployment'); vm.startBroadcast(); - AaveV4DeployOrchestration.FullDeploymentReport memory report = AaveV4DeployOrchestration - .deployAaveV4( - logger, - deployer, - inputs.admin, - inputs.nativeWrapperAddress, - inputs.hubLabels, - inputs.spokeLabels - ); + AaveV4DeployOrchestration.deployAaveV4( + logger, + deployer, + inputs.admin, + inputs.nativeWrapperAddress, + inputs.hubLabels, + inputs.spokeLabels, + inputs.setRoles + ); vm.stopBroadcast(); - // TODO : apply roles - logger.log('Batch Deployment Completed'); logger.log('Saving Logs'); logger.save(); diff --git a/src/deployments/batches/AaveV4AccessBatch.sol b/src/deployments/batches/AaveV4AccessBatch.sol index cf9d11f46..8e29244e8 100644 --- a/src/deployments/batches/AaveV4AccessBatch.sol +++ b/src/deployments/batches/AaveV4AccessBatch.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/types/BatchReports.sol'; -import {AaveV4AccessManagerDeployProcedure} from 'src/deployments/procedures/AaveV4AccessManagerDeployProcedure.sol'; +import {AaveV4AccessManagerDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4AccessManagerDeployProcedure.sol'; contract AaveV4AccessBatch is AaveV4AccessManagerDeployProcedure { BatchReports.AccessBatchReport internal _report; diff --git a/src/deployments/batches/AaveV4ConfiguratorBatch.sol b/src/deployments/batches/AaveV4ConfiguratorBatch.sol index 21fea9b00..b19e50e1a 100644 --- a/src/deployments/batches/AaveV4ConfiguratorBatch.sol +++ b/src/deployments/batches/AaveV4ConfiguratorBatch.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/types/BatchReports.sol'; -import {AaveV4HubConfiguratorDeployProcedure} from 'src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol'; -import {AaveV4SpokeConfiguratorDeployProcedure} from 'src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol'; +import {AaveV4HubConfiguratorDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol'; +import {AaveV4SpokeConfiguratorDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol'; contract AaveV4ConfiguratorBatch is AaveV4HubConfiguratorDeployProcedure, diff --git a/src/deployments/batches/AaveV4GatewaysBatch.sol b/src/deployments/batches/AaveV4GatewaysBatch.sol index 45c428f9e..36f829097 100644 --- a/src/deployments/batches/AaveV4GatewaysBatch.sol +++ b/src/deployments/batches/AaveV4GatewaysBatch.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/types/BatchReports.sol'; -import {AaveV4NativeTokenGatewayDeployProcedure} from 'src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol'; -import {AaveV4SignatureGatewayDeployProcedure} from 'src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol'; +import {AaveV4NativeTokenGatewayDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol'; +import {AaveV4SignatureGatewayDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol'; contract AaveV4GatewaysBatch is AaveV4NativeTokenGatewayDeployProcedure, diff --git a/src/deployments/batches/AaveV4HubBatch.sol b/src/deployments/batches/AaveV4HubBatch.sol index 8fb8c60b0..e3640a2c3 100644 --- a/src/deployments/batches/AaveV4HubBatch.sol +++ b/src/deployments/batches/AaveV4HubBatch.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/types/BatchReports.sol'; -import {AaveV4HubDeployProcedure} from 'src/deployments/procedures/AaveV4HubDeployProcedure.sol'; -import {AaveV4InterestRateStrategyDeployProcedure} from 'src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol'; -import {AaveV4TreasurySpokeDeployProcedure} from 'src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol'; +import {AaveV4HubDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol'; +import {AaveV4InterestRateStrategyDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol'; +import {AaveV4TreasurySpokeDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol'; contract AaveV4HubBatch is AaveV4HubDeployProcedure, diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 0e793503c..2fe0e2ef6 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -4,9 +4,9 @@ pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; import {BatchReports} from 'src/deployments/types/BatchReports.sol'; -import {AaveV4SpokeInstanceDeployProcedure} from 'src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol'; -import {AaveV4TransparentUpgradeableProxyDeployProcedure} from 'src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol'; -import {AaveV4AaveOracleDeployProcedure} from 'src/deployments/procedures/AaveV4AaveOracleDeployProcedure.sol'; +import {AaveV4SpokeInstanceDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol'; +import {AaveV4TransparentUpgradeableProxyDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol'; +import {AaveV4AaveOracleDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol'; contract AaveV4SpokeInstanceBatch is AaveV4SpokeInstanceDeployProcedure, diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index be0ae6b33..79dc0e113 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -5,12 +5,17 @@ import 'forge-std/Vm.sol'; import {Logger} from 'src/deployments/utils/Logger.sol'; import {BatchReports} from 'src/deployments/types/BatchReports.sol'; + import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; import {AaveV4ConfiguratorBatch} from 'src/deployments/batches/AaveV4ConfiguratorBatch.sol'; import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; import {AaveV4GatewaysBatch} from 'src/deployments/batches/AaveV4GatewaysBatch.sol'; +import {AaveV4AdminRolesProcedure} from 'src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol'; +import {AaveV4HubRolesProcedure} from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; +import {AaveV4SpokeRolesProcedure} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; + library AaveV4DeployOrchestration { Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); @@ -30,8 +35,8 @@ library AaveV4DeployOrchestration { struct FullDeploymentReport { BatchReports.AccessBatchReport accessBatchReport; BatchReports.ConfiguratorBatchReport configuratorBatchReport; - SpokeDeploymentReport spokeInstanceBatchReport; - HubDeploymentReport hubBatchReport; + SpokeDeploymentReport[] spokeInstanceBatchReports; + HubDeploymentReport[] hubBatchReports; BatchReports.GatewaysBatchReport gatewaysBatchReport; } @@ -41,12 +46,14 @@ library AaveV4DeployOrchestration { address admin, address nativeWrapper, string[] memory hubLabels, - string[] memory spokeLabels + string[] memory spokeLabels, + bool setRoles ) internal returns (FullDeploymentReport memory) { FullDeploymentReport memory report; // Deploy Access Batch - report.accessBatchReport = _deployAccessBatch(admin); + address accessManagerAdmin = setRoles ? deployer : admin; + report.accessBatchReport = _deployAccessBatch(accessManagerAdmin); logger.log('AccessManager', report.accessBatchReport.accessManagerAddress); // Deploy Configurator Batch @@ -56,35 +63,37 @@ library AaveV4DeployOrchestration { // Deploy Hub Batches uint256 hubCount = hubLabels.length; + report.hubBatchReports = new HubDeploymentReport[](hubCount); Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](hubCount); for (uint256 i; i < hubCount; i++) { - report.hubBatchReport.label = hubLabels[i]; - report.hubBatchReport.report = _deployHubBatch( + report.hubBatchReports[i].label = hubLabels[i]; + report.hubBatchReports[i].report = _deployHubBatch( admin, report.accessBatchReport.accessManagerAddress ); hubEntries[i] = Logger.AddressEntry({ label: hubLabels[i], - value: report.hubBatchReport.report.hubAddress + value: report.hubBatchReports[i].report.hubAddress }); - logger.log(string.concat(hubLabels[i], ' Hub'), report.hubBatchReport.report.hubAddress); + logger.log(string.concat(hubLabels[i], ' Hub'), report.hubBatchReports[i].report.hubAddress); logger.log( string.concat(hubLabels[i], ' InterestRateStrategy'), - report.hubBatchReport.report.irStrategyAddress + report.hubBatchReports[i].report.irStrategyAddress ); logger.log( string.concat(hubLabels[i], ' TreasurySpoke'), - report.hubBatchReport.report.treasurySpokeAddress + report.hubBatchReports[i].report.treasurySpokeAddress ); } logger.writeGroup('Hubs', hubEntries); // Deploy Spoke Instance Batches uint256 spokeCount = spokeLabels.length; + report.spokeInstanceBatchReports = new SpokeDeploymentReport[](spokeCount); Logger.AddressEntry[] memory spokeEntries = new Logger.AddressEntry[](spokeCount); for (uint256 i; i < spokeCount; i++) { - report.spokeInstanceBatchReport.label = spokeLabels[i]; - report.spokeInstanceBatchReport.report = _deploySpokeInstanceBatch( + report.spokeInstanceBatchReports[i].label = spokeLabels[i]; + report.spokeInstanceBatchReports[i].report = _deploySpokeInstanceBatch( deployer, admin, report.accessBatchReport.accessManagerAddress, @@ -92,19 +101,19 @@ library AaveV4DeployOrchestration { ); spokeEntries[i] = Logger.AddressEntry({ label: spokeLabels[i], - value: report.spokeInstanceBatchReport.report.spokeProxyAddress + value: report.spokeInstanceBatchReports[i].report.spokeProxyAddress }); logger.log( string.concat(spokeLabels[i], ' SpokeInstance Proxy'), - report.spokeInstanceBatchReport.report.spokeProxyAddress + report.spokeInstanceBatchReports[i].report.spokeProxyAddress ); logger.log( string.concat(spokeLabels[i], ' SpokeInstance Implementation'), - report.spokeInstanceBatchReport.report.spokeImplementationAddress + report.spokeInstanceBatchReports[i].report.spokeImplementationAddress ); logger.log( string.concat(spokeLabels[i], ' AaveOracle'), - report.spokeInstanceBatchReport.report.aaveOracleAddress + report.spokeInstanceBatchReports[i].report.aaveOracleAddress ); } logger.writeGroup('SpokeInstances', spokeEntries); @@ -114,6 +123,27 @@ library AaveV4DeployOrchestration { logger.log('NativeTokenGateway', report.gatewaysBatchReport.nativeGatewayAddress); logger.log('SignatureGateway', report.gatewaysBatchReport.signatureGatewayAddress); + // Set Roles if needed + if (setRoles) { + AaveV4AdminRolesProcedure.setConfiguratorAdminRoles( + report.accessBatchReport.accessManagerAddress, + report.configuratorBatchReport.spokeConfiguratorAddress, + report.configuratorBatchReport.hubConfiguratorAddress + ); + for (uint256 i; i < hubCount; i++) { + AaveV4HubRolesProcedure.setHubRoles( + report.accessBatchReport.accessManagerAddress, + report.hubBatchReports[i].report.hubAddress + ); + } + for (uint256 i; i < spokeCount; i++) { + AaveV4SpokeRolesProcedure.setSpokeRoles( + report.accessBatchReport.accessManagerAddress, + report.spokeInstanceBatchReports[i].report.spokeProxyAddress + ); + } + } + return report; } @@ -121,7 +151,8 @@ library AaveV4DeployOrchestration { Logger logger, address admin, address accessManagerAddress, - string memory label + string memory label, + bool setRoles ) internal returns (HubDeploymentReport memory) { HubDeploymentReport memory hubReport; hubReport.label = label; @@ -129,6 +160,11 @@ library AaveV4DeployOrchestration { logger.write('Hub', hubReport.report.hubAddress); logger.write('InterestRateStrategy', hubReport.report.irStrategyAddress); logger.write('TreasurySpoke', hubReport.report.treasurySpokeAddress); + + if (setRoles) { + AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); + } + return hubReport; } @@ -137,7 +173,8 @@ library AaveV4DeployOrchestration { address deployer, address admin, address accessManagerAddress, - string memory label + string memory label, + bool setRoles ) internal returns (SpokeDeploymentReport memory) { SpokeDeploymentReport memory spokeReport; spokeReport.label = label; @@ -145,6 +182,14 @@ library AaveV4DeployOrchestration { logger.write('SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); logger.write('SpokeInstance Implementation', spokeReport.report.spokeImplementationAddress); logger.write('AaveOracle', spokeReport.report.aaveOracleAddress); + + if (setRoles) { + AaveV4SpokeRolesProcedure.setSpokeRoles( + accessManagerAddress, + spokeReport.report.spokeProxyAddress + ); + } + return spokeReport; } diff --git a/src/deployments/procedures/AaveV4AaveOracleDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4AaveOracleDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol diff --git a/src/deployments/procedures/AaveV4AccessManagerDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AccessManagerDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4AccessManagerDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4AccessManagerDeployProcedure.sol diff --git a/src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4HubConfiguratorDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol diff --git a/src/deployments/procedures/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4HubDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol diff --git a/src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4InterestRateStrategyDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol diff --git a/src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol diff --git a/src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4SignatureGatewayDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol diff --git a/src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol diff --git a/src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4SpokeInstanceDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol diff --git a/src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4TransparentUpgradeableProxyDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol diff --git a/src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/AaveV4TreasurySpokeDeployProcedure.sol rename to src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol diff --git a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol new file mode 100644 index 000000000..fc6e6e703 --- /dev/null +++ b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Roles} from 'src/libraries/types/Roles.sol'; + +import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; + +library AaveV4AdminRolesProcedure { + function setConfiguratorAdminRoles( + address accessManagerAddress, + address spokeConfiguratorAddress, + address hubConfiguratorAddress + ) internal { + IAccessManager(accessManagerAddress).grantRole(Roles.HUB_ADMIN_ROLE, hubConfiguratorAddress, 0); + IAccessManager(accessManagerAddress).grantRole( + Roles.SPOKE_ADMIN_ROLE, + spokeConfiguratorAddress, + 0 + ); + } +} diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol new file mode 100644 index 000000000..176193e5c --- /dev/null +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Roles} from 'src/libraries/types/Roles.sol'; + +import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; +import {IHub} from 'src/hub/interfaces/IHub.sol'; + +library AaveV4HubRolesProcedure { + function setHubRoles(address accessManagerAddress, address hubAddress) internal { + bytes4[] memory selectors = new bytes4[](5); + selectors[0] = IHub.addAsset.selector; + selectors[1] = IHub.updateAssetConfig.selector; + selectors[2] = IHub.addSpoke.selector; + selectors[3] = IHub.updateSpokeConfig.selector; + selectors[4] = IHub.setInterestRateData.selector; + IAccessManager(accessManagerAddress).setTargetFunctionRole( + hubAddress, + selectors, + Roles.HUB_ADMIN_ROLE + ); + } +} diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol new file mode 100644 index 000000000..45cb3583e --- /dev/null +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Roles} from 'src/libraries/types/Roles.sol'; + +import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; +import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; + +library AaveV4SpokeRolesProcedure { + function setSpokeRoles(address accessManagerAddress, address spokeAddress) internal { + bytes4[] memory selectors = new bytes4[](7); + selectors[0] = ISpoke.updateLiquidationConfig.selector; + selectors[1] = ISpoke.addReserve.selector; + selectors[2] = ISpoke.updateReserveConfig.selector; + selectors[3] = ISpoke.updateReservePriceSource.selector; + selectors[4] = ISpoke.addDynamicReserveConfig.selector; + selectors[5] = ISpoke.updateDynamicReserveConfig.selector; + selectors[6] = ISpoke.updatePositionManager.selector; + IAccessManager(accessManagerAddress).setTargetFunctionRole( + spokeAddress, + selectors, + Roles.SPOKE_ADMIN_ROLE + ); + } +} diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index 5221170c7..174ca1d48 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -10,17 +10,20 @@ contract InputUtils { struct FullDeployInputs { address admin; address nativeWrapperAddress; + bool setRoles; string[] hubLabels; string[] spokeLabels; } struct SpokeDeployInputs { address admin; + bool setRoles; string spokeLabel; } struct HubDeployInputs { address admin; + bool setRoles; string hubLabel; } diff --git a/src/deployments/utils/Logger.sol b/src/deployments/utils/Logger.sol index e5c67df25..f0249f877 100644 --- a/src/deployments/utils/Logger.sol +++ b/src/deployments/utils/Logger.sol @@ -28,15 +28,15 @@ contract Logger { _outputPath = outputPath_; } - function log(string memory label, address value) public view { + function log(string memory label, address value) public pure { _log(label, value); } - function log(string memory label, uint256 value) public view { + function log(string memory label, uint256 value) public pure { _log(label, value); } - function log(string memory value) public view { + function log(string memory value) public pure { _log(value); } @@ -67,15 +67,15 @@ contract Logger { vm.writeJson(_root, _outputPath); } - function _log(string memory label, address value) internal view { + function _log(string memory label, address value) internal pure { console.log('%s: %s', label, value); } - function _log(string memory label, uint256 value) internal view { + function _log(string memory label, uint256 value) internal pure { console.log('%s: %s', label, value); } - function _log(string memory value) internal view { + function _log(string memory value) internal pure { console.log(value); } From 45813878c456ffc3cf24590e8b3300f037cda504 Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Tue, 11 Nov 2025 17:12:40 +0100 Subject: [PATCH 08/62] feat : test env orchestration (WIP) --- src/deployments/batches/TestTokensBatch.sol | 32 ++++ .../AaveV4DeployOrchestration.sol | 5 + .../orchestration/AaveV4TestOrchestration.sol | 168 ++++++++++++++++++ .../deploy/TestnetERC20DeployProcedure.sol | 16 ++ .../procedures/deploy/WETHDeployProcedure.sol | 12 ++ .../roles/AaveV4AdminRolesProcedure.sol | 30 ++++ .../roles/AaveV4SpokeRolesProcedure.sol | 14 ++ src/deployments/types/BatchReports.sol | 5 + 8 files changed, 282 insertions(+) create mode 100644 src/deployments/batches/TestTokensBatch.sol create mode 100644 src/deployments/orchestration/AaveV4TestOrchestration.sol create mode 100644 src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol create mode 100644 src/deployments/procedures/deploy/WETHDeployProcedure.sol diff --git a/src/deployments/batches/TestTokensBatch.sol b/src/deployments/batches/TestTokensBatch.sol new file mode 100644 index 000000000..18f8afc31 --- /dev/null +++ b/src/deployments/batches/TestTokensBatch.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {BatchReports} from 'src/deployments/types/BatchReports.sol'; + +import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; +import {TestnetERC20DeployProcedure} from 'src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol'; + +contract TestTokensBatch is WETHDeployProcedure, TestnetERC20DeployProcedure { + struct TestTokensInput { + string name; + string symbol; + uint8 decimals; + } + + BatchReports.TestTokensBatchReport internal _report; + + constructor(TestTokensInput[] memory inputs_) { + _report.tokenAddresses = new address[](inputs_.length); + _report.wethAddress = _deployWETH(); + + for (uint256 i; i < inputs_.length; i++) { + TestTokensInput memory input = inputs_[i]; + address tokenAddress = _deployTestnetERC20(input.name, input.symbol, input.decimals); + _report.tokenAddresses[i] = tokenAddress; + } + } + + function getReport() external view returns (BatchReports.TestTokensBatchReport memory) { + return _report; + } +} diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 79dc0e113..c28005f6d 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -142,6 +142,11 @@ library AaveV4DeployOrchestration { report.spokeInstanceBatchReports[i].report.spokeProxyAddress ); } + AaveV4AdminRolesProcedure.setNewAdminRole( + report.accessBatchReport.accessManagerAddress, + admin, + deployer + ); } return report; diff --git a/src/deployments/orchestration/AaveV4TestOrchestration.sol b/src/deployments/orchestration/AaveV4TestOrchestration.sol new file mode 100644 index 000000000..eee02fb13 --- /dev/null +++ b/src/deployments/orchestration/AaveV4TestOrchestration.sol @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import 'forge-std/Vm.sol'; + +import {BatchReports} from 'src/deployments/types/BatchReports.sol'; + +import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; +import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; +import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; + +import {TestTokensBatch} from 'src/deployments/batches/TestTokensBatch.sol'; + +import {AaveV4AdminRolesProcedure} from 'src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol'; +import {AaveV4HubRolesProcedure} from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; +import {AaveV4SpokeRolesProcedure} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; + +library AaveV4TestOrchestration { + Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); + + uint8 constant ORACLE_DECIMALS = 8; + string constant ORACLE_SUFFIX = ' (USD)'; + + struct TestHubReport { + address hubAddress; + address interestRateStrategyAddress; + address treasurySpokeAddress; + } + + struct TestSpokeReport { + address spokeAddress; + address aaveOracleAddress; + } + + struct TestEnvReport { + address wethAddress; + address[] testTokenAddresses; + address accessManagerAddress; + TestHubReport[] hubReports; + TestSpokeReport[] spokeReports; + } + + function deployTestEnv( + address admin, + address treasuryAdmin, + uint256 hubCount, + uint256 spokeCount, + TestTokensBatch.TestTokenInput[] memory tokenInputs, + ) external returns(TestEnvReport memory) { + TestEnvReport memory report; + + report.testTokenAddresses = new address[](tokenInputs.length); + report.hubReports = new TestHubReport[](hubCount); + report.spokeReports = new TestSpokeReport[](spokeCount); + + // Deploy Test Tokens Batch + BatchReports.TestTokensBatchReport memory tokensReport = _deployTokensBatch(tokenInputs); + report.wethAddress = tokensReport.wethAddress; + report.testTokenAddresses = tokensReport.tokenAddresses; + + // Deploy Access Batch + report.accessManagerAddress = _deployAccessBatch(admin).accessManagerAddress; + + // Deploy Hub Batches + for (uint256 i; i < hubCount; i++) { + BatchReports.HubBatchReport memory hubReport = _deployHubBatch( + treasuryAdmin, + report.accessManagerAddress + ); + report.hubReports[i].hubAddress = hubReport.hubAddress; + report.hubReports[i].interestRateStrategyAddress = hubReport.interestRateStrategyAddress; + report.hubReports[i].treasurySpokeAddress = hubReport.treasurySpokeAddress; + } + + // Deploy Spoke Instance Batches + for (uint256 i; i < spokeCount; i++) { + BatchReports.SpokeInstanceBatchReport memory spokeReport = _deploySpokeInstanceBatch( + admin, + report.accessManagerAddress, + string.concat('Spoke ', i, ' (USD)') + ); + report.spokeReports[i].spokeAddress = spokeReport.spokeProxyAddress; + report.spokeReports[i].aaveOracleAddress = spokeReport.aaveOracleAddress; + } + + return report; + } + + function setRolesTestEnv( + address admin, + address hubAdmin, + address spokeAdmin, + TestEnvReport memory report + ) external { + // Set Admin Roles + AaveV4AdminRolesProcedure.setAdminRoles( + report.accessManagerAddress, + admin + ); + AaveV4AdminRolesProcedure.setConfiguratorHubAdminRole( + report.accessManagerAddress, + hubAdmin + ); + AaveV4AdminRolesProcedure.setConfiguratorSpokeAdminRole( + report.accessManagerAddress, + spokeAdmin + ); + + // Set Hub Roles + for (uint256 i; i < report.hubReports.length; i++) { + AaveV4HubRolesProcedure.setHubRoles( + report.accessManagerAddress, + report.hubReports[i].hubAddress + ); + } + + // Set Spoke Roles + for (uint256 i; i < report.spokeReports.length; i++) { + AaveV4SpokeRolesProcedure.setSpokeRoles( + report.accessManagerAddress, + report.spokeReports[i].spokeAddress + ); + AaveV4SpokeRolesProcedure.setSpokeUserPositionAdapterRole( + report.accessManagerAddress, + report.spokeReports[i].spokeAddress + ); + } + } + + function _deployTokensBatch( + TestTokensBatch.TestTokenInput[] memory tokenInputs + ) internal returns (BatchReports.TestTokensBatchReport memory) { + TestTokensBatch tokensBatch = new TestTokensBatch(tokenInputs); + return tokensBatch.getReport(); + } + + function _deployAccessBatch( + address admin + ) internal returns (BatchReports.AccessBatchReport memory) { + AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin); + return accessBatch.getReport(); + } + + function _deployHubBatch( + address admin, + address accessManagerAddress + ) internal returns (BatchReports.HubBatchReport memory) { + AaveV4HubBatch hubBatch = new AaveV4HubBatch(admin, accessManagerAddress); + return hubBatch.getReport(); + } + + function _deploySpokeInstanceBatch( + address admin, + address accessManagerAddress, + string memory label + ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { + AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch( + vm, + admin, + admin, + accessManagerAddress, + 8, + label + ); + return spokeInstanceBatch.getReport(); + } + +} \ No newline at end of file diff --git a/src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol b/src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol new file mode 100644 index 000000000..a2bf2c130 --- /dev/null +++ b/src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {TestnetERC20} from 'tests/mocks/TestnetERC20.sol'; + +contract TestnetERC20DeployProcedure { + function _deployTestnetERC20( + string memory name_, + string memory symbol_, + uint8 decimals_ + ) internal returns (address) { + address token = address(new TestnetERC20(name_, symbol_, decimals_)); + + return token; + } +} diff --git a/src/deployments/procedures/deploy/WETHDeployProcedure.sol b/src/deployments/procedures/deploy/WETHDeployProcedure.sol new file mode 100644 index 000000000..938e1b304 --- /dev/null +++ b/src/deployments/procedures/deploy/WETHDeployProcedure.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {WETH9} from 'src/dependencies/weth/WETH9.sol'; + +contract WETHDeployProcedure { + function _deployWETH() internal returns (address) { + address weth = address(new WETH9()); + + return weth; + } +} diff --git a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol index fc6e6e703..067ab975f 100644 --- a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol @@ -18,4 +18,34 @@ library AaveV4AdminRolesProcedure { 0 ); } + + function setConfiguratorHubAdminRole( + address accessManagerAddress, + address hubConfiguratorAddress + ) internal { + IAccessManager(accessManagerAddress).grantRole(Roles.HUB_ADMIN_ROLE, hubConfiguratorAddress, 0); + } + + function setConfiguratorSpokeAdminRole( + address accessManagerAddress, + address spokeConfiguratorAddress + ) internal { + IAccessManager(accessManagerAddress).grantRole( + Roles.SPOKE_ADMIN_ROLE, + spokeConfiguratorAddress, + 0 + ); + } + + function setNewAdminRole( + address accessManagerAddress, + address newAdminAddress, + address currentAdminAddress + ) internal { + IAccessManager(accessManagerAddress).grantRole(Roles.DEFAULT_ADMIN_ROLE, newAdminAddress, 0); + IAccessManager(accessManagerAddress).renounceRole( + Roles.DEFAULT_ADMIN_ROLE, + currentAdminAddress + ); + } } diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol index 45cb3583e..e276b571f 100644 --- a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -22,4 +22,18 @@ library AaveV4SpokeRolesProcedure { Roles.SPOKE_ADMIN_ROLE ); } + + function setSpokeUserPositionAdapterRole( + address accessManagerAddress, + address spokeAddress + ) internal { + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = ISpoke.updateUserDynamicConfig.selector; + selectors[1] = ISpoke.updateUserRiskPremium.selector; + IAccessManager(accessManagerAddress).setTargetFunctionRole( + spokeAddress, + selectors, + Roles.USER_POSITION_UPDATER_ROLE + ); + } } diff --git a/src/deployments/types/BatchReports.sol b/src/deployments/types/BatchReports.sol index fe09353e8..1e40429ba 100644 --- a/src/deployments/types/BatchReports.sol +++ b/src/deployments/types/BatchReports.sol @@ -27,4 +27,9 @@ library BatchReports { address signatureGatewayAddress; address nativeGatewayAddress; } + + struct TestTokensBatchReport { + address wethAddress; + address[] tokenAddresses; + } } From b94ed13266e857bda1cd8c3b67dfddabe7a51b2f Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Tue, 11 Nov 2025 17:25:16 +0100 Subject: [PATCH 09/62] fix : fix errors test env orchestration --- src/deployments/batches/TestTokensBatch.sol | 6 ++--- .../orchestration/AaveV4TestOrchestration.sol | 23 +++++++------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/deployments/batches/TestTokensBatch.sol b/src/deployments/batches/TestTokensBatch.sol index 18f8afc31..441a60363 100644 --- a/src/deployments/batches/TestTokensBatch.sol +++ b/src/deployments/batches/TestTokensBatch.sol @@ -7,7 +7,7 @@ import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployP import {TestnetERC20DeployProcedure} from 'src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol'; contract TestTokensBatch is WETHDeployProcedure, TestnetERC20DeployProcedure { - struct TestTokensInput { + struct TestTokenInput { string name; string symbol; uint8 decimals; @@ -15,12 +15,12 @@ contract TestTokensBatch is WETHDeployProcedure, TestnetERC20DeployProcedure { BatchReports.TestTokensBatchReport internal _report; - constructor(TestTokensInput[] memory inputs_) { + constructor(TestTokenInput[] memory inputs_) { _report.tokenAddresses = new address[](inputs_.length); _report.wethAddress = _deployWETH(); for (uint256 i; i < inputs_.length; i++) { - TestTokensInput memory input = inputs_[i]; + TestTokenInput memory input = inputs_[i]; address tokenAddress = _deployTestnetERC20(input.name, input.symbol, input.decimals); _report.tokenAddresses[i] = tokenAddress; } diff --git a/src/deployments/orchestration/AaveV4TestOrchestration.sol b/src/deployments/orchestration/AaveV4TestOrchestration.sol index eee02fb13..5c241e6f4 100644 --- a/src/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/src/deployments/orchestration/AaveV4TestOrchestration.sol @@ -23,7 +23,7 @@ library AaveV4TestOrchestration { struct TestHubReport { address hubAddress; - address interestRateStrategyAddress; + address irStrategyAddress; address treasurySpokeAddress; } @@ -45,8 +45,8 @@ library AaveV4TestOrchestration { address treasuryAdmin, uint256 hubCount, uint256 spokeCount, - TestTokensBatch.TestTokenInput[] memory tokenInputs, - ) external returns(TestEnvReport memory) { + TestTokensBatch.TestTokenInput[] memory tokenInputs + ) external returns (TestEnvReport memory) { TestEnvReport memory report; report.testTokenAddresses = new address[](tokenInputs.length); @@ -68,7 +68,7 @@ library AaveV4TestOrchestration { report.accessManagerAddress ); report.hubReports[i].hubAddress = hubReport.hubAddress; - report.hubReports[i].interestRateStrategyAddress = hubReport.interestRateStrategyAddress; + report.hubReports[i].irStrategyAddress = hubReport.irStrategyAddress; report.hubReports[i].treasurySpokeAddress = hubReport.treasurySpokeAddress; } @@ -77,7 +77,7 @@ library AaveV4TestOrchestration { BatchReports.SpokeInstanceBatchReport memory spokeReport = _deploySpokeInstanceBatch( admin, report.accessManagerAddress, - string.concat('Spoke ', i, ' (USD)') + string.concat('Spoke ', string(abi.encode(i)), ' (USD)') ); report.spokeReports[i].spokeAddress = spokeReport.spokeProxyAddress; report.spokeReports[i].aaveOracleAddress = spokeReport.aaveOracleAddress; @@ -93,14 +93,8 @@ library AaveV4TestOrchestration { TestEnvReport memory report ) external { // Set Admin Roles - AaveV4AdminRolesProcedure.setAdminRoles( - report.accessManagerAddress, - admin - ); - AaveV4AdminRolesProcedure.setConfiguratorHubAdminRole( - report.accessManagerAddress, - hubAdmin - ); + AaveV4AdminRolesProcedure.setConfiguratorAdminRoles(report.accessManagerAddress, admin, admin); + AaveV4AdminRolesProcedure.setConfiguratorHubAdminRole(report.accessManagerAddress, hubAdmin); AaveV4AdminRolesProcedure.setConfiguratorSpokeAdminRole( report.accessManagerAddress, spokeAdmin @@ -164,5 +158,4 @@ library AaveV4TestOrchestration { ); return spokeInstanceBatch.getReport(); } - -} \ No newline at end of file +} From e455afbe3b61ba43b49645616cc18a320c86407d Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Wed, 12 Nov 2025 10:00:07 +0100 Subject: [PATCH 10/62] fix : apply latest main changes --- src/deployments/batches/AaveV4AccessBatch.sol | 6 +++--- .../deploy/AaveV4AccessManagerDeployProcedure.sol | 12 ------------ .../AaveV4AccessManagerEnumerableDeployProcedure.sol | 12 ++++++++++++ 3 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 src/deployments/procedures/deploy/AaveV4AccessManagerDeployProcedure.sol create mode 100644 src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol diff --git a/src/deployments/batches/AaveV4AccessBatch.sol b/src/deployments/batches/AaveV4AccessBatch.sol index 8e29244e8..166036e7d 100644 --- a/src/deployments/batches/AaveV4AccessBatch.sol +++ b/src/deployments/batches/AaveV4AccessBatch.sol @@ -2,13 +2,13 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/types/BatchReports.sol'; -import {AaveV4AccessManagerDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4AccessManagerDeployProcedure.sol'; +import {AaveV4AccessManagerEnumerableDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol'; -contract AaveV4AccessBatch is AaveV4AccessManagerDeployProcedure { +contract AaveV4AccessBatch is AaveV4AccessManagerEnumerableDeployProcedure { BatchReports.AccessBatchReport internal _report; constructor(address admin_) { - address accessManagerAddress = _deployAccessManager(admin_); + address accessManagerAddress = _deployAccessManagerEnumerable(admin_); _report = BatchReports.AccessBatchReport({accessManagerAddress: accessManagerAddress}); } diff --git a/src/deployments/procedures/deploy/AaveV4AccessManagerDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AccessManagerDeployProcedure.sol deleted file mode 100644 index cf4ef1595..000000000 --- a/src/deployments/procedures/deploy/AaveV4AccessManagerDeployProcedure.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {AccessManager} from 'src/dependencies/openzeppelin/AccessManager.sol'; - -contract AaveV4AccessManagerDeployProcedure { - function _deployAccessManager(address admin_) internal returns (address) { - address accessManager = address(new AccessManager(admin_)); - - return accessManager; - } -} diff --git a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol new file mode 100644 index 000000000..fa19d89ae --- /dev/null +++ b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AccessManagerEnumerable} from 'src/access/AccessManagerEnumerable.sol'; + +contract AaveV4AccessManagerEnumerableDeployProcedure { + function _deployAccessManagerEnumerable(address admin_) internal returns (address) { + address accessManager = address(new AccessManagerEnumerable(admin_)); + + return accessManager; + } +} From 00433e9595d3e481cf2417c4a02fbf6569740a91 Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Wed, 12 Nov 2025 16:23:01 +0100 Subject: [PATCH 11/62] feat : procedures for Hub & Spoke configs setup (WIP) --- .../AaveV4DeployOrchestration.sol | 1 + .../orchestration/AaveV4TestOrchestration.sol | 1 + .../config/AaveV4HubConfigProcedures.sol | 103 ++++++++++++++++++ .../config/AaveV4SpokeConfigProcedures.sol | 58 ++++++++++ 4 files changed, 163 insertions(+) create mode 100644 src/deployments/procedures/config/AaveV4HubConfigProcedures.sol create mode 100644 src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index c28005f6d..8856808c4 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -17,6 +17,7 @@ import {AaveV4HubRolesProcedure} from 'src/deployments/procedures/roles/AaveV4Hu import {AaveV4SpokeRolesProcedure} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; library AaveV4DeployOrchestration { + bool public constant IS_TEST = true; Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); uint8 constant ORACLE_DECIMALS = 8; diff --git a/src/deployments/orchestration/AaveV4TestOrchestration.sol b/src/deployments/orchestration/AaveV4TestOrchestration.sol index 5c241e6f4..9a03097ac 100644 --- a/src/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/src/deployments/orchestration/AaveV4TestOrchestration.sol @@ -16,6 +16,7 @@ import {AaveV4HubRolesProcedure} from 'src/deployments/procedures/roles/AaveV4Hu import {AaveV4SpokeRolesProcedure} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; library AaveV4TestOrchestration { + bool public constant IS_TEST = true; Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); uint8 constant ORACLE_DECIMALS = 8; diff --git a/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol b/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol new file mode 100644 index 000000000..62070bff0 --- /dev/null +++ b/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IHub} from 'src/hub/interfaces/IHub.sol'; +import {IHubConfigurator} from 'src/hub/interfaces/IHubConfigurator.sol'; + +library AaveV4HubConfigProcedures { + struct AddAssetParams { + address hub; + address underlying; + uint8 decimals; + address feeReceiver; + uint16 liquidityFee; + address irStrategy; + bytes irData; + } + + struct UpdateAssetConfigParams { + address hub; + uint256 assetId; + IHub.AssetConfig config; + bytes irData; + } + + struct AddSpokeParams { + address hub; + uint256 assetId; + address spoke; + IHub.SpokeConfig config; + } + + struct AddSpokeToAssetsParams { + address hub; + address spoke; + uint256[] assetIds; + IHub.SpokeConfig[] configs; + } + + function addAsset(AddAssetParams memory params) internal returns (uint256) { + uint256 assetId = IHub(params.hub).addAsset( + params.underlying, + params.decimals, + params.feeReceiver, + params.irStrategy, + params.irData + ); + if (params.liquidityFee > 0) { + IHub(params.hub).updateAssetConfig( + assetId, + IHub.AssetConfig({ + liquidityFee: params.liquidityFee, + feeReceiver: params.feeReceiver, + irStrategy: params.irStrategy, + reinvestmentController: address(0) + }), + new bytes(0) + ); + } + return assetId; + } + + function addAssetViaConfigurator( + address configurator, + AddAssetParams memory params + ) internal returns (uint256) { + return + IHubConfigurator(configurator).addAsset( + params.hub, + params.underlying, + params.decimals, + params.feeReceiver, + params.liquidityFee, + params.irStrategy, + params.irData + ); + } + + function updateAssetConfig(UpdateAssetConfigParams memory params) internal { + IHub(params.hub).updateAssetConfig(params.assetId, params.config, params.irData); + } + + function addSpoke(AddSpokeParams memory params) internal { + IHub(params.hub).addSpoke(params.assetId, params.spoke, params.config); + } + + function addSpokeViaConfigurator(address configurator, AddSpokeParams memory params) internal { + IHubConfigurator(configurator).addSpoke( + params.hub, + params.spoke, + params.assetId, + params.config + ); + } + + function addSpokeToAssets(address configurator, AddSpokeToAssetsParams memory params) internal { + IHubConfigurator(configurator).addSpokeToAssets( + params.hub, + params.spoke, + params.assetIds, + params.configs + ); + } +} diff --git a/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol b/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol new file mode 100644 index 000000000..20d5e450f --- /dev/null +++ b/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; +import {ISpokeConfigurator} from 'src/spoke/interfaces/ISpokeConfigurator.sol'; + +library AaveV4SpokeConfigProcedures { + struct UpdateLiquidationConfigParams { + address spoke; + ISpoke.LiquidationConfig config; + } + + struct AddReserveParams { + address spoke; + address hub; + uint256 assetId; + address priceSource; + ISpoke.ReserveConfig config; + ISpoke.DynamicReserveConfig dynamicConfig; + } + + function updateLiquidationConfig(UpdateLiquidationConfigParams memory params) internal { + ISpoke(params.spoke).updateLiquidationConfig(params.config); + } + + function updateLiquidationConfigViaConfigurator( + address configurator, + UpdateLiquidationConfigParams memory params + ) internal { + ISpokeConfigurator(configurator).updateLiquidationConfig(params.spoke, params.config); + } + + function addReserve(AddReserveParams memory params) internal returns (uint256) { + return + ISpoke(params.spoke).addReserve( + params.hub, + params.assetId, + params.priceSource, + params.config, + params.dynamicConfig + ); + } + + function addReserveViaConfigurator( + address configurator, + AddReserveParams memory params + ) internal returns (uint256) { + return + ISpokeConfigurator(configurator).addReserve( + params.spoke, + params.hub, + params.assetId, + params.priceSource, + params.config, + params.dynamicConfig + ); + } +} From 945619f1fb0129dbcdea83f8cf6c9e7c215897ba Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Thu, 13 Nov 2025 11:26:42 +0100 Subject: [PATCH 12/62] feat : finish test config engine & reorder structs --- scripts/deploy/AaveV4DeployBatch.s.sol | 2 - src/deployments/batches/AaveV4AccessBatch.sol | 2 +- .../batches/AaveV4ConfiguratorBatch.sol | 2 +- .../batches/AaveV4GatewaysBatch.sol | 2 +- src/deployments/batches/AaveV4HubBatch.sol | 2 +- .../batches/AaveV4SpokeInstanceBatch.sol | 2 +- src/deployments/batches/TestTokensBatch.sol | 2 +- .../{types => libraries}/BatchReports.sol | 0 src/deployments/libraries/ConfigData.sol | 52 ++++++++++++++ .../libraries/OrchestrationReports.sol | 43 +++++++++++ .../AaveV4DeployOrchestration.sol | 49 +++++-------- .../orchestration/AaveV4TestOrchestration.sol | 72 +++++++++++-------- .../config/AaveV4HubConfigProcedures.sol | 51 ++++--------- .../config/AaveV4SpokeConfigProcedures.sol | 26 +++---- 14 files changed, 180 insertions(+), 127 deletions(-) rename src/deployments/{types => libraries}/BatchReports.sol (100%) create mode 100644 src/deployments/libraries/ConfigData.sol create mode 100644 src/deployments/libraries/OrchestrationReports.sol diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index 908aa0a53..86e2280c4 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -7,8 +7,6 @@ import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; import {Logger} from 'src/deployments/utils/Logger.sol'; -import {BatchReports} from 'src/deployments/types/BatchReports.sol'; - import {AaveV4DeployOrchestration} from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { diff --git a/src/deployments/batches/AaveV4AccessBatch.sol b/src/deployments/batches/AaveV4AccessBatch.sol index 166036e7d..d0ce679e7 100644 --- a/src/deployments/batches/AaveV4AccessBatch.sol +++ b/src/deployments/batches/AaveV4AccessBatch.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {AaveV4AccessManagerEnumerableDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol'; contract AaveV4AccessBatch is AaveV4AccessManagerEnumerableDeployProcedure { diff --git a/src/deployments/batches/AaveV4ConfiguratorBatch.sol b/src/deployments/batches/AaveV4ConfiguratorBatch.sol index b19e50e1a..f9d3364af 100644 --- a/src/deployments/batches/AaveV4ConfiguratorBatch.sol +++ b/src/deployments/batches/AaveV4ConfiguratorBatch.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {AaveV4HubConfiguratorDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol'; import {AaveV4SpokeConfiguratorDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol'; diff --git a/src/deployments/batches/AaveV4GatewaysBatch.sol b/src/deployments/batches/AaveV4GatewaysBatch.sol index 36f829097..40c0dd994 100644 --- a/src/deployments/batches/AaveV4GatewaysBatch.sol +++ b/src/deployments/batches/AaveV4GatewaysBatch.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {AaveV4NativeTokenGatewayDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol'; import {AaveV4SignatureGatewayDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol'; diff --git a/src/deployments/batches/AaveV4HubBatch.sol b/src/deployments/batches/AaveV4HubBatch.sol index e3640a2c3..7a8129bc7 100644 --- a/src/deployments/batches/AaveV4HubBatch.sol +++ b/src/deployments/batches/AaveV4HubBatch.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {AaveV4HubDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol'; import {AaveV4InterestRateStrategyDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol'; import {AaveV4TreasurySpokeDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol'; diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 2fe0e2ef6..48a82b04f 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; -import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {AaveV4SpokeInstanceDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol'; import {AaveV4TransparentUpgradeableProxyDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol'; import {AaveV4AaveOracleDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol'; diff --git a/src/deployments/batches/TestTokensBatch.sol b/src/deployments/batches/TestTokensBatch.sol index 441a60363..ca7da0d97 100644 --- a/src/deployments/batches/TestTokensBatch.sol +++ b/src/deployments/batches/TestTokensBatch.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; import {TestnetERC20DeployProcedure} from 'src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol'; diff --git a/src/deployments/types/BatchReports.sol b/src/deployments/libraries/BatchReports.sol similarity index 100% rename from src/deployments/types/BatchReports.sol rename to src/deployments/libraries/BatchReports.sol diff --git a/src/deployments/libraries/ConfigData.sol b/src/deployments/libraries/ConfigData.sol new file mode 100644 index 000000000..db1445228 --- /dev/null +++ b/src/deployments/libraries/ConfigData.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IHub} from 'src/hub/interfaces/IHub.sol'; +import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; + +library ConfigData { + struct AddAssetParams { + address hub; + address underlying; + uint8 decimals; + address feeReceiver; + uint16 liquidityFee; + address irStrategy; + bytes irData; + } + + struct UpdateAssetConfigParams { + address hub; + uint256 assetId; + IHub.AssetConfig config; + bytes irData; + } + + struct AddSpokeParams { + address hub; + uint256 assetId; + address spoke; + IHub.SpokeConfig config; + } + + struct AddSpokeToAssetsParams { + address hub; + address spoke; + uint256[] assetIds; + IHub.SpokeConfig[] configs; + } + + struct UpdateLiquidationConfigParams { + address spoke; + ISpoke.LiquidationConfig config; + } + + struct AddReserveParams { + address spoke; + address hub; + uint256 assetId; + address priceSource; + ISpoke.ReserveConfig config; + ISpoke.DynamicReserveConfig dynamicConfig; + } +} diff --git a/src/deployments/libraries/OrchestrationReports.sol b/src/deployments/libraries/OrchestrationReports.sol new file mode 100644 index 000000000..afb24b48c --- /dev/null +++ b/src/deployments/libraries/OrchestrationReports.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; + +library OrchestrationReports { + struct SpokeDeploymentReport { + string label; + BatchReports.SpokeInstanceBatchReport report; + } + + struct HubDeploymentReport { + string label; + BatchReports.HubBatchReport report; + } + + struct FullDeploymentReport { + BatchReports.AccessBatchReport accessBatchReport; + BatchReports.ConfiguratorBatchReport configuratorBatchReport; + SpokeDeploymentReport[] spokeInstanceBatchReports; + HubDeploymentReport[] hubBatchReports; + BatchReports.GatewaysBatchReport gatewaysBatchReport; + } + + struct TestHubReport { + address hubAddress; + address irStrategyAddress; + address treasurySpokeAddress; + } + + struct TestSpokeReport { + address spokeAddress; + address aaveOracleAddress; + } + + struct TestEnvReport { + address wethAddress; + address[] testTokenAddresses; + address accessManagerAddress; + TestHubReport[] hubReports; + TestSpokeReport[] spokeReports; + } +} diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 8856808c4..ca49c2cf5 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -4,7 +4,8 @@ pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; import {Logger} from 'src/deployments/utils/Logger.sol'; -import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; +import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; import {AaveV4ConfiguratorBatch} from 'src/deployments/batches/AaveV4ConfiguratorBatch.sol'; @@ -20,26 +21,8 @@ library AaveV4DeployOrchestration { bool public constant IS_TEST = true; Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); - uint8 constant ORACLE_DECIMALS = 8; - string constant ORACLE_SUFFIX = ' (USD)'; - - struct SpokeDeploymentReport { - string label; - BatchReports.SpokeInstanceBatchReport report; - } - - struct HubDeploymentReport { - string label; - BatchReports.HubBatchReport report; - } - - struct FullDeploymentReport { - BatchReports.AccessBatchReport accessBatchReport; - BatchReports.ConfiguratorBatchReport configuratorBatchReport; - SpokeDeploymentReport[] spokeInstanceBatchReports; - HubDeploymentReport[] hubBatchReports; - BatchReports.GatewaysBatchReport gatewaysBatchReport; - } + uint8 private constant ORACLE_DECIMALS = 8; + string private constant ORACLE_SUFFIX = ' (USD)'; function deployAaveV4( Logger logger, @@ -49,8 +32,8 @@ library AaveV4DeployOrchestration { string[] memory hubLabels, string[] memory spokeLabels, bool setRoles - ) internal returns (FullDeploymentReport memory) { - FullDeploymentReport memory report; + ) internal returns (OrchestrationReports.FullDeploymentReport memory) { + OrchestrationReports.FullDeploymentReport memory report; // Deploy Access Batch address accessManagerAdmin = setRoles ? deployer : admin; @@ -64,9 +47,9 @@ library AaveV4DeployOrchestration { // Deploy Hub Batches uint256 hubCount = hubLabels.length; - report.hubBatchReports = new HubDeploymentReport[](hubCount); + report.hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](hubCount); - for (uint256 i; i < hubCount; i++) { + for (uint256 i; i < hubCount; ++i) { report.hubBatchReports[i].label = hubLabels[i]; report.hubBatchReports[i].report = _deployHubBatch( admin, @@ -90,9 +73,9 @@ library AaveV4DeployOrchestration { // Deploy Spoke Instance Batches uint256 spokeCount = spokeLabels.length; - report.spokeInstanceBatchReports = new SpokeDeploymentReport[](spokeCount); + report.spokeInstanceBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); Logger.AddressEntry[] memory spokeEntries = new Logger.AddressEntry[](spokeCount); - for (uint256 i; i < spokeCount; i++) { + for (uint256 i; i < spokeCount; ++i) { report.spokeInstanceBatchReports[i].label = spokeLabels[i]; report.spokeInstanceBatchReports[i].report = _deploySpokeInstanceBatch( deployer, @@ -131,13 +114,13 @@ library AaveV4DeployOrchestration { report.configuratorBatchReport.spokeConfiguratorAddress, report.configuratorBatchReport.hubConfiguratorAddress ); - for (uint256 i; i < hubCount; i++) { + for (uint256 i; i < hubCount; ++i) { AaveV4HubRolesProcedure.setHubRoles( report.accessBatchReport.accessManagerAddress, report.hubBatchReports[i].report.hubAddress ); } - for (uint256 i; i < spokeCount; i++) { + for (uint256 i; i < spokeCount; ++i) { AaveV4SpokeRolesProcedure.setSpokeRoles( report.accessBatchReport.accessManagerAddress, report.spokeInstanceBatchReports[i].report.spokeProxyAddress @@ -159,8 +142,8 @@ library AaveV4DeployOrchestration { address accessManagerAddress, string memory label, bool setRoles - ) internal returns (HubDeploymentReport memory) { - HubDeploymentReport memory hubReport; + ) internal returns (OrchestrationReports.HubDeploymentReport memory) { + OrchestrationReports.HubDeploymentReport memory hubReport; hubReport.label = label; hubReport.report = _deployHubBatch(admin, accessManagerAddress); logger.write('Hub', hubReport.report.hubAddress); @@ -181,8 +164,8 @@ library AaveV4DeployOrchestration { address accessManagerAddress, string memory label, bool setRoles - ) internal returns (SpokeDeploymentReport memory) { - SpokeDeploymentReport memory spokeReport; + ) internal returns (OrchestrationReports.SpokeDeploymentReport memory) { + OrchestrationReports.SpokeDeploymentReport memory spokeReport; spokeReport.label = label; spokeReport.report = _deploySpokeInstanceBatch(deployer, admin, accessManagerAddress, label); logger.write('SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); diff --git a/src/deployments/orchestration/AaveV4TestOrchestration.sol b/src/deployments/orchestration/AaveV4TestOrchestration.sol index 9a03097ac..67bcc8436 100644 --- a/src/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/src/deployments/orchestration/AaveV4TestOrchestration.sol @@ -3,7 +3,9 @@ pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; -import {BatchReports} from 'src/deployments/types/BatchReports.sol'; +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; +import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; +import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; @@ -15,31 +17,15 @@ import {AaveV4AdminRolesProcedure} from 'src/deployments/procedures/roles/AaveV4 import {AaveV4HubRolesProcedure} from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; import {AaveV4SpokeRolesProcedure} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; +import {AaveV4HubConfigProcedures} from 'src/deployments/procedures/config/AaveV4HubConfigProcedures.sol'; +import {AaveV4SpokeConfigProcedures} from 'src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol'; + library AaveV4TestOrchestration { bool public constant IS_TEST = true; Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); - uint8 constant ORACLE_DECIMALS = 8; - string constant ORACLE_SUFFIX = ' (USD)'; - - struct TestHubReport { - address hubAddress; - address irStrategyAddress; - address treasurySpokeAddress; - } - - struct TestSpokeReport { - address spokeAddress; - address aaveOracleAddress; - } - - struct TestEnvReport { - address wethAddress; - address[] testTokenAddresses; - address accessManagerAddress; - TestHubReport[] hubReports; - TestSpokeReport[] spokeReports; - } + uint8 private constant ORACLE_DECIMALS = 8; + string private constant ORACLE_SUFFIX = ' (USD)'; function deployTestEnv( address admin, @@ -47,12 +33,12 @@ library AaveV4TestOrchestration { uint256 hubCount, uint256 spokeCount, TestTokensBatch.TestTokenInput[] memory tokenInputs - ) external returns (TestEnvReport memory) { - TestEnvReport memory report; + ) external returns (OrchestrationReports.TestEnvReport memory) { + OrchestrationReports.TestEnvReport memory report; report.testTokenAddresses = new address[](tokenInputs.length); - report.hubReports = new TestHubReport[](hubCount); - report.spokeReports = new TestSpokeReport[](spokeCount); + report.hubReports = new OrchestrationReports.TestHubReport[](hubCount); + report.spokeReports = new OrchestrationReports.TestSpokeReport[](spokeCount); // Deploy Test Tokens Batch BatchReports.TestTokensBatchReport memory tokensReport = _deployTokensBatch(tokenInputs); @@ -63,7 +49,7 @@ library AaveV4TestOrchestration { report.accessManagerAddress = _deployAccessBatch(admin).accessManagerAddress; // Deploy Hub Batches - for (uint256 i; i < hubCount; i++) { + for (uint256 i; i < hubCount; ++i) { BatchReports.HubBatchReport memory hubReport = _deployHubBatch( treasuryAdmin, report.accessManagerAddress @@ -74,7 +60,7 @@ library AaveV4TestOrchestration { } // Deploy Spoke Instance Batches - for (uint256 i; i < spokeCount; i++) { + for (uint256 i; i < spokeCount; ++i) { BatchReports.SpokeInstanceBatchReport memory spokeReport = _deploySpokeInstanceBatch( admin, report.accessManagerAddress, @@ -91,7 +77,7 @@ library AaveV4TestOrchestration { address admin, address hubAdmin, address spokeAdmin, - TestEnvReport memory report + OrchestrationReports.TestEnvReport memory report ) external { // Set Admin Roles AaveV4AdminRolesProcedure.setConfiguratorAdminRoles(report.accessManagerAddress, admin, admin); @@ -102,7 +88,7 @@ library AaveV4TestOrchestration { ); // Set Hub Roles - for (uint256 i; i < report.hubReports.length; i++) { + for (uint256 i; i < report.hubReports.length; ++i) { AaveV4HubRolesProcedure.setHubRoles( report.accessManagerAddress, report.hubReports[i].hubAddress @@ -110,7 +96,7 @@ library AaveV4TestOrchestration { } // Set Spoke Roles - for (uint256 i; i < report.spokeReports.length; i++) { + for (uint256 i; i < report.spokeReports.length; ++i) { AaveV4SpokeRolesProcedure.setSpokeRoles( report.accessManagerAddress, report.spokeReports[i].spokeAddress @@ -122,6 +108,30 @@ library AaveV4TestOrchestration { } } + function configureHubsAssets(ConfigData.AddAssetParams[] memory paramsList) external { + for (uint256 i; i < paramsList.length; ++i) { + AaveV4HubConfigProcedures.addAsset(paramsList[i]); + } + } + + function configureHubsSpokes(ConfigData.AddSpokeParams[] memory paramsList) external { + for (uint256 i; i < paramsList.length; ++i) { + AaveV4HubConfigProcedures.addSpoke(paramsList[i]); + } + } + + function configureSpokes( + ConfigData.UpdateLiquidationConfigParams[] memory liquidationParamsList, + ConfigData.AddReserveParams[] memory reserveParamsList + ) external { + for (uint256 i; i < liquidationParamsList.length; ++i) { + AaveV4SpokeConfigProcedures.updateLiquidationConfig(liquidationParamsList[i]); + } + for (uint256 i; i < reserveParamsList.length; ++i) { + AaveV4SpokeConfigProcedures.addReserve(reserveParamsList[i]); + } + } + function _deployTokensBatch( TestTokensBatch.TestTokenInput[] memory tokenInputs ) internal returns (BatchReports.TestTokensBatchReport memory) { diff --git a/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol b/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol index 62070bff0..6fbfac405 100644 --- a/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol +++ b/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol @@ -1,42 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; + import {IHub} from 'src/hub/interfaces/IHub.sol'; import {IHubConfigurator} from 'src/hub/interfaces/IHubConfigurator.sol'; library AaveV4HubConfigProcedures { - struct AddAssetParams { - address hub; - address underlying; - uint8 decimals; - address feeReceiver; - uint16 liquidityFee; - address irStrategy; - bytes irData; - } - - struct UpdateAssetConfigParams { - address hub; - uint256 assetId; - IHub.AssetConfig config; - bytes irData; - } - - struct AddSpokeParams { - address hub; - uint256 assetId; - address spoke; - IHub.SpokeConfig config; - } - - struct AddSpokeToAssetsParams { - address hub; - address spoke; - uint256[] assetIds; - IHub.SpokeConfig[] configs; - } - - function addAsset(AddAssetParams memory params) internal returns (uint256) { + function addAsset(ConfigData.AddAssetParams memory params) internal returns (uint256) { uint256 assetId = IHub(params.hub).addAsset( params.underlying, params.decimals, @@ -61,7 +32,7 @@ library AaveV4HubConfigProcedures { function addAssetViaConfigurator( address configurator, - AddAssetParams memory params + ConfigData.AddAssetParams memory params ) internal returns (uint256) { return IHubConfigurator(configurator).addAsset( @@ -75,15 +46,18 @@ library AaveV4HubConfigProcedures { ); } - function updateAssetConfig(UpdateAssetConfigParams memory params) internal { + function updateAssetConfig(ConfigData.UpdateAssetConfigParams memory params) internal { IHub(params.hub).updateAssetConfig(params.assetId, params.config, params.irData); } - function addSpoke(AddSpokeParams memory params) internal { + function addSpoke(ConfigData.AddSpokeParams memory params) internal { IHub(params.hub).addSpoke(params.assetId, params.spoke, params.config); } - function addSpokeViaConfigurator(address configurator, AddSpokeParams memory params) internal { + function addSpokeViaConfigurator( + address configurator, + ConfigData.AddSpokeParams memory params + ) internal { IHubConfigurator(configurator).addSpoke( params.hub, params.spoke, @@ -92,7 +66,10 @@ library AaveV4HubConfigProcedures { ); } - function addSpokeToAssets(address configurator, AddSpokeToAssetsParams memory params) internal { + function addSpokeToAssets( + address configurator, + ConfigData.AddSpokeToAssetsParams memory params + ) internal { IHubConfigurator(configurator).addSpokeToAssets( params.hub, params.spoke, diff --git a/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol b/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol index 20d5e450f..3f92ef4a8 100644 --- a/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol +++ b/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol @@ -1,36 +1,26 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; + import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; import {ISpokeConfigurator} from 'src/spoke/interfaces/ISpokeConfigurator.sol'; library AaveV4SpokeConfigProcedures { - struct UpdateLiquidationConfigParams { - address spoke; - ISpoke.LiquidationConfig config; - } - - struct AddReserveParams { - address spoke; - address hub; - uint256 assetId; - address priceSource; - ISpoke.ReserveConfig config; - ISpoke.DynamicReserveConfig dynamicConfig; - } - - function updateLiquidationConfig(UpdateLiquidationConfigParams memory params) internal { + function updateLiquidationConfig( + ConfigData.UpdateLiquidationConfigParams memory params + ) internal { ISpoke(params.spoke).updateLiquidationConfig(params.config); } function updateLiquidationConfigViaConfigurator( address configurator, - UpdateLiquidationConfigParams memory params + ConfigData.UpdateLiquidationConfigParams memory params ) internal { ISpokeConfigurator(configurator).updateLiquidationConfig(params.spoke, params.config); } - function addReserve(AddReserveParams memory params) internal returns (uint256) { + function addReserve(ConfigData.AddReserveParams memory params) internal returns (uint256) { return ISpoke(params.spoke).addReserve( params.hub, @@ -43,7 +33,7 @@ library AaveV4SpokeConfigProcedures { function addReserveViaConfigurator( address configurator, - AddReserveParams memory params + ConfigData.AddReserveParams memory params ) internal returns (uint256) { return ISpokeConfigurator(configurator).addReserve( From 8680dd6b244677f1bec96339db702bf35db13402 Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Fri, 14 Nov 2025 11:19:23 +0100 Subject: [PATCH 13/62] fix : fix Licenses for payload engine --- scripts/deploy/AaveV4DeployBatch.s.sol | 3 ++- src/deployments/batches/AaveV4AccessBatch.sol | 3 ++- src/deployments/batches/AaveV4ConfiguratorBatch.sol | 3 ++- src/deployments/batches/AaveV4GatewaysBatch.sol | 3 ++- src/deployments/batches/AaveV4HubBatch.sol | 3 ++- src/deployments/batches/AaveV4SpokeInstanceBatch.sol | 3 ++- src/deployments/batches/TestTokensBatch.sol | 3 ++- src/deployments/libraries/BatchReports.sol | 3 ++- src/deployments/libraries/ConfigData.sol | 3 ++- src/deployments/libraries/OrchestrationReports.sol | 3 ++- src/deployments/orchestration/AaveV4DeployOrchestration.sol | 3 ++- src/deployments/orchestration/AaveV4TestOrchestration.sol | 3 ++- .../procedures/config/AaveV4HubConfigProcedures.sol | 3 ++- .../procedures/config/AaveV4SpokeConfigProcedures.sol | 3 ++- .../procedures/deploy/AaveV4AaveOracleDeployProcedure.sol | 3 ++- .../deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol | 3 ++- .../procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol | 3 ++- src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol | 3 ++- .../deploy/AaveV4InterestRateStrategyDeployProcedure.sol | 3 ++- .../deploy/AaveV4NativeTokenGatewayDeployProcedure.sol | 3 ++- .../deploy/AaveV4SignatureGatewayDeployProcedure.sol | 3 ++- .../deploy/AaveV4SpokeConfiguratorDeployProcedure.sol | 3 ++- .../procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol | 3 ++- .../AaveV4TransparentUpgradeableProxyDeployProcedure.sol | 3 ++- .../procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol | 3 ++- .../procedures/deploy/TestnetERC20DeployProcedure.sol | 3 ++- src/deployments/procedures/deploy/WETHDeployProcedure.sol | 3 ++- src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol | 3 ++- src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol | 3 ++- src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol | 3 ++- src/deployments/utils/DeployUtils.sol | 3 ++- src/deployments/utils/InputUtils.sol | 3 ++- src/deployments/utils/Logger.sol | 3 ++- 33 files changed, 66 insertions(+), 33 deletions(-) diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index 86e2280c4..e297d3b24 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {Script} from 'forge-std/Script.sol'; diff --git a/src/deployments/batches/AaveV4AccessBatch.sol b/src/deployments/batches/AaveV4AccessBatch.sol index d0ce679e7..4b1052cbd 100644 --- a/src/deployments/batches/AaveV4AccessBatch.sol +++ b/src/deployments/batches/AaveV4AccessBatch.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; diff --git a/src/deployments/batches/AaveV4ConfiguratorBatch.sol b/src/deployments/batches/AaveV4ConfiguratorBatch.sol index f9d3364af..46c31e21b 100644 --- a/src/deployments/batches/AaveV4ConfiguratorBatch.sol +++ b/src/deployments/batches/AaveV4ConfiguratorBatch.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; diff --git a/src/deployments/batches/AaveV4GatewaysBatch.sol b/src/deployments/batches/AaveV4GatewaysBatch.sol index 40c0dd994..6709fece7 100644 --- a/src/deployments/batches/AaveV4GatewaysBatch.sol +++ b/src/deployments/batches/AaveV4GatewaysBatch.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; diff --git a/src/deployments/batches/AaveV4HubBatch.sol b/src/deployments/batches/AaveV4HubBatch.sol index 7a8129bc7..3893d62b5 100644 --- a/src/deployments/batches/AaveV4HubBatch.sol +++ b/src/deployments/batches/AaveV4HubBatch.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 48a82b04f..c25a93419 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; diff --git a/src/deployments/batches/TestTokensBatch.sol b/src/deployments/batches/TestTokensBatch.sol index ca7da0d97..3ea45ac2d 100644 --- a/src/deployments/batches/TestTokensBatch.sol +++ b/src/deployments/batches/TestTokensBatch.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; diff --git a/src/deployments/libraries/BatchReports.sol b/src/deployments/libraries/BatchReports.sol index 1e40429ba..ca8643984 100644 --- a/src/deployments/libraries/BatchReports.sol +++ b/src/deployments/libraries/BatchReports.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; library BatchReports { diff --git a/src/deployments/libraries/ConfigData.sol b/src/deployments/libraries/ConfigData.sol index db1445228..6916ebc81 100644 --- a/src/deployments/libraries/ConfigData.sol +++ b/src/deployments/libraries/ConfigData.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {IHub} from 'src/hub/interfaces/IHub.sol'; diff --git a/src/deployments/libraries/OrchestrationReports.sol b/src/deployments/libraries/OrchestrationReports.sol index afb24b48c..960594e87 100644 --- a/src/deployments/libraries/OrchestrationReports.sol +++ b/src/deployments/libraries/OrchestrationReports.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index ca49c2cf5..694c8f0e6 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; diff --git a/src/deployments/orchestration/AaveV4TestOrchestration.sol b/src/deployments/orchestration/AaveV4TestOrchestration.sol index 67bcc8436..61cd8d8c6 100644 --- a/src/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/src/deployments/orchestration/AaveV4TestOrchestration.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; diff --git a/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol b/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol index 6fbfac405..6a87e6604 100644 --- a/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol +++ b/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; diff --git a/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol b/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol index 3f92ef4a8..bb9f3502c 100644 --- a/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol +++ b/src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol index 790ab8c18..f47581f9c 100644 --- a/src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {AaveOracle} from 'src/spoke/AaveOracle.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol index fa19d89ae..c37ea3fc7 100644 --- a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {AccessManagerEnumerable} from 'src/access/AccessManagerEnumerable.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol index e977302f6..cc4894e08 100644 --- a/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {HubConfigurator} from 'src/hub/HubConfigurator.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol index fe9bb7abe..e6bcc05f8 100644 --- a/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {Hub} from 'src/hub/Hub.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol index 80e74e1af..70324733c 100644 --- a/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {AssetInterestRateStrategy} from 'src/hub/AssetInterestRateStrategy.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol index b97e44108..66c4304d4 100644 --- a/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {NativeTokenGateway} from 'src/position-manager/NativeTokenGateway.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol index 21e2e24cb..eab654ea2 100644 --- a/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {SignatureGateway} from 'src/position-manager/SignatureGateway.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol index 3b074d5fc..ac1906a83 100644 --- a/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {SpokeConfigurator} from 'src/spoke/SpokeConfigurator.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol index 224f4fbcd..9684c5c0d 100644 --- a/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {SpokeInstance} from 'src/spoke/instances/SpokeInstance.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol index a890b6b9d..f8509f5c7 100644 --- a/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {TransparentUpgradeableProxy} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; diff --git a/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol index e79b06ffd..9968db9db 100644 --- a/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {TreasurySpoke} from 'src/spoke/TreasurySpoke.sol'; diff --git a/src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol b/src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol index a2bf2c130..866ecaf0e 100644 --- a/src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol +++ b/src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {TestnetERC20} from 'tests/mocks/TestnetERC20.sol'; diff --git a/src/deployments/procedures/deploy/WETHDeployProcedure.sol b/src/deployments/procedures/deploy/WETHDeployProcedure.sol index 938e1b304..79b631cb0 100644 --- a/src/deployments/procedures/deploy/WETHDeployProcedure.sol +++ b/src/deployments/procedures/deploy/WETHDeployProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {WETH9} from 'src/dependencies/weth/WETH9.sol'; diff --git a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol index 067ab975f..be1b8e1bf 100644 --- a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {Roles} from 'src/libraries/types/Roles.sol'; diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol index 176193e5c..a423a4004 100644 --- a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {Roles} from 'src/libraries/types/Roles.sol'; diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol index e276b571f..8dc22afb2 100644 --- a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import {Roles} from 'src/libraries/types/Roles.sol'; diff --git a/src/deployments/utils/DeployUtils.sol b/src/deployments/utils/DeployUtils.sol index 87b39f6a3..c3770cce3 100644 --- a/src/deployments/utils/DeployUtils.sol +++ b/src/deployments/utils/DeployUtils.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index 174ca1d48..ff3819d34 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import 'forge-std/StdJson.sol'; diff --git a/src/deployments/utils/Logger.sol b/src/deployments/utils/Logger.sol index f0249f877..743a36638 100644 --- a/src/deployments/utils/Logger.sol +++ b/src/deployments/utils/Logger.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; import 'forge-std/StdJson.sol'; From 21033d118b70fa646cdd88eb5f5405de5171b57d Mon Sep 17 00:00:00 2001 From: Kogaroshi Date: Fri, 14 Nov 2025 12:26:12 +0100 Subject: [PATCH 14/62] feat : use orchestration in test setup (WIP) --- .../Spoke.Operations.ZeroRiskPremium.json | 2 +- snapshots/Spoke.Operations.json | 2 +- src/deployments/batches/TestTokensBatch.sol | 11 +--- src/deployments/libraries/ConfigData.sol | 6 ++ .../libraries/OrchestrationReports.sol | 7 +- .../orchestration/AaveV4TestOrchestration.sol | 64 +++++++++++++++---- tests/Base.t.sol | 61 +++++++++++------- tests/Config.sol | 13 ++++ 8 files changed, 119 insertions(+), 47 deletions(-) create mode 100644 tests/Config.sol diff --git a/snapshots/Spoke.Operations.ZeroRiskPremium.json b/snapshots/Spoke.Operations.ZeroRiskPremium.json index 9472c138a..1d96a9365 100644 --- a/snapshots/Spoke.Operations.ZeroRiskPremium.json +++ b/snapshots/Spoke.Operations.ZeroRiskPremium.json @@ -5,7 +5,7 @@ "liquidationCall (receiveShares): partial": "294982", "liquidationCall: full": "303967", "liquidationCall: partial": "302289", - "permitReserve + repay (multicall)": "196047", + "permitReserve + repay (multicall)": "196035", "permitReserve + supply (multicall)": "173494", "permitReserve + supply + enable collateral (multicall)": "216808", "repay: full": "156200", diff --git a/snapshots/Spoke.Operations.json b/snapshots/Spoke.Operations.json index 48d0cd861..edf56ddf6 100644 --- a/snapshots/Spoke.Operations.json +++ b/snapshots/Spoke.Operations.json @@ -5,7 +5,7 @@ "liquidationCall (receiveShares): partial": "316685", "liquidationCall: full": "337150", "liquidationCall: partial": "323992", - "permitReserve + repay (multicall)": "195488", + "permitReserve + repay (multicall)": "195476", "permitReserve + supply (multicall)": "173494", "permitReserve + supply + enable collateral (multicall)": "216808", "repay: full": "155641", diff --git a/src/deployments/batches/TestTokensBatch.sol b/src/deployments/batches/TestTokensBatch.sol index 3ea45ac2d..0f52ab711 100644 --- a/src/deployments/batches/TestTokensBatch.sol +++ b/src/deployments/batches/TestTokensBatch.sol @@ -3,25 +3,20 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; +import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; import {TestnetERC20DeployProcedure} from 'src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol'; contract TestTokensBatch is WETHDeployProcedure, TestnetERC20DeployProcedure { - struct TestTokenInput { - string name; - string symbol; - uint8 decimals; - } - BatchReports.TestTokensBatchReport internal _report; - constructor(TestTokenInput[] memory inputs_) { + constructor(ConfigData.TestTokenInput[] memory inputs_) { _report.tokenAddresses = new address[](inputs_.length); _report.wethAddress = _deployWETH(); for (uint256 i; i < inputs_.length; i++) { - TestTokenInput memory input = inputs_[i]; + ConfigData.TestTokenInput memory input = inputs_[i]; address tokenAddress = _deployTestnetERC20(input.name, input.symbol, input.decimals); _report.tokenAddresses[i] = tokenAddress; } diff --git a/src/deployments/libraries/ConfigData.sol b/src/deployments/libraries/ConfigData.sol index 6916ebc81..879ca1986 100644 --- a/src/deployments/libraries/ConfigData.sol +++ b/src/deployments/libraries/ConfigData.sol @@ -50,4 +50,10 @@ library ConfigData { ISpoke.ReserveConfig config; ISpoke.DynamicReserveConfig dynamicConfig; } + + struct TestTokenInput { + string name; + string symbol; + uint8 decimals; + } } diff --git a/src/deployments/libraries/OrchestrationReports.sol b/src/deployments/libraries/OrchestrationReports.sol index 960594e87..a9a919cf1 100644 --- a/src/deployments/libraries/OrchestrationReports.sol +++ b/src/deployments/libraries/OrchestrationReports.sol @@ -35,10 +35,13 @@ library OrchestrationReports { } struct TestEnvReport { - address wethAddress; - address[] testTokenAddresses; address accessManagerAddress; TestHubReport[] hubReports; TestSpokeReport[] spokeReports; } + + struct TestTokensReport { + address wethAddress; + address[] testTokenAddresses; + } } diff --git a/src/deployments/orchestration/AaveV4TestOrchestration.sol b/src/deployments/orchestration/AaveV4TestOrchestration.sol index 61cd8d8c6..20cca0465 100644 --- a/src/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/src/deployments/orchestration/AaveV4TestOrchestration.sol @@ -32,20 +32,13 @@ library AaveV4TestOrchestration { address admin, address treasuryAdmin, uint256 hubCount, - uint256 spokeCount, - TestTokensBatch.TestTokenInput[] memory tokenInputs + uint256 spokeCount ) external returns (OrchestrationReports.TestEnvReport memory) { OrchestrationReports.TestEnvReport memory report; - report.testTokenAddresses = new address[](tokenInputs.length); report.hubReports = new OrchestrationReports.TestHubReport[](hubCount); report.spokeReports = new OrchestrationReports.TestSpokeReport[](spokeCount); - // Deploy Test Tokens Batch - BatchReports.TestTokensBatchReport memory tokensReport = _deployTokensBatch(tokenInputs); - report.wethAddress = tokensReport.wethAddress; - report.testTokenAddresses = tokensReport.tokenAddresses; - // Deploy Access Batch report.accessManagerAddress = _deployAccessBatch(admin).accessManagerAddress; @@ -74,6 +67,21 @@ library AaveV4TestOrchestration { return report; } + function deployTestTokens( + ConfigData.TestTokenInput[] memory tokenInputs + ) external returns (OrchestrationReports.TestTokensReport memory) { + OrchestrationReports.TestTokensReport memory report; + + report.testTokenAddresses = new address[](tokenInputs.length); + + // Deploy Test Tokens Batch + BatchReports.TestTokensBatchReport memory tokensReport = _deployTokensBatch(tokenInputs); + report.wethAddress = tokensReport.wethAddress; + report.testTokenAddresses = tokensReport.tokenAddresses; + + return report; + } + function setRolesTestEnv( address admin, address hubAdmin, @@ -109,10 +117,38 @@ library AaveV4TestOrchestration { } } - function configureHubsAssets(ConfigData.AddAssetParams[] memory paramsList) external { + function deployTestHub( + address admin, + address treasuryAdmin, + ConfigData.AddAssetParams[] memory paramsList + ) external returns (address, OrchestrationReports.TestHubReport memory) { + OrchestrationReports.TestHubReport memory report; + + address accessManagerAddress = _deployAccessBatch(admin).accessManagerAddress; + + // Deploy Hub Batch + BatchReports.HubBatchReport memory hubReport = _deployHubBatch( + treasuryAdmin, + accessManagerAddress + ); + report.hubAddress = hubReport.hubAddress; + report.irStrategyAddress = hubReport.irStrategyAddress; + report.treasurySpokeAddress = hubReport.treasurySpokeAddress; + + // Set Hub Roles + AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, report.hubAddress); + + return (accessManagerAddress, report); + } + + function configureHubsAssets( + ConfigData.AddAssetParams[] memory paramsList + ) external returns (uint256[] memory) { + uint256[] memory assetIds = new uint256[](paramsList.length); for (uint256 i; i < paramsList.length; ++i) { - AaveV4HubConfigProcedures.addAsset(paramsList[i]); + assetIds[i] = AaveV4HubConfigProcedures.addAsset(paramsList[i]); } + return assetIds; } function configureHubsSpokes(ConfigData.AddSpokeParams[] memory paramsList) external { @@ -124,17 +160,19 @@ library AaveV4TestOrchestration { function configureSpokes( ConfigData.UpdateLiquidationConfigParams[] memory liquidationParamsList, ConfigData.AddReserveParams[] memory reserveParamsList - ) external { + ) external returns (uint256[] memory) { for (uint256 i; i < liquidationParamsList.length; ++i) { AaveV4SpokeConfigProcedures.updateLiquidationConfig(liquidationParamsList[i]); } + uint256[] memory reserveIds = new uint256[](reserveParamsList.length); for (uint256 i; i < reserveParamsList.length; ++i) { - AaveV4SpokeConfigProcedures.addReserve(reserveParamsList[i]); + reserveIds[i] = AaveV4SpokeConfigProcedures.addReserve(reserveParamsList[i]); } + return reserveIds; } function _deployTokensBatch( - TestTokensBatch.TestTokenInput[] memory tokenInputs + ConfigData.TestTokenInput[] memory tokenInputs ) internal returns (BatchReports.TestTokensBatchReport memory) { TestTokensBatch tokensBatch = new TestTokensBatch(tokenInputs); return tokensBatch.getReport(); diff --git a/tests/Base.t.sol b/tests/Base.t.sol index 77fd997c9..6cfcbf9b4 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -68,6 +68,11 @@ import {SignatureGateway, ISignatureGateway} from 'src/position-manager/Signatur import {Constants} from 'tests/Constants.sol'; import {Utils} from 'tests/Utils.sol'; +// orchestration +import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; +import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; +import {AaveV4TestOrchestration} from 'src/deployments/orchestration/AaveV4TestOrchestration.sol'; + // mocks import {TestnetERC20} from 'tests/mocks/TestnetERC20.sol'; import {MockERC20} from 'tests/mocks/MockERC20.sol'; @@ -125,13 +130,6 @@ abstract contract Base is Test { uint256 internal constant MAX_LIQUIDATION_PROTOCOL_FEE_PERCENTAGE = PercentageMath.PERCENTAGE_FACTOR; - // TODO: remove after migrating to token list - IERC20 internal usdc; - IERC20 internal dai; - IERC20 internal usdt; - IERC20 internal eth; - IERC20 internal wbtc; - IAaveOracle internal oracle1; IAaveOracle internal oracle2; IAaveOracle internal oracle3; @@ -143,10 +141,6 @@ abstract contract Base is Test { AssetInterestRateStrategy internal irStrategy; IAccessManager internal accessManager; - // TODO: remove after migrating to other mock users - address internal USER1 = makeAddr('USER1'); - address internal USER2 = makeAddr('USER2'); - address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); address internal carol = makeAddr('carol'); @@ -290,11 +284,6 @@ abstract contract Base is Test { (spoke2, oracle2) = _deploySpokeWithOracle(ADMIN, address(accessManager), 'Spoke 2 (USD)'); (spoke3, oracle3) = _deploySpokeWithOracle(ADMIN, address(accessManager), 'Spoke 3 (USD)'); treasurySpoke = ITreasurySpoke(new TreasurySpoke(TREASURY_ADMIN, address(hub1))); - dai = new MockERC20(); - eth = new MockERC20(); - usdc = new MockERC20(); - usdt = new MockERC20(); - wbtc = new MockERC20(); vm.stopPrank(); vm.label(address(spoke1), 'spoke1'); @@ -357,13 +346,41 @@ abstract contract Base is Test { } function deployMintAndApproveTokenList() internal { + ConfigData.TestTokenInput[] memory tokenInputs = new ConfigData.TestTokenInput[](5); + tokenInputs[0] = ConfigData.TestTokenInput({ + name: 'USDX', + symbol: 'USDX', + decimals: decimals.usdx + }); + tokenInputs[1] = ConfigData.TestTokenInput({ + name: 'DAI', + symbol: 'DAI', + decimals: decimals.dai + }); + tokenInputs[2] = ConfigData.TestTokenInput({ + name: 'WBTC', + symbol: 'WBTC', + decimals: decimals.wbtc + }); + tokenInputs[3] = ConfigData.TestTokenInput({ + name: 'USDY', + symbol: 'USDY', + decimals: decimals.usdy + }); + tokenInputs[4] = ConfigData.TestTokenInput({ + name: 'USDZ', + symbol: 'USDZ', + decimals: decimals.usdz + }); + OrchestrationReports.TestTokensReport memory tokensReport = AaveV4TestOrchestration + .deployTestTokens(tokenInputs); tokenList = TokenList( - new WETH9(), - new TestnetERC20('USDX', 'USDX', decimals.usdx), - new TestnetERC20('DAI', 'DAI', decimals.dai), - new TestnetERC20('WBTC', 'WBTC', decimals.wbtc), - new TestnetERC20('USDY', 'USDY', decimals.usdy), - new TestnetERC20('USDZ', 'USDZ', decimals.usdz) + WETH9(payable(tokensReport.wethAddress)), + TestnetERC20(tokensReport.testTokenAddresses[0]), + TestnetERC20(tokensReport.testTokenAddresses[1]), + TestnetERC20(tokensReport.testTokenAddresses[2]), + TestnetERC20(tokensReport.testTokenAddresses[3]), + TestnetERC20(tokensReport.testTokenAddresses[4]) ); vm.label(address(tokenList.weth), 'WETH'); diff --git a/tests/Config.sol b/tests/Config.sol new file mode 100644 index 000000000..d63d641b9 --- /dev/null +++ b/tests/Config.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {IHub} from 'src/hub/interfaces/IHub.sol'; +import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; +import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; + +library Config { + // get Hub test configs + // get Spokes test liquidation configs + // get Spokes test reserve configs +} From 954521777a108f5da76643aab2ae5073de4f5a98 Mon Sep 17 00:00:00 2001 From: Kogaroshi <25688223+Kogaroshi@users.noreply.github.com> Date: Mon, 1 Dec 2025 10:59:40 +0100 Subject: [PATCH 15/62] fix : missing action --- src/deployments/orchestration/AaveV4TestOrchestration.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/deployments/orchestration/AaveV4TestOrchestration.sol b/src/deployments/orchestration/AaveV4TestOrchestration.sol index 20cca0465..2103bafd5 100644 --- a/src/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/src/deployments/orchestration/AaveV4TestOrchestration.sol @@ -138,12 +138,15 @@ library AaveV4TestOrchestration { // Set Hub Roles AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, report.hubAddress); + // Configure Hub Assets + configureHubsAssets(paramsList); + return (accessManagerAddress, report); } function configureHubsAssets( ConfigData.AddAssetParams[] memory paramsList - ) external returns (uint256[] memory) { + ) public returns (uint256[] memory) { uint256[] memory assetIds = new uint256[](paramsList.length); for (uint256 i; i < paramsList.length; ++i) { assetIds[i] = AaveV4HubConfigProcedures.addAsset(paramsList[i]); From 4d36444e099d354396454ead9a293e5e74d68222 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Mon, 1 Dec 2025 20:43:25 -0600 Subject: [PATCH 16/62] fix: clean up file paths; refactor --- .gitignore | 4 +- foundry.toml | 2 +- scripts/deploy/AaveV4DeployBatch.s.sol | 6 +- .../batches/AaveV4SpokeInstanceBatch.sol | 12 +++- .../inputs/AaveV4DeployInput.example.json | 7 ++ .../AaveV4DeployOrchestration.sol | 72 ++++++------------- 6 files changed, 44 insertions(+), 59 deletions(-) create mode 100644 src/deployments/inputs/AaveV4DeployInput.example.json diff --git a/.gitignore b/.gitignore index 619603d4d..174401493 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,6 @@ lcov* report/ .DS_Store -.venv/ \ No newline at end of file +.venv/ + +src/deployments/inputs/AaveV4DeployInput.json \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index 5ef86377d..baa06a090 100644 --- a/foundry.toml +++ b/foundry.toml @@ -7,7 +7,7 @@ fs_permissions = [ { access = "read", path = "tests/mocks/JsonBindings.sol" }, { access = "read", path = "./config" }, { access = "read-write", path = "./output" }, - { access = "read-write", path = "./scripts/input" } + { access = "read-write", path = "./src/deployments/inputs" } ] solc_version = "0.8.28" evm_version = "cancun" diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index e297d3b24..35c0076f2 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -8,10 +8,12 @@ import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; import {Logger} from 'src/deployments/utils/Logger.sol'; -import {AaveV4DeployOrchestration} from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; +import { + AaveV4DeployOrchestration +} from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { - string internal constant INPUT_PATH = 'scripts/deploy/input/AaveV4DeployInput.json'; + string internal constant INPUT_PATH = 'src/deployments/inputs/AaveV4DeployInput.json'; string internal constant OUTPUT_PATH = 'output/reports/deployments/AaveV4DeployBatch.json'; constructor() {} diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index c25a93419..2d2f44940 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -5,9 +5,15 @@ pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; -import {AaveV4SpokeInstanceDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol'; -import {AaveV4TransparentUpgradeableProxyDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol'; -import {AaveV4AaveOracleDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol'; +import { + AaveV4SpokeInstanceDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol'; +import { + AaveV4TransparentUpgradeableProxyDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol'; +import { + AaveV4AaveOracleDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol'; contract AaveV4SpokeInstanceBatch is AaveV4SpokeInstanceDeployProcedure, diff --git a/src/deployments/inputs/AaveV4DeployInput.example.json b/src/deployments/inputs/AaveV4DeployInput.example.json new file mode 100644 index 000000000..042677ddb --- /dev/null +++ b/src/deployments/inputs/AaveV4DeployInput.example.json @@ -0,0 +1,7 @@ +{ + "admin": "0x0000000000000000000000000000000000000000", + "nativeWrapperAddress": "0x0000000000000000000000000000000000000000", + "setRoles": false, + "hubLabels": ["Hub 1", "Hub 2"], + "spokeLabels": ["Spoke 1", "Spoke 2"] +} diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 694c8f0e6..ed61700b1 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -14,9 +14,15 @@ import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; import {AaveV4GatewaysBatch} from 'src/deployments/batches/AaveV4GatewaysBatch.sol'; -import {AaveV4AdminRolesProcedure} from 'src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol'; -import {AaveV4HubRolesProcedure} from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; -import {AaveV4SpokeRolesProcedure} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; +import { + AaveV4AdminRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol'; +import { + AaveV4HubRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; +import { + AaveV4SpokeRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; library AaveV4DeployOrchestration { bool public constant IS_TEST = true; @@ -51,23 +57,12 @@ library AaveV4DeployOrchestration { report.hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](hubCount); for (uint256 i; i < hubCount; ++i) { - report.hubBatchReports[i].label = hubLabels[i]; - report.hubBatchReports[i].report = _deployHubBatch( + report.hubBatchReports[i] = _deployHub( + logger, admin, - report.accessBatchReport.accessManagerAddress - ); - hubEntries[i] = Logger.AddressEntry({ - label: hubLabels[i], - value: report.hubBatchReports[i].report.hubAddress - }); - logger.log(string.concat(hubLabels[i], ' Hub'), report.hubBatchReports[i].report.hubAddress); - logger.log( - string.concat(hubLabels[i], ' InterestRateStrategy'), - report.hubBatchReports[i].report.irStrategyAddress - ); - logger.log( - string.concat(hubLabels[i], ' TreasurySpoke'), - report.hubBatchReports[i].report.treasurySpokeAddress + report.accessBatchReport.accessManagerAddress, + hubLabels[i], + setRoles ); } logger.writeGroup('Hubs', hubEntries); @@ -77,28 +72,13 @@ library AaveV4DeployOrchestration { report.spokeInstanceBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); Logger.AddressEntry[] memory spokeEntries = new Logger.AddressEntry[](spokeCount); for (uint256 i; i < spokeCount; ++i) { - report.spokeInstanceBatchReports[i].label = spokeLabels[i]; - report.spokeInstanceBatchReports[i].report = _deploySpokeInstanceBatch( + report.spokeInstanceBatchReports[i] = _deploySpoke( + logger, deployer, admin, report.accessBatchReport.accessManagerAddress, - spokeLabels[i] - ); - spokeEntries[i] = Logger.AddressEntry({ - label: spokeLabels[i], - value: report.spokeInstanceBatchReports[i].report.spokeProxyAddress - }); - logger.log( - string.concat(spokeLabels[i], ' SpokeInstance Proxy'), - report.spokeInstanceBatchReports[i].report.spokeProxyAddress - ); - logger.log( - string.concat(spokeLabels[i], ' SpokeInstance Implementation'), - report.spokeInstanceBatchReports[i].report.spokeImplementationAddress - ); - logger.log( - string.concat(spokeLabels[i], ' AaveOracle'), - report.spokeInstanceBatchReports[i].report.aaveOracleAddress + spokeLabels[i], + setRoles ); } logger.writeGroup('SpokeInstances', spokeEntries); @@ -115,18 +95,6 @@ library AaveV4DeployOrchestration { report.configuratorBatchReport.spokeConfiguratorAddress, report.configuratorBatchReport.hubConfiguratorAddress ); - for (uint256 i; i < hubCount; ++i) { - AaveV4HubRolesProcedure.setHubRoles( - report.accessBatchReport.accessManagerAddress, - report.hubBatchReports[i].report.hubAddress - ); - } - for (uint256 i; i < spokeCount; ++i) { - AaveV4SpokeRolesProcedure.setSpokeRoles( - report.accessBatchReport.accessManagerAddress, - report.spokeInstanceBatchReports[i].report.spokeProxyAddress - ); - } AaveV4AdminRolesProcedure.setNewAdminRole( report.accessBatchReport.accessManagerAddress, admin, @@ -137,7 +105,7 @@ library AaveV4DeployOrchestration { return report; } - function deployHub( + function _deployHub( Logger logger, address admin, address accessManagerAddress, @@ -158,7 +126,7 @@ library AaveV4DeployOrchestration { return hubReport; } - function deploySpoke( + function _deploySpoke( Logger logger, address deployer, address admin, From a951c309d95707024d83e77186ea9ecf727e82a4 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Tue, 2 Dec 2025 22:22:32 -0600 Subject: [PATCH 17/62] feat: use toml; clean up logs; rft; naming --- .gitignore | 2 +- scripts/deploy/AaveV4DeployBatch.s.sol | 10 +- ...tewaysBatch.sol => AaveV4GatewayBatch.sol} | 10 +- .../inputs/AaveV4DeployInput.example.json | 7 - src/deployments/inputs/AaveV4DeployInput.toml | 5 + .../AaveV4DeployOrchestration.sol | 144 ++++++++++++------ src/deployments/utils/InputUtils.sol | 15 +- src/deployments/utils/Logger.sol | 20 +-- 8 files changed, 135 insertions(+), 78 deletions(-) rename src/deployments/batches/{AaveV4GatewaysBatch.sol => AaveV4GatewayBatch.sol} (72%) delete mode 100644 src/deployments/inputs/AaveV4DeployInput.example.json create mode 100644 src/deployments/inputs/AaveV4DeployInput.toml diff --git a/.gitignore b/.gitignore index 174401493..52e2f2d53 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,4 @@ report/ .DS_Store .venv/ -src/deployments/inputs/AaveV4DeployInput.json \ No newline at end of file +output/ \ No newline at end of file diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index 35c0076f2..d73237061 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -13,14 +13,16 @@ import { } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { - string internal constant INPUT_PATH = 'src/deployments/inputs/AaveV4DeployInput.json'; - string internal constant OUTPUT_PATH = 'output/reports/deployments/AaveV4DeployBatch.json'; + string internal constant INPUT_PATH = 'src/deployments/inputs/AaveV4DeployInput.toml'; + string internal constant OUTPUT_DIR = 'output/reports/deployments/'; + string internal constant OUTPUT_FILE = 'AaveV4DeployBatch.json'; constructor() {} function run() external { - Logger logger = new Logger(OUTPUT_PATH); - FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); + vm.createDir(OUTPUT_DIR, true); + Logger logger = new Logger(string.concat(OUTPUT_DIR, OUTPUT_FILE)); + FullDeployInputs memory inputs = loadFullDeployInputs(OUTPUT_FILE); address deployer = msg.sender; diff --git a/src/deployments/batches/AaveV4GatewaysBatch.sol b/src/deployments/batches/AaveV4GatewayBatch.sol similarity index 72% rename from src/deployments/batches/AaveV4GatewaysBatch.sol rename to src/deployments/batches/AaveV4GatewayBatch.sol index 6709fece7..5f3ae5fce 100644 --- a/src/deployments/batches/AaveV4GatewaysBatch.sol +++ b/src/deployments/batches/AaveV4GatewayBatch.sol @@ -3,10 +3,14 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; -import {AaveV4NativeTokenGatewayDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol'; -import {AaveV4SignatureGatewayDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol'; +import { + AaveV4NativeTokenGatewayDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol'; +import { + AaveV4SignatureGatewayDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol'; -contract AaveV4GatewaysBatch is +contract AaveV4GatewayBatch is AaveV4NativeTokenGatewayDeployProcedure, AaveV4SignatureGatewayDeployProcedure { diff --git a/src/deployments/inputs/AaveV4DeployInput.example.json b/src/deployments/inputs/AaveV4DeployInput.example.json deleted file mode 100644 index 042677ddb..000000000 --- a/src/deployments/inputs/AaveV4DeployInput.example.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "admin": "0x0000000000000000000000000000000000000000", - "nativeWrapperAddress": "0x0000000000000000000000000000000000000000", - "setRoles": false, - "hubLabels": ["Hub 1", "Hub 2"], - "spokeLabels": ["Spoke 1", "Spoke 2"] -} diff --git a/src/deployments/inputs/AaveV4DeployInput.toml b/src/deployments/inputs/AaveV4DeployInput.toml new file mode 100644 index 000000000..88154bb9c --- /dev/null +++ b/src/deployments/inputs/AaveV4DeployInput.toml @@ -0,0 +1,5 @@ +admin = "0x0000000000000000000000000000000000000001" +nativeWrapperAddress = "0x0000000000000000000000000000000000000002" +setRoles = false +hubLabels = ["Hub 1", "Hub 2", "Hub 3"] +spokeLabels = ["Spoke 1", "Spoke 2", "Spoke 3"] \ No newline at end of file diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index ed61700b1..5cdaff0ac 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -12,7 +12,7 @@ import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; import {AaveV4ConfiguratorBatch} from 'src/deployments/batches/AaveV4ConfiguratorBatch.sol'; import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; -import {AaveV4GatewaysBatch} from 'src/deployments/batches/AaveV4GatewaysBatch.sol'; +import {AaveV4GatewayBatch} from 'src/deployments/batches/AaveV4GatewayBatch.sol'; import { AaveV4AdminRolesProcedure @@ -44,49 +44,32 @@ library AaveV4DeployOrchestration { // Deploy Access Batch address accessManagerAdmin = setRoles ? deployer : admin; - report.accessBatchReport = _deployAccessBatch(accessManagerAdmin); - logger.log('AccessManager', report.accessBatchReport.accessManagerAddress); + report.accessBatchReport = _deployAccessBatch(logger, accessManagerAdmin); // Deploy Configurator Batch - report.configuratorBatchReport = _deployConfiguratorBatch(admin); - logger.log('HubConfigurator', report.configuratorBatchReport.hubConfiguratorAddress); - logger.log('SpokeConfigurator', report.configuratorBatchReport.spokeConfiguratorAddress); + report.configuratorBatchReport = _deployConfiguratorBatch(logger, admin); // Deploy Hub Batches - uint256 hubCount = hubLabels.length; - report.hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); - Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](hubCount); - for (uint256 i; i < hubCount; ++i) { - report.hubBatchReports[i] = _deployHub( - logger, - admin, - report.accessBatchReport.accessManagerAddress, - hubLabels[i], - setRoles - ); - } - logger.writeGroup('Hubs', hubEntries); + report.hubBatchReports = _deployHubs( + logger, + admin, + report.accessBatchReport.accessManagerAddress, + hubLabels, + setRoles + ); - // Deploy Spoke Instance Batches - uint256 spokeCount = spokeLabels.length; - report.spokeInstanceBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); - Logger.AddressEntry[] memory spokeEntries = new Logger.AddressEntry[](spokeCount); - for (uint256 i; i < spokeCount; ++i) { - report.spokeInstanceBatchReports[i] = _deploySpoke( - logger, - deployer, - admin, - report.accessBatchReport.accessManagerAddress, - spokeLabels[i], - setRoles - ); - } - logger.writeGroup('SpokeInstances', spokeEntries); + // // Deploy Spoke Instance Batches + // report.spokeInstanceBatchReports = _deploySpokes( + // logger, + // deployer, + // admin, + // report.accessBatchReport.accessManagerAddress, + // spokeLabels, + // setRoles + // ); // Deploy Gateways Batch - report.gatewaysBatchReport = _deployGatewaysBatch(admin, nativeWrapper); - logger.log('NativeTokenGateway', report.gatewaysBatchReport.nativeGatewayAddress); - logger.log('SignatureGateway', report.gatewaysBatchReport.signatureGatewayAddress); + report.gatewaysBatchReport = _deployGatewayBatch(logger, admin, nativeWrapper); // Set Roles if needed if (setRoles) { @@ -105,6 +88,21 @@ library AaveV4DeployOrchestration { return report; } + function _deployHubs( + Logger logger, + address admin, + address accessManagerAddress, + string[] memory hubLabels, + bool setRoles + ) internal returns (OrchestrationReports.HubDeploymentReport[] memory hubBatchReports) { + uint256 hubCount = hubLabels.length; + hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); + for (uint256 i; i < hubCount; ++i) { + hubBatchReports[i] = _deployHub(logger, admin, accessManagerAddress, hubLabels[i], setRoles); + } + return hubBatchReports; + } + function _deployHub( Logger logger, address admin, @@ -115,9 +113,19 @@ library AaveV4DeployOrchestration { OrchestrationReports.HubDeploymentReport memory hubReport; hubReport.label = label; hubReport.report = _deployHubBatch(admin, accessManagerAddress); - logger.write('Hub', hubReport.report.hubAddress); - logger.write('InterestRateStrategy', hubReport.report.irStrategyAddress); - logger.write('TreasurySpoke', hubReport.report.treasurySpokeAddress); + + Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](3); + hubEntries[0] = Logger.AddressEntry({label: 'Hub', value: hubReport.report.hubAddress}); + hubEntries[1] = Logger.AddressEntry({ + label: 'InterestRateStrategy', + value: hubReport.report.irStrategyAddress + }); + hubEntries[2] = Logger.AddressEntry({ + label: 'TreasurySpoke', + value: hubReport.report.treasurySpokeAddress + }); + + logger.writeGroup(label, hubEntries); if (setRoles) { AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); @@ -126,6 +134,35 @@ library AaveV4DeployOrchestration { return hubReport; } + function _deploySpokes( + Logger logger, + address deployer, + address admin, + address accessManagerAddress, + string[] memory spokeLabels, + bool setRoles + ) internal returns (OrchestrationReports.SpokeDeploymentReport[] memory spokeBatchReports) { + uint256 spokeCount = spokeLabels.length; + spokeBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); + Logger.AddressEntry[] memory spokeEntries = new Logger.AddressEntry[](spokeCount); + for (uint256 i; i < spokeCount; ++i) { + spokeBatchReports[i] = _deploySpoke( + logger, + deployer, + admin, + accessManagerAddress, + spokeLabels[i], + setRoles + ); + spokeEntries[i] = Logger.AddressEntry({ + label: spokeLabels[i], + value: spokeBatchReports[i].report.spokeProxyAddress + }); + } + logger.writeGroup('SpokeInstances', spokeEntries); + return spokeBatchReports; + } + function _deploySpoke( Logger logger, address deployer, @@ -152,17 +189,24 @@ library AaveV4DeployOrchestration { } function _deployAccessBatch( + Logger logger, address admin - ) internal returns (BatchReports.AccessBatchReport memory) { + ) internal returns (BatchReports.AccessBatchReport memory report) { AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin); - return accessBatch.getReport(); + report = accessBatch.getReport(); + logger.write('AccessManager', report.accessManagerAddress); + return report; } function _deployConfiguratorBatch( + Logger logger, address admin - ) internal returns (BatchReports.ConfiguratorBatchReport memory) { + ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { AaveV4ConfiguratorBatch configuratorBatch = new AaveV4ConfiguratorBatch(admin); - return configuratorBatch.getReport(); + report = configuratorBatch.getReport(); + logger.write('HubConfigurator', report.hubConfiguratorAddress); + logger.write('SpokeConfigurator', report.spokeConfiguratorAddress); + return report; } function _deployHubBatch( @@ -190,11 +234,15 @@ library AaveV4DeployOrchestration { return spokeInstanceBatch.getReport(); } - function _deployGatewaysBatch( + function _deployGatewayBatch( + Logger logger, address admin, address nativeWrapper - ) internal returns (BatchReports.GatewaysBatchReport memory) { - AaveV4GatewaysBatch gatewaysBatch = new AaveV4GatewaysBatch(admin, nativeWrapper); - return gatewaysBatch.getReport(); + ) internal returns (BatchReports.GatewaysBatchReport memory report) { + AaveV4GatewayBatch gatewayBatch = new AaveV4GatewayBatch(admin, nativeWrapper); + report = gatewayBatch.getReport(); + logger.write('NativeTokenGateway', report.nativeGatewayAddress); + logger.write('SignatureGateway', report.signatureGatewayAddress); + return report; } } diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index ff3819d34..b6c59bd9b 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -2,11 +2,11 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import 'forge-std/StdJson.sol'; +import 'forge-std/stdToml.sol'; import 'forge-std/Vm.sol'; contract InputUtils { - using stdJson for string; + using stdToml for string; struct FullDeployInputs { address admin; @@ -32,10 +32,13 @@ contract InputUtils { function loadFullDeployInputs( string memory inputPath - ) public view returns (FullDeployInputs memory) { - string memory json = vm.readFile(inputPath); - bytes memory data = vm.parseJson(json); - FullDeployInputs memory inputs = abi.decode(data, (FullDeployInputs)); + ) public view returns (FullDeployInputs memory inputs) { + string memory toml = vm.readFile(inputPath); + inputs.admin = toml.readAddress('.admin'); + inputs.nativeWrapperAddress = toml.readAddress('.nativeWrapperAddress'); + inputs.setRoles = toml.readBool('.setRoles'); + inputs.hubLabels = toml.readStringArray('.hubLabels'); + inputs.spokeLabels = toml.readStringArray('.spokeLabels'); return inputs; } diff --git a/src/deployments/utils/Logger.sol b/src/deployments/utils/Logger.sol index 743a36638..98f359d4e 100644 --- a/src/deployments/utils/Logger.sol +++ b/src/deployments/utils/Logger.sol @@ -23,10 +23,12 @@ contract Logger { string internal _outputPath; string internal _root; + string internal _json; constructor(string memory outputPath_) { _root = 'root'; _outputPath = outputPath_; + _json = _root; } function log(string memory label, address value) public pure { @@ -64,8 +66,8 @@ contract Logger { function save() public { console.log(); console.log('Saving log to %s', _outputPath); - console.log(_root); - vm.writeJson(_root, _outputPath); + console.log(_json); + vm.writeJson(_json, _outputPath); } function _log(string memory label, address value) internal pure { @@ -82,17 +84,17 @@ contract Logger { function _write(string memory label, address value) internal { _log(label, value); - _root = vm.serializeAddress(_root, label, value); + _json = vm.serializeAddress(_root, label, value); } function _write(string memory label, uint256 value) internal { _log(label, value); - _root = vm.serializeString(_root, label, vm.toString(value)); + _json = vm.serializeString(_root, label, vm.toString(value)); } function _write(string memory value) internal { _log(value); - _root = vm.serializeString(_root, 'message', value); + _json = vm.serializeString(_root, 'message', value); } function _writeGroup(string memory groupLabel, AddressEntry[] memory entries) internal { @@ -100,9 +102,9 @@ contract Logger { _log(groupLabel); for (uint256 i = 0; i < entries.length; i++) { _log(entries[i].label, entries[i].value); - group = vm.serializeAddress(group, entries[i].label, entries[i].value); + group = vm.serializeAddress(groupLabel, entries[i].label, entries[i].value); } - _root = vm.serializeString(_root, groupLabel, group); + _json = vm.serializeString(_root, groupLabel, group); console.log(); } @@ -111,9 +113,9 @@ contract Logger { _log(groupLabel); for (uint256 i = 0; i < entries.length; i++) { _log(entries[i].label, entries[i].value); - group = vm.serializeString(group, entries[i].label, vm.toString(entries[i].value)); + group = vm.serializeString(groupLabel, entries[i].label, vm.toString(entries[i].value)); } - _root = vm.serializeString(_root, groupLabel, group); + _json = vm.serializeString(_root, groupLabel, group); console.log(); } } From 384aeefab5bb380b1415623adc7748dea8968ce5 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:38:55 -0600 Subject: [PATCH 18/62] fix: StdToml import --- src/deployments/utils/InputUtils.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index b6c59bd9b..cf81acfff 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -2,7 +2,7 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import 'forge-std/stdToml.sol'; +import 'forge-std/StdToml.sol'; import 'forge-std/Vm.sol'; contract InputUtils { From ac1dc8adf8a44168998d8a9a881d852e03bcbff8 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Thu, 4 Dec 2025 17:51:04 -0600 Subject: [PATCH 19/62] fix: debug mismatch of spoke instance --- scripts/deploy/AaveV4DeployBatch.s.sol | 3 ++- .../batches/AaveV4SpokeInstanceBatch.sol | 11 ++++++----- .../AaveV4DeployOrchestration.sol | 18 +++++++++--------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index d73237061..8880141a7 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -22,11 +22,12 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { function run() external { vm.createDir(OUTPUT_DIR, true); Logger logger = new Logger(string.concat(OUTPUT_DIR, OUTPUT_FILE)); - FullDeployInputs memory inputs = loadFullDeployInputs(OUTPUT_FILE); + FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); address deployer = msg.sender; logger.log('Starting Aave V4 Batch Deployment'); + logger.log('deployer', deployer); vm.startBroadcast(); AaveV4DeployOrchestration.deployAaveV4( diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 2d2f44940..924911966 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -4,6 +4,8 @@ pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; +import {console2 as console} from 'forge-std/console2.sol'; + import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import { AaveV4SpokeInstanceDeployProcedure @@ -23,16 +25,15 @@ contract AaveV4SpokeInstanceBatch is BatchReports.SpokeInstanceBatchReport internal _report; constructor( - Vm vm, - address deployer, + Vm vm_, address admin_, address accessManagerAddress_, uint8 oracleDecimals_, string memory oracleDescription_ ) { - address predictedSpokeInstanceAddress = vm.computeCreateAddress( - deployer, - vm.getNonce(deployer) + 2 + address predictedSpokeInstanceAddress = vm_.computeCreateAddress( + address(this), + vm_.getNonce(address(this)) + 2 ); address aaveOracleAddress = _deployAaveOracle( diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 5cdaff0ac..e0ea4fc24 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -58,15 +58,15 @@ library AaveV4DeployOrchestration { setRoles ); - // // Deploy Spoke Instance Batches - // report.spokeInstanceBatchReports = _deploySpokes( - // logger, - // deployer, - // admin, - // report.accessBatchReport.accessManagerAddress, - // spokeLabels, - // setRoles - // ); + // Deploy Spoke Instance Batches + report.spokeInstanceBatchReports = _deploySpokes( + logger, + deployer, + admin, + report.accessBatchReport.accessManagerAddress, + spokeLabels, + setRoles + ); // Deploy Gateways Batch report.gatewaysBatchReport = _deployGatewayBatch(logger, admin, nativeWrapper); From 1fd58308c975f260a10af6e3930f2bab10f7c6ab Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:54:17 -0600 Subject: [PATCH 20/62] tmp: push deploy progress w output json --- Makefile | 9 +++ scripts/deploy/AaveV4DeployBatch.s.sol | 56 +++++++++++++- .../batches/AaveV4SpokeInstanceBatch.sol | 15 ++-- .../AaveV4DeployOrchestration.sol | 74 +++++++++---------- .../orchestration/AaveV4TestOrchestration.sol | 24 ++++-- 5 files changed, 124 insertions(+), 54 deletions(-) diff --git a/Makefile b/Makefile index 45bd7435d..1a71efb51 100644 --- a/Makefile +++ b/Makefile @@ -29,3 +29,12 @@ coverage : make coverage-clean make coverage-report make coverage-badge + +# Deploy + +# Full deployment, including hubs, spokes, and gateways +deploy-full :; + FOUNDRY_PROFILE=${CHAIN} forge script scripts/deploy/AaveV4DeployBatch.s.sol:AaveV4DeployBatchScript \ + --rpc-url ${CHAIN} --sender ${SENDER} --account ${ACCOUNT} --slow \ + --broadcast + diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index 8880141a7..b7eb1c430 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -4,6 +4,8 @@ pragma solidity ^0.8.0; import {Script} from 'forge-std/Script.sol'; +import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; + import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; import {Logger} from 'src/deployments/utils/Logger.sol'; @@ -20,6 +22,8 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { constructor() {} function run() external { + OrchestrationReports.FullDeploymentReport memory report; + vm.createDir(OUTPUT_DIR, true); Logger logger = new Logger(string.concat(OUTPUT_DIR, OUTPUT_FILE)); FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); @@ -27,11 +31,9 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { address deployer = msg.sender; logger.log('Starting Aave V4 Batch Deployment'); - logger.log('deployer', deployer); vm.startBroadcast(); - AaveV4DeployOrchestration.deployAaveV4( - logger, + report = AaveV4DeployOrchestration.deployAaveV4( deployer, inputs.admin, inputs.nativeWrapperAddress, @@ -41,8 +43,56 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { ); vm.stopBroadcast(); + writeJsonReportMarket(logger, report); + logger.log('Batch Deployment Completed'); logger.log('Saving Logs'); logger.save(); } + + function writeJsonReportMarket( + Logger logger, + OrchestrationReports.FullDeploymentReport memory report + ) public { + logger.write('AccessBatchReport', report.accessBatchReport.accessManagerAddress); + logger.write('HubConfigurator', report.configuratorBatchReport.hubConfiguratorAddress); + logger.write('SpokeConfigurator', report.configuratorBatchReport.spokeConfiguratorAddress); + + for (uint256 i; i < report.hubBatchReports.length; i++) { + Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](3); + hubEntries[0] = Logger.AddressEntry({ + label: 'Hub', + value: report.hubBatchReports[i].report.hubAddress + }); + hubEntries[1] = Logger.AddressEntry({ + label: 'InterestRateStrategy', + value: report.hubBatchReports[i].report.hubAddress + }); + hubEntries[2] = Logger.AddressEntry({ + label: 'TreasurySpoke', + value: report.hubBatchReports[i].report.treasurySpokeAddress + }); + logger.writeGroup(report.hubBatchReports[i].label, hubEntries); + } + + for (uint256 i; i < report.spokeInstanceBatchReports.length; i++) { + Logger.AddressEntry[] memory spokeInstanceEntries = new Logger.AddressEntry[](3); + spokeInstanceEntries[0] = Logger.AddressEntry({ + label: 'SpokeInstance Proxy', + value: report.spokeInstanceBatchReports[i].report.spokeProxyAddress + }); + spokeInstanceEntries[1] = Logger.AddressEntry({ + label: 'SpokeInstance Implementation', + value: report.spokeInstanceBatchReports[i].report.spokeImplementationAddress + }); + spokeInstanceEntries[2] = Logger.AddressEntry({ + label: 'AaveOracle', + value: report.spokeInstanceBatchReports[i].report.aaveOracleAddress + }); + logger.writeGroup(report.spokeInstanceBatchReports[i].label, spokeInstanceEntries); + } + + logger.write('SignatureGateway', report.gatewaysBatchReport.signatureGatewayAddress); + logger.write('NativeTokenGateway', report.gatewaysBatchReport.nativeGatewayAddress); + } } diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 924911966..c0d83da22 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -24,17 +24,20 @@ contract AaveV4SpokeInstanceBatch is { BatchReports.SpokeInstanceBatchReport internal _report; + Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); + constructor( - Vm vm_, address admin_, address accessManagerAddress_, uint8 oracleDecimals_, string memory oracleDescription_ ) { - address predictedSpokeInstanceAddress = vm_.computeCreateAddress( - address(this), - vm_.getNonce(address(this)) + 2 - ); + // address predictedSpokeInstanceAddress = vm.computeCreateAddress( + // address(this), + // vm.getNonce(address(this)) + 2 + // ); + + address predictedSpokeInstanceAddress = address(this); // TODO: FIX address aaveOracleAddress = _deployAaveOracle( predictedSpokeInstanceAddress, @@ -48,7 +51,7 @@ contract AaveV4SpokeInstanceBatch is abi.encodeWithSignature('initialize(address)', accessManagerAddress_) ); - require(spokeProxyAddress == predictedSpokeInstanceAddress, 'SpokeInstance address mismatch'); + // require(spokeProxyAddress == predictedSpokeInstanceAddress_, 'SpokeInstance address mismatch'); // uncomment when fixed _report = BatchReports.SpokeInstanceBatchReport({ aaveOracleAddress: aaveOracleAddress, diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index e0ea4fc24..3c93d8ec6 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -32,7 +32,6 @@ library AaveV4DeployOrchestration { string private constant ORACLE_SUFFIX = ' (USD)'; function deployAaveV4( - Logger logger, address deployer, address admin, address nativeWrapper, @@ -44,14 +43,13 @@ library AaveV4DeployOrchestration { // Deploy Access Batch address accessManagerAdmin = setRoles ? deployer : admin; - report.accessBatchReport = _deployAccessBatch(logger, accessManagerAdmin); + report.accessBatchReport = _deployAccessBatch(accessManagerAdmin); // Deploy Configurator Batch - report.configuratorBatchReport = _deployConfiguratorBatch(logger, admin); + report.configuratorBatchReport = _deployConfiguratorBatch(admin); // Deploy Hub Batches report.hubBatchReports = _deployHubs( - logger, admin, report.accessBatchReport.accessManagerAddress, hubLabels, @@ -60,7 +58,6 @@ library AaveV4DeployOrchestration { // Deploy Spoke Instance Batches report.spokeInstanceBatchReports = _deploySpokes( - logger, deployer, admin, report.accessBatchReport.accessManagerAddress, @@ -69,7 +66,7 @@ library AaveV4DeployOrchestration { ); // Deploy Gateways Batch - report.gatewaysBatchReport = _deployGatewayBatch(logger, admin, nativeWrapper); + report.gatewaysBatchReport = _deployGatewayBatch(admin, nativeWrapper); // Set Roles if needed if (setRoles) { @@ -89,7 +86,6 @@ library AaveV4DeployOrchestration { } function _deployHubs( - Logger logger, address admin, address accessManagerAddress, string[] memory hubLabels, @@ -98,13 +94,13 @@ library AaveV4DeployOrchestration { uint256 hubCount = hubLabels.length; hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); for (uint256 i; i < hubCount; ++i) { - hubBatchReports[i] = _deployHub(logger, admin, accessManagerAddress, hubLabels[i], setRoles); + hubBatchReports[i] = _deployHub(admin, accessManagerAddress, hubLabels[i], setRoles); } return hubBatchReports; } function _deployHub( - Logger logger, + // Logger logger, address admin, address accessManagerAddress, string memory label, @@ -114,18 +110,18 @@ library AaveV4DeployOrchestration { hubReport.label = label; hubReport.report = _deployHubBatch(admin, accessManagerAddress); - Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](3); - hubEntries[0] = Logger.AddressEntry({label: 'Hub', value: hubReport.report.hubAddress}); - hubEntries[1] = Logger.AddressEntry({ - label: 'InterestRateStrategy', - value: hubReport.report.irStrategyAddress - }); - hubEntries[2] = Logger.AddressEntry({ - label: 'TreasurySpoke', - value: hubReport.report.treasurySpokeAddress - }); + // Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](3); + // hubEntries[0] = Logger.AddressEntry({label: 'Hub', value: hubReport.report.hubAddress}); + // hubEntries[1] = Logger.AddressEntry({ + // label: 'InterestRateStrategy', + // value: hubReport.report.irStrategyAddress + // }); + // hubEntries[2] = Logger.AddressEntry({ + // label: 'TreasurySpoke', + // value: hubReport.report.treasurySpokeAddress + // }); - logger.writeGroup(label, hubEntries); + // logger.writeGroup(label, hubEntries); if (setRoles) { AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); @@ -135,7 +131,7 @@ library AaveV4DeployOrchestration { } function _deploySpokes( - Logger logger, + // Logger logger, address deployer, address admin, address accessManagerAddress, @@ -147,7 +143,7 @@ library AaveV4DeployOrchestration { Logger.AddressEntry[] memory spokeEntries = new Logger.AddressEntry[](spokeCount); for (uint256 i; i < spokeCount; ++i) { spokeBatchReports[i] = _deploySpoke( - logger, + // logger, deployer, admin, accessManagerAddress, @@ -159,12 +155,12 @@ library AaveV4DeployOrchestration { value: spokeBatchReports[i].report.spokeProxyAddress }); } - logger.writeGroup('SpokeInstances', spokeEntries); + // logger.writeGroup('SpokeInstances', spokeEntries); return spokeBatchReports; } function _deploySpoke( - Logger logger, + // Logger logger, address deployer, address admin, address accessManagerAddress, @@ -172,11 +168,17 @@ library AaveV4DeployOrchestration { bool setRoles ) internal returns (OrchestrationReports.SpokeDeploymentReport memory) { OrchestrationReports.SpokeDeploymentReport memory spokeReport; + + // address predictedSpokeInstanceAddress = vm.computeCreateAddress( + // address(this), + // vm.getNonce(address(this)) + 2 + // ); + spokeReport.label = label; spokeReport.report = _deploySpokeInstanceBatch(deployer, admin, accessManagerAddress, label); - logger.write('SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); - logger.write('SpokeInstance Implementation', spokeReport.report.spokeImplementationAddress); - logger.write('AaveOracle', spokeReport.report.aaveOracleAddress); + // logger.write('SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); + // logger.write('SpokeInstance Implementation', spokeReport.report.spokeImplementationAddress); + // logger.write('AaveOracle', spokeReport.report.aaveOracleAddress); if (setRoles) { AaveV4SpokeRolesProcedure.setSpokeRoles( @@ -189,23 +191,23 @@ library AaveV4DeployOrchestration { } function _deployAccessBatch( - Logger logger, + // Logger logger, address admin ) internal returns (BatchReports.AccessBatchReport memory report) { AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin); report = accessBatch.getReport(); - logger.write('AccessManager', report.accessManagerAddress); + // logger.write('AccessManager', report.accessManagerAddress); return report; } function _deployConfiguratorBatch( - Logger logger, + // Logger logger, address admin ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { AaveV4ConfiguratorBatch configuratorBatch = new AaveV4ConfiguratorBatch(admin); report = configuratorBatch.getReport(); - logger.write('HubConfigurator', report.hubConfiguratorAddress); - logger.write('SpokeConfigurator', report.spokeConfiguratorAddress); + // logger.write('HubConfigurator', report.hubConfiguratorAddress); + // logger.write('SpokeConfigurator', report.spokeConfiguratorAddress); return report; } @@ -224,8 +226,6 @@ library AaveV4DeployOrchestration { string memory label ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch( - vm, - deployer, admin, accessManagerAddress, ORACLE_DECIMALS, @@ -235,14 +235,14 @@ library AaveV4DeployOrchestration { } function _deployGatewayBatch( - Logger logger, + // Logger logger, address admin, address nativeWrapper ) internal returns (BatchReports.GatewaysBatchReport memory report) { AaveV4GatewayBatch gatewayBatch = new AaveV4GatewayBatch(admin, nativeWrapper); report = gatewayBatch.getReport(); - logger.write('NativeTokenGateway', report.nativeGatewayAddress); - logger.write('SignatureGateway', report.signatureGatewayAddress); + // logger.write('NativeTokenGateway', report.nativeGatewayAddress); + // logger.write('SignatureGateway', report.signatureGatewayAddress); return report; } } diff --git a/src/deployments/orchestration/AaveV4TestOrchestration.sol b/src/deployments/orchestration/AaveV4TestOrchestration.sol index 2103bafd5..43f0537f7 100644 --- a/src/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/src/deployments/orchestration/AaveV4TestOrchestration.sol @@ -14,12 +14,22 @@ import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInsta import {TestTokensBatch} from 'src/deployments/batches/TestTokensBatch.sol'; -import {AaveV4AdminRolesProcedure} from 'src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol'; -import {AaveV4HubRolesProcedure} from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; -import {AaveV4SpokeRolesProcedure} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; - -import {AaveV4HubConfigProcedures} from 'src/deployments/procedures/config/AaveV4HubConfigProcedures.sol'; -import {AaveV4SpokeConfigProcedures} from 'src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol'; +import { + AaveV4AdminRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol'; +import { + AaveV4HubRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; +import { + AaveV4SpokeRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; + +import { + AaveV4HubConfigProcedures +} from 'src/deployments/procedures/config/AaveV4HubConfigProcedures.sol'; +import { + AaveV4SpokeConfigProcedures +} from 'src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol'; library AaveV4TestOrchestration { bool public constant IS_TEST = true; @@ -202,8 +212,6 @@ library AaveV4TestOrchestration { string memory label ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch( - vm, - admin, admin, accessManagerAddress, 8, From dd459c1c18cfd44bbe816c92f908db71d5f64b5c Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:18:17 -0600 Subject: [PATCH 21/62] fix: min logger interface; mv input toml file; resolve computeCreatedAddr --- foundry.toml | 3 +- scripts/deploy/AaveV4DeployBatch.s.sol | 13 +- .../deploy}/inputs/AaveV4DeployInput.toml | 0 .../batches/AaveV4SpokeInstanceBatch.sol | 21 +-- .../AaveV4DeployOrchestration.sol | 155 ++++++++++++------ .../roles/AaveV4AdminRolesProcedure.sol | 2 +- src/deployments/utils/Logger.sol | 23 +-- .../utils/interfaces/IProgressLogger.sol | 10 ++ 8 files changed, 146 insertions(+), 81 deletions(-) rename {src/deployments => scripts/deploy}/inputs/AaveV4DeployInput.toml (100%) create mode 100644 src/deployments/utils/interfaces/IProgressLogger.sol diff --git a/foundry.toml b/foundry.toml index baa06a090..4bb21e48f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -7,7 +7,7 @@ fs_permissions = [ { access = "read", path = "tests/mocks/JsonBindings.sol" }, { access = "read", path = "./config" }, { access = "read-write", path = "./output" }, - { access = "read-write", path = "./src/deployments/inputs" } + { access = "read-write", path = "./scripts/deploy/inputs" } ] solc_version = "0.8.28" evm_version = "cancun" @@ -54,6 +54,7 @@ zkevm = "${RPC_ZKEVM}" gnosis = "${RPC_GNOSIS}" bnb = "${RPC_BNB}" celo = "${RPC_CELO}" +anvil = "http://127.0.0.1:8545" [etherscan] mainnet = { key = "${ETHERSCAN_API_KEY_MAINNET}", chainId = 1 } diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index b7eb1c430..6900bead7 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import {Script} from 'forge-std/Script.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; - +import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; import {Logger} from 'src/deployments/utils/Logger.sol'; @@ -15,7 +15,7 @@ import { } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { - string internal constant INPUT_PATH = 'src/deployments/inputs/AaveV4DeployInput.toml'; + string internal constant INPUT_PATH = 'scripts/deploy/inputs/AaveV4DeployInput.toml'; string internal constant OUTPUT_DIR = 'output/reports/deployments/'; string internal constant OUTPUT_FILE = 'AaveV4DeployBatch.json'; @@ -30,10 +30,10 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { address deployer = msg.sender; - logger.log('Starting Aave V4 Batch Deployment'); + logger.log('...Starting Aave V4 Batch Deployment...'); - vm.startBroadcast(); report = AaveV4DeployOrchestration.deployAaveV4( + IProgressLogger(address(logger)), deployer, inputs.admin, inputs.nativeWrapperAddress, @@ -41,12 +41,11 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { inputs.spokeLabels, inputs.setRoles ); - vm.stopBroadcast(); writeJsonReportMarket(logger, report); - logger.log('Batch Deployment Completed'); - logger.log('Saving Logs'); + logger.log('...Batch Deployment Completed...'); + logger.log('...Saving Logs...'); logger.save(); } diff --git a/src/deployments/inputs/AaveV4DeployInput.toml b/scripts/deploy/inputs/AaveV4DeployInput.toml similarity index 100% rename from src/deployments/inputs/AaveV4DeployInput.toml rename to scripts/deploy/inputs/AaveV4DeployInput.toml diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index c0d83da22..02cb3cfdb 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -2,10 +2,6 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import 'forge-std/Vm.sol'; - -import {console2 as console} from 'forge-std/console2.sol'; - import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import { AaveV4SpokeInstanceDeployProcedure @@ -24,7 +20,7 @@ contract AaveV4SpokeInstanceBatch is { BatchReports.SpokeInstanceBatchReport internal _report; - Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); + // Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); constructor( address admin_, @@ -32,12 +28,7 @@ contract AaveV4SpokeInstanceBatch is uint8 oracleDecimals_, string memory oracleDescription_ ) { - // address predictedSpokeInstanceAddress = vm.computeCreateAddress( - // address(this), - // vm.getNonce(address(this)) + 2 - // ); - - address predictedSpokeInstanceAddress = address(this); // TODO: FIX + address predictedSpokeInstanceAddress = _computeCreateAddress(address(this), 3); address aaveOracleAddress = _deployAaveOracle( predictedSpokeInstanceAddress, @@ -51,7 +42,7 @@ contract AaveV4SpokeInstanceBatch is abi.encodeWithSignature('initialize(address)', accessManagerAddress_) ); - // require(spokeProxyAddress == predictedSpokeInstanceAddress_, 'SpokeInstance address mismatch'); // uncomment when fixed + require(spokeProxyAddress == predictedSpokeInstanceAddress, 'SpokeInstance address mismatch'); // uncomment when fixed _report = BatchReports.SpokeInstanceBatchReport({ aaveOracleAddress: aaveOracleAddress, @@ -63,4 +54,10 @@ contract AaveV4SpokeInstanceBatch is function getReport() external view returns (BatchReports.SpokeInstanceBatchReport memory) { return _report; } + + function _computeCreateAddress(address deployer, uint8 nonce) internal pure returns (address) { + // RLP([deployer, nonce]) for 1 <= nonce <= 0x7f + bytes memory rlp = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, nonce); + return address(uint160(uint256(keccak256(rlp)))); + } } diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 3c93d8ec6..ad27d1b8e 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; -import {Logger} from 'src/deployments/utils/Logger.sol'; +import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; @@ -32,6 +32,7 @@ library AaveV4DeployOrchestration { string private constant ORACLE_SUFFIX = ' (USD)'; function deployAaveV4( + IProgressLogger logger, address deployer, address admin, address nativeWrapper, @@ -43,13 +44,15 @@ library AaveV4DeployOrchestration { // Deploy Access Batch address accessManagerAdmin = setRoles ? deployer : admin; - report.accessBatchReport = _deployAccessBatch(accessManagerAdmin); + report.accessBatchReport = _deployAccessBatch(logger, deployer, accessManagerAdmin); // Deploy Configurator Batch - report.configuratorBatchReport = _deployConfiguratorBatch(admin); + report.configuratorBatchReport = _deployConfiguratorBatch(logger, deployer, admin); // Deploy Hub Batches report.hubBatchReports = _deployHubs( + logger, + deployer, admin, report.accessBatchReport.accessManagerAddress, hubLabels, @@ -58,6 +61,7 @@ library AaveV4DeployOrchestration { // Deploy Spoke Instance Batches report.spokeInstanceBatchReports = _deploySpokes( + logger, deployer, admin, report.accessBatchReport.accessManagerAddress, @@ -66,16 +70,19 @@ library AaveV4DeployOrchestration { ); // Deploy Gateways Batch - report.gatewaysBatchReport = _deployGatewayBatch(admin, nativeWrapper); + report.gatewaysBatchReport = _deployGatewayBatch(logger, deployer, admin, nativeWrapper); // Set Roles if needed if (setRoles) { + logger.log('...Setting Configurator roles...'); AaveV4AdminRolesProcedure.setConfiguratorAdminRoles( report.accessBatchReport.accessManagerAddress, report.configuratorBatchReport.spokeConfiguratorAddress, report.configuratorBatchReport.hubConfiguratorAddress ); - AaveV4AdminRolesProcedure.setNewAdminRole( + + logger.log('...Setting AccessManager Root Admin role...'); + AaveV4AdminRolesProcedure.setAccessManagerRootAdminRole( report.accessBatchReport.accessManagerAddress, admin, deployer @@ -85,7 +92,42 @@ library AaveV4DeployOrchestration { return report; } + function _deployAccessBatch( + IProgressLogger logger, + address deployer, + address admin + ) internal returns (BatchReports.AccessBatchReport memory report) { + logger.log('...Deploying AccessBatch...'); + + if (!IS_TEST) vm.broadcast(deployer); + AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin); + + report = accessBatch.getReport(); + logger.log('AccessManager', report.accessManagerAddress); + logger.log(''); + return report; + } + + function _deployConfiguratorBatch( + IProgressLogger logger, + address deployer, + address admin + ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { + logger.log('...Deploying ConfiguratorBatch...'); + + if (!IS_TEST) vm.broadcast(deployer); + AaveV4ConfiguratorBatch configuratorBatch = new AaveV4ConfiguratorBatch(admin); + + report = configuratorBatch.getReport(); + logger.log('HubConfigurator', report.hubConfiguratorAddress); + logger.log('SpokeConfigurator', report.spokeConfiguratorAddress); + logger.log(''); + return report; + } + function _deployHubs( + IProgressLogger logger, + address deployer, address admin, address accessManagerAddress, string[] memory hubLabels, @@ -94,13 +136,22 @@ library AaveV4DeployOrchestration { uint256 hubCount = hubLabels.length; hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); for (uint256 i; i < hubCount; ++i) { - hubBatchReports[i] = _deployHub(admin, accessManagerAddress, hubLabels[i], setRoles); + hubBatchReports[i] = _deployHub( + logger, + deployer, + admin, + accessManagerAddress, + hubLabels[i], + setRoles + ); } + logger.log(''); return hubBatchReports; } function _deployHub( - // Logger logger, + IProgressLogger logger, + address deployer, address admin, address accessManagerAddress, string memory label, @@ -108,7 +159,12 @@ library AaveV4DeployOrchestration { ) internal returns (OrchestrationReports.HubDeploymentReport memory) { OrchestrationReports.HubDeploymentReport memory hubReport; hubReport.label = label; - hubReport.report = _deployHubBatch(admin, accessManagerAddress); + hubReport.report = _deployHubBatch(logger, deployer, admin, accessManagerAddress); + + logger.log(label); + logger.log(' Hub', hubReport.report.hubAddress); + logger.log(' InterestRateStrategy', hubReport.report.irStrategyAddress); + logger.log(' TreasurySpoke', hubReport.report.treasurySpokeAddress); // Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](3); // hubEntries[0] = Logger.AddressEntry({label: 'Hub', value: hubReport.report.hubAddress}); @@ -124,6 +180,7 @@ library AaveV4DeployOrchestration { // logger.writeGroup(label, hubEntries); if (setRoles) { + logger.log('...Setting Hub roles...'); AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); } @@ -131,7 +188,7 @@ library AaveV4DeployOrchestration { } function _deploySpokes( - // Logger logger, + IProgressLogger logger, address deployer, address admin, address accessManagerAddress, @@ -140,27 +197,28 @@ library AaveV4DeployOrchestration { ) internal returns (OrchestrationReports.SpokeDeploymentReport[] memory spokeBatchReports) { uint256 spokeCount = spokeLabels.length; spokeBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); - Logger.AddressEntry[] memory spokeEntries = new Logger.AddressEntry[](spokeCount); + // Logger.AddressEntry[] memory spokeEntries = new Logger.AddressEntry[](spokeCount); for (uint256 i; i < spokeCount; ++i) { spokeBatchReports[i] = _deploySpoke( - // logger, + logger, deployer, admin, accessManagerAddress, spokeLabels[i], setRoles ); - spokeEntries[i] = Logger.AddressEntry({ - label: spokeLabels[i], - value: spokeBatchReports[i].report.spokeProxyAddress - }); + // spokeEntries[i] = Logger.AddressEntry({ + // label: spokeLabels[i], + // value: spokeBatchReports[i].report.spokeProxyAddress + // }); } // logger.writeGroup('SpokeInstances', spokeEntries); + logger.log(''); return spokeBatchReports; } function _deploySpoke( - // Logger logger, + IProgressLogger logger, address deployer, address admin, address accessManagerAddress, @@ -169,18 +227,22 @@ library AaveV4DeployOrchestration { ) internal returns (OrchestrationReports.SpokeDeploymentReport memory) { OrchestrationReports.SpokeDeploymentReport memory spokeReport; - // address predictedSpokeInstanceAddress = vm.computeCreateAddress( - // address(this), - // vm.getNonce(address(this)) + 2 - // ); - spokeReport.label = label; - spokeReport.report = _deploySpokeInstanceBatch(deployer, admin, accessManagerAddress, label); - // logger.write('SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); - // logger.write('SpokeInstance Implementation', spokeReport.report.spokeImplementationAddress); - // logger.write('AaveOracle', spokeReport.report.aaveOracleAddress); + spokeReport.report = _deploySpokeInstanceBatch( + logger, + deployer, + admin, + accessManagerAddress, + label + ); + + logger.log(label); + logger.log(' SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); + logger.log(' SpokeInstance Implementation', spokeReport.report.spokeImplementationAddress); + logger.log(' AaveOracle', spokeReport.report.aaveOracleAddress); if (setRoles) { + logger.log('...Setting Spoke roles...'); AaveV4SpokeRolesProcedure.setSpokeRoles( accessManagerAddress, spokeReport.report.spokeProxyAddress @@ -190,59 +252,54 @@ library AaveV4DeployOrchestration { return spokeReport; } - function _deployAccessBatch( - // Logger logger, - address admin - ) internal returns (BatchReports.AccessBatchReport memory report) { - AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin); - report = accessBatch.getReport(); - // logger.write('AccessManager', report.accessManagerAddress); - return report; - } - - function _deployConfiguratorBatch( - // Logger logger, - address admin - ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { - AaveV4ConfiguratorBatch configuratorBatch = new AaveV4ConfiguratorBatch(admin); - report = configuratorBatch.getReport(); - // logger.write('HubConfigurator', report.hubConfiguratorAddress); - // logger.write('SpokeConfigurator', report.spokeConfiguratorAddress); - return report; - } - function _deployHubBatch( + IProgressLogger logger, + address deployer, address admin, address accessManagerAddress ) internal returns (BatchReports.HubBatchReport memory) { + logger.log('...Deploying HubBatch...'); + + if (!IS_TEST) vm.broadcast(deployer); AaveV4HubBatch hubBatch = new AaveV4HubBatch(admin, accessManagerAddress); + return hubBatch.getReport(); } function _deploySpokeInstanceBatch( + IProgressLogger logger, address deployer, address admin, address accessManagerAddress, string memory label ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { + logger.log('...Deploying AaveV4SpokeInstanceBatch...'); + + if (!IS_TEST) vm.broadcast(deployer); AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch( admin, accessManagerAddress, ORACLE_DECIMALS, string.concat(label, ORACLE_SUFFIX) ); + return spokeInstanceBatch.getReport(); } function _deployGatewayBatch( - // Logger logger, + IProgressLogger logger, + address deployer, address admin, address nativeWrapper ) internal returns (BatchReports.GatewaysBatchReport memory report) { + logger.log('...Deploying GatewayBatch...'); + + if (!IS_TEST) vm.broadcast(deployer); AaveV4GatewayBatch gatewayBatch = new AaveV4GatewayBatch(admin, nativeWrapper); + report = gatewayBatch.getReport(); - // logger.write('NativeTokenGateway', report.nativeGatewayAddress); - // logger.write('SignatureGateway', report.signatureGatewayAddress); + logger.log('NativeTokenGateway', report.nativeGatewayAddress); + logger.log('SignatureGateway', report.signatureGatewayAddress); return report; } } diff --git a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol index be1b8e1bf..1b6adeefe 100644 --- a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol @@ -38,7 +38,7 @@ library AaveV4AdminRolesProcedure { ); } - function setNewAdminRole( + function setAccessManagerRootAdminRole( address accessManagerAddress, address newAdminAddress, address currentAdminAddress diff --git a/src/deployments/utils/Logger.sol b/src/deployments/utils/Logger.sol index 98f359d4e..fd25b1909 100644 --- a/src/deployments/utils/Logger.sol +++ b/src/deployments/utils/Logger.sol @@ -6,7 +6,9 @@ import 'forge-std/StdJson.sol'; import 'forge-std/Vm.sol'; import {console} from 'forge-std/console.sol'; -contract Logger { +import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; + +contract Logger is IProgressLogger { using stdJson for string; struct AddressEntry { @@ -66,7 +68,6 @@ contract Logger { function save() public { console.log(); console.log('Saving log to %s', _outputPath); - console.log(_json); vm.writeJson(_json, _outputPath); } @@ -83,39 +84,39 @@ contract Logger { } function _write(string memory label, address value) internal { - _log(label, value); + // _log(label, value); _json = vm.serializeAddress(_root, label, value); } function _write(string memory label, uint256 value) internal { - _log(label, value); + // _log(label, value); _json = vm.serializeString(_root, label, vm.toString(value)); } function _write(string memory value) internal { - _log(value); + // _log(value); _json = vm.serializeString(_root, 'message', value); } function _writeGroup(string memory groupLabel, AddressEntry[] memory entries) internal { string memory group; - _log(groupLabel); + // _log(groupLabel); for (uint256 i = 0; i < entries.length; i++) { - _log(entries[i].label, entries[i].value); + // _log(entries[i].label, entries[i].value); group = vm.serializeAddress(groupLabel, entries[i].label, entries[i].value); } _json = vm.serializeString(_root, groupLabel, group); - console.log(); + // console.log(); } function _writeGroup(string memory groupLabel, ValueEntry[] memory entries) internal { string memory group; - _log(groupLabel); + // _log(groupLabel); for (uint256 i = 0; i < entries.length; i++) { - _log(entries[i].label, entries[i].value); + // _log(entries[i].label, entries[i].value); group = vm.serializeString(groupLabel, entries[i].label, vm.toString(entries[i].value)); } _json = vm.serializeString(_root, groupLabel, group); - console.log(); + // console.log(); } } diff --git a/src/deployments/utils/interfaces/IProgressLogger.sol b/src/deployments/utils/interfaces/IProgressLogger.sol new file mode 100644 index 000000000..694c3da3e --- /dev/null +++ b/src/deployments/utils/interfaces/IProgressLogger.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; +interface IProgressLogger { + function log(string memory label, address value) external pure; + + function log(string memory label, uint256 value) external pure; + + function log(string memory value) external pure; +} From 11be630ac0101319470f8f789f1e5e477d212003 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:39:25 -0600 Subject: [PATCH 22/62] rft: DeployCore lib --- .../batches/AaveV4SpokeInstanceBatch.sol | 12 +--- .../orchestration/AaveV4DeployCore.sol | 60 +++++++++++++++++++ .../AaveV4DeployOrchestration.sol | 33 +++++----- .../orchestration/AaveV4TestOrchestration.sol | 53 +++++----------- src/deployments/utils/libraries/Utils.sol | 11 ++++ 5 files changed, 103 insertions(+), 66 deletions(-) create mode 100644 src/deployments/orchestration/AaveV4DeployCore.sol create mode 100644 src/deployments/utils/libraries/Utils.sol diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 02cb3cfdb..aa81e6c99 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -12,6 +12,7 @@ import { import { AaveV4AaveOracleDeployProcedure } from 'src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol'; +import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; contract AaveV4SpokeInstanceBatch is AaveV4SpokeInstanceDeployProcedure, @@ -20,15 +21,14 @@ contract AaveV4SpokeInstanceBatch is { BatchReports.SpokeInstanceBatchReport internal _report; - // Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); - constructor( address admin_, address accessManagerAddress_, uint8 oracleDecimals_, string memory oracleDescription_ ) { - address predictedSpokeInstanceAddress = _computeCreateAddress(address(this), 3); + // additional 3 nonces for AaveOracle, SpokeInstance, and TransparentUpgradeableProxy + address predictedSpokeInstanceAddress = Utils.computeCreateAddress(address(this), 3); address aaveOracleAddress = _deployAaveOracle( predictedSpokeInstanceAddress, @@ -54,10 +54,4 @@ contract AaveV4SpokeInstanceBatch is function getReport() external view returns (BatchReports.SpokeInstanceBatchReport memory) { return _report; } - - function _computeCreateAddress(address deployer, uint8 nonce) internal pure returns (address) { - // RLP([deployer, nonce]) for 1 <= nonce <= 0x7f - bytes memory rlp = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, nonce); - return address(uint160(uint256(keccak256(rlp)))); - } } diff --git a/src/deployments/orchestration/AaveV4DeployCore.sol b/src/deployments/orchestration/AaveV4DeployCore.sol new file mode 100644 index 000000000..f0d32ff7e --- /dev/null +++ b/src/deployments/orchestration/AaveV4DeployCore.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; +import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; + +import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; +import {AaveV4ConfiguratorBatch} from 'src/deployments/batches/AaveV4ConfiguratorBatch.sol'; +import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; +import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; +import {AaveV4GatewayBatch} from 'src/deployments/batches/AaveV4GatewayBatch.sol'; + +library AaveV4DeployCore { + function deployAccessBatch( + address accessManagerAdmin + ) internal returns (BatchReports.AccessBatchReport memory) { + AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(accessManagerAdmin); + return accessBatch.getReport(); + } + + function deployConfiguratorBatch( + address admin + ) internal returns (BatchReports.ConfiguratorBatchReport memory) { + AaveV4ConfiguratorBatch configuratorBatch = new AaveV4ConfiguratorBatch(admin); + return configuratorBatch.getReport(); + } + + function deployHubBatch( + address admin, + address accessManagerAddress + ) internal returns (BatchReports.HubBatchReport memory) { + AaveV4HubBatch hubBatch = new AaveV4HubBatch(admin, accessManagerAddress); + return hubBatch.getReport(); + } + + function deploySpokeInstanceBatch( + address admin, + address accessManagerAddress, + uint8 oracleDecimals, + string memory oracleSuffix, + string memory label + ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { + AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch( + admin, + accessManagerAddress, + oracleDecimals, + string.concat(label, oracleSuffix) + ); + return spokeInstanceBatch.getReport(); + } + + function deployGatewaysBatch( + address admin, + address nativeWrapper + ) internal returns (BatchReports.GatewaysBatchReport memory) { + AaveV4GatewayBatch gatewayBatch = new AaveV4GatewayBatch(admin, nativeWrapper); + return gatewayBatch.getReport(); + } +} diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index ad27d1b8e..dcf465bd1 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -7,6 +7,7 @@ import 'forge-std/Vm.sol'; import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; +import {AaveV4DeployCore} from 'src/deployments/orchestration/AaveV4DeployCore.sol'; import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; import {AaveV4ConfiguratorBatch} from 'src/deployments/batches/AaveV4ConfiguratorBatch.sol'; @@ -25,7 +26,6 @@ import { } from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; library AaveV4DeployOrchestration { - bool public constant IS_TEST = true; Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); uint8 private constant ORACLE_DECIMALS = 8; @@ -99,10 +99,9 @@ library AaveV4DeployOrchestration { ) internal returns (BatchReports.AccessBatchReport memory report) { logger.log('...Deploying AccessBatch...'); - if (!IS_TEST) vm.broadcast(deployer); - AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin); + vm.broadcast(deployer); + report = AaveV4DeployCore.deployAccessBatch(admin); - report = accessBatch.getReport(); logger.log('AccessManager', report.accessManagerAddress); logger.log(''); return report; @@ -115,10 +114,9 @@ library AaveV4DeployOrchestration { ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { logger.log('...Deploying ConfiguratorBatch...'); - if (!IS_TEST) vm.broadcast(deployer); - AaveV4ConfiguratorBatch configuratorBatch = new AaveV4ConfiguratorBatch(admin); + vm.broadcast(deployer); + report = AaveV4DeployCore.deployConfiguratorBatch(admin); - report = configuratorBatch.getReport(); logger.log('HubConfigurator', report.hubConfiguratorAddress); logger.log('SpokeConfigurator', report.spokeConfiguratorAddress); logger.log(''); @@ -260,10 +258,9 @@ library AaveV4DeployOrchestration { ) internal returns (BatchReports.HubBatchReport memory) { logger.log('...Deploying HubBatch...'); - if (!IS_TEST) vm.broadcast(deployer); - AaveV4HubBatch hubBatch = new AaveV4HubBatch(admin, accessManagerAddress); + vm.broadcast(deployer); - return hubBatch.getReport(); + return AaveV4DeployCore.deployHubBatch(admin, accessManagerAddress); } function _deploySpokeInstanceBatch( @@ -272,18 +269,19 @@ library AaveV4DeployOrchestration { address admin, address accessManagerAddress, string memory label - ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { + ) internal returns (BatchReports.SpokeInstanceBatchReport memory report) { logger.log('...Deploying AaveV4SpokeInstanceBatch...'); - if (!IS_TEST) vm.broadcast(deployer); - AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch( + vm.broadcast(deployer); + report = AaveV4DeployCore.deploySpokeInstanceBatch( admin, accessManagerAddress, ORACLE_DECIMALS, - string.concat(label, ORACLE_SUFFIX) + ORACLE_SUFFIX, + label ); - return spokeInstanceBatch.getReport(); + return report; } function _deployGatewayBatch( @@ -294,10 +292,9 @@ library AaveV4DeployOrchestration { ) internal returns (BatchReports.GatewaysBatchReport memory report) { logger.log('...Deploying GatewayBatch...'); - if (!IS_TEST) vm.broadcast(deployer); - AaveV4GatewayBatch gatewayBatch = new AaveV4GatewayBatch(admin, nativeWrapper); + vm.broadcast(deployer); - report = gatewayBatch.getReport(); + report = AaveV4DeployCore.deployGatewaysBatch(admin, nativeWrapper); logger.log('NativeTokenGateway', report.nativeGatewayAddress); logger.log('SignatureGateway', report.signatureGatewayAddress); return report; diff --git a/src/deployments/orchestration/AaveV4TestOrchestration.sol b/src/deployments/orchestration/AaveV4TestOrchestration.sol index 43f0537f7..9ae5eb01f 100644 --- a/src/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/src/deployments/orchestration/AaveV4TestOrchestration.sol @@ -31,8 +31,9 @@ import { AaveV4SpokeConfigProcedures } from 'src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol'; +import {AaveV4DeployCore} from 'src/deployments/orchestration/AaveV4DeployCore.sol'; + library AaveV4TestOrchestration { - bool public constant IS_TEST = true; Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); uint8 private constant ORACLE_DECIMALS = 8; @@ -50,11 +51,11 @@ library AaveV4TestOrchestration { report.spokeReports = new OrchestrationReports.TestSpokeReport[](spokeCount); // Deploy Access Batch - report.accessManagerAddress = _deployAccessBatch(admin).accessManagerAddress; + report.accessManagerAddress = AaveV4DeployCore.deployAccessBatch(admin).accessManagerAddress; // Deploy Hub Batches for (uint256 i; i < hubCount; ++i) { - BatchReports.HubBatchReport memory hubReport = _deployHubBatch( + BatchReports.HubBatchReport memory hubReport = AaveV4DeployCore.deployHubBatch( treasuryAdmin, report.accessManagerAddress ); @@ -65,11 +66,14 @@ library AaveV4TestOrchestration { // Deploy Spoke Instance Batches for (uint256 i; i < spokeCount; ++i) { - BatchReports.SpokeInstanceBatchReport memory spokeReport = _deploySpokeInstanceBatch( - admin, - report.accessManagerAddress, - string.concat('Spoke ', string(abi.encode(i)), ' (USD)') - ); + BatchReports.SpokeInstanceBatchReport memory spokeReport = AaveV4DeployCore + .deploySpokeInstanceBatch( + admin, + report.accessManagerAddress, + ORACLE_DECIMALS, + ORACLE_SUFFIX, + string.concat('Spoke ', string(abi.encode(i)), ' (USD)') + ); report.spokeReports[i].spokeAddress = spokeReport.spokeProxyAddress; report.spokeReports[i].aaveOracleAddress = spokeReport.aaveOracleAddress; } @@ -134,10 +138,10 @@ library AaveV4TestOrchestration { ) external returns (address, OrchestrationReports.TestHubReport memory) { OrchestrationReports.TestHubReport memory report; - address accessManagerAddress = _deployAccessBatch(admin).accessManagerAddress; + address accessManagerAddress = AaveV4DeployCore.deployAccessBatch(admin).accessManagerAddress; // Deploy Hub Batch - BatchReports.HubBatchReport memory hubReport = _deployHubBatch( + BatchReports.HubBatchReport memory hubReport = AaveV4DeployCore.deployHubBatch( treasuryAdmin, accessManagerAddress ); @@ -190,33 +194,4 @@ library AaveV4TestOrchestration { TestTokensBatch tokensBatch = new TestTokensBatch(tokenInputs); return tokensBatch.getReport(); } - - function _deployAccessBatch( - address admin - ) internal returns (BatchReports.AccessBatchReport memory) { - AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin); - return accessBatch.getReport(); - } - - function _deployHubBatch( - address admin, - address accessManagerAddress - ) internal returns (BatchReports.HubBatchReport memory) { - AaveV4HubBatch hubBatch = new AaveV4HubBatch(admin, accessManagerAddress); - return hubBatch.getReport(); - } - - function _deploySpokeInstanceBatch( - address admin, - address accessManagerAddress, - string memory label - ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { - AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch( - admin, - accessManagerAddress, - 8, - label - ); - return spokeInstanceBatch.getReport(); - } } diff --git a/src/deployments/utils/libraries/Utils.sol b/src/deployments/utils/libraries/Utils.sol new file mode 100644 index 000000000..fdaafbe7f --- /dev/null +++ b/src/deployments/utils/libraries/Utils.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +library Utils { + function computeCreateAddress(address deployer, uint8 nonce) internal pure returns (address) { + // RLP([deployer, nonce]) for 1 <= nonce <= 0x7f + bytes memory rlp = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, nonce); + return address(uint160(uint256(keccak256(rlp)))); + } +} From 7b16818ec07ec82906bddcb5645b428e006bd2a8 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:47:13 -0600 Subject: [PATCH 23/62] rft: metadata logger --- scripts/deploy/AaveV4DeployBatch.s.sol | 53 ++---------------------- src/deployments/utils/MetadataLogger.sol | 53 ++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 50 deletions(-) create mode 100644 src/deployments/utils/MetadataLogger.sol diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index 6900bead7..e86935b06 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -8,8 +8,7 @@ import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationRepor import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; -import {Logger} from 'src/deployments/utils/Logger.sol'; - +import {MetadataLogger} from 'src/deployments/utils/MetadataLogger.sol'; import { AaveV4DeployOrchestration } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; @@ -25,7 +24,7 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { OrchestrationReports.FullDeploymentReport memory report; vm.createDir(OUTPUT_DIR, true); - Logger logger = new Logger(string.concat(OUTPUT_DIR, OUTPUT_FILE)); + MetadataLogger logger = new MetadataLogger(string.concat(OUTPUT_DIR, OUTPUT_FILE)); FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); address deployer = msg.sender; @@ -42,56 +41,10 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { inputs.setRoles ); - writeJsonReportMarket(logger, report); + logger.writeJsonReportMarket(report); logger.log('...Batch Deployment Completed...'); logger.log('...Saving Logs...'); logger.save(); } - - function writeJsonReportMarket( - Logger logger, - OrchestrationReports.FullDeploymentReport memory report - ) public { - logger.write('AccessBatchReport', report.accessBatchReport.accessManagerAddress); - logger.write('HubConfigurator', report.configuratorBatchReport.hubConfiguratorAddress); - logger.write('SpokeConfigurator', report.configuratorBatchReport.spokeConfiguratorAddress); - - for (uint256 i; i < report.hubBatchReports.length; i++) { - Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](3); - hubEntries[0] = Logger.AddressEntry({ - label: 'Hub', - value: report.hubBatchReports[i].report.hubAddress - }); - hubEntries[1] = Logger.AddressEntry({ - label: 'InterestRateStrategy', - value: report.hubBatchReports[i].report.hubAddress - }); - hubEntries[2] = Logger.AddressEntry({ - label: 'TreasurySpoke', - value: report.hubBatchReports[i].report.treasurySpokeAddress - }); - logger.writeGroup(report.hubBatchReports[i].label, hubEntries); - } - - for (uint256 i; i < report.spokeInstanceBatchReports.length; i++) { - Logger.AddressEntry[] memory spokeInstanceEntries = new Logger.AddressEntry[](3); - spokeInstanceEntries[0] = Logger.AddressEntry({ - label: 'SpokeInstance Proxy', - value: report.spokeInstanceBatchReports[i].report.spokeProxyAddress - }); - spokeInstanceEntries[1] = Logger.AddressEntry({ - label: 'SpokeInstance Implementation', - value: report.spokeInstanceBatchReports[i].report.spokeImplementationAddress - }); - spokeInstanceEntries[2] = Logger.AddressEntry({ - label: 'AaveOracle', - value: report.spokeInstanceBatchReports[i].report.aaveOracleAddress - }); - logger.writeGroup(report.spokeInstanceBatchReports[i].label, spokeInstanceEntries); - } - - logger.write('SignatureGateway', report.gatewaysBatchReport.signatureGatewayAddress); - logger.write('NativeTokenGateway', report.gatewaysBatchReport.nativeGatewayAddress); - } } diff --git a/src/deployments/utils/MetadataLogger.sol b/src/deployments/utils/MetadataLogger.sol new file mode 100644 index 000000000..4315ea01a --- /dev/null +++ b/src/deployments/utils/MetadataLogger.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Logger} from 'src/deployments/utils/Logger.sol'; +import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; + +contract MetadataLogger is Logger { + constructor(string memory outputPath_) Logger(outputPath_) {} + + function writeJsonReportMarket(OrchestrationReports.FullDeploymentReport memory report) public { + write('AccessBatchReport', report.accessBatchReport.accessManagerAddress); + write('HubConfigurator', report.configuratorBatchReport.hubConfiguratorAddress); + write('SpokeConfigurator', report.configuratorBatchReport.spokeConfiguratorAddress); + + for (uint256 i; i < report.hubBatchReports.length; i++) { + Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](3); + hubEntries[0] = Logger.AddressEntry({ + label: 'Hub', + value: report.hubBatchReports[i].report.hubAddress + }); + hubEntries[1] = Logger.AddressEntry({ + label: 'InterestRateStrategy', + value: report.hubBatchReports[i].report.hubAddress + }); + hubEntries[2] = Logger.AddressEntry({ + label: 'TreasurySpoke', + value: report.hubBatchReports[i].report.treasurySpokeAddress + }); + writeGroup(report.hubBatchReports[i].label, hubEntries); + } + + for (uint256 i; i < report.spokeInstanceBatchReports.length; i++) { + Logger.AddressEntry[] memory spokeInstanceEntries = new Logger.AddressEntry[](3); + spokeInstanceEntries[0] = Logger.AddressEntry({ + label: 'SpokeInstance Proxy', + value: report.spokeInstanceBatchReports[i].report.spokeProxyAddress + }); + spokeInstanceEntries[1] = Logger.AddressEntry({ + label: 'SpokeInstance Implementation', + value: report.spokeInstanceBatchReports[i].report.spokeImplementationAddress + }); + spokeInstanceEntries[2] = Logger.AddressEntry({ + label: 'AaveOracle', + value: report.spokeInstanceBatchReports[i].report.aaveOracleAddress + }); + writeGroup(report.spokeInstanceBatchReports[i].label, spokeInstanceEntries); + } + + write('SignatureGateway', report.gatewaysBatchReport.signatureGatewayAddress); + write('NativeTokenGateway', report.gatewaysBatchReport.nativeGatewayAddress); + } +} From 8f7d6f77365fd932b2769eeafb0996493055f0b6 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:04:20 -0600 Subject: [PATCH 24/62] feat: include timestamp in log output --- foundry.toml | 1 + scripts/deploy/AaveV4DeployBatch.s.sol | 4 +-- .../AaveV4DeployOrchestration.sol | 29 ++++++++++++++++--- src/deployments/utils/Logger.sol | 20 +++++++++++-- src/deployments/utils/MetadataLogger.sol | 16 +++++----- 5 files changed, 53 insertions(+), 17 deletions(-) diff --git a/foundry.toml b/foundry.toml index 4bb21e48f..adec3f2db 100644 --- a/foundry.toml +++ b/foundry.toml @@ -16,6 +16,7 @@ optimizer_runs = 200 bytecode_hash = "none" gas_snapshot_check = false gas_limit = 1099511627776 +ffi = true [bind_json] out = "tests/mocks/JsonBindings.sol" diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index e86935b06..16a942571 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -24,7 +24,7 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { OrchestrationReports.FullDeploymentReport memory report; vm.createDir(OUTPUT_DIR, true); - MetadataLogger logger = new MetadataLogger(string.concat(OUTPUT_DIR, OUTPUT_FILE)); + MetadataLogger logger = new MetadataLogger(OUTPUT_DIR); FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); address deployer = msg.sender; @@ -45,6 +45,6 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { logger.log('...Batch Deployment Completed...'); logger.log('...Saving Logs...'); - logger.save(); + logger.save({fileName: OUTPUT_FILE, withTimestamp: true}); } } diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index dcf465bd1..7b7523448 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -39,9 +39,7 @@ library AaveV4DeployOrchestration { string[] memory hubLabels, string[] memory spokeLabels, bool setRoles - ) internal returns (OrchestrationReports.FullDeploymentReport memory) { - OrchestrationReports.FullDeploymentReport memory report; - + ) internal returns (OrchestrationReports.FullDeploymentReport memory report) { // Deploy Access Batch address accessManagerAdmin = setRoles ? deployer : admin; report.accessBatchReport = _deployAccessBatch(logger, deployer, accessManagerAdmin); @@ -89,7 +87,14 @@ library AaveV4DeployOrchestration { ); } - return report; + return + _generateFullReport( + report.accessBatchReport, + report.configuratorBatchReport, + report.hubBatchReports, + report.spokeInstanceBatchReports, + report.gatewaysBatchReport + ); } function _deployAccessBatch( @@ -299,4 +304,20 @@ library AaveV4DeployOrchestration { logger.log('SignatureGateway', report.signatureGatewayAddress); return report; } + + function _generateFullReport( + BatchReports.AccessBatchReport memory accessBatchReport, + BatchReports.ConfiguratorBatchReport memory configuratorBatchReport, + OrchestrationReports.HubDeploymentReport[] memory hubBatchReports, + OrchestrationReports.SpokeDeploymentReport[] memory spokeBatchReports, + BatchReports.GatewaysBatchReport memory gatewaysBatchReport + ) internal pure returns (OrchestrationReports.FullDeploymentReport memory report) { + report.accessBatchReport = accessBatchReport; + report.configuratorBatchReport = configuratorBatchReport; + report.hubBatchReports = hubBatchReports; + report.spokeInstanceBatchReports = spokeBatchReports; + report.gatewaysBatchReport = gatewaysBatchReport; + + return report; + } } diff --git a/src/deployments/utils/Logger.sol b/src/deployments/utils/Logger.sol index fd25b1909..ea5000e5d 100644 --- a/src/deployments/utils/Logger.sol +++ b/src/deployments/utils/Logger.sol @@ -7,8 +7,9 @@ import 'forge-std/Vm.sol'; import {console} from 'forge-std/console.sol'; import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; +import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; -contract Logger is IProgressLogger { +contract Logger is IProgressLogger, DeployUtils { using stdJson for string; struct AddressEntry { @@ -65,10 +66,11 @@ contract Logger is IProgressLogger { _writeGroup(groupLabel, entries); } - function save() public { + function save(string memory fileName, bool withTimestamp) public { console.log(); console.log('Saving log to %s', _outputPath); - vm.writeJson(_json, _outputPath); + string memory appendedMetadata = withTimestamp ? string.concat(getTimestamp(), '-') : ''; + vm.writeJson(_json, string.concat(_outputPath, appendedMetadata, fileName)); } function _log(string memory label, address value) internal pure { @@ -119,4 +121,16 @@ contract Logger is IProgressLogger { _json = vm.serializeString(_root, groupLabel, group); // console.log(); } + + function getTimestamp() public returns (string memory result) { + string[] memory command = new string[](3); + + command[0] = 'bash'; + command[1] = '-c'; + command[2] = 'response="$(date +%s)"; cast abi-encode "response(string)" $response;'; + bytes memory timestamp = vm.ffi(command); + (result) = abi.decode(timestamp, (string)); + + return result; + } } diff --git a/src/deployments/utils/MetadataLogger.sol b/src/deployments/utils/MetadataLogger.sol index 4315ea01a..19fbc0e82 100644 --- a/src/deployments/utils/MetadataLogger.sol +++ b/src/deployments/utils/MetadataLogger.sol @@ -2,16 +2,16 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {Logger} from 'src/deployments/utils/Logger.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; +import {Logger} from 'src/deployments/utils/Logger.sol'; contract MetadataLogger is Logger { constructor(string memory outputPath_) Logger(outputPath_) {} function writeJsonReportMarket(OrchestrationReports.FullDeploymentReport memory report) public { - write('AccessBatchReport', report.accessBatchReport.accessManagerAddress); - write('HubConfigurator', report.configuratorBatchReport.hubConfiguratorAddress); - write('SpokeConfigurator', report.configuratorBatchReport.spokeConfiguratorAddress); + _write('AccessBatchReport', report.accessBatchReport.accessManagerAddress); + _write('HubConfigurator', report.configuratorBatchReport.hubConfiguratorAddress); + _write('SpokeConfigurator', report.configuratorBatchReport.spokeConfiguratorAddress); for (uint256 i; i < report.hubBatchReports.length; i++) { Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](3); @@ -27,7 +27,7 @@ contract MetadataLogger is Logger { label: 'TreasurySpoke', value: report.hubBatchReports[i].report.treasurySpokeAddress }); - writeGroup(report.hubBatchReports[i].label, hubEntries); + _writeGroup(report.hubBatchReports[i].label, hubEntries); } for (uint256 i; i < report.spokeInstanceBatchReports.length; i++) { @@ -44,10 +44,10 @@ contract MetadataLogger is Logger { label: 'AaveOracle', value: report.spokeInstanceBatchReports[i].report.aaveOracleAddress }); - writeGroup(report.spokeInstanceBatchReports[i].label, spokeInstanceEntries); + _writeGroup(report.spokeInstanceBatchReports[i].label, spokeInstanceEntries); } - write('SignatureGateway', report.gatewaysBatchReport.signatureGatewayAddress); - write('NativeTokenGateway', report.gatewaysBatchReport.nativeGatewayAddress); + _write('SignatureGateway', report.gatewaysBatchReport.signatureGatewayAddress); + _write('NativeTokenGateway', report.gatewaysBatchReport.nativeGatewayAddress); } } From 63c93f92556617d2fde7cdbe9c42dc778869fb9f Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:43:30 -0600 Subject: [PATCH 25/62] fix: debug set roles --- scripts/deploy/AaveV4DeployBatch.s.sol | 26 ++++++------- scripts/deploy/inputs/AaveV4DeployInput.toml | 2 +- .../AaveV4DeployOrchestration.sol | 37 +++++++++++++++---- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index 16a942571..ee0e2d2cc 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -13,6 +13,8 @@ import { AaveV4DeployOrchestration } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; +import {console} from 'forge-std/console.sol'; + contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { string internal constant INPUT_PATH = 'scripts/deploy/inputs/AaveV4DeployInput.toml'; string internal constant OUTPUT_DIR = 'output/reports/deployments/'; @@ -21,8 +23,6 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { constructor() {} function run() external { - OrchestrationReports.FullDeploymentReport memory report; - vm.createDir(OUTPUT_DIR, true); MetadataLogger logger = new MetadataLogger(OUTPUT_DIR); FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); @@ -30,19 +30,17 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { address deployer = msg.sender; logger.log('...Starting Aave V4 Batch Deployment...'); - - report = AaveV4DeployOrchestration.deployAaveV4( - IProgressLogger(address(logger)), - deployer, - inputs.admin, - inputs.nativeWrapperAddress, - inputs.hubLabels, - inputs.spokeLabels, - inputs.setRoles - ); - + OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration + .deployAaveV4( + IProgressLogger(address(logger)), + deployer, + inputs.admin, + inputs.nativeWrapperAddress, + inputs.hubLabels, + inputs.spokeLabels, + inputs.setRoles + ); logger.writeJsonReportMarket(report); - logger.log('...Batch Deployment Completed...'); logger.log('...Saving Logs...'); logger.save({fileName: OUTPUT_FILE, withTimestamp: true}); diff --git a/scripts/deploy/inputs/AaveV4DeployInput.toml b/scripts/deploy/inputs/AaveV4DeployInput.toml index 88154bb9c..e40b8a949 100644 --- a/scripts/deploy/inputs/AaveV4DeployInput.toml +++ b/scripts/deploy/inputs/AaveV4DeployInput.toml @@ -1,5 +1,5 @@ admin = "0x0000000000000000000000000000000000000001" nativeWrapperAddress = "0x0000000000000000000000000000000000000002" -setRoles = false +setRoles = true hubLabels = ["Hub 1", "Hub 2", "Hub 3"] spokeLabels = ["Spoke 1", "Spoke 2", "Spoke 3"] \ No newline at end of file diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 7b7523448..6d4f62623 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -15,6 +15,8 @@ import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; import {AaveV4GatewayBatch} from 'src/deployments/batches/AaveV4GatewayBatch.sol'; +import {console} from 'forge-std/console.sol'; + import { AaveV4AdminRolesProcedure } from 'src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol'; @@ -73,18 +75,24 @@ library AaveV4DeployOrchestration { // Set Roles if needed if (setRoles) { logger.log('...Setting Configurator roles...'); + + vm.startBroadcast(deployer); AaveV4AdminRolesProcedure.setConfiguratorAdminRoles( report.accessBatchReport.accessManagerAddress, report.configuratorBatchReport.spokeConfiguratorAddress, report.configuratorBatchReport.hubConfiguratorAddress ); + vm.stopBroadcast(); logger.log('...Setting AccessManager Root Admin role...'); + + vm.startBroadcast(deployer); AaveV4AdminRolesProcedure.setAccessManagerRootAdminRole( report.accessBatchReport.accessManagerAddress, admin, deployer ); + vm.stopBroadcast(); } return @@ -104,8 +112,9 @@ library AaveV4DeployOrchestration { ) internal returns (BatchReports.AccessBatchReport memory report) { logger.log('...Deploying AccessBatch...'); - vm.broadcast(deployer); + vm.startBroadcast(deployer); report = AaveV4DeployCore.deployAccessBatch(admin); + vm.stopBroadcast(); logger.log('AccessManager', report.accessManagerAddress); logger.log(''); @@ -119,8 +128,9 @@ library AaveV4DeployOrchestration { ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { logger.log('...Deploying ConfiguratorBatch...'); - vm.broadcast(deployer); + vm.startBroadcast(deployer); report = AaveV4DeployCore.deployConfiguratorBatch(admin); + vm.stopBroadcast(); logger.log('HubConfigurator', report.hubConfiguratorAddress); logger.log('SpokeConfigurator', report.spokeConfiguratorAddress); @@ -184,7 +194,11 @@ library AaveV4DeployOrchestration { if (setRoles) { logger.log('...Setting Hub roles...'); + console.log('accessManagerAddress', accessManagerAddress); + + vm.startBroadcast(deployer); AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); + vm.stopBroadcast(); } return hubReport; @@ -246,10 +260,13 @@ library AaveV4DeployOrchestration { if (setRoles) { logger.log('...Setting Spoke roles...'); + + vm.startBroadcast(deployer); AaveV4SpokeRolesProcedure.setSpokeRoles( accessManagerAddress, spokeReport.report.spokeProxyAddress ); + vm.stopBroadcast(); } return spokeReport; @@ -260,12 +277,14 @@ library AaveV4DeployOrchestration { address deployer, address admin, address accessManagerAddress - ) internal returns (BatchReports.HubBatchReport memory) { + ) internal returns (BatchReports.HubBatchReport memory report) { logger.log('...Deploying HubBatch...'); - vm.broadcast(deployer); + vm.startBroadcast(deployer); + report = AaveV4DeployCore.deployHubBatch(admin, accessManagerAddress); + vm.stopBroadcast(); - return AaveV4DeployCore.deployHubBatch(admin, accessManagerAddress); + return report; } function _deploySpokeInstanceBatch( @@ -277,7 +296,7 @@ library AaveV4DeployOrchestration { ) internal returns (BatchReports.SpokeInstanceBatchReport memory report) { logger.log('...Deploying AaveV4SpokeInstanceBatch...'); - vm.broadcast(deployer); + vm.startBroadcast(deployer); report = AaveV4DeployCore.deploySpokeInstanceBatch( admin, accessManagerAddress, @@ -285,6 +304,7 @@ library AaveV4DeployOrchestration { ORACLE_SUFFIX, label ); + vm.stopBroadcast(); return report; } @@ -297,9 +317,10 @@ library AaveV4DeployOrchestration { ) internal returns (BatchReports.GatewaysBatchReport memory report) { logger.log('...Deploying GatewayBatch...'); - vm.broadcast(deployer); - + vm.startBroadcast(deployer); report = AaveV4DeployCore.deployGatewaysBatch(admin, nativeWrapper); + vm.stopBroadcast(); + logger.log('NativeTokenGateway', report.nativeGatewayAddress); logger.log('SignatureGateway', report.signatureGatewayAddress); return report; From e38a93cc84a5529e017212f6ec02abac2f5243af Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 16:18:32 -0600 Subject: [PATCH 26/62] fix: clean up comments --- scripts/deploy/AaveV4DeployBatch.s.sol | 5 +---- .../AaveV4DeployOrchestration.sol | 22 ------------------- src/deployments/utils/Logger.sol | 9 -------- .../utils/interfaces/IProgressLogger.sol | 1 + 4 files changed, 2 insertions(+), 35 deletions(-) diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index ee0e2d2cc..364a3af06 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -13,8 +13,6 @@ import { AaveV4DeployOrchestration } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; -import {console} from 'forge-std/console.sol'; - contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { string internal constant INPUT_PATH = 'scripts/deploy/inputs/AaveV4DeployInput.toml'; string internal constant OUTPUT_DIR = 'output/reports/deployments/'; @@ -27,9 +25,8 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { MetadataLogger logger = new MetadataLogger(OUTPUT_DIR); FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); - address deployer = msg.sender; - logger.log('...Starting Aave V4 Batch Deployment...'); + address deployer = msg.sender; OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration .deployAaveV4( IProgressLogger(address(logger)), diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 6d4f62623..55f771d8f 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -15,8 +15,6 @@ import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; import {AaveV4GatewayBatch} from 'src/deployments/batches/AaveV4GatewayBatch.sol'; -import {console} from 'forge-std/console.sol'; - import { AaveV4AdminRolesProcedure } from 'src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol'; @@ -179,22 +177,8 @@ library AaveV4DeployOrchestration { logger.log(' InterestRateStrategy', hubReport.report.irStrategyAddress); logger.log(' TreasurySpoke', hubReport.report.treasurySpokeAddress); - // Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](3); - // hubEntries[0] = Logger.AddressEntry({label: 'Hub', value: hubReport.report.hubAddress}); - // hubEntries[1] = Logger.AddressEntry({ - // label: 'InterestRateStrategy', - // value: hubReport.report.irStrategyAddress - // }); - // hubEntries[2] = Logger.AddressEntry({ - // label: 'TreasurySpoke', - // value: hubReport.report.treasurySpokeAddress - // }); - - // logger.writeGroup(label, hubEntries); - if (setRoles) { logger.log('...Setting Hub roles...'); - console.log('accessManagerAddress', accessManagerAddress); vm.startBroadcast(deployer); AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); @@ -214,7 +198,6 @@ library AaveV4DeployOrchestration { ) internal returns (OrchestrationReports.SpokeDeploymentReport[] memory spokeBatchReports) { uint256 spokeCount = spokeLabels.length; spokeBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); - // Logger.AddressEntry[] memory spokeEntries = new Logger.AddressEntry[](spokeCount); for (uint256 i; i < spokeCount; ++i) { spokeBatchReports[i] = _deploySpoke( logger, @@ -224,12 +207,7 @@ library AaveV4DeployOrchestration { spokeLabels[i], setRoles ); - // spokeEntries[i] = Logger.AddressEntry({ - // label: spokeLabels[i], - // value: spokeBatchReports[i].report.spokeProxyAddress - // }); } - // logger.writeGroup('SpokeInstances', spokeEntries); logger.log(''); return spokeBatchReports; } diff --git a/src/deployments/utils/Logger.sol b/src/deployments/utils/Logger.sol index ea5000e5d..078e3e327 100644 --- a/src/deployments/utils/Logger.sol +++ b/src/deployments/utils/Logger.sol @@ -86,40 +86,31 @@ contract Logger is IProgressLogger, DeployUtils { } function _write(string memory label, address value) internal { - // _log(label, value); _json = vm.serializeAddress(_root, label, value); } function _write(string memory label, uint256 value) internal { - // _log(label, value); _json = vm.serializeString(_root, label, vm.toString(value)); } function _write(string memory value) internal { - // _log(value); _json = vm.serializeString(_root, 'message', value); } function _writeGroup(string memory groupLabel, AddressEntry[] memory entries) internal { string memory group; - // _log(groupLabel); for (uint256 i = 0; i < entries.length; i++) { - // _log(entries[i].label, entries[i].value); group = vm.serializeAddress(groupLabel, entries[i].label, entries[i].value); } _json = vm.serializeString(_root, groupLabel, group); - // console.log(); } function _writeGroup(string memory groupLabel, ValueEntry[] memory entries) internal { string memory group; - // _log(groupLabel); for (uint256 i = 0; i < entries.length; i++) { - // _log(entries[i].label, entries[i].value); group = vm.serializeString(groupLabel, entries[i].label, vm.toString(entries[i].value)); } _json = vm.serializeString(_root, groupLabel, group); - // console.log(); } function getTimestamp() public returns (string memory result) { diff --git a/src/deployments/utils/interfaces/IProgressLogger.sol b/src/deployments/utils/interfaces/IProgressLogger.sol index 694c3da3e..d7d07cf07 100644 --- a/src/deployments/utils/interfaces/IProgressLogger.sol +++ b/src/deployments/utils/interfaces/IProgressLogger.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; + interface IProgressLogger { function log(string memory label, address value) external pure; From 563f04f18a4a9321f41a87b9dc25358ed8a426ea Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 18:03:59 -0600 Subject: [PATCH 27/62] feat: broadcast flag; BatchTestProcedures tests --- scripts/deploy/AaveV4DeployBatch.s.sol | 4 +- .../AaveV4DeployOrchestration.sol | 107 +++++--- .../roles/AaveV4AdminRolesProcedure.sol | 1 - .../roles/AaveV4HubRolesProcedure.sol | 3 +- tests/deployments/AaveV4BatchDeployment.t.sol | 55 ++++ tests/mocks/MockLogger.sol | 20 ++ tests/utils/BatchTestProcedures.sol | 238 ++++++++++++++++++ 7 files changed, 388 insertions(+), 40 deletions(-) create mode 100644 tests/deployments/AaveV4BatchDeployment.t.sol create mode 100644 tests/mocks/MockLogger.sol create mode 100644 tests/utils/BatchTestProcedures.sol diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index 364a3af06..e19425177 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -27,6 +27,7 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { logger.log('...Starting Aave V4 Batch Deployment...'); address deployer = msg.sender; + bool broadcast = true; OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration .deployAaveV4( IProgressLogger(address(logger)), @@ -35,7 +36,8 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { inputs.nativeWrapperAddress, inputs.hubLabels, inputs.spokeLabels, - inputs.setRoles + inputs.setRoles, + broadcast ); logger.writeJsonReportMarket(report); logger.log('...Batch Deployment Completed...'); diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 55f771d8f..4806d5697 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -38,14 +38,15 @@ library AaveV4DeployOrchestration { address nativeWrapper, string[] memory hubLabels, string[] memory spokeLabels, - bool setRoles + bool setRoles, + bool broadcast ) internal returns (OrchestrationReports.FullDeploymentReport memory report) { // Deploy Access Batch address accessManagerAdmin = setRoles ? deployer : admin; - report.accessBatchReport = _deployAccessBatch(logger, deployer, accessManagerAdmin); + report.accessBatchReport = _deployAccessBatch(logger, deployer, accessManagerAdmin, broadcast); // Deploy Configurator Batch - report.configuratorBatchReport = _deployConfiguratorBatch(logger, deployer, admin); + report.configuratorBatchReport = _deployConfiguratorBatch(logger, deployer, admin, broadcast); // Deploy Hub Batches report.hubBatchReports = _deployHubs( @@ -54,7 +55,8 @@ library AaveV4DeployOrchestration { admin, report.accessBatchReport.accessManagerAddress, hubLabels, - setRoles + setRoles, + broadcast ); // Deploy Spoke Instance Batches @@ -64,33 +66,40 @@ library AaveV4DeployOrchestration { admin, report.accessBatchReport.accessManagerAddress, spokeLabels, - setRoles + setRoles, + broadcast ); // Deploy Gateways Batch - report.gatewaysBatchReport = _deployGatewayBatch(logger, deployer, admin, nativeWrapper); + report.gatewaysBatchReport = _deployGatewayBatch( + logger, + deployer, + admin, + nativeWrapper, + broadcast + ); // Set Roles if needed if (setRoles) { logger.log('...Setting Configurator roles...'); - vm.startBroadcast(deployer); + _startBroadcastIf(broadcast, deployer); AaveV4AdminRolesProcedure.setConfiguratorAdminRoles( report.accessBatchReport.accessManagerAddress, report.configuratorBatchReport.spokeConfiguratorAddress, report.configuratorBatchReport.hubConfiguratorAddress ); - vm.stopBroadcast(); + _stopBroadcastIf(broadcast); logger.log('...Setting AccessManager Root Admin role...'); - vm.startBroadcast(deployer); + _startBroadcastIf(broadcast, deployer); AaveV4AdminRolesProcedure.setAccessManagerRootAdminRole( report.accessBatchReport.accessManagerAddress, admin, deployer ); - vm.stopBroadcast(); + _stopBroadcastIf(broadcast); } return @@ -106,13 +115,14 @@ library AaveV4DeployOrchestration { function _deployAccessBatch( IProgressLogger logger, address deployer, - address admin + address admin, + bool broadcast ) internal returns (BatchReports.AccessBatchReport memory report) { logger.log('...Deploying AccessBatch...'); - vm.startBroadcast(deployer); + _startBroadcastIf(broadcast, deployer); report = AaveV4DeployCore.deployAccessBatch(admin); - vm.stopBroadcast(); + _stopBroadcastIf(broadcast); logger.log('AccessManager', report.accessManagerAddress); logger.log(''); @@ -122,13 +132,14 @@ library AaveV4DeployOrchestration { function _deployConfiguratorBatch( IProgressLogger logger, address deployer, - address admin + address admin, + bool broadcast ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { logger.log('...Deploying ConfiguratorBatch...'); - vm.startBroadcast(deployer); + _startBroadcastIf(broadcast, deployer); report = AaveV4DeployCore.deployConfiguratorBatch(admin); - vm.stopBroadcast(); + _stopBroadcastIf(broadcast); logger.log('HubConfigurator', report.hubConfiguratorAddress); logger.log('SpokeConfigurator', report.spokeConfiguratorAddress); @@ -142,7 +153,8 @@ library AaveV4DeployOrchestration { address admin, address accessManagerAddress, string[] memory hubLabels, - bool setRoles + bool setRoles, + bool broadcast ) internal returns (OrchestrationReports.HubDeploymentReport[] memory hubBatchReports) { uint256 hubCount = hubLabels.length; hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); @@ -153,7 +165,8 @@ library AaveV4DeployOrchestration { admin, accessManagerAddress, hubLabels[i], - setRoles + setRoles, + broadcast ); } logger.log(''); @@ -166,11 +179,12 @@ library AaveV4DeployOrchestration { address admin, address accessManagerAddress, string memory label, - bool setRoles + bool setRoles, + bool broadcast ) internal returns (OrchestrationReports.HubDeploymentReport memory) { OrchestrationReports.HubDeploymentReport memory hubReport; hubReport.label = label; - hubReport.report = _deployHubBatch(logger, deployer, admin, accessManagerAddress); + hubReport.report = _deployHubBatch(logger, deployer, admin, accessManagerAddress, broadcast); logger.log(label); logger.log(' Hub', hubReport.report.hubAddress); @@ -180,9 +194,9 @@ library AaveV4DeployOrchestration { if (setRoles) { logger.log('...Setting Hub roles...'); - vm.startBroadcast(deployer); + _startBroadcastIf(broadcast, deployer); AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); - vm.stopBroadcast(); + _stopBroadcastIf(broadcast); } return hubReport; @@ -194,7 +208,8 @@ library AaveV4DeployOrchestration { address admin, address accessManagerAddress, string[] memory spokeLabels, - bool setRoles + bool setRoles, + bool broadcast ) internal returns (OrchestrationReports.SpokeDeploymentReport[] memory spokeBatchReports) { uint256 spokeCount = spokeLabels.length; spokeBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); @@ -205,7 +220,8 @@ library AaveV4DeployOrchestration { admin, accessManagerAddress, spokeLabels[i], - setRoles + setRoles, + broadcast ); } logger.log(''); @@ -218,7 +234,8 @@ library AaveV4DeployOrchestration { address admin, address accessManagerAddress, string memory label, - bool setRoles + bool setRoles, + bool broadcast ) internal returns (OrchestrationReports.SpokeDeploymentReport memory) { OrchestrationReports.SpokeDeploymentReport memory spokeReport; @@ -228,7 +245,8 @@ library AaveV4DeployOrchestration { deployer, admin, accessManagerAddress, - label + label, + broadcast ); logger.log(label); @@ -239,12 +257,16 @@ library AaveV4DeployOrchestration { if (setRoles) { logger.log('...Setting Spoke roles...'); - vm.startBroadcast(deployer); + _startBroadcastIf(broadcast, deployer); AaveV4SpokeRolesProcedure.setSpokeRoles( accessManagerAddress, spokeReport.report.spokeProxyAddress ); - vm.stopBroadcast(); + AaveV4SpokeRolesProcedure.setSpokeUserPositionAdapterRole( + accessManagerAddress, + spokeReport.report.spokeProxyAddress + ); + _stopBroadcastIf(broadcast); } return spokeReport; @@ -254,13 +276,14 @@ library AaveV4DeployOrchestration { IProgressLogger logger, address deployer, address admin, - address accessManagerAddress + address accessManagerAddress, + bool broadcast ) internal returns (BatchReports.HubBatchReport memory report) { logger.log('...Deploying HubBatch...'); - vm.startBroadcast(deployer); + _startBroadcastIf(broadcast, deployer); report = AaveV4DeployCore.deployHubBatch(admin, accessManagerAddress); - vm.stopBroadcast(); + _stopBroadcastIf(broadcast); return report; } @@ -270,11 +293,12 @@ library AaveV4DeployOrchestration { address deployer, address admin, address accessManagerAddress, - string memory label + string memory label, + bool broadcast ) internal returns (BatchReports.SpokeInstanceBatchReport memory report) { logger.log('...Deploying AaveV4SpokeInstanceBatch...'); - vm.startBroadcast(deployer); + _startBroadcastIf(broadcast, deployer); report = AaveV4DeployCore.deploySpokeInstanceBatch( admin, accessManagerAddress, @@ -282,7 +306,7 @@ library AaveV4DeployOrchestration { ORACLE_SUFFIX, label ); - vm.stopBroadcast(); + _stopBroadcastIf(broadcast); return report; } @@ -291,13 +315,14 @@ library AaveV4DeployOrchestration { IProgressLogger logger, address deployer, address admin, - address nativeWrapper + address nativeWrapper, + bool broadcast ) internal returns (BatchReports.GatewaysBatchReport memory report) { logger.log('...Deploying GatewayBatch...'); - vm.startBroadcast(deployer); + _startBroadcastIf(broadcast, deployer); report = AaveV4DeployCore.deployGatewaysBatch(admin, nativeWrapper); - vm.stopBroadcast(); + _stopBroadcastIf(broadcast); logger.log('NativeTokenGateway', report.nativeGatewayAddress); logger.log('SignatureGateway', report.signatureGatewayAddress); @@ -319,4 +344,12 @@ library AaveV4DeployOrchestration { return report; } + + function _startBroadcastIf(bool broadcast, address deployer) private { + if (broadcast) vm.startBroadcast(deployer); + } + + function _stopBroadcastIf(bool broadcast) private { + if (broadcast) vm.stopBroadcast(); + } } diff --git a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol index 1b6adeefe..f1c4baba0 100644 --- a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.0; import {Roles} from 'src/libraries/types/Roles.sol'; - import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; library AaveV4AdminRolesProcedure { diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol index a423a4004..42f477d8e 100644 --- a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -9,12 +9,13 @@ import {IHub} from 'src/hub/interfaces/IHub.sol'; library AaveV4HubRolesProcedure { function setHubRoles(address accessManagerAddress, address hubAddress) internal { - bytes4[] memory selectors = new bytes4[](5); + bytes4[] memory selectors = new bytes4[](6); selectors[0] = IHub.addAsset.selector; selectors[1] = IHub.updateAssetConfig.selector; selectors[2] = IHub.addSpoke.selector; selectors[3] = IHub.updateSpokeConfig.selector; selectors[4] = IHub.setInterestRateData.selector; + selectors[5] = IHub.mintFeeShares.selector; IAccessManager(accessManagerAddress).setTargetFunctionRole( hubAddress, selectors, diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol new file mode 100644 index 000000000..9cbb7ec35 --- /dev/null +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/utils/BatchTestProcedures.sol'; + +contract AaveV4BatchDeploymentTest is BatchTestProcedures { + address public deployer; + IProgressLogger public logger; + FullDeployInputs public inputs; + address public weth9; + + string[] public hubLabels; + string[] public spokeLabels; + + function setUp() public override { + super.setUp(); + + deployer = makeAddr('deployer'); + logger = new MockLogger(); + weth9 = _deployWETH(); + + hubLabels = ['hub1', 'hub2', 'hub3']; + spokeLabels = ['spoke1', 'spoke2', 'spoke3']; + + inputs = FullDeployInputs({ + admin: makeAddr('admin'), + nativeWrapperAddress: weth9, + setRoles: true, + hubLabels: hubLabels, + spokeLabels: spokeLabels + }); + } + + function testAaveV4BatchDeployment_withRoles() public { + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet( + deployer, + logger, + inputs + ); + _checkFullReport(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withoutRoles() public { + inputs.setRoles = false; + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet( + deployer, + logger, + inputs + ); + _checkFullReport(report, inputs); + } +} diff --git a/tests/mocks/MockLogger.sol b/tests/mocks/MockLogger.sol new file mode 100644 index 000000000..2f6574c09 --- /dev/null +++ b/tests/mocks/MockLogger.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; +import {console2 as console} from 'forge-std/console2.sol'; + +contract MockLogger is IProgressLogger { + function log(string memory label, address value) external pure { + // console.log(label, value); + } + + function log(string memory label, uint256 value) external pure { + // console.log(label, value); + } + + function log(string memory value) external pure { + // console.log(value); + } +} diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol new file mode 100644 index 000000000..a711c69ed --- /dev/null +++ b/tests/utils/BatchTestProcedures.sol @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Test} from 'forge-std/Test.sol'; +import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; +import { + AaveV4DeployOrchestration +} from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; +import {Roles} from 'src/libraries/types/Roles.sol'; +import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; +import {MockLogger} from 'tests/mocks/MockLogger.sol'; +import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; +import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; +import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; +import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; +import {IHub} from 'src/hub/interfaces/IHub.sol'; + +contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { + bytes4[] public spokeAdminRoleSelectors; + bytes4[] public hubAdminRoleSelectors; + bytes4[] public userPositionUpdaterRoleSelectors; + + function setUp() public virtual { + spokeAdminRoleSelectors = new bytes4[](7); + spokeAdminRoleSelectors[0] = ISpoke.updateLiquidationConfig.selector; + spokeAdminRoleSelectors[1] = ISpoke.addReserve.selector; + spokeAdminRoleSelectors[2] = ISpoke.updateReserveConfig.selector; + spokeAdminRoleSelectors[3] = ISpoke.updateDynamicReserveConfig.selector; + spokeAdminRoleSelectors[4] = ISpoke.addDynamicReserveConfig.selector; + spokeAdminRoleSelectors[5] = ISpoke.updatePositionManager.selector; + spokeAdminRoleSelectors[6] = ISpoke.updateReservePriceSource.selector; + + hubAdminRoleSelectors = new bytes4[](6); + hubAdminRoleSelectors[0] = IHub.addAsset.selector; + hubAdminRoleSelectors[1] = IHub.updateAssetConfig.selector; + hubAdminRoleSelectors[2] = IHub.addSpoke.selector; + hubAdminRoleSelectors[3] = IHub.updateSpokeConfig.selector; + hubAdminRoleSelectors[4] = IHub.setInterestRateData.selector; + hubAdminRoleSelectors[5] = IHub.mintFeeShares.selector; + + userPositionUpdaterRoleSelectors = new bytes4[](2); + userPositionUpdaterRoleSelectors[0] = ISpoke.updateUserDynamicConfig.selector; + userPositionUpdaterRoleSelectors[1] = ISpoke.updateUserRiskPremium.selector; + } + + function deployAaveV4Testnet( + address deployer, + IProgressLogger logger, + FullDeployInputs memory inputs + ) public returns (OrchestrationReports.FullDeploymentReport memory) { + vm.startPrank(deployer); + OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration + .deployAaveV4( + logger, + deployer, + inputs.admin, + inputs.nativeWrapperAddress, + inputs.hubLabels, + inputs.spokeLabels, + inputs.setRoles, + false + ); + vm.stopPrank(); + return report; + } + + function _checkFullReport( + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal pure { + assertNotEq(report.accessBatchReport.accessManagerAddress, address(0), 'AccessManagerAddress'); + assertNotEq( + report.configuratorBatchReport.spokeConfiguratorAddress, + address(0), + 'SpokeConfiguratorAddress' + ); + assertNotEq( + report.configuratorBatchReport.hubConfiguratorAddress, + address(0), + 'HubConfiguratorAddress' + ); + assertNotEq( + report.gatewaysBatchReport.nativeGatewayAddress, + address(0), + 'NativeGatewayAddress' + ); + assertNotEq( + report.gatewaysBatchReport.signatureGatewayAddress, + address(0), + 'SignatureGatewayAddress' + ); + for (uint256 i = 0; i < report.hubBatchReports.length; i++) { + assertNotEq(report.hubBatchReports[i].report.hubAddress, address(0), 'HubAddress'); + assertNotEq( + report.hubBatchReports[i].report.irStrategyAddress, + address(0), + 'IRStrategyAddress' + ); + assertNotEq( + report.hubBatchReports[i].report.treasurySpokeAddress, + address(0), + 'TreasurySpokeAddress' + ); + } + for (uint256 i = 0; i < report.spokeInstanceBatchReports.length; i++) { + assertNotEq( + report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + address(0), + 'SpokeProxyAddress' + ); + assertNotEq( + report.spokeInstanceBatchReports[i].report.aaveOracleAddress, + address(0), + 'AaveOracleAddress' + ); + } + assertEq(report.hubBatchReports.length, inputs.hubLabels.length, 'HubBatchReportsLength'); + assertEq( + report.spokeInstanceBatchReports.length, + inputs.spokeLabels.length, + 'SpokeInstanceBatchReportsLength' + ); + } + + function _checkRoles( + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + IAccessManagerEnumerable accessManager = IAccessManagerEnumerable( + report.accessBatchReport.accessManagerAddress + ); + _checkAccessManagerRoles(accessManager, report, inputs); + _checkSpokeAdminRoles(accessManager, report, inputs); + _checkHubAdminRoles(accessManager, report, inputs); + // _checkUserPositionUpdaterRoles(report, inputs); + } + + function _checkAccessManagerRoles( + IAccessManagerEnumerable accessManager, + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + assertEq( + accessManager.getRoleMemberCount(Roles.DEFAULT_ADMIN_ROLE), + 1, + 'DefaultAdminRoleCount' + ); + assertEq( + accessManager.getRoleMember(Roles.DEFAULT_ADMIN_ROLE, 0), + inputs.admin, + 'DefaultAdminRoleMember' + ); + assertEq(accessManager.getRoleMemberCount(Roles.HUB_ADMIN_ROLE), 1, 'HubAdminRoleCount'); + for (uint256 i = 0; i < inputs.hubLabels.length; i++) { + assertEq( + accessManager.getRoleMember(Roles.HUB_ADMIN_ROLE, 0), + report.configuratorBatchReport.hubConfiguratorAddress, + 'HubAdminRoleMember' + ); + } + assertEq(accessManager.getRoleMemberCount(Roles.SPOKE_ADMIN_ROLE), 1, 'SpokeAdminRoleCount'); + for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { + assertEq( + accessManager.getRoleMember(Roles.SPOKE_ADMIN_ROLE, 0), + report.configuratorBatchReport.spokeConfiguratorAddress, + 'SpokeAdminRoleMember' + ); + } + } + + function _checkSpokeAdminRoles( + IAccessManagerEnumerable accessManager, + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { + (bool allowed, uint32 delay) = accessManager.canCall( + report.configuratorBatchReport.spokeConfiguratorAddress, + report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + spokeAdminRoleSelectors[i] + ); + assertTrue(allowed, 'SpokeAdminRoleCanCall'); + assertEq(delay, 0, 'SpokeAdminRoleDelay'); + + // check target function roles on spoke admin role + for (uint256 j = 0; j < spokeAdminRoleSelectors.length; j++) { + assertEq( + accessManager.getTargetFunctionRole( + report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + spokeAdminRoleSelectors[j] + ), + Roles.SPOKE_ADMIN_ROLE, + 'SpokeAdminRoleTargetFunction' + ); + } + + // check target function roles on user position updater role + for (uint256 j = 0; j < userPositionUpdaterRoleSelectors.length; j++) { + assertEq( + accessManager.getTargetFunctionRole( + report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + userPositionUpdaterRoleSelectors[j] + ), + Roles.USER_POSITION_UPDATER_ROLE, + 'UserPositionUpdaterRoleTargetFunction' + ); + } + } + } + + function _checkHubAdminRoles( + IAccessManagerEnumerable accessManager, + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + for (uint256 i = 0; i < inputs.hubLabels.length; i++) { + (bool allowed, uint32 delay) = accessManager.canCall( + report.configuratorBatchReport.hubConfiguratorAddress, + report.hubBatchReports[i].report.hubAddress, + hubAdminRoleSelectors[i] + ); + assertTrue(allowed, 'HubAdminRoleCanCall'); + assertEq(delay, 0, 'HubAdminRoleDelay'); + + for (uint256 j = 0; j < hubAdminRoleSelectors.length; j++) { + assertEq( + accessManager.getTargetFunctionRole( + report.hubBatchReports[i].report.hubAddress, + hubAdminRoleSelectors[j] + ), + Roles.HUB_ADMIN_ROLE, + 'HubAdminRoleTargetFunction' + ); + } + } + } +} From a455a578e1fc6230ef683d49739325b042d885d4 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:05:49 -0600 Subject: [PATCH 28/62] test: batch deployment --- tests/deployments/AaveV4BatchDeployment.t.sol | 4 +- tests/utils/BatchTestProcedures.sol | 78 ++++++++++++++++++- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index 9cbb7ec35..e891f366a 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -38,7 +38,7 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { logger, inputs ); - _checkFullReport(report, inputs); + _checkDeployment(report, inputs); _checkRoles(report, inputs); } @@ -50,6 +50,6 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { logger, inputs ); - _checkFullReport(report, inputs); + _checkDeployment(report, inputs); } } diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index a711c69ed..241e3a775 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -2,21 +2,34 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import {console2 as console} from 'forge-std/console2.sol'; import {Test} from 'forge-std/Test.sol'; + +import {Ownable} from 'src/dependencies/openzeppelin/Ownable.sol'; + import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; import { AaveV4DeployOrchestration } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; + import {Roles} from 'src/libraries/types/Roles.sol'; import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {MockLogger} from 'tests/mocks/MockLogger.sol'; import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; + import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; +import {IAssetInterestRateStrategy} from 'src/hub/interfaces/IAssetInterestRateStrategy.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; import {IHub} from 'src/hub/interfaces/IHub.sol'; +import {ITreasurySpoke} from 'src/spoke/interfaces/ITreasurySpoke.sol'; contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { + bytes32 internal constant ERC1967_ADMIN_SLOT = + 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + bytes32 internal constant IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + bytes4[] public spokeAdminRoleSelectors; bytes4[] public hubAdminRoleSelectors; bytes4[] public userPositionUpdaterRoleSelectors; @@ -65,6 +78,15 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { return report; } + function _checkDeployment( + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + _checkFullReport(report, inputs); + _checkSpokeBatchDeployment(report, inputs); + _checkHubBatchDeployment(report, inputs); + } + function _checkFullReport( OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs @@ -133,7 +155,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { _checkAccessManagerRoles(accessManager, report, inputs); _checkSpokeAdminRoles(accessManager, report, inputs); _checkHubAdminRoles(accessManager, report, inputs); - // _checkUserPositionUpdaterRoles(report, inputs); } function _checkAccessManagerRoles( @@ -235,4 +256,59 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { } } } + + function _checkSpokeBatchDeployment( + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { + address proxyAdmin = _getProxyAdminAddress( + report.spokeInstanceBatchReports[i].report.spokeProxyAddress + ); + assertEq(Ownable(proxyAdmin).owner(), inputs.admin, 'SpokeDeploymentAdmin'); + assertEq( + _getImplementationAddress(report.spokeInstanceBatchReports[i].report.spokeProxyAddress), + report.spokeInstanceBatchReports[i].report.spokeImplementationAddress, + 'SpokeDeploymentImplementation' + ); + } + } + + function _checkHubBatchDeployment( + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + for (uint256 i = 0; i < inputs.hubLabels.length; i++) { + assertEq( + IHub(report.hubBatchReports[i].report.hubAddress).authority(), + report.accessBatchReport.accessManagerAddress, + 'Hub Authority' + ); + assertEq( + IAssetInterestRateStrategy(report.hubBatchReports[i].report.irStrategyAddress).HUB(), + report.hubBatchReports[i].report.hubAddress, + 'InterestRateStrategy Hub' + ); + assertEq( + Ownable(report.hubBatchReports[i].report.treasurySpokeAddress).owner(), + inputs.admin, + 'TreasurySpoke owner' + ); + assertEq( + address(ITreasurySpoke(report.hubBatchReports[i].report.treasurySpokeAddress).HUB()), + report.hubBatchReports[i].report.hubAddress, + 'TreasurySpoke Hub' + ); + } + } + + function _getProxyAdminAddress(address proxy) internal view returns (address) { + bytes32 slotData = vm.load(proxy, ERC1967_ADMIN_SLOT); + return address(uint160(uint256(slotData))); + } + + function _getImplementationAddress(address proxy) internal view returns (address) { + bytes32 slotData = vm.load(proxy, IMPLEMENTATION_SLOT); + return address(uint160(uint256(slotData))); + } } From e3642d36255696140b7d57c80d7cb2780361f4f4 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:16:46 -0600 Subject: [PATCH 29/62] fix: move test files --- tests/Base.t.sol | 13 ++++++++++--- .../deployments/batches/TestTokensBatch.sol | 0 .../orchestration/AaveV4TestOrchestration.sol | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) rename {src => tests}/deployments/batches/TestTokensBatch.sol (100%) rename {src => tests}/deployments/orchestration/AaveV4TestOrchestration.sol (98%) diff --git a/tests/Base.t.sol b/tests/Base.t.sol index 87c33aa57..c9699f3ff 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -11,7 +11,10 @@ import {console2 as console} from 'forge-std/console2.sol'; // dependencies import {AggregatorV3Interface} from 'src/dependencies/chainlink/AggregatorV3Interface.sol'; -import {TransparentUpgradeableProxy, ITransparentUpgradeableProxy} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; +import { + TransparentUpgradeableProxy, + ITransparentUpgradeableProxy +} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; import {IERC20Metadata} from 'src/dependencies/openzeppelin/IERC20Metadata.sol'; import {SafeCast} from 'src/dependencies/openzeppelin/SafeCast.sol'; import {IERC20Errors} from 'src/dependencies/openzeppelin/IERC20Errors.sol'; @@ -44,7 +47,11 @@ import {AccessManagerEnumerable} from 'src/access/AccessManagerEnumerable.sol'; import {HubConfigurator, IHubConfigurator} from 'src/hub/HubConfigurator.sol'; import {Hub, IHub, IHubBase} from 'src/hub/Hub.sol'; import {SharesMath} from 'src/hub/libraries/SharesMath.sol'; -import {AssetInterestRateStrategy, IAssetInterestRateStrategy, IBasicInterestRateStrategy} from 'src/hub/AssetInterestRateStrategy.sol'; +import { + AssetInterestRateStrategy, + IAssetInterestRateStrategy, + IBasicInterestRateStrategy +} from 'src/hub/AssetInterestRateStrategy.sol'; // spoke import {Spoke, ISpoke, ISpokeBase} from 'src/spoke/Spoke.sol'; @@ -71,7 +78,7 @@ import {Utils} from 'tests/Utils.sol'; // orchestration import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; -import {AaveV4TestOrchestration} from 'src/deployments/orchestration/AaveV4TestOrchestration.sol'; +import {AaveV4TestOrchestration} from 'tests/deployments/orchestration/AaveV4TestOrchestration.sol'; // mocks import {TestnetERC20} from 'tests/mocks/TestnetERC20.sol'; diff --git a/src/deployments/batches/TestTokensBatch.sol b/tests/deployments/batches/TestTokensBatch.sol similarity index 100% rename from src/deployments/batches/TestTokensBatch.sol rename to tests/deployments/batches/TestTokensBatch.sol diff --git a/src/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol similarity index 98% rename from src/deployments/orchestration/AaveV4TestOrchestration.sol rename to tests/deployments/orchestration/AaveV4TestOrchestration.sol index 9ae5eb01f..8c5e0564e 100644 --- a/src/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -12,7 +12,7 @@ import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; -import {TestTokensBatch} from 'src/deployments/batches/TestTokensBatch.sol'; +import {TestTokensBatch} from 'tests/deployments/batches/TestTokensBatch.sol'; import { AaveV4AdminRolesProcedure From b06da1a26b325d6c6a2be5e77dad419f5fc29d20 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:27:17 -0600 Subject: [PATCH 30/62] fix: CI --- tests/Base.t.sol | 4 +++- ...eV4TestOrchestration.sol => AaveV4TestOrchestration.t.sol} | 0 2 files changed, 3 insertions(+), 1 deletion(-) rename tests/deployments/orchestration/{AaveV4TestOrchestration.sol => AaveV4TestOrchestration.t.sol} (100%) diff --git a/tests/Base.t.sol b/tests/Base.t.sol index c9699f3ff..4fade7ed4 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -78,7 +78,9 @@ import {Utils} from 'tests/Utils.sol'; // orchestration import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; -import {AaveV4TestOrchestration} from 'tests/deployments/orchestration/AaveV4TestOrchestration.sol'; +import { + AaveV4TestOrchestration +} from 'tests/deployments/orchestration/AaveV4TestOrchestration.t.sol'; // mocks import {TestnetERC20} from 'tests/mocks/TestnetERC20.sol'; diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.t.sol similarity index 100% rename from tests/deployments/orchestration/AaveV4TestOrchestration.sol rename to tests/deployments/orchestration/AaveV4TestOrchestration.t.sol From 05c0dc0b19d7d7e2d278f366b95585ccd4eb0df5 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:28:56 -0600 Subject: [PATCH 31/62] fix: comments --- src/deployments/batches/AaveV4SpokeInstanceBatch.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index aa81e6c99..8b1933ac4 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -42,7 +42,7 @@ contract AaveV4SpokeInstanceBatch is abi.encodeWithSignature('initialize(address)', accessManagerAddress_) ); - require(spokeProxyAddress == predictedSpokeInstanceAddress, 'SpokeInstance address mismatch'); // uncomment when fixed + require(spokeProxyAddress == predictedSpokeInstanceAddress, 'SpokeInstance address mismatch'); _report = BatchReports.SpokeInstanceBatchReport({ aaveOracleAddress: aaveOracleAddress, From d5affff86e25cf99a6215c485bba70dce255558e Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:36:54 -0600 Subject: [PATCH 32/62] fix: CI --- .github/workflows/tests-pr.yml | 4 ++-- ...eV4TestOrchestration.t.sol => AaveV4TestOrchestration.sol} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/deployments/orchestration/{AaveV4TestOrchestration.t.sol => AaveV4TestOrchestration.sol} (100%) diff --git a/.github/workflows/tests-pr.yml b/.github/workflows/tests-pr.yml index cb1ff90f1..4c6b916b4 100644 --- a/.github/workflows/tests-pr.yml +++ b/.github/workflows/tests-pr.yml @@ -21,8 +21,8 @@ jobs: with: FOUNDRY_VERSION: stable - - name: Run Forge size - uses: bgd-labs/github-workflows/.github/actions/foundry-size@main + #- name: Run Forge size + # uses: bgd-labs/github-workflows/.github/actions/foundry-size@main - name: Run Gas report uses: bgd-labs/github-workflows/.github/actions/foundry-gas-report@main diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.t.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol similarity index 100% rename from tests/deployments/orchestration/AaveV4TestOrchestration.t.sol rename to tests/deployments/orchestration/AaveV4TestOrchestration.sol From 265a3a7d0d37bcdfff4f765395c259c86c43e144 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:37:42 -0600 Subject: [PATCH 33/62] fix: CI --- tests/Base.t.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/Base.t.sol b/tests/Base.t.sol index 4fade7ed4..c9699f3ff 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -78,9 +78,7 @@ import {Utils} from 'tests/Utils.sol'; // orchestration import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; -import { - AaveV4TestOrchestration -} from 'tests/deployments/orchestration/AaveV4TestOrchestration.t.sol'; +import {AaveV4TestOrchestration} from 'tests/deployments/orchestration/AaveV4TestOrchestration.sol'; // mocks import {TestnetERC20} from 'tests/mocks/TestnetERC20.sol'; From 8d4cef058a3adb23aee105e6037aaa94ec5c468b Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 23:14:46 -0600 Subject: [PATCH 34/62] fix: clean up; --- scripts/deploy/AaveV4DeployBatch.s.sol | 8 +- scripts/deploy/inputs/AaveV4DeployInput.json | 8 ++ scripts/deploy/inputs/AaveV4DeployInput.toml | 2 +- .../AaveV4DeployOrchestration.sol | 119 +++--------------- src/deployments/utils/InputUtils.sol | 18 +-- tests/utils/BatchTestProcedures.sol | 3 +- 6 files changed, 43 insertions(+), 115 deletions(-) create mode 100644 scripts/deploy/inputs/AaveV4DeployInput.json diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index e19425177..6089ecb84 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -14,7 +14,7 @@ import { } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { - string internal constant INPUT_PATH = 'scripts/deploy/inputs/AaveV4DeployInput.toml'; + string internal constant INPUT_PATH = 'scripts/deploy/inputs/AaveV4DeployInput.json'; string internal constant OUTPUT_DIR = 'output/reports/deployments/'; string internal constant OUTPUT_FILE = 'AaveV4DeployBatch.json'; @@ -27,7 +27,7 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { logger.log('...Starting Aave V4 Batch Deployment...'); address deployer = msg.sender; - bool broadcast = true; + vm.startBroadcast(deployer); OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration .deployAaveV4( IProgressLogger(address(logger)), @@ -36,9 +36,9 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { inputs.nativeWrapperAddress, inputs.hubLabels, inputs.spokeLabels, - inputs.setRoles, - broadcast + inputs.setRoles ); + vm.stopBroadcast(); logger.writeJsonReportMarket(report); logger.log('...Batch Deployment Completed...'); logger.log('...Saving Logs...'); diff --git a/scripts/deploy/inputs/AaveV4DeployInput.json b/scripts/deploy/inputs/AaveV4DeployInput.json new file mode 100644 index 000000000..7afe7a962 --- /dev/null +++ b/scripts/deploy/inputs/AaveV4DeployInput.json @@ -0,0 +1,8 @@ +{ + "admin": "0x0000000000000000000000000000000000000001", + "nativeWrapperAddress": "0x0000000000000000000000000000000000000002", + "setRoles": true, + "hubLabels": ["Hub 1", "Hub 2", "Hub 3"], + "spokeLabels": ["Spoke 1", "Spoke 2", "Spoke 3"] +} + diff --git a/scripts/deploy/inputs/AaveV4DeployInput.toml b/scripts/deploy/inputs/AaveV4DeployInput.toml index e40b8a949..150aab314 100644 --- a/scripts/deploy/inputs/AaveV4DeployInput.toml +++ b/scripts/deploy/inputs/AaveV4DeployInput.toml @@ -1,5 +1,5 @@ admin = "0x0000000000000000000000000000000000000001" +hubLabels = ["Hub 1", "Hub 2", "Hub 3"] nativeWrapperAddress = "0x0000000000000000000000000000000000000002" setRoles = true -hubLabels = ["Hub 1", "Hub 2", "Hub 3"] spokeLabels = ["Spoke 1", "Spoke 2", "Spoke 3"] \ No newline at end of file diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 4806d5697..c13cf1276 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -38,68 +38,51 @@ library AaveV4DeployOrchestration { address nativeWrapper, string[] memory hubLabels, string[] memory spokeLabels, - bool setRoles, - bool broadcast + bool setRoles ) internal returns (OrchestrationReports.FullDeploymentReport memory report) { // Deploy Access Batch address accessManagerAdmin = setRoles ? deployer : admin; - report.accessBatchReport = _deployAccessBatch(logger, deployer, accessManagerAdmin, broadcast); + report.accessBatchReport = _deployAccessBatch(logger, accessManagerAdmin); // Deploy Configurator Batch - report.configuratorBatchReport = _deployConfiguratorBatch(logger, deployer, admin, broadcast); + report.configuratorBatchReport = _deployConfiguratorBatch(logger, admin); // Deploy Hub Batches report.hubBatchReports = _deployHubs( logger, - deployer, admin, report.accessBatchReport.accessManagerAddress, hubLabels, - setRoles, - broadcast + setRoles ); // Deploy Spoke Instance Batches report.spokeInstanceBatchReports = _deploySpokes( logger, - deployer, admin, report.accessBatchReport.accessManagerAddress, spokeLabels, - setRoles, - broadcast + setRoles ); // Deploy Gateways Batch - report.gatewaysBatchReport = _deployGatewayBatch( - logger, - deployer, - admin, - nativeWrapper, - broadcast - ); + report.gatewaysBatchReport = _deployGatewayBatch(logger, admin, nativeWrapper); // Set Roles if needed if (setRoles) { logger.log('...Setting Configurator roles...'); - - _startBroadcastIf(broadcast, deployer); AaveV4AdminRolesProcedure.setConfiguratorAdminRoles( report.accessBatchReport.accessManagerAddress, report.configuratorBatchReport.spokeConfiguratorAddress, report.configuratorBatchReport.hubConfiguratorAddress ); - _stopBroadcastIf(broadcast); logger.log('...Setting AccessManager Root Admin role...'); - - _startBroadcastIf(broadcast, deployer); AaveV4AdminRolesProcedure.setAccessManagerRootAdminRole( report.accessBatchReport.accessManagerAddress, admin, deployer ); - _stopBroadcastIf(broadcast); } return @@ -114,15 +97,11 @@ library AaveV4DeployOrchestration { function _deployAccessBatch( IProgressLogger logger, - address deployer, - address admin, - bool broadcast + address admin ) internal returns (BatchReports.AccessBatchReport memory report) { logger.log('...Deploying AccessBatch...'); - _startBroadcastIf(broadcast, deployer); report = AaveV4DeployCore.deployAccessBatch(admin); - _stopBroadcastIf(broadcast); logger.log('AccessManager', report.accessManagerAddress); logger.log(''); @@ -131,15 +110,11 @@ library AaveV4DeployOrchestration { function _deployConfiguratorBatch( IProgressLogger logger, - address deployer, - address admin, - bool broadcast + address admin ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { logger.log('...Deploying ConfiguratorBatch...'); - _startBroadcastIf(broadcast, deployer); report = AaveV4DeployCore.deployConfiguratorBatch(admin); - _stopBroadcastIf(broadcast); logger.log('HubConfigurator', report.hubConfiguratorAddress); logger.log('SpokeConfigurator', report.spokeConfiguratorAddress); @@ -149,25 +124,15 @@ library AaveV4DeployOrchestration { function _deployHubs( IProgressLogger logger, - address deployer, address admin, address accessManagerAddress, string[] memory hubLabels, - bool setRoles, - bool broadcast + bool setRoles ) internal returns (OrchestrationReports.HubDeploymentReport[] memory hubBatchReports) { uint256 hubCount = hubLabels.length; hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); for (uint256 i; i < hubCount; ++i) { - hubBatchReports[i] = _deployHub( - logger, - deployer, - admin, - accessManagerAddress, - hubLabels[i], - setRoles, - broadcast - ); + hubBatchReports[i] = _deployHub(logger, admin, accessManagerAddress, hubLabels[i], setRoles); } logger.log(''); return hubBatchReports; @@ -175,16 +140,14 @@ library AaveV4DeployOrchestration { function _deployHub( IProgressLogger logger, - address deployer, address admin, address accessManagerAddress, string memory label, - bool setRoles, - bool broadcast + bool setRoles ) internal returns (OrchestrationReports.HubDeploymentReport memory) { OrchestrationReports.HubDeploymentReport memory hubReport; hubReport.label = label; - hubReport.report = _deployHubBatch(logger, deployer, admin, accessManagerAddress, broadcast); + hubReport.report = _deployHubBatch(logger, admin, accessManagerAddress); logger.log(label); logger.log(' Hub', hubReport.report.hubAddress); @@ -194,9 +157,7 @@ library AaveV4DeployOrchestration { if (setRoles) { logger.log('...Setting Hub roles...'); - _startBroadcastIf(broadcast, deployer); AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); - _stopBroadcastIf(broadcast); } return hubReport; @@ -204,24 +165,20 @@ library AaveV4DeployOrchestration { function _deploySpokes( IProgressLogger logger, - address deployer, address admin, address accessManagerAddress, string[] memory spokeLabels, - bool setRoles, - bool broadcast + bool setRoles ) internal returns (OrchestrationReports.SpokeDeploymentReport[] memory spokeBatchReports) { uint256 spokeCount = spokeLabels.length; spokeBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); for (uint256 i; i < spokeCount; ++i) { spokeBatchReports[i] = _deploySpoke( logger, - deployer, admin, accessManagerAddress, spokeLabels[i], - setRoles, - broadcast + setRoles ); } logger.log(''); @@ -230,24 +187,15 @@ library AaveV4DeployOrchestration { function _deploySpoke( IProgressLogger logger, - address deployer, address admin, address accessManagerAddress, string memory label, - bool setRoles, - bool broadcast + bool setRoles ) internal returns (OrchestrationReports.SpokeDeploymentReport memory) { OrchestrationReports.SpokeDeploymentReport memory spokeReport; spokeReport.label = label; - spokeReport.report = _deploySpokeInstanceBatch( - logger, - deployer, - admin, - accessManagerAddress, - label, - broadcast - ); + spokeReport.report = _deploySpokeInstanceBatch(logger, admin, accessManagerAddress, label); logger.log(label); logger.log(' SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); @@ -257,7 +205,6 @@ library AaveV4DeployOrchestration { if (setRoles) { logger.log('...Setting Spoke roles...'); - _startBroadcastIf(broadcast, deployer); AaveV4SpokeRolesProcedure.setSpokeRoles( accessManagerAddress, spokeReport.report.spokeProxyAddress @@ -266,7 +213,6 @@ library AaveV4DeployOrchestration { accessManagerAddress, spokeReport.report.spokeProxyAddress ); - _stopBroadcastIf(broadcast); } return spokeReport; @@ -274,31 +220,21 @@ library AaveV4DeployOrchestration { function _deployHubBatch( IProgressLogger logger, - address deployer, address admin, - address accessManagerAddress, - bool broadcast + address accessManagerAddress ) internal returns (BatchReports.HubBatchReport memory report) { logger.log('...Deploying HubBatch...'); - - _startBroadcastIf(broadcast, deployer); report = AaveV4DeployCore.deployHubBatch(admin, accessManagerAddress); - _stopBroadcastIf(broadcast); - return report; } function _deploySpokeInstanceBatch( IProgressLogger logger, - address deployer, address admin, address accessManagerAddress, - string memory label, - bool broadcast + string memory label ) internal returns (BatchReports.SpokeInstanceBatchReport memory report) { logger.log('...Deploying AaveV4SpokeInstanceBatch...'); - - _startBroadcastIf(broadcast, deployer); report = AaveV4DeployCore.deploySpokeInstanceBatch( admin, accessManagerAddress, @@ -306,24 +242,16 @@ library AaveV4DeployOrchestration { ORACLE_SUFFIX, label ); - _stopBroadcastIf(broadcast); - return report; } function _deployGatewayBatch( IProgressLogger logger, - address deployer, address admin, - address nativeWrapper, - bool broadcast + address nativeWrapper ) internal returns (BatchReports.GatewaysBatchReport memory report) { logger.log('...Deploying GatewayBatch...'); - - _startBroadcastIf(broadcast, deployer); report = AaveV4DeployCore.deployGatewaysBatch(admin, nativeWrapper); - _stopBroadcastIf(broadcast); - logger.log('NativeTokenGateway', report.nativeGatewayAddress); logger.log('SignatureGateway', report.signatureGatewayAddress); return report; @@ -341,15 +269,6 @@ library AaveV4DeployOrchestration { report.hubBatchReports = hubBatchReports; report.spokeInstanceBatchReports = spokeBatchReports; report.gatewaysBatchReport = gatewaysBatchReport; - return report; } - - function _startBroadcastIf(bool broadcast, address deployer) private { - if (broadcast) vm.startBroadcast(deployer); - } - - function _stopBroadcastIf(bool broadcast) private { - if (broadcast) vm.stopBroadcast(); - } } diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index cf81acfff..1409c46b8 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -2,11 +2,13 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import 'forge-std/StdToml.sol'; +// import 'forge-std/StdToml.sol'; +import 'forge-std/StdJson.sol'; import 'forge-std/Vm.sol'; contract InputUtils { - using stdToml for string; + // using stdToml for string; + using stdJson for string; struct FullDeployInputs { address admin; @@ -33,12 +35,12 @@ contract InputUtils { function loadFullDeployInputs( string memory inputPath ) public view returns (FullDeployInputs memory inputs) { - string memory toml = vm.readFile(inputPath); - inputs.admin = toml.readAddress('.admin'); - inputs.nativeWrapperAddress = toml.readAddress('.nativeWrapperAddress'); - inputs.setRoles = toml.readBool('.setRoles'); - inputs.hubLabels = toml.readStringArray('.hubLabels'); - inputs.spokeLabels = toml.readStringArray('.spokeLabels'); + string memory json = vm.readFile(inputPath); + inputs.admin = json.readAddress('.admin'); + inputs.nativeWrapperAddress = json.readAddress('.nativeWrapperAddress'); + inputs.setRoles = json.readBool('.setRoles'); + inputs.hubLabels = json.readStringArray('.hubLabels'); + inputs.spokeLabels = json.readStringArray('.spokeLabels'); return inputs; } diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 241e3a775..69351c14f 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -71,8 +71,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { inputs.nativeWrapperAddress, inputs.hubLabels, inputs.spokeLabels, - inputs.setRoles, - false + inputs.setRoles ); vm.stopPrank(); return report; From beea9236277a9f4c01210074f3d171c23224890a Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 23:17:16 -0600 Subject: [PATCH 35/62] fix: CI; move back to json --- .github/workflows/tests-pr.yml | 4 ++-- scripts/deploy/inputs/AaveV4DeployInput.toml | 5 ----- tests/deployments/orchestration/AaveV4TestOrchestration.sol | 1 + 3 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 scripts/deploy/inputs/AaveV4DeployInput.toml diff --git a/.github/workflows/tests-pr.yml b/.github/workflows/tests-pr.yml index 4c6b916b4..cb1ff90f1 100644 --- a/.github/workflows/tests-pr.yml +++ b/.github/workflows/tests-pr.yml @@ -21,8 +21,8 @@ jobs: with: FOUNDRY_VERSION: stable - #- name: Run Forge size - # uses: bgd-labs/github-workflows/.github/actions/foundry-size@main + - name: Run Forge size + uses: bgd-labs/github-workflows/.github/actions/foundry-size@main - name: Run Gas report uses: bgd-labs/github-workflows/.github/actions/foundry-gas-report@main diff --git a/scripts/deploy/inputs/AaveV4DeployInput.toml b/scripts/deploy/inputs/AaveV4DeployInput.toml deleted file mode 100644 index 150aab314..000000000 --- a/scripts/deploy/inputs/AaveV4DeployInput.toml +++ /dev/null @@ -1,5 +0,0 @@ -admin = "0x0000000000000000000000000000000000000001" -hubLabels = ["Hub 1", "Hub 2", "Hub 3"] -nativeWrapperAddress = "0x0000000000000000000000000000000000000002" -setRoles = true -spokeLabels = ["Spoke 1", "Spoke 2", "Spoke 3"] \ No newline at end of file diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol index 8c5e0564e..f8ed232e5 100644 --- a/tests/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -34,6 +34,7 @@ import { import {AaveV4DeployCore} from 'src/deployments/orchestration/AaveV4DeployCore.sol'; library AaveV4TestOrchestration { + bool public constant IS_TEST = true; Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); uint8 private constant ORACLE_DECIMALS = 8; From 31509cf8d2407a7d5a089a3d406e03e60f1e2608 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 23:24:44 -0600 Subject: [PATCH 36/62] fix: clean up logger --- scripts/deploy/AaveV4DeployBatch.s.sol | 3 +-- .../AaveV4DeployOrchestration.sol | 22 +++++++++---------- src/deployments/utils/InputUtils.sol | 2 -- src/deployments/utils/Logger.sol | 4 +--- .../utils/interfaces/IProgressLogger.sol | 11 ---------- tests/deployments/AaveV4BatchDeployment.t.sol | 4 ++-- tests/mocks/MockLogger.sol | 20 ----------------- tests/utils/BatchTestProcedures.sol | 5 ++--- 8 files changed, 17 insertions(+), 54 deletions(-) delete mode 100644 src/deployments/utils/interfaces/IProgressLogger.sol delete mode 100644 tests/mocks/MockLogger.sol diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index 6089ecb84..50ec4ab1c 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -5,7 +5,6 @@ pragma solidity ^0.8.0; import {Script} from 'forge-std/Script.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; -import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; import {MetadataLogger} from 'src/deployments/utils/MetadataLogger.sol'; @@ -30,7 +29,7 @@ contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { vm.startBroadcast(deployer); OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration .deployAaveV4( - IProgressLogger(address(logger)), + logger, deployer, inputs.admin, inputs.nativeWrapperAddress, diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index c13cf1276..436402cc5 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import 'forge-std/Vm.sol'; -import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; +import {Logger} from 'src/deployments/utils/Logger.sol'; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; import {AaveV4DeployCore} from 'src/deployments/orchestration/AaveV4DeployCore.sol'; @@ -32,7 +32,7 @@ library AaveV4DeployOrchestration { string private constant ORACLE_SUFFIX = ' (USD)'; function deployAaveV4( - IProgressLogger logger, + Logger logger, address deployer, address admin, address nativeWrapper, @@ -96,7 +96,7 @@ library AaveV4DeployOrchestration { } function _deployAccessBatch( - IProgressLogger logger, + Logger logger, address admin ) internal returns (BatchReports.AccessBatchReport memory report) { logger.log('...Deploying AccessBatch...'); @@ -109,7 +109,7 @@ library AaveV4DeployOrchestration { } function _deployConfiguratorBatch( - IProgressLogger logger, + Logger logger, address admin ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { logger.log('...Deploying ConfiguratorBatch...'); @@ -123,7 +123,7 @@ library AaveV4DeployOrchestration { } function _deployHubs( - IProgressLogger logger, + Logger logger, address admin, address accessManagerAddress, string[] memory hubLabels, @@ -139,7 +139,7 @@ library AaveV4DeployOrchestration { } function _deployHub( - IProgressLogger logger, + Logger logger, address admin, address accessManagerAddress, string memory label, @@ -164,7 +164,7 @@ library AaveV4DeployOrchestration { } function _deploySpokes( - IProgressLogger logger, + Logger logger, address admin, address accessManagerAddress, string[] memory spokeLabels, @@ -186,7 +186,7 @@ library AaveV4DeployOrchestration { } function _deploySpoke( - IProgressLogger logger, + Logger logger, address admin, address accessManagerAddress, string memory label, @@ -219,7 +219,7 @@ library AaveV4DeployOrchestration { } function _deployHubBatch( - IProgressLogger logger, + Logger logger, address admin, address accessManagerAddress ) internal returns (BatchReports.HubBatchReport memory report) { @@ -229,7 +229,7 @@ library AaveV4DeployOrchestration { } function _deploySpokeInstanceBatch( - IProgressLogger logger, + Logger logger, address admin, address accessManagerAddress, string memory label @@ -246,7 +246,7 @@ library AaveV4DeployOrchestration { } function _deployGatewayBatch( - IProgressLogger logger, + Logger logger, address admin, address nativeWrapper ) internal returns (BatchReports.GatewaysBatchReport memory report) { diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index 1409c46b8..472cbb93f 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -2,12 +2,10 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -// import 'forge-std/StdToml.sol'; import 'forge-std/StdJson.sol'; import 'forge-std/Vm.sol'; contract InputUtils { - // using stdToml for string; using stdJson for string; struct FullDeployInputs { diff --git a/src/deployments/utils/Logger.sol b/src/deployments/utils/Logger.sol index 078e3e327..3c0d3765c 100644 --- a/src/deployments/utils/Logger.sol +++ b/src/deployments/utils/Logger.sol @@ -5,11 +5,9 @@ pragma solidity ^0.8.0; import 'forge-std/StdJson.sol'; import 'forge-std/Vm.sol'; import {console} from 'forge-std/console.sol'; - -import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; -contract Logger is IProgressLogger, DeployUtils { +contract Logger is DeployUtils { using stdJson for string; struct AddressEntry { diff --git a/src/deployments/utils/interfaces/IProgressLogger.sol b/src/deployments/utils/interfaces/IProgressLogger.sol deleted file mode 100644 index d7d07cf07..000000000 --- a/src/deployments/utils/interfaces/IProgressLogger.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.0; - -interface IProgressLogger { - function log(string memory label, address value) external pure; - - function log(string memory label, uint256 value) external pure; - - function log(string memory value) external pure; -} diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index e891f366a..3a28caf02 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -6,7 +6,7 @@ import 'tests/utils/BatchTestProcedures.sol'; contract AaveV4BatchDeploymentTest is BatchTestProcedures { address public deployer; - IProgressLogger public logger; + Logger public logger; FullDeployInputs public inputs; address public weth9; @@ -17,7 +17,7 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { super.setUp(); deployer = makeAddr('deployer'); - logger = new MockLogger(); + logger = new Logger('dummy/path'); weth9 = _deployWETH(); hubLabels = ['hub1', 'hub2', 'hub3']; diff --git a/tests/mocks/MockLogger.sol b/tests/mocks/MockLogger.sol deleted file mode 100644 index 2f6574c09..000000000 --- a/tests/mocks/MockLogger.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.0; - -import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; -import {console2 as console} from 'forge-std/console2.sol'; - -contract MockLogger is IProgressLogger { - function log(string memory label, address value) external pure { - // console.log(label, value); - } - - function log(string memory label, uint256 value) external pure { - // console.log(label, value); - } - - function log(string memory value) external pure { - // console.log(value); - } -} diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 69351c14f..156c78784 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -7,14 +7,13 @@ import {Test} from 'forge-std/Test.sol'; import {Ownable} from 'src/dependencies/openzeppelin/Ownable.sol'; -import {IProgressLogger} from 'src/deployments/utils/interfaces/IProgressLogger.sol'; import { AaveV4DeployOrchestration } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; +import {Logger} from 'src/deployments/utils/Logger.sol'; import {Roles} from 'src/libraries/types/Roles.sol'; import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; -import {MockLogger} from 'tests/mocks/MockLogger.sol'; import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; @@ -59,7 +58,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function deployAaveV4Testnet( address deployer, - IProgressLogger logger, + Logger logger, FullDeployInputs memory inputs ) public returns (OrchestrationReports.FullDeploymentReport memory) { vm.startPrank(deployer); From ac59e59935feaab916ffb1686577a4da42e90fcf Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 5 Dec 2025 23:26:14 -0600 Subject: [PATCH 37/62] fix: lint --- scripts/deploy/inputs/AaveV4DeployInput.json | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/deploy/inputs/AaveV4DeployInput.json b/scripts/deploy/inputs/AaveV4DeployInput.json index 7afe7a962..3b13169f6 100644 --- a/scripts/deploy/inputs/AaveV4DeployInput.json +++ b/scripts/deploy/inputs/AaveV4DeployInput.json @@ -5,4 +5,3 @@ "hubLabels": ["Hub 1", "Hub 2", "Hub 3"], "spokeLabels": ["Spoke 1", "Spoke 2", "Spoke 3"] } - From a224fe868934c73ed929d4adba7d229320f08f20 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:13:27 -0600 Subject: [PATCH 38/62] rft: hub/spoke roles + tests --- .../AaveV4DeployOrchestration.sol | 61 ++- .../AaveV4AccessManagerRolesProcedure.sol | 24 ++ .../roles/AaveV4AdminRolesProcedure.sol | 51 --- .../roles/AaveV4HubRolesProcedure.sol | 48 ++- .../roles/AaveV4SpokeRolesProcedure.sol | 61 ++- src/libraries/types/Roles.sol | 5 +- tests/Base.t.sol | 21 +- tests/Constants.sol | 3 + .../orchestration/AaveV4TestOrchestration.sol | 29 +- tests/unit/SpokeConfigurator.t.sol | 10 +- tests/utils/BatchTestProcedures.sol | 404 +++++++++++++----- 11 files changed, 494 insertions(+), 223 deletions(-) create mode 100644 src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol delete mode 100644 src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 436402cc5..afecff95a 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -16,8 +16,8 @@ import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInsta import {AaveV4GatewayBatch} from 'src/deployments/batches/AaveV4GatewayBatch.sol'; import { - AaveV4AdminRolesProcedure -} from 'src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol'; + AaveV4AccessManagerRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol'; import { AaveV4HubRolesProcedure } from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; @@ -70,15 +70,30 @@ library AaveV4DeployOrchestration { // Set Roles if needed if (setRoles) { - logger.log('...Setting Configurator roles...'); - AaveV4AdminRolesProcedure.setConfiguratorAdminRoles( + logger.log('...Granting Hub Admin role...'); + AaveV4HubRolesProcedure.grantHubAdminRole( report.accessBatchReport.accessManagerAddress, - report.configuratorBatchReport.spokeConfiguratorAddress, - report.configuratorBatchReport.hubConfiguratorAddress + admin ); - logger.log('...Setting AccessManager Root Admin role...'); - AaveV4AdminRolesProcedure.setAccessManagerRootAdminRole( + logger.log('...Granting Spoke Admin role...'); + AaveV4SpokeRolesProcedure.grantSpokeAdminRole( + report.accessBatchReport.accessManagerAddress, + admin + ); + + logger.log('...Granting Configurator roles...'); + AaveV4HubRolesProcedure.grantHubConfiguratorRole({ + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + hubConfiguratorAddress: report.configuratorBatchReport.hubConfiguratorAddress + }); + AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole({ + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + spokeConfiguratorAddress: report.configuratorBatchReport.spokeConfiguratorAddress + }); + + logger.log('...Granting AccessManager Root Admin role...'); + AaveV4AccessManagerRolesProcedure.grantRootAdminRole( report.accessBatchReport.accessManagerAddress, admin, deployer @@ -157,7 +172,11 @@ library AaveV4DeployOrchestration { if (setRoles) { logger.log('...Setting Hub roles...'); - AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); + AaveV4HubRolesProcedure.setHubAdminRole(accessManagerAddress, hubReport.report.hubAddress); + AaveV4HubRolesProcedure.setHubConfiguratorRole( + accessManagerAddress, + hubReport.report.hubAddress + ); } return hubReport; @@ -205,11 +224,11 @@ library AaveV4DeployOrchestration { if (setRoles) { logger.log('...Setting Spoke roles...'); - AaveV4SpokeRolesProcedure.setSpokeRoles( + AaveV4SpokeRolesProcedure.setSpokeConfiguratorRole( accessManagerAddress, spokeReport.report.spokeProxyAddress ); - AaveV4SpokeRolesProcedure.setSpokeUserPositionAdapterRole( + AaveV4SpokeRolesProcedure.setSpokeAdminRole( accessManagerAddress, spokeReport.report.spokeProxyAddress ); @@ -218,16 +237,6 @@ library AaveV4DeployOrchestration { return spokeReport; } - function _deployHubBatch( - Logger logger, - address admin, - address accessManagerAddress - ) internal returns (BatchReports.HubBatchReport memory report) { - logger.log('...Deploying HubBatch...'); - report = AaveV4DeployCore.deployHubBatch(admin, accessManagerAddress); - return report; - } - function _deploySpokeInstanceBatch( Logger logger, address admin, @@ -245,6 +254,16 @@ library AaveV4DeployOrchestration { return report; } + function _deployHubBatch( + Logger logger, + address admin, + address accessManagerAddress + ) internal returns (BatchReports.HubBatchReport memory report) { + logger.log('...Deploying HubBatch...'); + report = AaveV4DeployCore.deployHubBatch(admin, accessManagerAddress); + return report; + } + function _deployGatewayBatch( Logger logger, address admin, diff --git a/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol new file mode 100644 index 000000000..600376144 --- /dev/null +++ b/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Roles} from 'src/libraries/types/Roles.sol'; +import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; + +library AaveV4AccessManagerRolesProcedure { + function grantRootAdminRole( + address accessManagerAddress, + address newAdminAddress, + address currentAdminAddress + ) internal { + IAccessManager(accessManagerAddress).grantRole({ + roleId: Roles.DEFAULT_ADMIN_ROLE, + account: newAdminAddress, + executionDelay: 0 + }); + IAccessManager(accessManagerAddress).renounceRole({ + roleId: Roles.DEFAULT_ADMIN_ROLE, + callerConfirmation: currentAdminAddress + }); + } +} diff --git a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol deleted file mode 100644 index f1c4baba0..000000000 --- a/src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.0; - -import {Roles} from 'src/libraries/types/Roles.sol'; -import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; - -library AaveV4AdminRolesProcedure { - function setConfiguratorAdminRoles( - address accessManagerAddress, - address spokeConfiguratorAddress, - address hubConfiguratorAddress - ) internal { - IAccessManager(accessManagerAddress).grantRole(Roles.HUB_ADMIN_ROLE, hubConfiguratorAddress, 0); - IAccessManager(accessManagerAddress).grantRole( - Roles.SPOKE_ADMIN_ROLE, - spokeConfiguratorAddress, - 0 - ); - } - - function setConfiguratorHubAdminRole( - address accessManagerAddress, - address hubConfiguratorAddress - ) internal { - IAccessManager(accessManagerAddress).grantRole(Roles.HUB_ADMIN_ROLE, hubConfiguratorAddress, 0); - } - - function setConfiguratorSpokeAdminRole( - address accessManagerAddress, - address spokeConfiguratorAddress - ) internal { - IAccessManager(accessManagerAddress).grantRole( - Roles.SPOKE_ADMIN_ROLE, - spokeConfiguratorAddress, - 0 - ); - } - - function setAccessManagerRootAdminRole( - address accessManagerAddress, - address newAdminAddress, - address currentAdminAddress - ) internal { - IAccessManager(accessManagerAddress).grantRole(Roles.DEFAULT_ADMIN_ROLE, newAdminAddress, 0); - IAccessManager(accessManagerAddress).renounceRole( - Roles.DEFAULT_ADMIN_ROLE, - currentAdminAddress - ); - } -} diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol index 42f477d8e..5b14eef36 100644 --- a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -8,18 +8,58 @@ import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; import {IHub} from 'src/hub/interfaces/IHub.sol'; library AaveV4HubRolesProcedure { - function setHubRoles(address accessManagerAddress, address hubAddress) internal { - bytes4[] memory selectors = new bytes4[](6); + function grantHubAdminRole(address accessManagerAddress, address hubAdminAddress) internal { + IAccessManager(accessManagerAddress).grantRole({ + roleId: Roles.HUB_ADMIN_ROLE, + account: hubAdminAddress, + executionDelay: 0 + }); + grantHubConfiguratorRole(accessManagerAddress, hubAdminAddress); + } + + function grantHubConfiguratorRole( + address accessManagerAddress, + address hubConfiguratorAddress + ) internal { + IAccessManager(accessManagerAddress).grantRole({ + roleId: Roles.HUB_CONFIGURATOR_ROLE, + account: hubConfiguratorAddress, + executionDelay: 0 + }); + } + + function setHubAdminRole(address accessManagerAddress, address hubAddress) internal { + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = IHub.mintFeeShares.selector; + IAccessManager(accessManagerAddress).setTargetFunctionRole( + hubAddress, + selectors, + Roles.HUB_ADMIN_ROLE + ); + } + + function setHubConfiguratorRole(address accessManagerAddress, address hubAddress) internal { + bytes4[] memory selectors = new bytes4[](5); selectors[0] = IHub.addAsset.selector; selectors[1] = IHub.updateAssetConfig.selector; selectors[2] = IHub.addSpoke.selector; selectors[3] = IHub.updateSpokeConfig.selector; selectors[4] = IHub.setInterestRateData.selector; - selectors[5] = IHub.mintFeeShares.selector; IAccessManager(accessManagerAddress).setTargetFunctionRole( hubAddress, selectors, - Roles.HUB_ADMIN_ROLE + Roles.HUB_CONFIGURATOR_ROLE ); } + + function getHubAdminRoleSelectors() internal pure returns (bytes4[] memory) { + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = IHub.mintFeeShares.selector; + return selectors; + } + + function getHubConfiguratorRoleSelectors() internal pure returns (bytes4[] memory) { + bytes4[] memory selectors = new bytes4[](5); + selectors[0] = IHub.addAsset.selector; + } } diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol index 8dc22afb2..b14fce94d 100644 --- a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -8,15 +8,28 @@ import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; library AaveV4SpokeRolesProcedure { - function setSpokeRoles(address accessManagerAddress, address spokeAddress) internal { - bytes4[] memory selectors = new bytes4[](7); - selectors[0] = ISpoke.updateLiquidationConfig.selector; - selectors[1] = ISpoke.addReserve.selector; - selectors[2] = ISpoke.updateReserveConfig.selector; - selectors[3] = ISpoke.updateReservePriceSource.selector; - selectors[4] = ISpoke.addDynamicReserveConfig.selector; - selectors[5] = ISpoke.updateDynamicReserveConfig.selector; - selectors[6] = ISpoke.updatePositionManager.selector; + function grantSpokeConfiguratorRole( + address accessManagerAddress, + address spokeConfiguratorAddress + ) internal { + IAccessManager(accessManagerAddress).grantRole({ + roleId: Roles.SPOKE_CONFIGURATOR_ROLE, + account: spokeConfiguratorAddress, + executionDelay: 0 + }); + } + + function grantSpokeAdminRole(address accessManagerAddress, address spokeAdminAddress) internal { + IAccessManager(accessManagerAddress).grantRole({ + roleId: Roles.SPOKE_ADMIN_ROLE, + account: spokeAdminAddress, + executionDelay: 0 + }); + grantSpokeConfiguratorRole(accessManagerAddress, spokeAdminAddress); + } + + function setSpokeAdminRole(address accessManagerAddress, address spokeAddress) internal { + bytes4[] memory selectors = getSpokeAdminRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( spokeAddress, selectors, @@ -24,17 +37,31 @@ library AaveV4SpokeRolesProcedure { ); } - function setSpokeUserPositionAdapterRole( - address accessManagerAddress, - address spokeAddress - ) internal { - bytes4[] memory selectors = new bytes4[](2); - selectors[0] = ISpoke.updateUserDynamicConfig.selector; - selectors[1] = ISpoke.updateUserRiskPremium.selector; + function setSpokeConfiguratorRole(address accessManagerAddress, address spokeAddress) internal { + bytes4[] memory selectors = getSpokeConfiguratorRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( spokeAddress, selectors, - Roles.USER_POSITION_UPDATER_ROLE + Roles.SPOKE_CONFIGURATOR_ROLE ); } + + function getSpokeAdminRoleSelectors() internal pure returns (bytes4[] memory) { + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = ISpoke.updateUserDynamicConfig.selector; + selectors[1] = ISpoke.updateUserRiskPremium.selector; + return selectors; + } + + function getSpokeConfiguratorRoleSelectors() internal pure returns (bytes4[] memory) { + bytes4[] memory selectors = new bytes4[](7); + selectors[0] = ISpoke.updateLiquidationConfig.selector; + selectors[1] = ISpoke.addReserve.selector; + selectors[2] = ISpoke.updateReserveConfig.selector; + selectors[3] = ISpoke.updateDynamicReserveConfig.selector; + selectors[4] = ISpoke.addDynamicReserveConfig.selector; + selectors[5] = ISpoke.updatePositionManager.selector; + selectors[6] = ISpoke.updateReservePriceSource.selector; + return selectors; + } } diff --git a/src/libraries/types/Roles.sol b/src/libraries/types/Roles.sol index ed3436165..8063d49a1 100644 --- a/src/libraries/types/Roles.sol +++ b/src/libraries/types/Roles.sol @@ -8,6 +8,7 @@ pragma solidity ^0.8.20; library Roles { uint64 public constant DEFAULT_ADMIN_ROLE = 0; uint64 public constant HUB_ADMIN_ROLE = 1; - uint64 public constant SPOKE_ADMIN_ROLE = 2; - uint64 public constant USER_POSITION_UPDATER_ROLE = 3; + uint64 public constant HUB_CONFIGURATOR_ROLE = 2; + uint64 public constant SPOKE_ADMIN_ROLE = 3; + uint64 public constant SPOKE_CONFIGURATOR_ROLE = 4; } diff --git a/tests/Base.t.sol b/tests/Base.t.sol index c9699f3ff..42e41d02d 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -309,11 +309,10 @@ abstract contract Base is Test { manager.grantRole(Roles.HUB_ADMIN_ROLE, ADMIN, 0); manager.grantRole(Roles.HUB_ADMIN_ROLE, HUB_ADMIN, 0); - manager.grantRole(Roles.SPOKE_ADMIN_ROLE, ADMIN, 0); + manager.grantRole(Roles.SPOKE_CONFIGURATOR_ROLE, ADMIN, 0); + manager.grantRole(Roles.SPOKE_CONFIGURATOR_ROLE, SPOKE_ADMIN, 0); manager.grantRole(Roles.SPOKE_ADMIN_ROLE, SPOKE_ADMIN, 0); - - manager.grantRole(Roles.USER_POSITION_UPDATER_ROLE, SPOKE_ADMIN, 0); - manager.grantRole(Roles.USER_POSITION_UPDATER_ROLE, USER_POSITION_UPDATER, 0); + manager.grantRole(Roles.SPOKE_ADMIN_ROLE, USER_POSITION_UPDATER, 0); // Grant responsibilities to roles { @@ -325,14 +324,14 @@ abstract contract Base is Test { selectors[4] = ISpoke.addDynamicReserveConfig.selector; selectors[5] = ISpoke.updatePositionManager.selector; selectors[6] = ISpoke.updateReservePriceSource.selector; - manager.setTargetFunctionRole(address(spoke), selectors, Roles.SPOKE_ADMIN_ROLE); + manager.setTargetFunctionRole(address(spoke), selectors, Roles.SPOKE_CONFIGURATOR_ROLE); } { bytes4[] memory selectors = new bytes4[](2); selectors[0] = ISpoke.updateUserDynamicConfig.selector; selectors[1] = ISpoke.updateUserRiskPremium.selector; - manager.setTargetFunctionRole(address(spoke), selectors, Roles.USER_POSITION_UPDATER_ROLE); + manager.setTargetFunctionRole(address(spoke), selectors, Roles.SPOKE_ADMIN_ROLE); } { @@ -348,6 +347,16 @@ abstract contract Base is Test { vm.stopPrank(); } + function _grantSpokeConfiguratorRole(ISpoke spoke, address spokeConfigurator) internal { + vm.startPrank(ADMIN); + IAccessManager(spoke.authority()).grantRole( + Roles.SPOKE_CONFIGURATOR_ROLE, + spokeConfigurator, + 0 + ); + vm.stopPrank(); + } + function initEnvironment() internal { deployMintAndApproveTokenList(); configureTokenList(); diff --git a/tests/Constants.sol b/tests/Constants.sol index b32ed1d4f..4352a81db 100644 --- a/tests/Constants.sol +++ b/tests/Constants.sol @@ -19,4 +19,7 @@ library Constants { // keccak256('SetUserPositionManager(address positionManager,address user,bool approve,uint256 nonce,uint256 deadline)') 0x758d23a3c07218b7ea0b4f7f63903c4e9d5cbde72d3bcfe3e9896639025a0214; uint256 public constant MAX_ALLOWED_ASSET_ID = type(uint16).max; + + /// @dev Deployments + string public constant ORACLE_SUFFIX = ' (USD)'; } diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol index f8ed232e5..69e641412 100644 --- a/tests/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -15,8 +15,8 @@ import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInsta import {TestTokensBatch} from 'tests/deployments/batches/TestTokensBatch.sol'; import { - AaveV4AdminRolesProcedure -} from 'src/deployments/procedures/roles/AaveV4AdminRolesProcedure.sol'; + AaveV4AccessManagerRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol'; import { AaveV4HubRolesProcedure } from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; @@ -103,17 +103,20 @@ library AaveV4TestOrchestration { address spokeAdmin, OrchestrationReports.TestEnvReport memory report ) external { - // Set Admin Roles - AaveV4AdminRolesProcedure.setConfiguratorAdminRoles(report.accessManagerAddress, admin, admin); - AaveV4AdminRolesProcedure.setConfiguratorHubAdminRole(report.accessManagerAddress, hubAdmin); - AaveV4AdminRolesProcedure.setConfiguratorSpokeAdminRole( - report.accessManagerAddress, - spokeAdmin - ); + // Set ConfiguratorAdmin Roles + // AaveV4AccessManagerRolesProcedure.grantRootAdminRole({ + // accessManagerAddress: report.accessManagerAddress, + // newAdminAddress: admin, + // currentAdminAddress: admin + // }); // Set Hub Roles for (uint256 i; i < report.hubReports.length; ++i) { - AaveV4HubRolesProcedure.setHubRoles( + AaveV4HubRolesProcedure.setHubAdminRole( + report.accessManagerAddress, + report.hubReports[i].hubAddress + ); + AaveV4HubRolesProcedure.setHubConfiguratorRole( report.accessManagerAddress, report.hubReports[i].hubAddress ); @@ -121,11 +124,11 @@ library AaveV4TestOrchestration { // Set Spoke Roles for (uint256 i; i < report.spokeReports.length; ++i) { - AaveV4SpokeRolesProcedure.setSpokeRoles( + AaveV4SpokeRolesProcedure.setSpokeAdminRole( report.accessManagerAddress, report.spokeReports[i].spokeAddress ); - AaveV4SpokeRolesProcedure.setSpokeUserPositionAdapterRole( + AaveV4SpokeRolesProcedure.setSpokeConfiguratorRole( report.accessManagerAddress, report.spokeReports[i].spokeAddress ); @@ -151,7 +154,7 @@ library AaveV4TestOrchestration { report.treasurySpokeAddress = hubReport.treasurySpokeAddress; // Set Hub Roles - AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, report.hubAddress); + AaveV4HubRolesProcedure.setHubAdminRole(accessManagerAddress, report.hubAddress); // Configure Hub Assets configureHubsAssets(paramsList); diff --git a/tests/unit/SpokeConfigurator.t.sol b/tests/unit/SpokeConfigurator.t.sol index 30e97f21a..5bd959a67 100644 --- a/tests/unit/SpokeConfigurator.t.sol +++ b/tests/unit/SpokeConfigurator.t.sol @@ -24,14 +24,8 @@ contract SpokeConfiguratorTest is SpokeBase { _reserveId = 0; invalidReserveId = spoke.getReserveCount(); - // Grant spokeConfigurator spoke admin role with 0 delay - vm.startPrank(ADMIN); - IAccessManager(spoke1.authority()).grantRole( - Roles.SPOKE_ADMIN_ROLE, - address(spokeConfigurator), - 0 - ); - vm.stopPrank(); + // Grant spokeConfigurator spoke admin role + _grantSpokeConfiguratorRole(spoke, address(spokeConfigurator)); } function test_updateReservePriceSource_revertsWith_OwnableUnauthorizedAccount() public { diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 156c78784..4d3356b60 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -4,24 +4,32 @@ pragma solidity ^0.8.0; import {console2 as console} from 'forge-std/console2.sol'; import {Test} from 'forge-std/Test.sol'; - import {Ownable} from 'src/dependencies/openzeppelin/Ownable.sol'; import { AaveV4DeployOrchestration } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; - +import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; +import { + AaveV4SpokeRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; +import { + AaveV4HubRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; import {Logger} from 'src/deployments/utils/Logger.sol'; -import {Roles} from 'src/libraries/types/Roles.sol'; import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; -import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; +import {Constants} from 'tests/Constants.sol'; + +import {Roles} from 'src/libraries/types/Roles.sol'; +import {IAccessManaged} from 'src/dependencies/openzeppelin/IAccessManaged.sol'; import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; import {IAssetInterestRateStrategy} from 'src/hub/interfaces/IAssetInterestRateStrategy.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; import {IHub} from 'src/hub/interfaces/IHub.sol'; import {ITreasurySpoke} from 'src/spoke/interfaces/ITreasurySpoke.sol'; +import {IAaveOracle} from 'src/spoke/interfaces/IAaveOracle.sol'; contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { bytes32 internal constant ERC1967_ADMIN_SLOT = @@ -30,30 +38,16 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; bytes4[] public spokeAdminRoleSelectors; + bytes4[] public spokeConfiguratorRoleSelectors; bytes4[] public hubAdminRoleSelectors; - bytes4[] public userPositionUpdaterRoleSelectors; + bytes4[] public hubConfiguratorRoleSelectors; function setUp() public virtual { - spokeAdminRoleSelectors = new bytes4[](7); - spokeAdminRoleSelectors[0] = ISpoke.updateLiquidationConfig.selector; - spokeAdminRoleSelectors[1] = ISpoke.addReserve.selector; - spokeAdminRoleSelectors[2] = ISpoke.updateReserveConfig.selector; - spokeAdminRoleSelectors[3] = ISpoke.updateDynamicReserveConfig.selector; - spokeAdminRoleSelectors[4] = ISpoke.addDynamicReserveConfig.selector; - spokeAdminRoleSelectors[5] = ISpoke.updatePositionManager.selector; - spokeAdminRoleSelectors[6] = ISpoke.updateReservePriceSource.selector; - - hubAdminRoleSelectors = new bytes4[](6); - hubAdminRoleSelectors[0] = IHub.addAsset.selector; - hubAdminRoleSelectors[1] = IHub.updateAssetConfig.selector; - hubAdminRoleSelectors[2] = IHub.addSpoke.selector; - hubAdminRoleSelectors[3] = IHub.updateSpokeConfig.selector; - hubAdminRoleSelectors[4] = IHub.setInterestRateData.selector; - hubAdminRoleSelectors[5] = IHub.mintFeeShares.selector; - - userPositionUpdaterRoleSelectors = new bytes4[](2); - userPositionUpdaterRoleSelectors[0] = ISpoke.updateUserDynamicConfig.selector; - userPositionUpdaterRoleSelectors[1] = ISpoke.updateUserRiskPremium.selector; + spokeAdminRoleSelectors = AaveV4SpokeRolesProcedure.getSpokeAdminRoleSelectors(); + spokeConfiguratorRoleSelectors = AaveV4SpokeRolesProcedure.getSpokeConfiguratorRoleSelectors(); + + hubAdminRoleSelectors = AaveV4HubRolesProcedure.getHubAdminRoleSelectors(); + hubConfiguratorRoleSelectors = AaveV4HubRolesProcedure.getHubConfiguratorRoleSelectors(); } function deployAaveV4Testnet( @@ -81,8 +75,8 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { FullDeployInputs memory inputs ) internal view { _checkFullReport(report, inputs); - _checkSpokeBatchDeployment(report, inputs); - _checkHubBatchDeployment(report, inputs); + _checkSpokeBatchDeployments(report, inputs); + _checkHubBatchDeployments(report, inputs); } function _checkFullReport( @@ -151,8 +145,8 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { report.accessBatchReport.accessManagerAddress ); _checkAccessManagerRoles(accessManager, report, inputs); - _checkSpokeAdminRoles(accessManager, report, inputs); - _checkHubAdminRoles(accessManager, report, inputs); + _checkSpokeRoles(accessManager, report, inputs); + _checkHubRoles(accessManager, report, inputs); } function _checkAccessManagerRoles( @@ -170,21 +164,66 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { inputs.admin, 'DefaultAdminRoleMember' ); - assertEq(accessManager.getRoleMemberCount(Roles.HUB_ADMIN_ROLE), 1, 'HubAdminRoleCount'); - for (uint256 i = 0; i < inputs.hubLabels.length; i++) { - assertEq( - accessManager.getRoleMember(Roles.HUB_ADMIN_ROLE, 0), - report.configuratorBatchReport.hubConfiguratorAddress, - 'HubAdminRoleMember' - ); - } - assertEq(accessManager.getRoleMemberCount(Roles.SPOKE_ADMIN_ROLE), 1, 'SpokeAdminRoleCount'); + } + + function _checkSpokeRoles( + IAccessManagerEnumerable accessManager, + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + _checkSpokeAdminRoles(accessManager, report, inputs); + _checkSpokeConfiguratorRoles(accessManager, report, inputs); + } + + function _checkSpokeConfiguratorRoles( + IAccessManagerEnumerable accessManager, + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + assertEq( + accessManager.getRoleMemberCount(Roles.SPOKE_CONFIGURATOR_ROLE), + 2, + 'SpokeConfiguratorRole member count' + ); + assertEq( + accessManager.getRoleMember(Roles.SPOKE_CONFIGURATOR_ROLE, 0), + inputs.admin, + 'SpokeConfiguratorRole member - spoke admin' + ); + assertEq( + accessManager.getRoleMember(Roles.SPOKE_CONFIGURATOR_ROLE, 1), + report.configuratorBatchReport.spokeConfiguratorAddress, + 'SpokeConfiguratorRole member - spoke configurator' + ); + for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { - assertEq( - accessManager.getRoleMember(Roles.SPOKE_ADMIN_ROLE, 0), - report.configuratorBatchReport.spokeConfiguratorAddress, - 'SpokeAdminRoleMember' - ); + for (uint256 j = 0; j < spokeConfiguratorRoleSelectors.length; j++) { + assertEq( + accessManager.getTargetFunctionRole( + report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + spokeConfiguratorRoleSelectors[j] + ), + Roles.SPOKE_CONFIGURATOR_ROLE, + 'SpokeConfiguratorRole target function' + ); + + (bool allowed, uint32 delay) = accessManager.canCall( + report.configuratorBatchReport.spokeConfiguratorAddress, + report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + spokeConfiguratorRoleSelectors[j] + ); + assertTrue(allowed, 'SpokeConfiguratorRole allowed - configurator'); + assertEq(delay, 0, 'SpokeConfiguratorRole delay - configurator'); + + // spoke admin role encompasses spoke configurator role + (allowed, delay) = accessManager.canCall( + inputs.admin, + report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + spokeConfiguratorRoleSelectors[j] + ); + assertTrue(allowed, 'SpokeConfiguratorRole allowed - admin'); + assertEq(delay, 0, 'SpokeConfiguratorRole delay - admin'); + } } } @@ -193,113 +232,276 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { - for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { - (bool allowed, uint32 delay) = accessManager.canCall( - report.configuratorBatchReport.spokeConfiguratorAddress, - report.spokeInstanceBatchReports[i].report.spokeProxyAddress, - spokeAdminRoleSelectors[i] - ); - assertTrue(allowed, 'SpokeAdminRoleCanCall'); - assertEq(delay, 0, 'SpokeAdminRoleDelay'); + assertEq( + accessManager.getRoleMemberCount(Roles.SPOKE_ADMIN_ROLE), + 1, + 'SpokeAdminRole member count' + ); + assertEq( + accessManager.getRoleMember(Roles.SPOKE_ADMIN_ROLE, 0), + inputs.admin, + 'SpokeAdminRole member - spoke admin' + ); - // check target function roles on spoke admin role + for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { for (uint256 j = 0; j < spokeAdminRoleSelectors.length; j++) { + (bool allowed, uint32 delay) = accessManager.canCall( + inputs.admin, + report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + spokeAdminRoleSelectors[j] + ); + assertTrue(allowed, 'SpokeAdminRole allowed'); + assertEq(delay, 0, 'SpokeAdminRole delay'); + assertEq( accessManager.getTargetFunctionRole( report.spokeInstanceBatchReports[i].report.spokeProxyAddress, spokeAdminRoleSelectors[j] ), Roles.SPOKE_ADMIN_ROLE, - 'SpokeAdminRoleTargetFunction' + 'SpokeAdminRole target function' ); } + } + } + + function _checkHubRoles( + IAccessManagerEnumerable accessManager, + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + _checkHubAdminRoles(accessManager, report, inputs); + _checkHubConfiguratorRoles(accessManager, report, inputs); + } - // check target function roles on user position updater role - for (uint256 j = 0; j < userPositionUpdaterRoleSelectors.length; j++) { + function _checkHubAdminRoles( + IAccessManagerEnumerable accessManager, + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + assertEq(accessManager.getRoleMemberCount(Roles.HUB_ADMIN_ROLE), 1, 'HubAdminRoleCount'); + assertEq( + accessManager.getRoleMember(Roles.HUB_ADMIN_ROLE, 0), + inputs.admin, + 'HubAdminRole member - hub admin' + ); + for (uint256 i = 0; i < inputs.hubLabels.length; i++) { + for (uint256 j = 0; j < hubAdminRoleSelectors.length; j++) { assertEq( accessManager.getTargetFunctionRole( - report.spokeInstanceBatchReports[i].report.spokeProxyAddress, - userPositionUpdaterRoleSelectors[j] + report.hubBatchReports[i].report.hubAddress, + hubAdminRoleSelectors[j] ), - Roles.USER_POSITION_UPDATER_ROLE, - 'UserPositionUpdaterRoleTargetFunction' + Roles.HUB_ADMIN_ROLE, + 'HubAdminRole target function' + ); + + (bool allowed, uint32 delay) = accessManager.canCall( + inputs.admin, + report.hubBatchReports[i].report.hubAddress, + hubAdminRoleSelectors[j] ); + assertTrue(allowed, 'HubAdminRole allowed'); + assertEq(delay, 0, 'HubAdminRole delay'); } } } - function _checkHubAdminRoles( + function _checkHubConfiguratorRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { + assertEq( + accessManager.getRoleMemberCount(Roles.HUB_CONFIGURATOR_ROLE), + 2, + 'HubConfiguratorRole member count' + ); + assertEq( + accessManager.getRoleMember(Roles.HUB_CONFIGURATOR_ROLE, 0), + inputs.admin, + 'HubConfiguratorRole member - hub admin' + ); + assertEq( + accessManager.getRoleMember(Roles.HUB_CONFIGURATOR_ROLE, 1), + report.configuratorBatchReport.hubConfiguratorAddress, + 'HubConfiguratorRole member - hub configurator' + ); for (uint256 i = 0; i < inputs.hubLabels.length; i++) { - (bool allowed, uint32 delay) = accessManager.canCall( - report.configuratorBatchReport.hubConfiguratorAddress, - report.hubBatchReports[i].report.hubAddress, - hubAdminRoleSelectors[i] - ); - assertTrue(allowed, 'HubAdminRoleCanCall'); - assertEq(delay, 0, 'HubAdminRoleDelay'); - - for (uint256 j = 0; j < hubAdminRoleSelectors.length; j++) { + for (uint256 j = 0; j < hubConfiguratorRoleSelectors.length; j++) { assertEq( accessManager.getTargetFunctionRole( report.hubBatchReports[i].report.hubAddress, - hubAdminRoleSelectors[j] + hubConfiguratorRoleSelectors[j] ), - Roles.HUB_ADMIN_ROLE, - 'HubAdminRoleTargetFunction' + Roles.HUB_CONFIGURATOR_ROLE, + 'HubConfiguratorRole target function' ); + bool allowed; + uint32 delay; + + (allowed, delay) = accessManager.canCall( + report.configuratorBatchReport.hubConfiguratorAddress, + report.hubBatchReports[i].report.hubAddress, + hubConfiguratorRoleSelectors[j] + ); + assertTrue(allowed, 'HubConfiguratorRole allowed - configurator'); + assertEq(delay, 0, 'HubConfiguratorRole delay - configurator'); + + (allowed, delay) = accessManager.canCall( + inputs.admin, + report.hubBatchReports[i].report.hubAddress, + hubConfiguratorRoleSelectors[j] + ); + assertTrue(allowed, 'HubConfiguratorRole allowed - admin'); + assertEq(delay, 0, 'HubConfiguratorRole delay - admin'); } } } - function _checkSpokeBatchDeployment( + function _checkSpokeBatchDeployments( OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { + string memory globalLabel = 'SpokeDeployment'; for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { - address proxyAdmin = _getProxyAdminAddress( - report.spokeInstanceBatchReports[i].report.spokeProxyAddress - ); - assertEq(Ownable(proxyAdmin).owner(), inputs.admin, 'SpokeDeploymentAdmin'); - assertEq( - _getImplementationAddress(report.spokeInstanceBatchReports[i].report.spokeProxyAddress), - report.spokeInstanceBatchReports[i].report.spokeImplementationAddress, - 'SpokeDeploymentImplementation' + _checkSpokeBatchDeployment( + report.spokeInstanceBatchReports[i], + inputs, + report.accessBatchReport.accessManagerAddress, + string.concat(globalLabel, ', ', inputs.spokeLabels[i]) ); } } - function _checkHubBatchDeployment( + function _checkSpokeBatchDeployment( + OrchestrationReports.SpokeDeploymentReport memory report, + FullDeployInputs memory inputs, + address accessManagerAddress, + string memory label + ) internal view { + _checkSpokeDeployment(report, inputs, accessManagerAddress, label); + _checkOracleDeployment(report, inputs, label); + } + + function _checkSpokeDeployment( + OrchestrationReports.SpokeDeploymentReport memory report, + FullDeployInputs memory inputs, + address accessManagerAddress, + string memory label + ) internal view { + assertEq( + Ownable(_getProxyAdminAddress(report.report.spokeProxyAddress)).owner(), + inputs.admin, + string.concat(label, ' proxy admin owner') + ); + assertEq( + _getImplementationAddress(report.report.spokeProxyAddress), + report.report.spokeImplementationAddress, + string.concat(label, ' implementation') + ); + assertEq( + ISpoke(report.report.spokeProxyAddress).ORACLE(), + report.report.aaveOracleAddress, + string.concat(label, ' oracle on spoke') + ); + assertEq( + IAccessManaged(report.report.spokeProxyAddress).authority(), + accessManagerAddress, + string.concat(label, ' spoke authority') + ); + } + + function _checkOracleDeployment( + OrchestrationReports.SpokeDeploymentReport memory report, + FullDeployInputs memory inputs, + string memory label + ) internal view { + assertEq( + IAaveOracle(report.report.aaveOracleAddress).SPOKE(), + report.report.spokeProxyAddress, + string.concat(label, ' spoke on oracle') + ); + assertEq( + IAaveOracle(report.report.aaveOracleAddress).DECIMALS(), + Constants.ORACLE_DECIMALS, + string.concat(label, ' oracle decimals') + ); + assertEq( + IAaveOracle(report.report.aaveOracleAddress).DESCRIPTION(), + string.concat(report.label, Constants.ORACLE_SUFFIX), + string.concat(label, ' oracle description') + ); + } + + function _checkHubBatchDeployments( OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { + string memory label = 'HubDeployment'; for (uint256 i = 0; i < inputs.hubLabels.length; i++) { - assertEq( - IHub(report.hubBatchReports[i].report.hubAddress).authority(), - report.accessBatchReport.accessManagerAddress, - 'Hub Authority' - ); - assertEq( - IAssetInterestRateStrategy(report.hubBatchReports[i].report.irStrategyAddress).HUB(), - report.hubBatchReports[i].report.hubAddress, - 'InterestRateStrategy Hub' - ); - assertEq( - Ownable(report.hubBatchReports[i].report.treasurySpokeAddress).owner(), - inputs.admin, - 'TreasurySpoke owner' - ); - assertEq( - address(ITreasurySpoke(report.hubBatchReports[i].report.treasurySpokeAddress).HUB()), - report.hubBatchReports[i].report.hubAddress, - 'TreasurySpoke Hub' + _checkHubBatchDeployment( + report, + report.hubBatchReports[i], + inputs, + string.concat(label, ', ', inputs.hubLabels[i]) ); } } + function _checkHubBatchDeployment( + OrchestrationReports.FullDeploymentReport memory fullReport, + OrchestrationReports.HubDeploymentReport memory report, + FullDeployInputs memory inputs, + string memory label + ) internal view { + _checkHubDeployment(report, inputs, fullReport.accessBatchReport.accessManagerAddress, label); + _checkInterestRateStrategyDeployment(report, inputs, label); + _checkTreasurySpokeDeployment(report, inputs, label); + } + + function _checkHubDeployment( + OrchestrationReports.HubDeploymentReport memory report, + FullDeployInputs memory inputs, + address accessManagerAddress, + string memory label + ) internal view { + assertEq( + IAccessManaged(report.report.hubAddress).authority(), + accessManagerAddress, + string.concat(label, ' hub authority') + ); + } + + function _checkInterestRateStrategyDeployment( + OrchestrationReports.HubDeploymentReport memory report, + FullDeployInputs memory inputs, + string memory label + ) internal view { + assertEq( + IAssetInterestRateStrategy(report.report.irStrategyAddress).HUB(), + report.report.hubAddress, + string.concat(label, ' hub on interest rate strategy') + ); + } + + function _checkTreasurySpokeDeployment( + OrchestrationReports.HubDeploymentReport memory report, + FullDeployInputs memory inputs, + string memory label + ) internal view { + assertEq( + address(ITreasurySpoke(report.report.treasurySpokeAddress).HUB()), + report.report.hubAddress, + string.concat(label, ' hub on treasury spoke') + ); + assertEq( + Ownable(report.report.treasurySpokeAddress).owner(), + inputs.admin, + string.concat(label, ' treasury spoke owner') + ); + } + function _getProxyAdminAddress(address proxy) internal view returns (address) { bytes32 slotData = vm.load(proxy, ERC1967_ADMIN_SLOT); return address(uint160(uint256(slotData))); From 17db1f2be0adfdb7016a054f94311591e458f620 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:44:31 -0600 Subject: [PATCH 39/62] feat: loadWarnings; abstract contract; zero addr native wrapper case --- scripts/deploy/AaveV4DeployBatch.s.sol | 43 +----------- scripts/deploy/AaveV4DeployBatchBase.s.sol | 65 +++++++++++++++++++ .../batches/AaveV4GatewayBatch.sol | 5 +- .../AaveV4DeployOrchestration.sol | 4 +- .../roles/AaveV4HubRolesProcedure.sol | 15 ++--- tests/deployments/AaveV4BatchDeployment.t.sol | 11 ++++ tests/utils/BatchTestProcedures.sol | 19 ++++-- 7 files changed, 106 insertions(+), 56 deletions(-) create mode 100644 scripts/deploy/AaveV4DeployBatchBase.s.sol diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index 50ec4ab1c..cf7ed14a8 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -2,45 +2,6 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {Script} from 'forge-std/Script.sol'; +import 'scripts/deploy/AaveV4DeployBatchBase.s.sol'; -import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; -import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; -import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; -import {MetadataLogger} from 'src/deployments/utils/MetadataLogger.sol'; -import { - AaveV4DeployOrchestration -} from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; - -contract AaveV4DeployBatchScript is Script, DeployUtils, InputUtils { - string internal constant INPUT_PATH = 'scripts/deploy/inputs/AaveV4DeployInput.json'; - string internal constant OUTPUT_DIR = 'output/reports/deployments/'; - string internal constant OUTPUT_FILE = 'AaveV4DeployBatch.json'; - - constructor() {} - - function run() external { - vm.createDir(OUTPUT_DIR, true); - MetadataLogger logger = new MetadataLogger(OUTPUT_DIR); - FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); - - logger.log('...Starting Aave V4 Batch Deployment...'); - address deployer = msg.sender; - vm.startBroadcast(deployer); - OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration - .deployAaveV4( - logger, - deployer, - inputs.admin, - inputs.nativeWrapperAddress, - inputs.hubLabels, - inputs.spokeLabels, - inputs.setRoles - ); - vm.stopBroadcast(); - logger.writeJsonReportMarket(report); - logger.log('...Batch Deployment Completed...'); - logger.log('...Saving Logs...'); - logger.save({fileName: OUTPUT_FILE, withTimestamp: true}); - } -} +contract AaveV4DeployBatchScript is AaveV4DeployBatchBaseScript {} diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol new file mode 100644 index 000000000..0f8802044 --- /dev/null +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Script} from 'forge-std/Script.sol'; + +import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; +import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; +import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; +import {MetadataLogger} from 'src/deployments/utils/MetadataLogger.sol'; +import { + AaveV4DeployOrchestration +} from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; + +abstract contract AaveV4DeployBatchBaseScript is Script, DeployUtils, InputUtils { + string internal constant INPUT_PATH = 'scripts/deploy/inputs/AaveV4DeployInput.json'; + string internal constant OUTPUT_DIR = 'output/reports/deployments/'; + string internal constant OUTPUT_FILE = 'AaveV4DeployBatch.json'; + + function run() external { + vm.createDir(OUTPUT_DIR, true); + MetadataLogger logger = new MetadataLogger(OUTPUT_DIR); + FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); + + _loadWarnings(logger, inputs); + + logger.log('...Starting Aave V4 Batch Deployment...'); + address deployer = msg.sender; + vm.startBroadcast(deployer); + OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration + .deployAaveV4({ + logger: logger, + deployer: deployer, + admin: inputs.admin, + nativeWrapper: inputs.nativeWrapperAddress, + hubLabels: inputs.hubLabels, + spokeLabels: inputs.spokeLabels, + setRoles: inputs.setRoles + }); + vm.stopBroadcast(); + logger.writeJsonReportMarket(report); + logger.log('...Batch Deployment Completed...'); + logger.log('...Saving Logs...'); + logger.save({fileName: OUTPUT_FILE, withTimestamp: true}); + } + + function _loadWarnings( + MetadataLogger logger, + FullDeployInputs memory inputs + ) internal pure virtual { + if (inputs.setRoles) { + logger.log('WARNING: Roles are being set'); + } + if (inputs.hubLabels.length == 0) { + logger.log('WARNING: Hub will not be deployed'); + } + if (inputs.spokeLabels.length == 0) { + logger.log('WARNING: Spoke will not be deployed'); + } + if (inputs.nativeWrapperAddress == address(0)) { + logger.log('WARNING: Native wrapper zero address; NativeTokenGateway will not be deployed'); + } + logger.log(''); + } +} diff --git a/src/deployments/batches/AaveV4GatewayBatch.sol b/src/deployments/batches/AaveV4GatewayBatch.sol index 5f3ae5fce..1683711f4 100644 --- a/src/deployments/batches/AaveV4GatewayBatch.sol +++ b/src/deployments/batches/AaveV4GatewayBatch.sol @@ -17,7 +17,10 @@ contract AaveV4GatewayBatch is BatchReports.GatewaysBatchReport internal _report; constructor(address admin_, address nativeWrapper_) { - address nativeGatewayAddress = _deployNativeTokenGateway(nativeWrapper_, admin_); + address nativeGatewayAddress; + if (nativeWrapper_ != address(0)) { + nativeGatewayAddress = _deployNativeTokenGateway(nativeWrapper_, admin_); + } address signatureGatewayAddress = _deploySignatureGateway(admin_); _report = BatchReports.GatewaysBatchReport({ diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index afecff95a..896ab4a44 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -82,11 +82,13 @@ library AaveV4DeployOrchestration { admin ); - logger.log('...Granting Configurator roles...'); + logger.log('...Granting Hub Configurator roles...'); AaveV4HubRolesProcedure.grantHubConfiguratorRole({ accessManagerAddress: report.accessBatchReport.accessManagerAddress, hubConfiguratorAddress: report.configuratorBatchReport.hubConfiguratorAddress }); + + logger.log('...Granting Spoke Configurator roles...'); AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole({ accessManagerAddress: report.accessBatchReport.accessManagerAddress, spokeConfiguratorAddress: report.configuratorBatchReport.spokeConfiguratorAddress diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol index 5b14eef36..b659e64f3 100644 --- a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -29,8 +29,7 @@ library AaveV4HubRolesProcedure { } function setHubAdminRole(address accessManagerAddress, address hubAddress) internal { - bytes4[] memory selectors = new bytes4[](1); - selectors[0] = IHub.mintFeeShares.selector; + bytes4[] memory selectors = getHubAdminRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( hubAddress, selectors, @@ -39,12 +38,7 @@ library AaveV4HubRolesProcedure { } function setHubConfiguratorRole(address accessManagerAddress, address hubAddress) internal { - bytes4[] memory selectors = new bytes4[](5); - selectors[0] = IHub.addAsset.selector; - selectors[1] = IHub.updateAssetConfig.selector; - selectors[2] = IHub.addSpoke.selector; - selectors[3] = IHub.updateSpokeConfig.selector; - selectors[4] = IHub.setInterestRateData.selector; + bytes4[] memory selectors = getHubConfiguratorRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( hubAddress, selectors, @@ -61,5 +55,10 @@ library AaveV4HubRolesProcedure { function getHubConfiguratorRoleSelectors() internal pure returns (bytes4[] memory) { bytes4[] memory selectors = new bytes4[](5); selectors[0] = IHub.addAsset.selector; + selectors[1] = IHub.updateAssetConfig.selector; + selectors[2] = IHub.addSpoke.selector; + selectors[3] = IHub.updateSpokeConfig.selector; + selectors[4] = IHub.setInterestRateData.selector; + return selectors; } } diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index 3a28caf02..c5d308d79 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -52,4 +52,15 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { ); _checkDeployment(report, inputs); } + + function testAaveV4BatchDeployment_withoutNativeGateway() public { + inputs.nativeWrapperAddress = address(0); + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet( + deployer, + logger, + inputs + ); + _checkDeployment(report, inputs); + } } diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 4d3356b60..a6d043c3b 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -83,6 +83,20 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal pure { + if (inputs.nativeWrapperAddress != address(0)) { + assertNotEq( + report.gatewaysBatchReport.nativeGatewayAddress, + address(0), + 'NativeGatewayAddress' + ); + } else { + assertEq( + report.gatewaysBatchReport.nativeGatewayAddress, + address(0), + 'Zero NativeGatewayAddress' + ); + } + assertNotEq(report.accessBatchReport.accessManagerAddress, address(0), 'AccessManagerAddress'); assertNotEq( report.configuratorBatchReport.spokeConfiguratorAddress, @@ -94,11 +108,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { address(0), 'HubConfiguratorAddress' ); - assertNotEq( - report.gatewaysBatchReport.nativeGatewayAddress, - address(0), - 'NativeGatewayAddress' - ); assertNotEq( report.gatewaysBatchReport.signatureGatewayAddress, address(0), From c49467f36fc50ef82d8c8897b0129bdd3f27d71f Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:55:34 -0600 Subject: [PATCH 40/62] fix: warnings --- .../orchestration/AaveV4TestOrchestration.sol | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol index 69e641412..d577505f7 100644 --- a/tests/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -99,16 +99,14 @@ library AaveV4TestOrchestration { function setRolesTestEnv( address admin, - address hubAdmin, - address spokeAdmin, OrchestrationReports.TestEnvReport memory report ) external { // Set ConfiguratorAdmin Roles - // AaveV4AccessManagerRolesProcedure.grantRootAdminRole({ - // accessManagerAddress: report.accessManagerAddress, - // newAdminAddress: admin, - // currentAdminAddress: admin - // }); + AaveV4AccessManagerRolesProcedure.grantRootAdminRole({ + accessManagerAddress: report.accessManagerAddress, + newAdminAddress: admin, + currentAdminAddress: admin + }); // Set Hub Roles for (uint256 i; i < report.hubReports.length; ++i) { From 65b44c9e3c86405e280f0e1e7bd4b20b6998e65c Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Mon, 8 Dec 2025 17:21:17 -0600 Subject: [PATCH 41/62] fix: consolidate setting roles --- .../AaveV4DeployOrchestration.sol | 12 ++----- .../roles/AaveV4HubRolesProcedure.sol | 5 +++ .../roles/AaveV4SpokeRolesProcedure.sol | 5 +++ .../orchestration/AaveV4TestOrchestration.sol | 12 ++----- tests/utils/BatchTestProcedures.sol | 34 ++++++++++++------- 5 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 896ab4a44..4fb576f89 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -174,11 +174,7 @@ library AaveV4DeployOrchestration { if (setRoles) { logger.log('...Setting Hub roles...'); - AaveV4HubRolesProcedure.setHubAdminRole(accessManagerAddress, hubReport.report.hubAddress); - AaveV4HubRolesProcedure.setHubConfiguratorRole( - accessManagerAddress, - hubReport.report.hubAddress - ); + AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); } return hubReport; @@ -226,11 +222,7 @@ library AaveV4DeployOrchestration { if (setRoles) { logger.log('...Setting Spoke roles...'); - AaveV4SpokeRolesProcedure.setSpokeConfiguratorRole( - accessManagerAddress, - spokeReport.report.spokeProxyAddress - ); - AaveV4SpokeRolesProcedure.setSpokeAdminRole( + AaveV4SpokeRolesProcedure.setSpokeRoles( accessManagerAddress, spokeReport.report.spokeProxyAddress ); diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol index b659e64f3..5559b6028 100644 --- a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -28,6 +28,11 @@ library AaveV4HubRolesProcedure { }); } + function setHubRoles(address accessManagerAddress, address hubAddress) internal { + setHubAdminRole(accessManagerAddress, hubAddress); + setHubConfiguratorRole(accessManagerAddress, hubAddress); + } + function setHubAdminRole(address accessManagerAddress, address hubAddress) internal { bytes4[] memory selectors = getHubAdminRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol index b14fce94d..a64f9d025 100644 --- a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -28,6 +28,11 @@ library AaveV4SpokeRolesProcedure { grantSpokeConfiguratorRole(accessManagerAddress, spokeAdminAddress); } + function setSpokeRoles(address accessManagerAddress, address spokeAddress) internal { + setSpokeAdminRole(accessManagerAddress, spokeAddress); + setSpokeConfiguratorRole(accessManagerAddress, spokeAddress); + } + function setSpokeAdminRole(address accessManagerAddress, address spokeAddress) internal { bytes4[] memory selectors = getSpokeAdminRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol index d577505f7..66e2d8955 100644 --- a/tests/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -110,11 +110,7 @@ library AaveV4TestOrchestration { // Set Hub Roles for (uint256 i; i < report.hubReports.length; ++i) { - AaveV4HubRolesProcedure.setHubAdminRole( - report.accessManagerAddress, - report.hubReports[i].hubAddress - ); - AaveV4HubRolesProcedure.setHubConfiguratorRole( + AaveV4HubRolesProcedure.setHubRoles( report.accessManagerAddress, report.hubReports[i].hubAddress ); @@ -122,11 +118,7 @@ library AaveV4TestOrchestration { // Set Spoke Roles for (uint256 i; i < report.spokeReports.length; ++i) { - AaveV4SpokeRolesProcedure.setSpokeAdminRole( - report.accessManagerAddress, - report.spokeReports[i].spokeAddress - ); - AaveV4SpokeRolesProcedure.setSpokeConfiguratorRole( + AaveV4SpokeRolesProcedure.setSpokeRoles( report.accessManagerAddress, report.spokeReports[i].spokeAddress ); diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index a6d043c3b..a2562c941 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -153,26 +153,37 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { IAccessManagerEnumerable accessManager = IAccessManagerEnumerable( report.accessBatchReport.accessManagerAddress ); - _checkAccessManagerRoles(accessManager, report, inputs); + _checkAccessManagerRoles(accessManager, inputs); _checkSpokeRoles(accessManager, report, inputs); _checkHubRoles(accessManager, report, inputs); } function _checkAccessManagerRoles( IAccessManagerEnumerable accessManager, - OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { - assertEq( - accessManager.getRoleMemberCount(Roles.DEFAULT_ADMIN_ROLE), - 1, - 'DefaultAdminRoleCount' - ); assertEq( accessManager.getRoleMember(Roles.DEFAULT_ADMIN_ROLE, 0), inputs.admin, 'DefaultAdminRoleMember' ); + assertEq( + accessManager.getRoleMemberCount(Roles.DEFAULT_ADMIN_ROLE), + 1, + 'DefaultAdminRoleCount' + ); + (bool hasRole, ) = accessManager.hasRole(Roles.DEFAULT_ADMIN_ROLE, inputs.admin); + if (inputs.setRoles) { + assertTrue(hasRole, 'admin has default admin role'); + } else { + assertFalse(hasRole, 'admin does not have default admin role'); + } + (hasRole, ) = accessManager.hasRole(Roles.DEFAULT_ADMIN_ROLE, msg.sender); + if (inputs.setRoles) { + assertFalse(hasRole, 'deployer does not have default admin role'); + } else { + assertTrue(hasRole, 'deployer has default admin role'); + } } function _checkSpokeRoles( @@ -390,7 +401,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { string memory label ) internal view { _checkSpokeDeployment(report, inputs, accessManagerAddress, label); - _checkOracleDeployment(report, inputs, label); + _checkOracleDeployment(report, label); } function _checkSpokeDeployment( @@ -423,7 +434,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function _checkOracleDeployment( OrchestrationReports.SpokeDeploymentReport memory report, - FullDeployInputs memory inputs, string memory label ) internal view { assertEq( @@ -464,14 +474,13 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { FullDeployInputs memory inputs, string memory label ) internal view { - _checkHubDeployment(report, inputs, fullReport.accessBatchReport.accessManagerAddress, label); - _checkInterestRateStrategyDeployment(report, inputs, label); + _checkHubDeployment(report, fullReport.accessBatchReport.accessManagerAddress, label); + _checkInterestRateStrategyDeployment(report, label); _checkTreasurySpokeDeployment(report, inputs, label); } function _checkHubDeployment( OrchestrationReports.HubDeploymentReport memory report, - FullDeployInputs memory inputs, address accessManagerAddress, string memory label ) internal view { @@ -484,7 +493,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function _checkInterestRateStrategyDeployment( OrchestrationReports.HubDeploymentReport memory report, - FullDeployInputs memory inputs, string memory label ) internal view { assertEq( From 25a3ae4a6ebe749f43bb0fc49939067b2f8501d6 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Mon, 8 Dec 2025 18:54:47 -0600 Subject: [PATCH 42/62] feat: grantRoles bool; conditional test logic --- scripts/deploy/AaveV4DeployBatchBase.s.sol | 7 +- scripts/deploy/inputs/AaveV4DeployInput.json | 2 +- .../AaveV4DeployOrchestration.sol | 149 +++++------ .../roles/AaveV4SpokeRolesProcedure.sol | 1 - src/deployments/utils/InputUtils.sol | 8 +- tests/deployments/AaveV4BatchDeployment.t.sol | 59 +++-- tests/utils/BatchTestProcedures.sol | 238 +++++++++++------- 7 files changed, 268 insertions(+), 196 deletions(-) diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index 0f8802044..d7edf5a96 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -35,7 +35,7 @@ abstract contract AaveV4DeployBatchBaseScript is Script, DeployUtils, InputUtils nativeWrapper: inputs.nativeWrapperAddress, hubLabels: inputs.hubLabels, spokeLabels: inputs.spokeLabels, - setRoles: inputs.setRoles + grantRoles: inputs.grantRoles }); vm.stopBroadcast(); logger.writeJsonReportMarket(report); @@ -48,8 +48,11 @@ abstract contract AaveV4DeployBatchBaseScript is Script, DeployUtils, InputUtils MetadataLogger logger, FullDeployInputs memory inputs ) internal pure virtual { - if (inputs.setRoles) { + if (inputs.grantRoles) { logger.log('WARNING: Roles are being set'); + if (inputs.admin == address(0)) { + logger.log('WARNING: Admin is zero address; Roles can not be set'); + } } if (inputs.hubLabels.length == 0) { logger.log('WARNING: Hub will not be deployed'); diff --git a/scripts/deploy/inputs/AaveV4DeployInput.json b/scripts/deploy/inputs/AaveV4DeployInput.json index 3b13169f6..e6fdb158f 100644 --- a/scripts/deploy/inputs/AaveV4DeployInput.json +++ b/scripts/deploy/inputs/AaveV4DeployInput.json @@ -1,7 +1,7 @@ { "admin": "0x0000000000000000000000000000000000000001", "nativeWrapperAddress": "0x0000000000000000000000000000000000000002", - "setRoles": true, + "grantRoles": true, "hubLabels": ["Hub 1", "Hub 2", "Hub 3"], "spokeLabels": ["Spoke 1", "Spoke 2", "Spoke 3"] } diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 4fb576f89..cd03f0f6c 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -2,13 +2,12 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import 'forge-std/Vm.sol'; +// import 'forge-std/Vm.sol'; import {Logger} from 'src/deployments/utils/Logger.sol'; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; import {AaveV4DeployCore} from 'src/deployments/orchestration/AaveV4DeployCore.sol'; - import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; import {AaveV4ConfiguratorBatch} from 'src/deployments/batches/AaveV4ConfiguratorBatch.sol'; import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; @@ -26,7 +25,7 @@ import { } from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; library AaveV4DeployOrchestration { - Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); + // Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); uint8 private constant ORACLE_DECIMALS = 8; string private constant ORACLE_SUFFIX = ' (USD)'; @@ -38,68 +37,55 @@ library AaveV4DeployOrchestration { address nativeWrapper, string[] memory hubLabels, string[] memory spokeLabels, - bool setRoles + bool grantRoles ) internal returns (OrchestrationReports.FullDeploymentReport memory report) { // Deploy Access Batch - address accessManagerAdmin = setRoles ? deployer : admin; + address accessManagerAdmin = deployer; report.accessBatchReport = _deployAccessBatch(logger, accessManagerAdmin); + // if admin is zero address, use deployer as contract admin + // spoke proxyAdmin owner; hubAdmin; spokeAdmin + address contractAdmin = admin != address(0) ? admin : deployer; + // Deploy Configurator Batch - report.configuratorBatchReport = _deployConfiguratorBatch(logger, admin); + report.configuratorBatchReport = _deployConfiguratorBatch(logger, contractAdmin); // Deploy Hub Batches report.hubBatchReports = _deployHubs( logger, - admin, + contractAdmin, report.accessBatchReport.accessManagerAddress, - hubLabels, - setRoles + hubLabels ); // Deploy Spoke Instance Batches report.spokeInstanceBatchReports = _deploySpokes( logger, - admin, + contractAdmin, report.accessBatchReport.accessManagerAddress, - spokeLabels, - setRoles + spokeLabels ); // Deploy Gateways Batch - report.gatewaysBatchReport = _deployGatewayBatch(logger, admin, nativeWrapper); + report.gatewaysBatchReport = _deployGatewayBatch(logger, contractAdmin, nativeWrapper); // Set Roles if needed - if (setRoles) { - logger.log('...Granting Hub Admin role...'); - AaveV4HubRolesProcedure.grantHubAdminRole( - report.accessBatchReport.accessManagerAddress, - admin - ); - - logger.log('...Granting Spoke Admin role...'); - AaveV4SpokeRolesProcedure.grantSpokeAdminRole( - report.accessBatchReport.accessManagerAddress, - admin - ); - - logger.log('...Granting Hub Configurator roles...'); - AaveV4HubRolesProcedure.grantHubConfiguratorRole({ - accessManagerAddress: report.accessBatchReport.accessManagerAddress, - hubConfiguratorAddress: report.configuratorBatchReport.hubConfiguratorAddress - }); - - logger.log('...Granting Spoke Configurator roles...'); - AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole({ - accessManagerAddress: report.accessBatchReport.accessManagerAddress, - spokeConfiguratorAddress: report.configuratorBatchReport.spokeConfiguratorAddress - }); - - logger.log('...Granting AccessManager Root Admin role...'); - AaveV4AccessManagerRolesProcedure.grantRootAdminRole( - report.accessBatchReport.accessManagerAddress, - admin, - deployer - ); + if (grantRoles) { + if (hubLabels.length > 0) { + _grantHubRoles(logger, report, contractAdmin); + } + if (spokeLabels.length > 0) { + _grantSpokeRoles(logger, report, contractAdmin); + } + + if (contractAdmin != deployer) { + logger.log('...Granting AccessManager Root Admin role...'); + AaveV4AccessManagerRolesProcedure.grantRootAdminRole( + report.accessBatchReport.accessManagerAddress, + contractAdmin, + deployer + ); + } } return @@ -112,6 +98,39 @@ library AaveV4DeployOrchestration { ); } + function _grantHubRoles( + Logger logger, + OrchestrationReports.FullDeploymentReport memory report, + address admin + ) internal { + logger.log('...Granting Hub Admin role...'); + AaveV4HubRolesProcedure.grantHubAdminRole(report.accessBatchReport.accessManagerAddress, admin); + + logger.log('...Granting Hub Configurator roles...'); + AaveV4HubRolesProcedure.grantHubConfiguratorRole({ + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + hubConfiguratorAddress: report.configuratorBatchReport.hubConfiguratorAddress + }); + } + + function _grantSpokeRoles( + Logger logger, + OrchestrationReports.FullDeploymentReport memory report, + address admin + ) internal { + logger.log('...Granting Spoke Admin role...'); + AaveV4SpokeRolesProcedure.grantSpokeAdminRole( + report.accessBatchReport.accessManagerAddress, + admin + ); + + logger.log('...Granting Spoke Configurator roles...'); + AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole({ + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + spokeConfiguratorAddress: report.configuratorBatchReport.spokeConfiguratorAddress + }); + } + function _deployAccessBatch( Logger logger, address admin @@ -143,13 +162,12 @@ library AaveV4DeployOrchestration { Logger logger, address admin, address accessManagerAddress, - string[] memory hubLabels, - bool setRoles + string[] memory hubLabels ) internal returns (OrchestrationReports.HubDeploymentReport[] memory hubBatchReports) { uint256 hubCount = hubLabels.length; hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); for (uint256 i; i < hubCount; ++i) { - hubBatchReports[i] = _deployHub(logger, admin, accessManagerAddress, hubLabels[i], setRoles); + hubBatchReports[i] = _deployHub(logger, admin, accessManagerAddress, hubLabels[i]); } logger.log(''); return hubBatchReports; @@ -159,8 +177,7 @@ library AaveV4DeployOrchestration { Logger logger, address admin, address accessManagerAddress, - string memory label, - bool setRoles + string memory label ) internal returns (OrchestrationReports.HubDeploymentReport memory) { OrchestrationReports.HubDeploymentReport memory hubReport; hubReport.label = label; @@ -171,11 +188,8 @@ library AaveV4DeployOrchestration { logger.log(' InterestRateStrategy', hubReport.report.irStrategyAddress); logger.log(' TreasurySpoke', hubReport.report.treasurySpokeAddress); - if (setRoles) { - logger.log('...Setting Hub roles...'); - - AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); - } + logger.log('...Setting Hub roles...'); + AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); return hubReport; } @@ -184,19 +198,12 @@ library AaveV4DeployOrchestration { Logger logger, address admin, address accessManagerAddress, - string[] memory spokeLabels, - bool setRoles + string[] memory spokeLabels ) internal returns (OrchestrationReports.SpokeDeploymentReport[] memory spokeBatchReports) { uint256 spokeCount = spokeLabels.length; spokeBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); for (uint256 i; i < spokeCount; ++i) { - spokeBatchReports[i] = _deploySpoke( - logger, - admin, - accessManagerAddress, - spokeLabels[i], - setRoles - ); + spokeBatchReports[i] = _deploySpoke(logger, admin, accessManagerAddress, spokeLabels[i]); } logger.log(''); return spokeBatchReports; @@ -206,8 +213,7 @@ library AaveV4DeployOrchestration { Logger logger, address admin, address accessManagerAddress, - string memory label, - bool setRoles + string memory label ) internal returns (OrchestrationReports.SpokeDeploymentReport memory) { OrchestrationReports.SpokeDeploymentReport memory spokeReport; @@ -219,14 +225,11 @@ library AaveV4DeployOrchestration { logger.log(' SpokeInstance Implementation', spokeReport.report.spokeImplementationAddress); logger.log(' AaveOracle', spokeReport.report.aaveOracleAddress); - if (setRoles) { - logger.log('...Setting Spoke roles...'); - - AaveV4SpokeRolesProcedure.setSpokeRoles( - accessManagerAddress, - spokeReport.report.spokeProxyAddress - ); - } + logger.log('...Setting Spoke roles...'); + AaveV4SpokeRolesProcedure.setSpokeRoles( + accessManagerAddress, + spokeReport.report.spokeProxyAddress + ); return spokeReport; } diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol index a64f9d025..95f978f69 100644 --- a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.0; import {Roles} from 'src/libraries/types/Roles.sol'; - import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index 472cbb93f..fda1700f6 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -11,20 +11,20 @@ contract InputUtils { struct FullDeployInputs { address admin; address nativeWrapperAddress; - bool setRoles; + bool grantRoles; string[] hubLabels; string[] spokeLabels; } struct SpokeDeployInputs { address admin; - bool setRoles; + bool grantRoles; string spokeLabel; } struct HubDeployInputs { address admin; - bool setRoles; + bool grantRoles; string hubLabel; } @@ -36,7 +36,7 @@ contract InputUtils { string memory json = vm.readFile(inputPath); inputs.admin = json.readAddress('.admin'); inputs.nativeWrapperAddress = json.readAddress('.nativeWrapperAddress'); - inputs.setRoles = json.readBool('.setRoles'); + inputs.grantRoles = json.readBool('.grantRoles'); inputs.hubLabels = json.readStringArray('.hubLabels'); inputs.spokeLabels = json.readStringArray('.spokeLabels'); return inputs; diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index c5d308d79..365a72c85 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -5,7 +5,6 @@ pragma solidity ^0.8.0; import 'tests/utils/BatchTestProcedures.sol'; contract AaveV4BatchDeploymentTest is BatchTestProcedures { - address public deployer; Logger public logger; FullDeployInputs public inputs; address public weth9; @@ -26,41 +25,63 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { inputs = FullDeployInputs({ admin: makeAddr('admin'), nativeWrapperAddress: weth9, - setRoles: true, + grantRoles: true, hubLabels: hubLabels, spokeLabels: spokeLabels }); } - function testAaveV4BatchDeployment_withRoles() public { - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet( - deployer, - logger, - inputs - ); + function testAaveV4BatchDeployment() public { + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); _checkDeployment(report, inputs); _checkRoles(report, inputs); } function testAaveV4BatchDeployment_withoutRoles() public { - inputs.setRoles = false; + inputs.grantRoles = false; - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet( - deployer, - logger, - inputs - ); + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); _checkDeployment(report, inputs); } function testAaveV4BatchDeployment_withoutNativeGateway() public { inputs.nativeWrapperAddress = address(0); - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet( - deployer, - logger, - inputs - ); + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withoutHubs() public { + inputs.hubLabels = new string[](0); + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withoutSpokes() public { + inputs.spokeLabels = new string[](0); + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withZeroAdminAddress() public { + inputs.admin = address(0); + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withZeroAdminAddress_withoutRoles() public { + inputs.admin = address(0); + inputs.grantRoles = false; + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); } } diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index a2562c941..1631ffd9c 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -2,10 +2,14 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {console2 as console} from 'forge-std/console2.sol'; import {Test} from 'forge-std/Test.sol'; +import {console2 as console} from 'forge-std/console2.sol'; + +// dependencies import {Ownable} from 'src/dependencies/openzeppelin/Ownable.sol'; +import {IAccessManaged} from 'src/dependencies/openzeppelin/IAccessManaged.sol'; +// orchestration import { AaveV4DeployOrchestration } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; @@ -22,8 +26,6 @@ import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationRepor import {Constants} from 'tests/Constants.sol'; import {Roles} from 'src/libraries/types/Roles.sol'; - -import {IAccessManaged} from 'src/dependencies/openzeppelin/IAccessManaged.sol'; import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; import {IAssetInterestRateStrategy} from 'src/hub/interfaces/IAssetInterestRateStrategy.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; @@ -41,6 +43,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { bytes4[] public spokeConfiguratorRoleSelectors; bytes4[] public hubAdminRoleSelectors; bytes4[] public hubConfiguratorRoleSelectors; + address public deployer; function setUp() public virtual { spokeAdminRoleSelectors = AaveV4SpokeRolesProcedure.getSpokeAdminRoleSelectors(); @@ -51,7 +54,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { } function deployAaveV4Testnet( - address deployer, Logger logger, FullDeployInputs memory inputs ) public returns (OrchestrationReports.FullDeploymentReport memory) { @@ -64,7 +66,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { inputs.nativeWrapperAddress, inputs.hubLabels, inputs.spokeLabels, - inputs.setRoles + inputs.grantRoles ); vm.stopPrank(); return report; @@ -150,21 +152,24 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { + address contractAdmin = inputs.admin != address(0) ? inputs.admin : deployer; + IAccessManagerEnumerable accessManager = IAccessManagerEnumerable( report.accessBatchReport.accessManagerAddress ); - _checkAccessManagerRoles(accessManager, inputs); - _checkSpokeRoles(accessManager, report, inputs); - _checkHubRoles(accessManager, report, inputs); + _checkAccessManagerRoles(accessManager, inputs, contractAdmin); + _checkSpokeRoles(accessManager, report, inputs, contractAdmin); + _checkHubRoles(accessManager, report, inputs, contractAdmin); } function _checkAccessManagerRoles( IAccessManagerEnumerable accessManager, - FullDeployInputs memory inputs + FullDeployInputs memory inputs, + address contractAdmin ) internal view { assertEq( accessManager.getRoleMember(Roles.DEFAULT_ADMIN_ROLE, 0), - inputs.admin, + contractAdmin, 'DefaultAdminRoleMember' ); assertEq( @@ -172,49 +177,55 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { 1, 'DefaultAdminRoleCount' ); - (bool hasRole, ) = accessManager.hasRole(Roles.DEFAULT_ADMIN_ROLE, inputs.admin); - if (inputs.setRoles) { - assertTrue(hasRole, 'admin has default admin role'); - } else { - assertFalse(hasRole, 'admin does not have default admin role'); - } - (hasRole, ) = accessManager.hasRole(Roles.DEFAULT_ADMIN_ROLE, msg.sender); - if (inputs.setRoles) { - assertFalse(hasRole, 'deployer does not have default admin role'); + + (bool adminHasRole, ) = accessManager.hasRole(Roles.DEFAULT_ADMIN_ROLE, contractAdmin); + bool expectAdminHasRole = inputs.grantRoles || inputs.admin == address(0); + if (expectAdminHasRole) { + assertTrue(adminHasRole, 'contract admin has default admin role'); } else { - assertTrue(hasRole, 'deployer has default admin role'); + assertFalse(adminHasRole, 'contract admin does not have default admin role'); } } function _checkSpokeRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs + FullDeployInputs memory inputs, + address contractAdmin ) internal view { - _checkSpokeAdminRoles(accessManager, report, inputs); - _checkSpokeConfiguratorRoles(accessManager, report, inputs); + _checkSpokeAdminRoles(accessManager, report, inputs, contractAdmin); + _checkSpokeConfiguratorRoles(accessManager, report, inputs, contractAdmin); } function _checkSpokeConfiguratorRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs + FullDeployInputs memory inputs, + address contractAdmin ) internal view { - assertEq( - accessManager.getRoleMemberCount(Roles.SPOKE_CONFIGURATOR_ROLE), - 2, - 'SpokeConfiguratorRole member count' - ); - assertEq( - accessManager.getRoleMember(Roles.SPOKE_CONFIGURATOR_ROLE, 0), - inputs.admin, - 'SpokeConfiguratorRole member - spoke admin' - ); - assertEq( - accessManager.getRoleMember(Roles.SPOKE_CONFIGURATOR_ROLE, 1), - report.configuratorBatchReport.spokeConfiguratorAddress, - 'SpokeConfiguratorRole member - spoke configurator' - ); + if (inputs.spokeLabels.length > 0 && inputs.grantRoles) { + assertEq( + accessManager.getRoleMemberCount(Roles.SPOKE_CONFIGURATOR_ROLE), + 2, + 'SpokeConfiguratorRole member count' + ); + assertEq( + accessManager.getRoleMember(Roles.SPOKE_CONFIGURATOR_ROLE, 0), + contractAdmin, + 'SpokeConfiguratorRole member - spoke admin' + ); + assertEq( + accessManager.getRoleMember(Roles.SPOKE_CONFIGURATOR_ROLE, 1), + report.configuratorBatchReport.spokeConfiguratorAddress, + 'SpokeConfiguratorRole member - spoke configurator' + ); + } else { + assertEq( + accessManager.getRoleMemberCount(Roles.SPOKE_CONFIGURATOR_ROLE), + 0, + 'SpokeConfiguratorRole member count' + ); + } for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { for (uint256 j = 0; j < spokeConfiguratorRoleSelectors.length; j++) { @@ -232,16 +243,24 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { report.spokeInstanceBatchReports[i].report.spokeProxyAddress, spokeConfiguratorRoleSelectors[j] ); - assertTrue(allowed, 'SpokeConfiguratorRole allowed - configurator'); + assertEq( + allowed, + inputs.grantRoles ? true : false, + 'SpokeConfiguratorRole allowed - configurator' + ); assertEq(delay, 0, 'SpokeConfiguratorRole delay - configurator'); // spoke admin role encompasses spoke configurator role (allowed, delay) = accessManager.canCall( - inputs.admin, + contractAdmin, report.spokeInstanceBatchReports[i].report.spokeProxyAddress, spokeConfiguratorRoleSelectors[j] ); - assertTrue(allowed, 'SpokeConfiguratorRole allowed - admin'); + assertEq( + allowed, + inputs.grantRoles ? true : false, + 'SpokeConfiguratorRole allowed - admin' + ); assertEq(delay, 0, 'SpokeConfiguratorRole delay - admin'); } } @@ -250,27 +269,32 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function _checkSpokeAdminRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs + FullDeployInputs memory inputs, + address contractAdmin ) internal view { - assertEq( - accessManager.getRoleMemberCount(Roles.SPOKE_ADMIN_ROLE), - 1, - 'SpokeAdminRole member count' - ); - assertEq( - accessManager.getRoleMember(Roles.SPOKE_ADMIN_ROLE, 0), - inputs.admin, - 'SpokeAdminRole member - spoke admin' - ); + if (inputs.spokeLabels.length > 0 && inputs.grantRoles) { + assertEq( + accessManager.getRoleMemberCount(Roles.SPOKE_ADMIN_ROLE), + 1, + 'SpokeAdminRole member count' + ); + assertEq( + accessManager.getRoleMember(Roles.SPOKE_ADMIN_ROLE, 0), + contractAdmin, + 'SpokeAdminRole member - spoke admin' + ); + } else { + assertEq(accessManager.getRoleMemberCount(Roles.SPOKE_ADMIN_ROLE), 0, 'HubAdminRoleCount'); + } for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { for (uint256 j = 0; j < spokeAdminRoleSelectors.length; j++) { (bool allowed, uint32 delay) = accessManager.canCall( - inputs.admin, + contractAdmin, report.spokeInstanceBatchReports[i].report.spokeProxyAddress, spokeAdminRoleSelectors[j] ); - assertTrue(allowed, 'SpokeAdminRole allowed'); + assertEq(allowed, inputs.grantRoles ? true : false, 'SpokeAdminRole allowed'); assertEq(delay, 0, 'SpokeAdminRole delay'); assertEq( @@ -288,23 +312,29 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function _checkHubRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs + FullDeployInputs memory inputs, + address contractAdmin ) internal view { - _checkHubAdminRoles(accessManager, report, inputs); - _checkHubConfiguratorRoles(accessManager, report, inputs); + _checkHubAdminRoles(accessManager, report, inputs, contractAdmin); + _checkHubConfiguratorRoles(accessManager, report, inputs, contractAdmin); } function _checkHubAdminRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs + FullDeployInputs memory inputs, + address contractAdmin ) internal view { - assertEq(accessManager.getRoleMemberCount(Roles.HUB_ADMIN_ROLE), 1, 'HubAdminRoleCount'); - assertEq( - accessManager.getRoleMember(Roles.HUB_ADMIN_ROLE, 0), - inputs.admin, - 'HubAdminRole member - hub admin' - ); + if (inputs.hubLabels.length > 0 && inputs.grantRoles) { + assertEq(accessManager.getRoleMemberCount(Roles.HUB_ADMIN_ROLE), 1, 'HubAdminRoleCount'); + assertEq( + accessManager.getRoleMember(Roles.HUB_ADMIN_ROLE, 0), + contractAdmin, + 'HubAdminRole member - hub admin' + ); + } else { + assertEq(accessManager.getRoleMemberCount(Roles.HUB_ADMIN_ROLE), 0, 'HubAdminRoleCount'); + } for (uint256 i = 0; i < inputs.hubLabels.length; i++) { for (uint256 j = 0; j < hubAdminRoleSelectors.length; j++) { assertEq( @@ -317,11 +347,11 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ); (bool allowed, uint32 delay) = accessManager.canCall( - inputs.admin, + contractAdmin, report.hubBatchReports[i].report.hubAddress, hubAdminRoleSelectors[j] ); - assertTrue(allowed, 'HubAdminRole allowed'); + assertEq(allowed, inputs.grantRoles ? true : false, 'HubAdminRole allowed'); assertEq(delay, 0, 'HubAdminRole delay'); } } @@ -330,23 +360,32 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function _checkHubConfiguratorRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs + FullDeployInputs memory inputs, + address contractAdmin ) internal view { - assertEq( - accessManager.getRoleMemberCount(Roles.HUB_CONFIGURATOR_ROLE), - 2, - 'HubConfiguratorRole member count' - ); - assertEq( - accessManager.getRoleMember(Roles.HUB_CONFIGURATOR_ROLE, 0), - inputs.admin, - 'HubConfiguratorRole member - hub admin' - ); - assertEq( - accessManager.getRoleMember(Roles.HUB_CONFIGURATOR_ROLE, 1), - report.configuratorBatchReport.hubConfiguratorAddress, - 'HubConfiguratorRole member - hub configurator' - ); + if (inputs.hubLabels.length > 0 && inputs.grantRoles) { + assertEq( + accessManager.getRoleMemberCount(Roles.HUB_CONFIGURATOR_ROLE), + 2, + 'HubConfiguratorRole member count' + ); + assertEq( + accessManager.getRoleMember(Roles.HUB_CONFIGURATOR_ROLE, 0), + contractAdmin, + 'HubConfiguratorRole member - hub admin' + ); + assertEq( + accessManager.getRoleMember(Roles.HUB_CONFIGURATOR_ROLE, 1), + report.configuratorBatchReport.hubConfiguratorAddress, + 'HubConfiguratorRole member - hub configurator' + ); + } else { + assertEq( + accessManager.getRoleMemberCount(Roles.HUB_CONFIGURATOR_ROLE), + 0, + 'HubConfiguratorRole member count' + ); + } for (uint256 i = 0; i < inputs.hubLabels.length; i++) { for (uint256 j = 0; j < hubConfiguratorRoleSelectors.length; j++) { assertEq( @@ -365,15 +404,19 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { report.hubBatchReports[i].report.hubAddress, hubConfiguratorRoleSelectors[j] ); - assertTrue(allowed, 'HubConfiguratorRole allowed - configurator'); + assertEq( + allowed, + inputs.grantRoles ? true : false, + 'HubConfiguratorRole allowed - configurator' + ); assertEq(delay, 0, 'HubConfiguratorRole delay - configurator'); (allowed, delay) = accessManager.canCall( - inputs.admin, + contractAdmin, report.hubBatchReports[i].report.hubAddress, hubConfiguratorRoleSelectors[j] ); - assertTrue(allowed, 'HubConfiguratorRole allowed - admin'); + assertEq(allowed, inputs.grantRoles ? true : false, 'HubConfiguratorRole allowed - admin'); assertEq(delay, 0, 'HubConfiguratorRole delay - admin'); } } @@ -410,11 +453,13 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { address accessManagerAddress, string memory label ) internal view { - assertEq( - Ownable(_getProxyAdminAddress(report.report.spokeProxyAddress)).owner(), - inputs.admin, - string.concat(label, ' proxy admin owner') - ); + address proxyAdminOwner = Ownable(_getProxyAdminAddress(report.report.spokeProxyAddress)) + .owner(); + if (inputs.admin != address(0)) { + assertEq(proxyAdminOwner, inputs.admin, string.concat(label, ' proxy admin owner')); + } else { + assertEq(proxyAdminOwner, deployer, string.concat(label, ' proxy admin owner')); + } assertEq( _getImplementationAddress(report.report.spokeProxyAddress), report.report.spokeImplementationAddress, @@ -512,11 +557,12 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { report.report.hubAddress, string.concat(label, ' hub on treasury spoke') ); - assertEq( - Ownable(report.report.treasurySpokeAddress).owner(), - inputs.admin, - string.concat(label, ' treasury spoke owner') - ); + address treasurySpokeOwner = Ownable(report.report.treasurySpokeAddress).owner(); + if (inputs.admin != address(0)) { + assertEq(treasurySpokeOwner, inputs.admin, string.concat(label, ' treasury spoke owner')); + } else { + assertEq(treasurySpokeOwner, deployer, string.concat(label, ' treasury spoke owner')); + } } function _getProxyAdminAddress(address proxy) internal view returns (address) { From e597f1c53b5f78f2387a210ddbfc0ef235689269 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Thu, 11 Dec 2025 23:14:23 -0600 Subject: [PATCH 43/62] rft: test suite setup --- snapshots/Hub.Operations.json | 10 +- snapshots/NativeTokenGateway.Operations.json | 12 +- snapshots/SignatureGateway.Operations.json | 16 +- .../Spoke.Operations.ZeroRiskPremium.json | 4 +- snapshots/Spoke.Operations.json | 4 +- tests/Base.t.sol | 1215 +++++++++-------- tests/Constants.sol | 4 +- .../orchestration/AaveV4TestOrchestration.sol | 166 ++- tests/gas/Gateways.Operations.gas.t.sol | 2 +- tests/gas/Hub.Operations.gas.t.sol | 4 +- tests/gas/Spoke.Getters.gas.t.sol | 4 +- tests/gas/Spoke.Operations.gas.t.sol | 4 +- tests/unit/AaveOracle.t.sol | 2 +- tests/unit/AssetInterestRateStrategy.t.sol | 2 +- tests/unit/Hub/Hub.Access.t.sol | 9 +- tests/unit/Hub/Hub.Restore.t.sol | 5 +- tests/unit/Hub/HubAccrueInterest.t.sol | 2 +- tests/unit/Hub/HubBase.t.sol | 2 +- tests/unit/HubConfigurator.t.sol | 5 +- tests/unit/Rescuable.t.sol | 2 +- tests/unit/Spoke/Spoke.Config.t.sol | 4 +- .../Spoke/Spoke.DynamicConfig.Triggers.t.sol | 5 +- tests/unit/Spoke/Spoke.DynamicConfig.t.sol | 8 +- tests/unit/Spoke/Spoke.Getters.t.sol | 5 +- tests/unit/Spoke/Spoke.MultipleHub.Base.t.sol | 4 +- tests/unit/Spoke/Spoke.MultipleHub.t.sol | 4 +- tests/unit/Spoke/Spoke.Upgradeable.t.sol | 30 +- tests/unit/Spoke/SpokeBase.t.sol | 8 +- .../LiquidationLogic.LiquidateUser.t.sol | 2 +- tests/unit/misc/GatewayBase.t.sol | 2 +- .../SignatureGateway.Base.t.sol | 4 +- tests/utils/BatchTestProcedures.sol | 22 +- tests/utils/ProxyHelper.sol | 31 + tests/utils/TestTypes.sol | 22 + 34 files changed, 900 insertions(+), 725 deletions(-) create mode 100644 tests/utils/ProxyHelper.sol create mode 100644 tests/utils/TestTypes.sol diff --git a/snapshots/Hub.Operations.json b/snapshots/Hub.Operations.json index 54b1b87c4..c43282a8f 100644 --- a/snapshots/Hub.Operations.json +++ b/snapshots/Hub.Operations.json @@ -1,9 +1,9 @@ { "add": "88006", - "add: with transfer": "109613", + "add: with transfer": "109642", "draw": "105931", - "eliminateDeficit: full": "59781", - "eliminateDeficit: partial": "69429", + "eliminateDeficit: full": "59769", + "eliminateDeficit: partial": "69417", "mintFeeShares": "84007", "payFee": "72302", "refreshPremium": "71999", @@ -11,8 +11,8 @@ "remove: partial": "81640", "reportDeficit": "115225", "restore: full": "80471", - "restore: full - with transfer": "173377", + "restore: full - with transfer": "173397", "restore: partial": "89137", - "restore: partial - with transfer": "147400", + "restore: partial - with transfer": "147429", "transferShares": "71192" } \ No newline at end of file diff --git a/snapshots/NativeTokenGateway.Operations.json b/snapshots/NativeTokenGateway.Operations.json index 45aeca137..ec7958115 100644 --- a/snapshots/NativeTokenGateway.Operations.json +++ b/snapshots/NativeTokenGateway.Operations.json @@ -1,8 +1,8 @@ { - "borrowNative": "229316", - "repayNative": "168024", - "supplyAsCollateralNative": "160373", - "supplyNative": "136476", - "withdrawNative: full": "125620", - "withdrawNative: partial": "136825" + "borrowNative": "229304", + "repayNative": "168012", + "supplyAsCollateralNative": "160361", + "supplyNative": "136467", + "withdrawNative: full": "125611", + "withdrawNative: partial": "136813" } \ No newline at end of file diff --git a/snapshots/SignatureGateway.Operations.json b/snapshots/SignatureGateway.Operations.json index 96eb0ef3e..c8f045985 100644 --- a/snapshots/SignatureGateway.Operations.json +++ b/snapshots/SignatureGateway.Operations.json @@ -1,10 +1,10 @@ { - "borrowWithSig": "215605", - "repayWithSig": "188872", - "setSelfAsUserPositionManagerWithSig": "75402", - "setUsingAsCollateralWithSig": "85053", - "supplyWithSig": "153205", - "updateUserDynamicConfigWithSig": "62769", - "updateUserRiskPremiumWithSig": "61579", - "withdrawWithSig": "131696" + "borrowWithSig": "215593", + "repayWithSig": "188848", + "setSelfAsUserPositionManagerWithSig": "75390", + "setUsingAsCollateralWithSig": "85041", + "supplyWithSig": "153196", + "updateUserDynamicConfigWithSig": "62757", + "updateUserRiskPremiumWithSig": "61567", + "withdrawWithSig": "131686" } \ No newline at end of file diff --git a/snapshots/Spoke.Operations.ZeroRiskPremium.json b/snapshots/Spoke.Operations.ZeroRiskPremium.json index 506cd1a0e..8e8cdc94f 100644 --- a/snapshots/Spoke.Operations.ZeroRiskPremium.json +++ b/snapshots/Spoke.Operations.ZeroRiskPremium.json @@ -5,12 +5,12 @@ "liquidationCall (receiveShares): partial": "299821", "liquidationCall: full": "310468", "liquidationCall: partial": "310186", - "permitReserve + repay (multicall)": "166017", + "permitReserve + repay (multicall)": "166029", "permitReserve + supply (multicall)": "146862", "permitReserve + supply + enable collateral (multicall)": "160573", "repay: full": "126094", "repay: partial": "130983", - "setUserPositionManagerWithSig: disable": "44846", + "setUserPositionManagerWithSig: disable": "44834", "setUserPositionManagerWithSig: enable": "68875", "supply + enable collateral (multicall)": "140624", "supply: 0 borrows, collateral disabled": "123679", diff --git a/snapshots/Spoke.Operations.json b/snapshots/Spoke.Operations.json index ccb5e2cec..d5986df06 100644 --- a/snapshots/Spoke.Operations.json +++ b/snapshots/Spoke.Operations.json @@ -5,12 +5,12 @@ "liquidationCall (receiveShares): partial": "333384", "liquidationCall: full": "344031", "liquidationCall: partial": "343749", - "permitReserve + repay (multicall)": "163264", + "permitReserve + repay (multicall)": "163273", "permitReserve + supply (multicall)": "146862", "permitReserve + supply + enable collateral (multicall)": "160573", "repay: full": "120256", "repay: partial": "139545", - "setUserPositionManagerWithSig: disable": "44846", + "setUserPositionManagerWithSig: disable": "44834", "setUserPositionManagerWithSig: enable": "68875", "supply + enable collateral (multicall)": "140624", "supply: 0 borrows, collateral disabled": "123679", diff --git a/tests/Base.t.sol b/tests/Base.t.sol index 42e41d02d..a4bc205c6 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -26,7 +26,6 @@ import {IAccessManaged} from 'src/dependencies/openzeppelin/IAccessManaged.sol'; import {AuthorityUtils} from 'src/dependencies/openzeppelin/AuthorityUtils.sol'; import {Ownable2Step, Ownable} from 'src/dependencies/openzeppelin/Ownable2Step.sol'; import {Math} from 'src/dependencies/openzeppelin/Math.sol'; -import {WETH9} from 'src/dependencies/weth/WETH9.sol'; import {LibBit} from 'src/dependencies/solady/LibBit.sol'; import {Initializable} from 'src/dependencies/openzeppelin-upgradeable/Initializable.sol'; @@ -74,11 +73,11 @@ import {SignatureGateway, ISignatureGateway} from 'src/position-manager/Signatur // test import {Constants} from 'tests/Constants.sol'; import {Utils} from 'tests/Utils.sol'; +import {TestTypes} from 'tests/utils/TestTypes.sol'; // orchestration import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; -import {AaveV4TestOrchestration} from 'tests/deployments/orchestration/AaveV4TestOrchestration.sol'; // mocks import {TestnetERC20} from 'tests/mocks/TestnetERC20.sol'; @@ -93,7 +92,9 @@ import {MockERC1271Wallet} from 'tests/mocks/MockERC1271Wallet.sol'; import {MockSpokeInstance} from 'tests/mocks/MockSpokeInstance.sol'; import {MockSkimSpoke} from 'tests/mocks/MockSkimSpoke.sol'; -abstract contract Base is Test { +import 'tests/utils/BatchTestProcedures.sol'; + +abstract contract Base is BatchTestProcedures { using stdStorage for StdStorage; using WadRayMath for *; using SharesMath for uint256; @@ -102,22 +103,11 @@ abstract contract Base is Test { using MathUtils for uint256; using ReserveFlagsMap for ReserveFlags; - bytes32 internal constant ERC1967_ADMIN_SLOT = - 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; - bytes32 internal constant IMPLEMENTATION_SLOT = - 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - uint256 internal constant MAX_SUPPLY_AMOUNT = 1e30; uint256 internal constant MIN_TOKEN_DECIMALS_SUPPORTED = 6; uint256 internal constant MAX_TOKEN_DECIMALS_SUPPORTED = 18; uint256 internal constant MAX_SUPPLY_ASSET_UNITS = MAX_SUPPLY_AMOUNT / 10 ** MAX_TOKEN_DECIMALS_SUPPORTED; - uint256 internal MAX_SUPPLY_AMOUNT_USDX; - uint256 internal MAX_SUPPLY_AMOUNT_DAI; - uint256 internal MAX_SUPPLY_AMOUNT_WBTC; - uint256 internal MAX_SUPPLY_AMOUNT_WETH; - uint256 internal MAX_SUPPLY_AMOUNT_USDY; - uint256 internal MAX_SUPPLY_AMOUNT_USDZ; uint256 internal constant MAX_SUPPLY_IN_BASE_CURRENCY = 1e39; uint24 internal constant MIN_COLLATERAL_RISK_BPS = 1; uint24 internal constant MAX_COLLATERAL_RISK_BPS = 1000_00; @@ -139,6 +129,14 @@ abstract contract Base is Test { PercentageMath.PERCENTAGE_FACTOR; IHubBase.PremiumDelta internal ZERO_PREMIUM_DELTA = ZERO_PREMIUM_DELTA; + /// + IHub[] internal _hubs; + ISpoke[] internal _spokes; + IAaveOracle[] internal _oracles; + ITreasurySpoke[] internal _treasurySpokes; + AssetInterestRateStrategy[] internal _irStrategies; + IAccessManager[] internal _accessManagers; + IAaveOracle internal oracle1; IAaveOracle internal oracle2; IAaveOracle internal oracle3; @@ -163,7 +161,7 @@ abstract contract Base is Test { address internal LIQUIDATOR = makeAddr('LIQUIDATOR'); address internal POSITION_MANAGER = makeAddr('POSITION_MANAGER'); - TokenList internal tokenList; + TestTypes.TokenList internal tokenList; uint256 internal wethAssetId = 0; uint256 internal usdxAssetId = 1; uint256 internal daiAssetId = 2; @@ -178,6 +176,13 @@ abstract contract Base is Test { uint256 internal mintAmount_USDY = MAX_SUPPLY_AMOUNT; uint256 internal mintAmount_USDZ = MAX_SUPPLY_AMOUNT; + uint256 internal MAX_SUPPLY_AMOUNT_USDX; + uint256 internal MAX_SUPPLY_AMOUNT_DAI; + uint256 internal MAX_SUPPLY_AMOUNT_WBTC; + uint256 internal MAX_SUPPLY_AMOUNT_WETH; + uint256 internal MAX_SUPPLY_AMOUNT_USDY; + uint256 internal MAX_SUPPLY_AMOUNT_USDZ; + Decimals internal _decimals = Decimals({usdx: 6, usdy: 18, dai: 18, wbtc: 8, weth: 18, usdz: 18}); struct Decimals { @@ -189,15 +194,6 @@ abstract contract Base is Test { uint8 usdz; } - struct TokenList { - WETH9 weth; - TestnetERC20 usdx; - TestnetERC20 dai; - TestnetERC20 wbtc; - TestnetERC20 usdy; - TestnetERC20 usdz; - } - struct SpokeInfo { ReserveInfo weth; ReserveInfo wbtc; @@ -214,6 +210,12 @@ abstract contract Base is Test { ISpoke.DynamicReserveConfig dynReserveConfig; } + struct FixtureAssetList { + IERC20Metadata underlying; + uint16 liquidityFee; + bytes irData; + } + struct DrawnAccounting { uint256 totalOwed; uint256 drawn; @@ -269,100 +271,98 @@ abstract contract Base is Test { mapping(ISpoke => SpokeInfo) internal spokeInfo; - function setUp() public virtual { - deployFixtures(); - } - - function _getProxyAdminAddress(address proxy) internal view returns (address) { - bytes32 slotData = vm.load(proxy, ERC1967_ADMIN_SLOT); - return address(uint160(uint256(slotData))); - } - - function _getImplementationAddress(address proxy) internal view returns (address) { - bytes32 slotData = vm.load(proxy, IMPLEMENTATION_SLOT); - return address(uint160(uint256(slotData))); - } - - function deployFixtures() internal virtual { - vm.startPrank(ADMIN); - accessManager = IAccessManager(address(new AccessManagerEnumerable(ADMIN))); - hub1 = new Hub(address(accessManager)); - irStrategy = new AssetInterestRateStrategy(address(hub1)); - (spoke1, oracle1) = _deploySpokeWithOracle(ADMIN, address(accessManager), 'Spoke 1 (USD)'); - (spoke2, oracle2) = _deploySpokeWithOracle(ADMIN, address(accessManager), 'Spoke 2 (USD)'); - (spoke3, oracle3) = _deploySpokeWithOracle(ADMIN, address(accessManager), 'Spoke 3 (USD)'); - treasurySpoke = ITreasurySpoke(new TreasurySpoke(TREASURY_ADMIN, address(hub1))); - vm.stopPrank(); - - vm.label(address(spoke1), 'spoke1'); - vm.label(address(spoke2), 'spoke2'); - vm.label(address(spoke3), 'spoke3'); - - setUpRoles(hub1, spoke1, accessManager); - setUpRoles(hub1, spoke2, accessManager); - setUpRoles(hub1, spoke3, accessManager); - } - - function setUpRoles(IHub targetHub, ISpoke spoke, IAccessManager manager) internal virtual { - vm.startPrank(ADMIN); - // Grant roles with 0 delay - manager.grantRole(Roles.HUB_ADMIN_ROLE, ADMIN, 0); - manager.grantRole(Roles.HUB_ADMIN_ROLE, HUB_ADMIN, 0); - - manager.grantRole(Roles.SPOKE_CONFIGURATOR_ROLE, ADMIN, 0); - manager.grantRole(Roles.SPOKE_CONFIGURATOR_ROLE, SPOKE_ADMIN, 0); - manager.grantRole(Roles.SPOKE_ADMIN_ROLE, SPOKE_ADMIN, 0); - manager.grantRole(Roles.SPOKE_ADMIN_ROLE, USER_POSITION_UPDATER, 0); + IAssetInterestRateStrategy.InterestRateData internal _defaultIrData = + IAssetInterestRateStrategy.InterestRateData({ + optimalUsageRatio: 90_00, // 90.00% + baseVariableBorrowRate: 5_00, // 5.00% + variableRateSlope1: 5_00, // 5.00% + variableRateSlope2: 5_00 // 5.00% + }); - // Grant responsibilities to roles - { - bytes4[] memory selectors = new bytes4[](7); - selectors[0] = ISpoke.updateLiquidationConfig.selector; - selectors[1] = ISpoke.addReserve.selector; - selectors[2] = ISpoke.updateReserveConfig.selector; - selectors[3] = ISpoke.updateDynamicReserveConfig.selector; - selectors[4] = ISpoke.addDynamicReserveConfig.selector; - selectors[5] = ISpoke.updatePositionManager.selector; - selectors[6] = ISpoke.updateReservePriceSource.selector; - manager.setTargetFunctionRole(address(spoke), selectors, Roles.SPOKE_CONFIGURATOR_ROLE); + function setUp() public virtual override { + _setupFixtures(); + } + + function _setupFixtures() internal virtual { + OrchestrationReports.TestEnvReport memory report = _deployFixtures({numHubs: 1, numSpokes: 3}); + _setupFixturesRoles(report); + + // todo rm when tests adapted to multiple hubs and spokes + hub1 = IHub(report.hubReports[0].hubAddress); + irStrategy = AssetInterestRateStrategy(report.hubReports[0].irStrategyAddress); + treasurySpoke = ITreasurySpoke(report.hubReports[0].treasurySpokeAddress); + spoke1 = ISpoke(report.spokeReports[0].spokeAddress); + spoke2 = ISpoke(report.spokeReports[1].spokeAddress); + spoke3 = ISpoke(report.spokeReports[2].spokeAddress); + oracle1 = IAaveOracle(report.spokeReports[0].aaveOracleAddress); + oracle2 = IAaveOracle(report.spokeReports[1].aaveOracleAddress); + oracle3 = IAaveOracle(report.spokeReports[2].aaveOracleAddress); + accessManager = IAccessManager(report.accessManagerAddress); + } + + function _deployFixtures( + uint256 numHubs, + uint256 numSpokes + ) internal virtual returns (OrchestrationReports.TestEnvReport memory report) { + report = AaveV4TestOrchestration.deployTestEnv({ + admin: ADMIN, + treasuryAdmin: TREASURY_ADMIN, + hubCount: numHubs, + spokeCount: numSpokes + }); + for (uint256 i; i < numHubs; ++i) { + _hubs.push(IHub(report.hubReports[i].hubAddress)); + _irStrategies.push(AssetInterestRateStrategy(report.hubReports[i].irStrategyAddress)); + _treasurySpokes.push(ITreasurySpoke(report.hubReports[i].treasurySpokeAddress)); + + vm.label(report.hubReports[i].hubAddress, string.concat('hub', string(abi.encode(i)))); + vm.label( + report.hubReports[i].irStrategyAddress, + string.concat('irStrategy', string(abi.encode(i))) + ); + vm.label( + report.hubReports[i].treasurySpokeAddress, + string.concat('treasurySpoke', string(abi.encode(i))) + ); } - { - bytes4[] memory selectors = new bytes4[](2); - selectors[0] = ISpoke.updateUserDynamicConfig.selector; - selectors[1] = ISpoke.updateUserRiskPremium.selector; - manager.setTargetFunctionRole(address(spoke), selectors, Roles.SPOKE_ADMIN_ROLE); - } + for (uint256 i; i < numSpokes; ++i) { + _spokes.push(ISpoke(report.spokeReports[i].spokeAddress)); + _oracles.push(IAaveOracle(report.spokeReports[i].aaveOracleAddress)); - { - bytes4[] memory selectors = new bytes4[](6); - selectors[0] = IHub.addAsset.selector; - selectors[1] = IHub.updateAssetConfig.selector; - selectors[2] = IHub.addSpoke.selector; - selectors[3] = IHub.updateSpokeConfig.selector; - selectors[4] = IHub.setInterestRateData.selector; - selectors[5] = IHub.mintFeeShares.selector; - manager.setTargetFunctionRole(address(targetHub), selectors, Roles.HUB_ADMIN_ROLE); + vm.label(report.spokeReports[i].spokeAddress, string.concat('spoke', string(abi.encode(i)))); + vm.label( + report.spokeReports[i].aaveOracleAddress, + string.concat('oracle', string(abi.encode(i))) + ); } - vm.stopPrank(); + + return report; } - function _grantSpokeConfiguratorRole(ISpoke spoke, address spokeConfigurator) internal { + function _setupFixturesRoles(OrchestrationReports.TestEnvReport memory report) internal virtual { + if (report.accessManagerAddress == address(0)) + report.accessManagerAddress = address(accessManager); + IAccessManager accessManager = IAccessManager(report.accessManagerAddress); + + // temporary grant admin role to address(this) to execute setAndGrantRolesTestEnv from its context vm.startPrank(ADMIN); - IAccessManager(spoke.authority()).grantRole( - Roles.SPOKE_CONFIGURATOR_ROLE, - spokeConfigurator, - 0 - ); + accessManager.grantRole(Roles.DEFAULT_ADMIN_ROLE, address(this), 0); vm.stopPrank(); + + AaveV4TestOrchestration.setRolesTestEnv(report); + AaveV4TestOrchestration.grantRolesTestEnv(report, ADMIN, HUB_ADMIN, SPOKE_ADMIN); + + accessManager.renounceRole(Roles.DEFAULT_ADMIN_ROLE, address(this)); } - function initEnvironment() internal { - deployMintAndApproveTokenList(); - configureTokenList(); + function _initEnvironment() internal { + _initTokenList(); + _mintAndApproveTokenList(); + _configureTokenList(); } - function deployMintAndApproveTokenList() internal { + function _initTokenList() internal { ConfigData.TestTokenInput[] memory tokenInputs = new ConfigData.TestTokenInput[](5); tokenInputs[0] = ConfigData.TestTokenInput({ name: 'USDX', @@ -389,16 +389,8 @@ abstract contract Base is Test { symbol: 'USDZ', decimals: _decimals.usdz }); - OrchestrationReports.TestTokensReport memory tokensReport = AaveV4TestOrchestration - .deployTestTokens(tokenInputs); - tokenList = TokenList( - WETH9(payable(tokensReport.wethAddress)), - TestnetERC20(tokensReport.testTokenAddresses[0]), - TestnetERC20(tokensReport.testTokenAddresses[1]), - TestnetERC20(tokensReport.testTokenAddresses[2]), - TestnetERC20(tokensReport.testTokenAddresses[3]), - TestnetERC20(tokensReport.testTokenAddresses[4]) - ); + + tokenList = AaveV4TestOrchestration.deployTestTokens(tokenInputs); vm.label(address(tokenList.weth), 'WETH'); vm.label(address(tokenList.usdx), 'USDX'); @@ -412,7 +404,9 @@ abstract contract Base is Test { MAX_SUPPLY_AMOUNT_WBTC = MAX_SUPPLY_ASSET_UNITS * 10 ** tokenList.wbtc.decimals(); MAX_SUPPLY_AMOUNT_USDY = MAX_SUPPLY_ASSET_UNITS * 10 ** tokenList.usdy.decimals(); MAX_SUPPLY_AMOUNT_USDZ = MAX_SUPPLY_ASSET_UNITS * 10 ** tokenList.usdz.decimals(); + } + function _mintAndApproveTokenList() internal { address[7] memory users = [ alice, bob, @@ -423,13 +417,6 @@ abstract contract Base is Test { POSITION_MANAGER ]; - address[4] memory spokes = [ - address(spoke1), - address(spoke2), - address(spoke3), - address(treasurySpoke) - ]; - for (uint256 x; x < users.length; ++x) { tokenList.usdx.mint(users[x], mintAmount_USDX); tokenList.dai.mint(users[x], mintAmount_DAI); @@ -439,13 +426,23 @@ abstract contract Base is Test { deal(address(tokenList.weth), users[x], mintAmount_WETH); vm.startPrank(users[x]); - for (uint256 y; y < spokes.length; ++y) { - tokenList.weth.approve(spokes[y], UINT256_MAX); - tokenList.usdx.approve(spokes[y], UINT256_MAX); - tokenList.dai.approve(spokes[y], UINT256_MAX); - tokenList.wbtc.approve(spokes[y], UINT256_MAX); - tokenList.usdy.approve(spokes[y], UINT256_MAX); - tokenList.usdz.approve(spokes[y], UINT256_MAX); + for (uint256 y; y < _spokes.length; ++y) { + address spoke = address(_spokes[y]); + tokenList.weth.approve(spoke, UINT256_MAX); + tokenList.usdx.approve(spoke, UINT256_MAX); + tokenList.dai.approve(spoke, UINT256_MAX); + tokenList.wbtc.approve(spoke, UINT256_MAX); + tokenList.usdy.approve(spoke, UINT256_MAX); + tokenList.usdz.approve(spoke, UINT256_MAX); + } + for (uint256 y; y < _treasurySpokes.length; ++y) { + address spoke = address(_treasurySpokes[y]); + tokenList.weth.approve(spoke, UINT256_MAX); + tokenList.usdx.approve(spoke, UINT256_MAX); + tokenList.dai.approve(spoke, UINT256_MAX); + tokenList.wbtc.approve(spoke, UINT256_MAX); + tokenList.usdy.approve(spoke, UINT256_MAX); + tokenList.usdz.approve(spoke, UINT256_MAX); } vm.stopPrank(); } @@ -479,7 +476,58 @@ abstract contract Base is Test { } } - function configureTokenList() internal { + function _configureTokenList() internal { + vm.startPrank(ADMIN); + accessManager.grantRole(Roles.HUB_CONFIGURATOR_ROLE, address(this), 0); + accessManager.grantRole(Roles.SPOKE_CONFIGURATOR_ROLE, address(this), 0); + vm.stopPrank(); + + ( + ConfigData.UpdateLiquidationConfigParams[] memory liquidationParams, + ConfigData.AddReserveParams[] memory reserveParams + ) = _getSpokeReserveParams(); + AaveV4TestOrchestration.configureHubsAssets(_getTestAssetParams()); + AaveV4TestOrchestration.configureHubsSpokes(_getAddSpokeParams()); + TestTypes.SpokeReserveId[] memory spokeReserveIds = AaveV4TestOrchestration.configureSpokes( + liquidationParams, + reserveParams + ); + + _loadSpokeInfo(spokeReserveIds); + + accessManager.renounceRole(Roles.HUB_CONFIGURATOR_ROLE, address(this)); + accessManager.renounceRole(Roles.SPOKE_CONFIGURATOR_ROLE, address(this)); + } + + function _loadSpokeInfo(TestTypes.SpokeReserveId[] memory spokeReserveIds) internal { + // Persist reserveIds into spokeInfo to mirror manual configureTokenList setup + for (uint256 i; i < spokeReserveIds.length; ++i) { + TestTypes.SpokeReserveId memory spokeReserveId = spokeReserveIds[i]; + uint256 reserveId = spokeReserveId.reserveId; + ISpoke spoke = ISpoke(spokeReserveId.spoke); + uint256 assetId = spoke.getReserve(reserveId).assetId; + + if (assetId == wethAssetId) { + spokeInfo[spoke].weth.reserveId = reserveId; + } else if (assetId == wbtcAssetId) { + spokeInfo[spoke].wbtc.reserveId = reserveId; + } else if (assetId == daiAssetId) { + spokeInfo[spoke].dai.reserveId = reserveId; + } else if (assetId == usdxAssetId) { + spokeInfo[spoke].usdx.reserveId = reserveId; + } else if (assetId == usdyAssetId) { + spokeInfo[spoke].usdy.reserveId = reserveId; + } else if (assetId == usdzAssetId) { + spokeInfo[spoke].usdz.reserveId = reserveId; + } + } + } + + function _getAddSpokeParams() + internal + view + returns (ConfigData.AddSpokeParams[] memory paramsList) + { IHub.SpokeConfig memory spokeConfig = IHub.SpokeConfig({ active: true, paused: false, @@ -487,373 +535,390 @@ abstract contract Base is Test { drawCap: Constants.MAX_ALLOWED_SPOKE_CAP, riskPremiumThreshold: Constants.MAX_ALLOWED_COLLATERAL_RISK }); + paramsList = new ConfigData.AddSpokeParams[](15); + + // spoke1 + paramsList[0] = ConfigData.AddSpokeParams({ + spoke: address(spoke1), + hub: address(hub1), + assetId: wethAssetId, + config: spokeConfig + }); + paramsList[1] = ConfigData.AddSpokeParams({ + spoke: address(spoke1), + hub: address(hub1), + assetId: wbtcAssetId, + config: spokeConfig + }); + paramsList[2] = ConfigData.AddSpokeParams({ + spoke: address(spoke1), + hub: address(hub1), + assetId: daiAssetId, + config: spokeConfig + }); + paramsList[3] = ConfigData.AddSpokeParams({ + spoke: address(spoke1), + hub: address(hub1), + assetId: usdxAssetId, + config: spokeConfig + }); + paramsList[4] = ConfigData.AddSpokeParams({ + spoke: address(spoke1), + hub: address(hub1), + assetId: usdyAssetId, + config: spokeConfig + }); - bytes memory encodedIrData = abi.encode( - IAssetInterestRateStrategy.InterestRateData({ - optimalUsageRatio: 90_00, // 90.00% - baseVariableBorrowRate: 5_00, // 5.00% - variableRateSlope1: 5_00, // 5.00% - variableRateSlope2: 5_00 // 5.00% - }) - ); + // spoke2 + paramsList[5] = ConfigData.AddSpokeParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: wbtcAssetId, + config: spokeConfig + }); + paramsList[6] = ConfigData.AddSpokeParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: wethAssetId, + config: spokeConfig + }); + paramsList[7] = ConfigData.AddSpokeParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: daiAssetId, + config: spokeConfig + }); + paramsList[8] = ConfigData.AddSpokeParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: usdxAssetId, + config: spokeConfig + }); + paramsList[9] = ConfigData.AddSpokeParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: usdyAssetId, + config: spokeConfig + }); + paramsList[10] = ConfigData.AddSpokeParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: usdzAssetId, + config: spokeConfig + }); - // Add all assets to the Hub - vm.startPrank(ADMIN); - // add WETH - hub1.addAsset( - address(tokenList.weth), - tokenList.weth.decimals(), - address(treasurySpoke), - address(irStrategy), - encodedIrData - ); - hub1.updateAssetConfig( - wethAssetId, - IHub.AssetConfig({ - liquidityFee: 10_00, - feeReceiver: address(treasurySpoke), - irStrategy: address(irStrategy), - reinvestmentController: address(0) - }), - new bytes(0) - ); - // add USDX - hub1.addAsset( - address(tokenList.usdx), - tokenList.usdx.decimals(), - address(treasurySpoke), - address(irStrategy), - encodedIrData - ); - hub1.updateAssetConfig( - usdxAssetId, - IHub.AssetConfig({ - liquidityFee: 5_00, - feeReceiver: address(treasurySpoke), - irStrategy: address(irStrategy), - reinvestmentController: address(0) - }), - new bytes(0) - ); - // add DAI - hub1.addAsset( - address(tokenList.dai), - tokenList.dai.decimals(), - address(treasurySpoke), - address(irStrategy), - encodedIrData - ); - hub1.updateAssetConfig( - daiAssetId, - IHub.AssetConfig({ - liquidityFee: 5_00, - feeReceiver: address(treasurySpoke), - irStrategy: address(irStrategy), - reinvestmentController: address(0) - }), - new bytes(0) - ); - // add WBTC - hub1.addAsset( - address(tokenList.wbtc), - tokenList.wbtc.decimals(), - address(treasurySpoke), - address(irStrategy), - encodedIrData - ); - hub1.updateAssetConfig( - wbtcAssetId, - IHub.AssetConfig({ - liquidityFee: 10_00, - feeReceiver: address(treasurySpoke), - irStrategy: address(irStrategy), - reinvestmentController: address(0) - }), - new bytes(0) - ); - // add USDY - hub1.addAsset( - address(tokenList.usdy), - tokenList.usdy.decimals(), - address(treasurySpoke), - address(irStrategy), - encodedIrData - ); - hub1.updateAssetConfig( - usdyAssetId, - IHub.AssetConfig({ - liquidityFee: 10_00, - feeReceiver: address(treasurySpoke), - irStrategy: address(irStrategy), - reinvestmentController: address(0) - }), - new bytes(0) - ); - // add USDZ - hub1.addAsset( - address(tokenList.usdz), - tokenList.usdz.decimals(), - address(treasurySpoke), - address(irStrategy), - encodedIrData - ); - hub1.updateAssetConfig( - hub1.getAssetCount() - 1, - IHub.AssetConfig({ - liquidityFee: 5_00, - feeReceiver: address(treasurySpoke), - irStrategy: address(irStrategy), - reinvestmentController: address(0) - }), - new bytes(0) - ); + // spoke3 + paramsList[11] = ConfigData.AddSpokeParams({ + spoke: address(spoke3), + hub: address(hub1), + assetId: daiAssetId, + config: spokeConfig + }); + paramsList[12] = ConfigData.AddSpokeParams({ + spoke: address(spoke3), + hub: address(hub1), + assetId: usdxAssetId, + config: spokeConfig + }); + paramsList[13] = ConfigData.AddSpokeParams({ + spoke: address(spoke3), + hub: address(hub1), + assetId: wethAssetId, + config: spokeConfig + }); + paramsList[14] = ConfigData.AddSpokeParams({ + spoke: address(spoke3), + hub: address(hub1), + assetId: wbtcAssetId, + config: spokeConfig + }); - // Liquidation configs - spoke1.updateLiquidationConfig( - ISpoke.LiquidationConfig({ + return paramsList; + } + + function _getSpokeReserveParams() + internal + returns ( + ConfigData.UpdateLiquidationConfigParams[] memory, + ConfigData.AddReserveParams[] memory + ) + { + ConfigData.UpdateLiquidationConfigParams[] + memory liquidationParams = new ConfigData.UpdateLiquidationConfigParams[](3); + liquidationParams[0] = ConfigData.UpdateLiquidationConfigParams({ + spoke: address(spoke1), + config: ISpoke.LiquidationConfig({ targetHealthFactor: 1.05e18, healthFactorForMaxBonus: 0.7e18, liquidationBonusFactor: 20_00 }) - ); - spoke2.updateLiquidationConfig( - ISpoke.LiquidationConfig({ + }); + liquidationParams[1] = ConfigData.UpdateLiquidationConfigParams({ + spoke: address(spoke2), + config: ISpoke.LiquidationConfig({ targetHealthFactor: 1.04e18, healthFactorForMaxBonus: 0.8e18, liquidationBonusFactor: 15_00 }) - ); - spoke3.updateLiquidationConfig( - ISpoke.LiquidationConfig({ + }); + liquidationParams[2] = ConfigData.UpdateLiquidationConfigParams({ + spoke: address(spoke3), + config: ISpoke.LiquidationConfig({ targetHealthFactor: 1.03e18, healthFactorForMaxBonus: 0.9e18, liquidationBonusFactor: 10_00 }) - ); + }); - // Spoke 1 reserve configs - spokeInfo[spoke1].weth.reserveConfig = _getDefaultReserveConfig(15_00); - spokeInfo[spoke1].weth.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 80_00, - maxLiquidationBonus: 105_00, - liquidationFee: 10_00 + ConfigData.AddReserveParams[] memory reserveParams = new ConfigData.AddReserveParams[](15); + // spoke1 + reserveParams[0] = ConfigData.AddReserveParams({ + spoke: address(spoke1), + hub: address(hub1), + assetId: wethAssetId, + priceSource: _deployMockPriceFeed(spoke1, 2000e8), + config: _getDefaultReserveConfig(15_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 80_00, + maxLiquidationBonus: 105_00, + liquidationFee: 10_00 + }) }); - spokeInfo[spoke1].wbtc.reserveConfig = _getDefaultReserveConfig(15_00); - spokeInfo[spoke1].wbtc.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 75_00, - maxLiquidationBonus: 103_00, - liquidationFee: 15_00 + reserveParams[1] = ConfigData.AddReserveParams({ + spoke: address(spoke1), + hub: address(hub1), + assetId: wbtcAssetId, + priceSource: _deployMockPriceFeed(spoke1, 50_000e8), + config: _getDefaultReserveConfig(15_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 75_00, + maxLiquidationBonus: 103_00, + liquidationFee: 15_00 + }) }); - spokeInfo[spoke1].dai.reserveConfig = _getDefaultReserveConfig(20_00); - spokeInfo[spoke1].dai.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 78_00, - maxLiquidationBonus: 102_00, - liquidationFee: 10_00 + reserveParams[2] = ConfigData.AddReserveParams({ + spoke: address(spoke1), + hub: address(hub1), + assetId: daiAssetId, + priceSource: _deployMockPriceFeed(spoke1, 1e8), + config: _getDefaultReserveConfig(20_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 78_00, + maxLiquidationBonus: 102_00, + liquidationFee: 10_00 + }) }); - spokeInfo[spoke1].usdx.reserveConfig = _getDefaultReserveConfig(50_00); - spokeInfo[spoke1].usdx.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 78_00, - maxLiquidationBonus: 101_00, - liquidationFee: 12_00 + reserveParams[3] = ConfigData.AddReserveParams({ + spoke: address(spoke1), + hub: address(hub1), + assetId: usdxAssetId, + priceSource: _deployMockPriceFeed(spoke1, 1e8), + config: _getDefaultReserveConfig(50_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 78_00, + maxLiquidationBonus: 101_00, + liquidationFee: 12_00 + }) }); - spokeInfo[spoke1].usdy.reserveConfig = _getDefaultReserveConfig(50_00); - spokeInfo[spoke1].usdy.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 78_00, - maxLiquidationBonus: 101_50, - liquidationFee: 15_00 + reserveParams[4] = ConfigData.AddReserveParams({ + spoke: address(spoke1), + hub: address(hub1), + assetId: usdyAssetId, + priceSource: _deployMockPriceFeed(spoke1, 1e8), + config: _getDefaultReserveConfig(50_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 78_00, + maxLiquidationBonus: 101_50, + liquidationFee: 15_00 + }) }); - spokeInfo[spoke1].weth.reserveId = spoke1.addReserve( - address(hub1), - wethAssetId, - _deployMockPriceFeed(spoke1, 2000e8), - spokeInfo[spoke1].weth.reserveConfig, - spokeInfo[spoke1].weth.dynReserveConfig - ); - spokeInfo[spoke1].wbtc.reserveId = spoke1.addReserve( - address(hub1), - wbtcAssetId, - _deployMockPriceFeed(spoke1, 50_000e8), - spokeInfo[spoke1].wbtc.reserveConfig, - spokeInfo[spoke1].wbtc.dynReserveConfig - ); - spokeInfo[spoke1].dai.reserveId = spoke1.addReserve( - address(hub1), - daiAssetId, - _deployMockPriceFeed(spoke1, 1e8), - spokeInfo[spoke1].dai.reserveConfig, - spokeInfo[spoke1].dai.dynReserveConfig - ); - spokeInfo[spoke1].usdx.reserveId = spoke1.addReserve( - address(hub1), - usdxAssetId, - _deployMockPriceFeed(spoke1, 1e8), - spokeInfo[spoke1].usdx.reserveConfig, - spokeInfo[spoke1].usdx.dynReserveConfig - ); - spokeInfo[spoke1].usdy.reserveId = spoke1.addReserve( - address(hub1), - usdyAssetId, - _deployMockPriceFeed(spoke1, 1e8), - spokeInfo[spoke1].usdy.reserveConfig, - spokeInfo[spoke1].usdy.dynReserveConfig - ); - - hub1.addSpoke(wethAssetId, address(spoke1), spokeConfig); - hub1.addSpoke(wbtcAssetId, address(spoke1), spokeConfig); - hub1.addSpoke(daiAssetId, address(spoke1), spokeConfig); - hub1.addSpoke(usdxAssetId, address(spoke1), spokeConfig); - hub1.addSpoke(usdyAssetId, address(spoke1), spokeConfig); - - // Spoke 2 reserve configs - spokeInfo[spoke2].wbtc.reserveConfig = _getDefaultReserveConfig(0); - spokeInfo[spoke2].wbtc.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 80_00, - maxLiquidationBonus: 105_00, - liquidationFee: 10_00 + // spoke2 + reserveParams[5] = ConfigData.AddReserveParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: wbtcAssetId, + priceSource: _deployMockPriceFeed(spoke2, 50_000e8), + config: _getDefaultReserveConfig(0), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 80_00, + maxLiquidationBonus: 105_00, + liquidationFee: 10_00 + }) }); - spokeInfo[spoke2].weth.reserveConfig = _getDefaultReserveConfig(10_00); - spokeInfo[spoke2].weth.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 76_00, - maxLiquidationBonus: 103_00, - liquidationFee: 15_00 + reserveParams[6] = ConfigData.AddReserveParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: wethAssetId, + priceSource: _deployMockPriceFeed(spoke2, 2000e8), + config: _getDefaultReserveConfig(10_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 76_00, + maxLiquidationBonus: 103_00, + liquidationFee: 15_00 + }) }); - spokeInfo[spoke2].dai.reserveConfig = _getDefaultReserveConfig(20_00); - spokeInfo[spoke2].dai.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 72_00, - maxLiquidationBonus: 102_00, - liquidationFee: 10_00 + reserveParams[7] = ConfigData.AddReserveParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: daiAssetId, + priceSource: _deployMockPriceFeed(spoke2, 1e8), + config: _getDefaultReserveConfig(20_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 72_00, + maxLiquidationBonus: 102_00, + liquidationFee: 10_00 + }) }); - spokeInfo[spoke2].usdx.reserveConfig = _getDefaultReserveConfig(50_00); - spokeInfo[spoke2].usdx.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 72_00, - maxLiquidationBonus: 101_00, - liquidationFee: 12_00 + reserveParams[8] = ConfigData.AddReserveParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: usdxAssetId, + priceSource: _deployMockPriceFeed(spoke2, 1e8), + config: _getDefaultReserveConfig(50_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 72_00, + maxLiquidationBonus: 101_00, + liquidationFee: 12_00 + }) }); - spokeInfo[spoke2].usdy.reserveConfig = _getDefaultReserveConfig(50_00); - spokeInfo[spoke2].usdy.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 72_00, - maxLiquidationBonus: 101_50, - liquidationFee: 15_00 + reserveParams[9] = ConfigData.AddReserveParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: usdyAssetId, + priceSource: _deployMockPriceFeed(spoke2, 1e8), + config: _getDefaultReserveConfig(50_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 72_00, + maxLiquidationBonus: 101_50, + liquidationFee: 15_00 + }) }); - spokeInfo[spoke2].usdz.reserveConfig = _getDefaultReserveConfig(100_00); - spokeInfo[spoke2].usdz.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 70_00, - maxLiquidationBonus: 106_00, - liquidationFee: 10_00 + reserveParams[10] = ConfigData.AddReserveParams({ + spoke: address(spoke2), + hub: address(hub1), + assetId: usdzAssetId, + priceSource: _deployMockPriceFeed(spoke2, 1e8), + config: _getDefaultReserveConfig(100_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 70_00, + maxLiquidationBonus: 106_00, + liquidationFee: 10_00 + }) }); - spokeInfo[spoke2].wbtc.reserveId = spoke2.addReserve( - address(hub1), - wbtcAssetId, - _deployMockPriceFeed(spoke2, 50_000e8), - spokeInfo[spoke2].wbtc.reserveConfig, - spokeInfo[spoke2].wbtc.dynReserveConfig - ); - spokeInfo[spoke2].weth.reserveId = spoke2.addReserve( - address(hub1), - wethAssetId, - _deployMockPriceFeed(spoke2, 2000e8), - spokeInfo[spoke2].weth.reserveConfig, - spokeInfo[spoke2].weth.dynReserveConfig - ); - spokeInfo[spoke2].dai.reserveId = spoke2.addReserve( - address(hub1), - daiAssetId, - _deployMockPriceFeed(spoke2, 1e8), - spokeInfo[spoke2].dai.reserveConfig, - spokeInfo[spoke2].dai.dynReserveConfig - ); - spokeInfo[spoke2].usdx.reserveId = spoke2.addReserve( - address(hub1), - usdxAssetId, - _deployMockPriceFeed(spoke2, 1e8), - spokeInfo[spoke2].usdx.reserveConfig, - spokeInfo[spoke2].usdx.dynReserveConfig - ); - spokeInfo[spoke2].usdy.reserveId = spoke2.addReserve( - address(hub1), - usdyAssetId, - _deployMockPriceFeed(spoke2, 1e8), - spokeInfo[spoke2].usdy.reserveConfig, - spokeInfo[spoke2].usdy.dynReserveConfig - ); - spokeInfo[spoke2].usdz.reserveId = spoke2.addReserve( - address(hub1), - usdzAssetId, - _deployMockPriceFeed(spoke2, 1e8), - spokeInfo[spoke2].usdz.reserveConfig, - spokeInfo[spoke2].usdz.dynReserveConfig - ); - - hub1.addSpoke(wbtcAssetId, address(spoke2), spokeConfig); - hub1.addSpoke(wethAssetId, address(spoke2), spokeConfig); - hub1.addSpoke(daiAssetId, address(spoke2), spokeConfig); - hub1.addSpoke(usdxAssetId, address(spoke2), spokeConfig); - hub1.addSpoke(usdyAssetId, address(spoke2), spokeConfig); - hub1.addSpoke(usdzAssetId, address(spoke2), spokeConfig); - - // Spoke 3 reserve configs - spokeInfo[spoke3].dai.reserveConfig = _getDefaultReserveConfig(0); - spokeInfo[spoke3].dai.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 75_00, - maxLiquidationBonus: 104_00, - liquidationFee: 11_00 + // spoke3 + reserveParams[11] = ConfigData.AddReserveParams({ + spoke: address(spoke3), + hub: address(hub1), + assetId: daiAssetId, + priceSource: _deployMockPriceFeed(spoke3, 1e8), + config: _getDefaultReserveConfig(0), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 75_00, + maxLiquidationBonus: 104_00, + liquidationFee: 11_00 + }) }); - spokeInfo[spoke3].usdx.reserveConfig = _getDefaultReserveConfig(10_00); - spokeInfo[spoke3].usdx.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 75_00, - maxLiquidationBonus: 103_00, - liquidationFee: 15_00 + reserveParams[12] = ConfigData.AddReserveParams({ + spoke: address(spoke3), + hub: address(hub1), + assetId: usdxAssetId, + priceSource: _deployMockPriceFeed(spoke3, 1e8), + config: _getDefaultReserveConfig(10_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 75_00, + maxLiquidationBonus: 103_00, + liquidationFee: 15_00 + }) }); - spokeInfo[spoke3].weth.reserveConfig = _getDefaultReserveConfig(20_00); - spokeInfo[spoke3].weth.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 79_00, - maxLiquidationBonus: 102_00, - liquidationFee: 10_00 + reserveParams[13] = ConfigData.AddReserveParams({ + spoke: address(spoke3), + hub: address(hub1), + assetId: wethAssetId, + priceSource: _deployMockPriceFeed(spoke3, 2000e8), + config: _getDefaultReserveConfig(20_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 79_00, + maxLiquidationBonus: 102_00, + liquidationFee: 10_00 + }) }); - spokeInfo[spoke3].wbtc.reserveConfig = _getDefaultReserveConfig(50_00); - spokeInfo[spoke3].wbtc.dynReserveConfig = ISpoke.DynamicReserveConfig({ - collateralFactor: 77_00, - maxLiquidationBonus: 101_00, - liquidationFee: 12_00 + reserveParams[14] = ConfigData.AddReserveParams({ + spoke: address(spoke3), + hub: address(hub1), + assetId: wbtcAssetId, + priceSource: _deployMockPriceFeed(spoke3, 50_000e8), + config: _getDefaultReserveConfig(50_00), + dynamicConfig: ISpoke.DynamicReserveConfig({ + collateralFactor: 77_00, + maxLiquidationBonus: 101_00, + liquidationFee: 12_00 + }) }); - spokeInfo[spoke3].dai.reserveId = spoke3.addReserve( - address(hub1), - daiAssetId, - _deployMockPriceFeed(spoke3, 1e8), - spokeInfo[spoke3].dai.reserveConfig, - spokeInfo[spoke3].dai.dynReserveConfig - ); - spokeInfo[spoke3].usdx.reserveId = spoke3.addReserve( - address(hub1), - usdxAssetId, - _deployMockPriceFeed(spoke3, 1e8), - spokeInfo[spoke3].usdx.reserveConfig, - spokeInfo[spoke3].usdx.dynReserveConfig - ); - spokeInfo[spoke3].weth.reserveId = spoke3.addReserve( - address(hub1), - wethAssetId, - _deployMockPriceFeed(spoke3, 2000e8), - spokeInfo[spoke3].weth.reserveConfig, - spokeInfo[spoke3].weth.dynReserveConfig - ); - spokeInfo[spoke3].wbtc.reserveId = spoke3.addReserve( - address(hub1), - wbtcAssetId, - _deployMockPriceFeed(spoke3, 50_000e8), - spokeInfo[spoke3].wbtc.reserveConfig, - spokeInfo[spoke3].wbtc.dynReserveConfig - ); + return (liquidationParams, reserveParams); + } - hub1.addSpoke(daiAssetId, address(spoke3), spokeConfig); - hub1.addSpoke(usdxAssetId, address(spoke3), spokeConfig); - hub1.addSpoke(wethAssetId, address(spoke3), spokeConfig); - hub1.addSpoke(wbtcAssetId, address(spoke3), spokeConfig); + function _getTestAssetParams() internal view returns (ConfigData.AddAssetParams[] memory) { + bytes memory encodedIrData = abi.encode(_defaultIrData); - vm.stopPrank(); + ConfigData.AddAssetParams[] memory assetParams = new ConfigData.AddAssetParams[](6); + assetParams[0] = ConfigData.AddAssetParams({ + hub: address(hub1), + underlying: address(tokenList.weth), + decimals: tokenList.weth.decimals(), + feeReceiver: address(treasurySpoke), + liquidityFee: 10_00, + irStrategy: address(irStrategy), + irData: encodedIrData + }); + assetParams[1] = ConfigData.AddAssetParams({ + hub: address(hub1), + underlying: address(tokenList.usdx), + decimals: tokenList.usdx.decimals(), + feeReceiver: address(treasurySpoke), + liquidityFee: 5_00, + irStrategy: address(irStrategy), + irData: encodedIrData + }); + assetParams[2] = ConfigData.AddAssetParams({ + hub: address(hub1), + underlying: address(tokenList.dai), + decimals: tokenList.dai.decimals(), + feeReceiver: address(treasurySpoke), + liquidityFee: 5_00, + irStrategy: address(irStrategy), + irData: encodedIrData + }); + assetParams[3] = ConfigData.AddAssetParams({ + hub: address(hub1), + underlying: address(tokenList.wbtc), + decimals: tokenList.wbtc.decimals(), + feeReceiver: address(treasurySpoke), + liquidityFee: 10_00, + irStrategy: address(irStrategy), + irData: encodedIrData + }); + assetParams[4] = ConfigData.AddAssetParams({ + hub: address(hub1), + underlying: address(tokenList.usdy), + decimals: tokenList.usdy.decimals(), + feeReceiver: address(treasurySpoke), + liquidityFee: 10_00, + irStrategy: address(irStrategy), + irData: encodedIrData + }); + assetParams[5] = ConfigData.AddAssetParams({ + hub: address(hub1), + underlying: address(tokenList.usdz), + decimals: tokenList.usdz.decimals(), + feeReceiver: address(treasurySpoke), + liquidityFee: 5_00, + irStrategy: address(irStrategy), + irData: encodedIrData + }); + return assetParams; } /* @dev Configures Hub 2 with the following assetIds: @@ -862,65 +927,34 @@ abstract contract Base is Test { * 2: DAI * 3: WBTC */ - function hub2Fixture() internal returns (IHub, AssetInterestRateStrategy) { - IAccessManager accessManager2 = IAccessManager(address(new AccessManagerEnumerable(ADMIN))); - IHub hub2 = new Hub(address(accessManager2)); - vm.label(address(hub2), 'Hub2'); - AssetInterestRateStrategy hub2IrStrategy = new AssetInterestRateStrategy(address(hub2)); - - // Configure IR Strategy for hub 2 - bytes memory encodedIrData = abi.encode( - IAssetInterestRateStrategy.InterestRateData({ - optimalUsageRatio: 90_00, // 90.00% - baseVariableBorrowRate: 5_00, // 5.00% - variableRateSlope1: 5_00, // 5.00% - variableRateSlope2: 5_00 // 5.00% - }) - ); - - vm.startPrank(ADMIN); - - // Add assets to the second hub - // Add WETH - hub2.addAsset( - address(tokenList.weth), - tokenList.weth.decimals(), - address(treasurySpoke), - address(hub2IrStrategy), - encodedIrData - ); - - // Add USDX - hub2.addAsset( - address(tokenList.usdx), - tokenList.usdx.decimals(), - address(treasurySpoke), - address(hub2IrStrategy), - encodedIrData - ); - - // Add DAI - hub2.addAsset( - address(tokenList.dai), - tokenList.dai.decimals(), - address(treasurySpoke), - address(hub2IrStrategy), - encodedIrData - ); + function _hub2Fixture() internal returns (IHub, AssetInterestRateStrategy) { + FixtureAssetList[] memory assetsList = new FixtureAssetList[](4); + assetsList[0] = FixtureAssetList({ + underlying: IERC20Metadata(address(tokenList.weth)), + liquidityFee: 0, + irData: abi.encode(_defaultIrData) + }); + assetsList[1] = FixtureAssetList({ + underlying: IERC20Metadata(address(tokenList.usdx)), + liquidityFee: 0, + irData: abi.encode(_defaultIrData) + }); + assetsList[2] = FixtureAssetList({ + underlying: IERC20Metadata(address(tokenList.dai)), + liquidityFee: 0, + irData: abi.encode(_defaultIrData) + }); + assetsList[3] = FixtureAssetList({ + underlying: IERC20Metadata(address(tokenList.wbtc)), + liquidityFee: 0, + irData: abi.encode(_defaultIrData) + }); - // Add WBTC - hub2.addAsset( - address(tokenList.wbtc), - tokenList.wbtc.decimals(), - address(treasurySpoke), - address(hub2IrStrategy), - encodedIrData + OrchestrationReports.TestEnvReport memory report = _addFixture('2', assetsList); + return ( + IHub(report.hubReports[0].hubAddress), + AssetInterestRateStrategy(report.hubReports[0].irStrategyAddress) ); - vm.stopPrank(); - - setUpRoles(hub2, spoke1, accessManager2); - - return (hub2, hub2IrStrategy); } /* @dev Configures Hub 3 with the following assetIds: @@ -929,63 +963,112 @@ abstract contract Base is Test { * 2: WBTC * 3: WETH */ - function hub3Fixture() internal returns (IHub, AssetInterestRateStrategy) { - IAccessManager accessManager3 = IAccessManager(address(new AccessManagerEnumerable(ADMIN))); - IHub hub3 = new Hub(address(accessManager3)); - AssetInterestRateStrategy hub3IrStrategy = new AssetInterestRateStrategy(address(hub3)); - - // Configure IR Strategy for hub 3 - bytes memory encodedIrData = abi.encode( - IAssetInterestRateStrategy.InterestRateData({ - optimalUsageRatio: 90_00, // 90.00% - baseVariableBorrowRate: 5_00, // 5.00% - variableRateSlope1: 5_00, // 5.00% - variableRateSlope2: 5_00 // 5.00% - }) - ); + function _hub3Fixture() internal returns (IHub, AssetInterestRateStrategy) { + FixtureAssetList[] memory assetsList = new FixtureAssetList[](4); + assetsList[0] = FixtureAssetList({ + underlying: IERC20Metadata(address(tokenList.dai)), + liquidityFee: 0, + irData: abi.encode(_defaultIrData) + }); + assetsList[1] = FixtureAssetList({ + underlying: IERC20Metadata(address(tokenList.usdx)), + liquidityFee: 0, + irData: abi.encode(_defaultIrData) + }); + assetsList[2] = FixtureAssetList({ + underlying: IERC20Metadata(address(tokenList.wbtc)), + liquidityFee: 0, + irData: abi.encode(_defaultIrData) + }); + assetsList[3] = FixtureAssetList({ + underlying: IERC20Metadata(address(tokenList.weth)), + liquidityFee: 0, + irData: abi.encode(_defaultIrData) + }); - vm.startPrank(ADMIN); - // Add DAI - hub3.addAsset( - address(tokenList.dai), - tokenList.dai.decimals(), - address(treasurySpoke), - address(hub3IrStrategy), - encodedIrData + OrchestrationReports.TestEnvReport memory report = _addFixture('3', assetsList); + return ( + IHub(report.hubReports[0].hubAddress), + AssetInterestRateStrategy(report.hubReports[0].irStrategyAddress) ); + } + + function _addFixture( + string memory label, + FixtureAssetList[] memory assetsList + ) internal returns (OrchestrationReports.TestEnvReport memory report) { + report = _deployFixtures({numHubs: 1, numSpokes: 0}); + _setupFixturesRoles(report); - // Add USDX - hub3.addAsset( - address(tokenList.usdx), - tokenList.usdx.decimals(), - address(treasurySpoke), - address(hub3IrStrategy), - encodedIrData + ConfigData.AddAssetParams[] memory assetParams = new ConfigData.AddAssetParams[]( + assetsList.length ); + for (uint256 i; i < assetsList.length; ++i) { + assetParams[i] = ConfigData.AddAssetParams({ + hub: report.hubReports[0].hubAddress, + underlying: address(assetsList[i].underlying), + decimals: assetsList[i].underlying.decimals(), + feeReceiver: report.hubReports[0].treasurySpokeAddress, + liquidityFee: assetsList[i].liquidityFee, + irStrategy: report.hubReports[0].irStrategyAddress, + irData: assetsList[i].irData + }); + } - // Add WBTC - hub3.addAsset( - address(tokenList.wbtc), - tokenList.wbtc.decimals(), - address(treasurySpoke), - address(hub3IrStrategy), - encodedIrData + vm.startPrank(ADMIN); + IAccessManager(report.accessManagerAddress).grantRole( + Roles.HUB_CONFIGURATOR_ROLE, + address(this), + 0 ); + IAccessManager(report.accessManagerAddress).grantRole( + Roles.SPOKE_CONFIGURATOR_ROLE, + address(this), + 0 + ); + vm.stopPrank(); - // Add WETH - hub3.addAsset( - address(tokenList.weth), - tokenList.weth.decimals(), - address(treasurySpoke), - address(hub3IrStrategy), - encodedIrData + AaveV4TestOrchestration.configureHubsAssets(assetParams); + + // Renounce temporary roles + IAccessManager(report.accessManagerAddress).renounceRole( + Roles.HUB_CONFIGURATOR_ROLE, + address(this) + ); + IAccessManager(report.accessManagerAddress).renounceRole( + Roles.SPOKE_CONFIGURATOR_ROLE, + address(this) ); + vm.label(report.hubReports[0].hubAddress, string.concat('Hub', label)); + vm.label(report.hubReports[0].irStrategyAddress, string.concat('IrStrategy', label)); + vm.label(report.hubReports[0].treasurySpokeAddress, string.concat('TreasurySpoke', label)); + + return report; + } + + function _grantSpokeConfiguratorRole(ISpoke spoke, address spokeConfigurator) internal { + vm.startPrank(ADMIN); + IAccessManager(spoke.authority()).grantRole( + Roles.SPOKE_CONFIGURATOR_ROLE, + spokeConfigurator, + 0 + ); vm.stopPrank(); + } - setUpRoles(hub3, spoke1, accessManager3); + function _grantHubAdminRole(IHub hub, address admin) internal { + vm.startPrank(ADMIN); + // hub admin consists of hub admin role and hub configurator role + IAccessManager(hub.authority()).grantRole(Roles.HUB_ADMIN_ROLE, admin, 0); + IAccessManager(hub.authority()).grantRole(Roles.HUB_CONFIGURATOR_ROLE, admin, 0); + vm.stopPrank(); + } - return (hub3, hub3IrStrategy); + function _grantHubConfiguratorRole(IHub hub, address admin) internal { + vm.startPrank(ADMIN); + IAccessManager(hub.authority()).grantRole(Roles.HUB_CONFIGURATOR_ROLE, admin, 0); + vm.stopPrank(); } function updateAssetFeeReceiver( @@ -2196,9 +2279,9 @@ abstract contract Base is Test { user != address(spoke1) && user != address(spoke2) && user != address(spoke3) && - user != _getProxyAdminAddress(address(spoke1)) && - user != _getProxyAdminAddress(address(spoke2)) && - user != _getProxyAdminAddress(address(spoke3)) + user != ProxyHelper.getProxyAdmin(address(spoke1)) && + user != ProxyHelper.getProxyAdmin(address(spoke2)) && + user != ProxyHelper.getProxyAdmin(address(spoke3)) ); } diff --git a/tests/Constants.sol b/tests/Constants.sol index 4352a81db..3c9693d8d 100644 --- a/tests/Constants.sol +++ b/tests/Constants.sol @@ -3,6 +3,8 @@ pragma solidity ^0.8.0; library Constants { + bool public constant IS_TEST = true; + /// @dev Hub Constants uint8 public constant MAX_ALLOWED_UNDERLYING_DECIMALS = 18; uint8 public constant MIN_ALLOWED_UNDERLYING_DECIMALS = 6; @@ -10,7 +12,6 @@ library Constants { uint24 public constant MAX_RISK_PREMIUM_THRESHOLD = type(uint24).max; // 167772.15% /// @dev Spoke Constants - uint8 public constant ORACLE_DECIMALS = 8; uint64 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1e18; uint256 public constant DUST_LIQUIDATION_THRESHOLD = 1000e26; uint24 public constant MAX_ALLOWED_COLLATERAL_RISK = 1000_00; // 1000.00% @@ -21,5 +22,6 @@ library Constants { uint256 public constant MAX_ALLOWED_ASSET_ID = type(uint16).max; /// @dev Deployments + uint8 public constant ORACLE_DECIMALS = 8; string public constant ORACLE_SUFFIX = ' (USD)'; } diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol index 66e2d8955..1e45a9a71 100644 --- a/tests/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -33,12 +33,31 @@ import { import {AaveV4DeployCore} from 'src/deployments/orchestration/AaveV4DeployCore.sol'; +import {TestTypes} from 'tests/utils/TestTypes.sol'; +import {WETH9} from 'src/dependencies/weth/WETH9.sol'; + +import {Constants} from 'tests/Constants.sol'; + +import {TestnetERC20} from 'tests/mocks/TestnetERC20.sol'; + library AaveV4TestOrchestration { bool public constant IS_TEST = true; Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); - uint8 private constant ORACLE_DECIMALS = 8; - string private constant ORACLE_SUFFIX = ' (USD)'; + function deployTestTokens( + ConfigData.TestTokenInput[] memory tokenInputs + ) external returns (TestTypes.TokenList memory) { + OrchestrationReports.TestTokensReport memory tokensReport = _deployTestTokensBatch(tokenInputs); + + TestTypes.TokenList memory tokenList; + tokenList.weth = WETH9(payable(tokensReport.wethAddress)); + tokenList.usdx = TestnetERC20(tokensReport.testTokenAddresses[0]); + tokenList.dai = TestnetERC20(tokensReport.testTokenAddresses[1]); + tokenList.wbtc = TestnetERC20(tokensReport.testTokenAddresses[2]); + tokenList.usdy = TestnetERC20(tokensReport.testTokenAddresses[3]); + tokenList.usdz = TestnetERC20(tokensReport.testTokenAddresses[4]); + return tokenList; + } function deployTestEnv( address admin, @@ -71,9 +90,9 @@ library AaveV4TestOrchestration { .deploySpokeInstanceBatch( admin, report.accessManagerAddress, - ORACLE_DECIMALS, - ORACLE_SUFFIX, - string.concat('Spoke ', string(abi.encode(i)), ' (USD)') + Constants.ORACLE_DECIMALS, + Constants.ORACLE_SUFFIX, + string.concat('Spoke ', string(abi.encode(i)), Constants.ORACLE_SUFFIX) ); report.spokeReports[i].spokeAddress = spokeReport.spokeProxyAddress; report.spokeReports[i].aaveOracleAddress = spokeReport.aaveOracleAddress; @@ -82,32 +101,7 @@ library AaveV4TestOrchestration { return report; } - function deployTestTokens( - ConfigData.TestTokenInput[] memory tokenInputs - ) external returns (OrchestrationReports.TestTokensReport memory) { - OrchestrationReports.TestTokensReport memory report; - - report.testTokenAddresses = new address[](tokenInputs.length); - - // Deploy Test Tokens Batch - BatchReports.TestTokensBatchReport memory tokensReport = _deployTokensBatch(tokenInputs); - report.wethAddress = tokensReport.wethAddress; - report.testTokenAddresses = tokensReport.tokenAddresses; - - return report; - } - - function setRolesTestEnv( - address admin, - OrchestrationReports.TestEnvReport memory report - ) external { - // Set ConfiguratorAdmin Roles - AaveV4AccessManagerRolesProcedure.grantRootAdminRole({ - accessManagerAddress: report.accessManagerAddress, - newAdminAddress: admin, - currentAdminAddress: admin - }); - + function setRolesTestEnv(OrchestrationReports.TestEnvReport memory report) public { // Set Hub Roles for (uint256 i; i < report.hubReports.length; ++i) { AaveV4HubRolesProcedure.setHubRoles( @@ -125,32 +119,74 @@ library AaveV4TestOrchestration { } } - function deployTestHub( + function grantRolesTestEnv( + OrchestrationReports.TestEnvReport memory report, address admin, - address treasuryAdmin, - ConfigData.AddAssetParams[] memory paramsList - ) external returns (address, OrchestrationReports.TestHubReport memory) { - OrchestrationReports.TestHubReport memory report; + address hubAdmin, + address spokeAdmin + ) public { + grantHubRolesTestEnv(report, admin, hubAdmin); + grantSpokeRolesTestEnv(report, admin, spokeAdmin); + } - address accessManagerAddress = AaveV4DeployCore.deployAccessBatch(admin).accessManagerAddress; + // function grantAccessManagerRolesTestEnv( + // OrchestrationReports.TestEnvReport memory report, + // address admin + // ) external { + // // grant RootAdmin Role + // AaveV4AccessManagerRolesProcedure.grantRootAdminRole({ + // accessManagerAddress: report.accessManagerAddress, + // newAdminAddress: admin, + // currentAdminAddress: admin + // }); + // } + + function grantHubRolesTestEnv( + OrchestrationReports.TestEnvReport memory report, + address admin, + address hubAdmin + ) public { + // grant Hub roles + AaveV4HubRolesProcedure.grantHubAdminRole(report.accessManagerAddress, admin); + AaveV4HubRolesProcedure.grantHubAdminRole(report.accessManagerAddress, hubAdmin); + } - // Deploy Hub Batch - BatchReports.HubBatchReport memory hubReport = AaveV4DeployCore.deployHubBatch( - treasuryAdmin, - accessManagerAddress - ); - report.hubAddress = hubReport.hubAddress; - report.irStrategyAddress = hubReport.irStrategyAddress; - report.treasurySpokeAddress = hubReport.treasurySpokeAddress; + function grantSpokeRolesTestEnv( + OrchestrationReports.TestEnvReport memory report, + address admin, + address spokeAdmin + ) public { + // grant Spoke roles + AaveV4SpokeRolesProcedure.grantSpokeAdminRole(report.accessManagerAddress, admin); + AaveV4SpokeRolesProcedure.grantSpokeAdminRole(report.accessManagerAddress, spokeAdmin); + } - // Set Hub Roles - AaveV4HubRolesProcedure.setHubAdminRole(accessManagerAddress, report.hubAddress); + // function deployTestHub( + // address admin, + // address treasuryAdmin, + // ConfigData.AddAssetParams[] memory paramsList + // ) external returns (address, OrchestrationReports.TestHubReport memory) { + // OrchestrationReports.TestHubReport memory report; - // Configure Hub Assets - configureHubsAssets(paramsList); + // address accessManagerAddress = AaveV4DeployCore.deployAccessBatch(admin).accessManagerAddress; - return (accessManagerAddress, report); - } + // // Deploy Hub Batch + // BatchReports.HubBatchReport memory hubReport = AaveV4DeployCore.deployHubBatch( + // treasuryAdmin, + // accessManagerAddress + // ); + // report.hubAddress = hubReport.hubAddress; + // report.irStrategyAddress = hubReport.irStrategyAddress; + // report.treasurySpokeAddress = hubReport.treasurySpokeAddress; + + // // Set Hub Roles + // AaveV4HubRolesProcedure.setHubAdminRole(accessManagerAddress, report.hubAddress); + + // // Configure Hub Assets + // configureHubsAssets(paramsList); + + // return (accessManagerAddress, report); + // } function configureHubsAssets( ConfigData.AddAssetParams[] memory paramsList @@ -171,15 +207,35 @@ library AaveV4TestOrchestration { function configureSpokes( ConfigData.UpdateLiquidationConfigParams[] memory liquidationParamsList, ConfigData.AddReserveParams[] memory reserveParamsList - ) external returns (uint256[] memory) { + ) external returns (TestTypes.SpokeReserveId[] memory) { for (uint256 i; i < liquidationParamsList.length; ++i) { AaveV4SpokeConfigProcedures.updateLiquidationConfig(liquidationParamsList[i]); } - uint256[] memory reserveIds = new uint256[](reserveParamsList.length); + TestTypes.SpokeReserveId[] memory spokeReserveIds = new TestTypes.SpokeReserveId[]( + reserveParamsList.length + ); for (uint256 i; i < reserveParamsList.length; ++i) { - reserveIds[i] = AaveV4SpokeConfigProcedures.addReserve(reserveParamsList[i]); + spokeReserveIds[i] = TestTypes.SpokeReserveId({ + spoke: reserveParamsList[i].spoke, + reserveId: AaveV4SpokeConfigProcedures.addReserve(reserveParamsList[i]) + }); } - return reserveIds; + return spokeReserveIds; + } + + function _deployTestTokensBatch( + ConfigData.TestTokenInput[] memory tokenInputs + ) internal returns (OrchestrationReports.TestTokensReport memory) { + OrchestrationReports.TestTokensReport memory report; + + report.testTokenAddresses = new address[](tokenInputs.length); + + // Deploy Test Tokens Batch + BatchReports.TestTokensBatchReport memory tokensReport = _deployTokensBatch(tokenInputs); + report.wethAddress = tokensReport.wethAddress; + report.testTokenAddresses = tokensReport.tokenAddresses; + + return report; } function _deployTokensBatch( diff --git a/tests/gas/Gateways.Operations.gas.t.sol b/tests/gas/Gateways.Operations.gas.t.sol index c2ab0743f..078908309 100644 --- a/tests/gas/Gateways.Operations.gas.t.sol +++ b/tests/gas/Gateways.Operations.gas.t.sol @@ -13,7 +13,7 @@ contract NativeTokenGateway_Gas_Tests is Base { function setUp() public virtual override { super.setUp(); - initEnvironment(); + _initEnvironment(); nativeTokenGateway = new NativeTokenGateway(address(tokenList.weth), address(ADMIN)); diff --git a/tests/gas/Hub.Operations.gas.t.sol b/tests/gas/Hub.Operations.gas.t.sol index 6723966cd..3c375dd9f 100644 --- a/tests/gas/Hub.Operations.gas.t.sol +++ b/tests/gas/Hub.Operations.gas.t.sol @@ -10,8 +10,8 @@ contract HubOperations_Gas_Tests is Base { using WadRayMath for uint256; function setUp() public override { - deployFixtures(); - initEnvironment(); + _setupFixtures(); + _initEnvironment(); } function test_add() public { diff --git a/tests/gas/Spoke.Getters.gas.t.sol b/tests/gas/Spoke.Getters.gas.t.sol index 31c23b8f5..e114e7ce2 100644 --- a/tests/gas/Spoke.Getters.gas.t.sol +++ b/tests/gas/Spoke.Getters.gas.t.sol @@ -7,8 +7,8 @@ import 'tests/Base.t.sol'; /// forge-config: default.isolate = true contract SpokeGetters_Gas_Tests is Base { function setUp() public override { - deployFixtures(); - initEnvironment(); + _setupFixtures(); + _initEnvironment(); } function test_getUserAccountData() external { diff --git a/tests/gas/Spoke.Operations.gas.t.sol b/tests/gas/Spoke.Operations.gas.t.sol index aa6d2b8d9..b84af1fec 100644 --- a/tests/gas/Spoke.Operations.gas.t.sol +++ b/tests/gas/Spoke.Operations.gas.t.sol @@ -11,8 +11,8 @@ contract SpokeOperations_Gas_Tests is SpokeBase { ISpoke internal spoke; function setUp() public virtual override { - deployFixtures(); - initEnvironment(); + _setupFixtures(); + _initEnvironment(); spoke = spoke1; reserveId = _getReserveIds(spoke); _seed(); diff --git a/tests/unit/AaveOracle.t.sol b/tests/unit/AaveOracle.t.sol index b5803807a..a38361cdd 100644 --- a/tests/unit/AaveOracle.t.sol +++ b/tests/unit/AaveOracle.t.sol @@ -21,7 +21,7 @@ contract AaveOracleTest is Base { uint256 private constant reserveId2 = 1; function setUp() public override { - deployFixtures(); + _setupFixtures(); oracle = new AaveOracle(address(spoke1), _oracleDecimals, _description); } diff --git a/tests/unit/AssetInterestRateStrategy.t.sol b/tests/unit/AssetInterestRateStrategy.t.sol index 63777d97b..4ae40d8c2 100644 --- a/tests/unit/AssetInterestRateStrategy.t.sol +++ b/tests/unit/AssetInterestRateStrategy.t.sol @@ -15,7 +15,7 @@ contract AssetInterestRateStrategyTest is Base { bytes public encodedRateData; function setUp() public override { - deployFixtures(); + _setupFixtures(); rateStrategy = new AssetInterestRateStrategy(address(hub1)); rateData = IAssetInterestRateStrategy.InterestRateData({ diff --git a/tests/unit/Hub/Hub.Access.t.sol b/tests/unit/Hub/Hub.Access.t.sol index ca9a7af03..e6756a84f 100644 --- a/tests/unit/Hub/Hub.Access.t.sol +++ b/tests/unit/Hub/Hub.Access.t.sol @@ -159,12 +159,9 @@ contract HubAccessTest is HubBase { ); // Say addresses Alice, Bob, and Carol all have the HUB_ADMIN role, allowing them to set interest rate data. - // Grant roles with 0 delay - vm.startPrank(ADMIN); - accessManager.grantRole(Roles.HUB_ADMIN_ROLE, alice, 0); - accessManager.grantRole(Roles.HUB_ADMIN_ROLE, bob, 0); - accessManager.grantRole(Roles.HUB_ADMIN_ROLE, carol, 0); - vm.stopPrank(); + _grantHubAdminRole(hub1, alice); + _grantHubAdminRole(hub1, bob); + _grantHubAdminRole(hub1, carol); vm.prank(alice); hub1.setInterestRateData(daiAssetId, encodedIrData); diff --git a/tests/unit/Hub/Hub.Restore.t.sol b/tests/unit/Hub/Hub.Restore.t.sol index 996c0a64e..c78db366d 100644 --- a/tests/unit/Hub/Hub.Restore.t.sol +++ b/tests/unit/Hub/Hub.Restore.t.sol @@ -18,10 +18,7 @@ contract HubRestoreTest is HubBase { // Set up a hub configurator to test freezing and pausing assets hubConfigurator = new HubConfigurator(HUB_CONFIGURATOR_ADMIN); - IAccessManager accessManager = IAccessManager(hub1.authority()); - // Grant hubConfigurator hub admin role with 0 delay - vm.prank(ADMIN); - accessManager.grantRole(Roles.HUB_ADMIN_ROLE, address(hubConfigurator), 0); + _grantHubConfiguratorRole(hub1, address(hubConfigurator)); } function test_restore_revertsWith_SurplusDrawnRestored() public { diff --git a/tests/unit/Hub/HubAccrueInterest.t.sol b/tests/unit/Hub/HubAccrueInterest.t.sol index 0a5aaa5e0..0e4cfb548 100644 --- a/tests/unit/Hub/HubAccrueInterest.t.sol +++ b/tests/unit/Hub/HubAccrueInterest.t.sol @@ -45,7 +45,7 @@ contract HubAccrueInterestTest is Base { function setUp() public override { super.setUp(); - initEnvironment(); + _initEnvironment(); spokeMintAndApprove(); } diff --git a/tests/unit/Hub/HubBase.t.sol b/tests/unit/Hub/HubBase.t.sol index 1fe787157..ba2350b8e 100644 --- a/tests/unit/Hub/HubBase.t.sol +++ b/tests/unit/Hub/HubBase.t.sol @@ -48,7 +48,7 @@ contract HubBase is Base { function setUp() public virtual override { super.setUp(); - initEnvironment(); + _initEnvironment(); } function _updateAddCap(uint256 assetId, address spoke, uint40 newAddCap) internal { diff --git a/tests/unit/HubConfigurator.t.sol b/tests/unit/HubConfigurator.t.sol index c75ca4aa5..28a6c0fd5 100644 --- a/tests/unit/HubConfigurator.t.sol +++ b/tests/unit/HubConfigurator.t.sol @@ -22,10 +22,7 @@ contract HubConfiguratorTest is HubBase { function setUp() public virtual override { super.setUp(); hubConfigurator = new HubConfigurator(HUB_CONFIGURATOR_ADMIN); - IAccessManager accessManager = IAccessManager(hub1.authority()); - // Grant hubConfigurator hub admin role with 0 delay - vm.prank(ADMIN); - accessManager.grantRole(Roles.HUB_ADMIN_ROLE, address(hubConfigurator), 0); + _grantHubConfiguratorRole(hub1, address(hubConfigurator)); _assetId = daiAssetId; _encodedIrData = abi.encode( IAssetInterestRateStrategy.InterestRateData({ diff --git a/tests/unit/Rescuable.t.sol b/tests/unit/Rescuable.t.sol index 82dda5f2d..fedde75d9 100644 --- a/tests/unit/Rescuable.t.sol +++ b/tests/unit/Rescuable.t.sol @@ -9,7 +9,7 @@ contract RescuableTest is Base { function setUp() public virtual override { super.setUp(); - initEnvironment(); + _initEnvironment(); rescuable = new RescuableWrapper(ADMIN); } diff --git a/tests/unit/Spoke/Spoke.Config.t.sol b/tests/unit/Spoke/Spoke.Config.t.sol index 3531ed70e..0544cb5da 100644 --- a/tests/unit/Spoke/Spoke.Config.t.sol +++ b/tests/unit/Spoke/Spoke.Config.t.sol @@ -38,7 +38,9 @@ contract SpokeConfigTest is SpokeBase { address caller ) public { vm.assume( - caller != SPOKE_ADMIN && caller != ADMIN && caller != _getProxyAdminAddress(address(spoke1)) + caller != SPOKE_ADMIN && + caller != ADMIN && + caller != ProxyHelper.getProxyAdmin(address(spoke1)) ); vm.expectRevert( abi.encodeWithSelector(IAccessManaged.AccessManagedUnauthorized.selector, caller) diff --git a/tests/unit/Spoke/Spoke.DynamicConfig.Triggers.t.sol b/tests/unit/Spoke/Spoke.DynamicConfig.Triggers.t.sol index 7060c33a4..c63bd8c92 100644 --- a/tests/unit/Spoke/Spoke.DynamicConfig.Triggers.t.sol +++ b/tests/unit/Spoke/Spoke.DynamicConfig.Triggers.t.sol @@ -209,10 +209,10 @@ contract SpokeDynamicConfigTriggersTest is SpokeBase { function test_updateUserDynamicConfig_reverts_when_not_authorized(address caller) public { vm.assume( caller != alice && + caller != ADMIN && caller != POSITION_MANAGER && caller != SPOKE_ADMIN && - caller != USER_POSITION_UPDATER && - caller != _getProxyAdminAddress(address(spoke1)) + caller != ProxyHelper.getProxyAdmin(address(spoke1)) ); Utils.supplyCollateral(spoke1, _usdxReserveId(spoke1), alice, 1000e6, alice); @@ -249,7 +249,6 @@ contract SpokeDynamicConfigTriggersTest is SpokeBase { _updateUserDynamicConfig({caller: alice, existingConfigs: configs}); _updateUserDynamicConfig({caller: POSITION_MANAGER, existingConfigs: configs}); _updateUserDynamicConfig({caller: SPOKE_ADMIN, existingConfigs: configs}); - _updateUserDynamicConfig({caller: USER_POSITION_UPDATER, existingConfigs: configs}); } function test_updateUserDynamicConfig_updatesRP() public { diff --git a/tests/unit/Spoke/Spoke.DynamicConfig.t.sol b/tests/unit/Spoke/Spoke.DynamicConfig.t.sol index d15c6f280..dd05237e4 100644 --- a/tests/unit/Spoke/Spoke.DynamicConfig.t.sol +++ b/tests/unit/Spoke/Spoke.DynamicConfig.t.sol @@ -111,7 +111,9 @@ contract SpokeDynamicConfigTest is SpokeBase { address caller ) public { vm.assume( - caller != SPOKE_ADMIN && caller != ADMIN && caller != _getProxyAdminAddress(address(spoke1)) + caller != SPOKE_ADMIN && + caller != ADMIN && + caller != ProxyHelper.getProxyAdmin(address(spoke1)) ); uint256 reserveId = _randomReserveId(spoke1); uint24 dynamicConfigKey = _randomInitializedConfigKey(spoke1, reserveId); @@ -219,7 +221,9 @@ contract SpokeDynamicConfigTest is SpokeBase { address caller ) public { vm.assume( - caller != SPOKE_ADMIN && caller != ADMIN && caller != _getProxyAdminAddress(address(spoke1)) + caller != SPOKE_ADMIN && + caller != ADMIN && + caller != ProxyHelper.getProxyAdmin(address(spoke1)) ); uint256 reserveId = _randomReserveId(spoke1); uint24 dynamicConfigKey = _randomInitializedConfigKey(spoke1, reserveId); diff --git a/tests/unit/Spoke/Spoke.Getters.t.sol b/tests/unit/Spoke/Spoke.Getters.t.sol index 80d635e13..c10d0b0e5 100644 --- a/tests/unit/Spoke/Spoke.Getters.t.sol +++ b/tests/unit/Spoke/Spoke.Getters.t.sol @@ -16,8 +16,9 @@ contract SpokeGettersTest is SpokeBase { super.setUp(); // Deploy new spoke without setting the liquidation config - (spoke, ) = _deploySpokeWithOracle(ADMIN, address(accessManager), 'New Spoke (USD)'); - setUpRoles(hub1, spoke, accessManager); + OrchestrationReports.TestEnvReport memory report = _deployFixtures({numHubs: 0, numSpokes: 1}); + _setupFixturesRoles(report); + spoke = ISpoke(report.spokeReports[0].spokeAddress); IHub.SpokeConfig memory spokeConfig = IHub.SpokeConfig({ active: true, diff --git a/tests/unit/Spoke/Spoke.MultipleHub.Base.t.sol b/tests/unit/Spoke/Spoke.MultipleHub.Base.t.sol index 9c8ed245d..a11e9afed 100644 --- a/tests/unit/Spoke/Spoke.MultipleHub.Base.t.sol +++ b/tests/unit/Spoke/Spoke.MultipleHub.Base.t.sol @@ -30,10 +30,10 @@ contract SpokeMultipleHubBase is SpokeBase { bytes internal encodedIrData = abi.encode(irData); function setUp() public virtual override { - deployFixtures(); + _deployFixtures(); } - function deployFixtures() internal virtual override { + function _deployFixtures() internal virtual { vm.startPrank(ADMIN); accessManager = IAccessManager(address(new AccessManagerEnumerable(ADMIN))); // Canonical hub and spoke diff --git a/tests/unit/Spoke/Spoke.MultipleHub.t.sol b/tests/unit/Spoke/Spoke.MultipleHub.t.sol index 5ceb851e0..faf3e9aa3 100644 --- a/tests/unit/Spoke/Spoke.MultipleHub.t.sol +++ b/tests/unit/Spoke/Spoke.MultipleHub.t.sol @@ -23,8 +23,8 @@ contract SpokeMultipleHubTest is SpokeBase { super.setUp(); // Configure both hubs - (hub2, hub2IrStrategy) = hub2Fixture(); - (hub3, hub3IrStrategy) = hub3Fixture(); + (hub2, hub2IrStrategy) = _hub2Fixture(); + (hub3, hub3IrStrategy) = _hub3Fixture(); vm.startPrank(ADMIN); // Relist hub 2's dai on spoke1 diff --git a/tests/unit/Spoke/Spoke.Upgradeable.t.sol b/tests/unit/Spoke/Spoke.Upgradeable.t.sol index 65fc3c3c8..4145005a1 100644 --- a/tests/unit/Spoke/Spoke.Upgradeable.t.sol +++ b/tests/unit/Spoke/Spoke.Upgradeable.t.sol @@ -5,9 +5,6 @@ pragma solidity ^0.8.0; import 'tests/unit/Spoke/SpokeBase.t.sol'; contract SpokeUpgradeableTest is SpokeBase { - bytes32 internal constant INITIALIZABLE_STORAGE = - 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; - address internal proxyAdminOwner = makeAddr('proxyAdminOwner'); address internal oracle = makeAddr('AaveOracle'); @@ -25,7 +22,7 @@ contract SpokeUpgradeableTest is SpokeBase { assertEq(address(spokeImpl), spokeImplAddress); assertEq(spokeImpl.SPOKE_REVISION(), revision); - assertEq(_getProxyInitializedVersion(spokeImplAddress), type(uint64).max); + assertEq(ProxyHelper.getProxyInitializedVersion(spokeImplAddress), type(uint64).max); vm.expectRevert(Initializable.InvalidInitialization.selector); spokeImpl.initialize(address(accessManager)); @@ -69,10 +66,10 @@ contract SpokeUpgradeableTest is SpokeBase { ); assertEq(address(spokeProxy), spokeProxyAddress); - assertEq(_getProxyAdminAddress(address(spokeProxy)), proxyAdminAddress); - assertEq(_getImplementationAddress(address(spokeProxy)), address(spokeImpl)); + assertEq(ProxyHelper.getProxyAdmin(address(spokeProxy)), proxyAdminAddress); + assertEq(ProxyHelper.getImplementation(address(spokeProxy)), address(spokeImpl)); - assertEq(_getProxyInitializedVersion(address(spokeProxy)), revision); + assertEq(ProxyHelper.getProxyInitializedVersion(address(spokeProxy)), revision); assertEq(spokeProxy.getLiquidationConfig(), expectedLiquidationConfig); } @@ -89,7 +86,11 @@ contract SpokeUpgradeableTest is SpokeBase { ) ); - setUpRoles(hub1, ISpoke(address(spokeProxy)), accessManager); + OrchestrationReports.TestEnvReport memory report; + report.spokeReports = new OrchestrationReports.TestSpokeReport[](1); + report.spokeReports[0].spokeAddress = address(spokeProxy); + _setupFixturesRoles(report); + uint128 targetHealthFactor = 1.05e18; _updateTargetHealthFactor(ISpoke(address(spokeProxy)), targetHealthFactor); @@ -99,7 +100,7 @@ contract SpokeUpgradeableTest is SpokeBase { vm.expectEmit(address(spokeProxy)); emit IAccessManaged.AuthorityUpdated(address(accessManager)); vm.recordLogs(); - vm.prank(_getProxyAdminAddress(address(spokeProxy))); + vm.prank(ProxyHelper.getProxyAdmin(address(spokeProxy))); spokeProxy.upgradeToAndCall( address(spokeImpl2), _getInitializeCalldata(address(accessManager)) @@ -138,13 +139,13 @@ contract SpokeUpgradeableTest is SpokeBase { ); vm.expectRevert(Initializable.InvalidInitialization.selector); - vm.prank(_getProxyAdminAddress(address(spokeProxy))); + vm.prank(ProxyHelper.getProxyAdmin(address(spokeProxy))); spokeProxy.upgradeToAndCall(address(spokeImpl), _getInitializeCalldata(address(accessManager))); uint64 secondRevision = uint64(vm.randomUint(0, initialRevision - 1)); SpokeInstance spokeImpl2 = _deployMockSpokeInstance(secondRevision); vm.expectRevert(Initializable.InvalidInitialization.selector); - vm.prank(_getProxyAdminAddress(address(spokeProxy))); + vm.prank(ProxyHelper.getProxyAdmin(address(spokeProxy))); spokeProxy.upgradeToAndCall( address(spokeImpl2), _getInitializeCalldata(address(accessManager)) @@ -175,7 +176,7 @@ contract SpokeUpgradeableTest is SpokeBase { SpokeInstance spokeImpl2 = _deployMockSpokeInstance(2); vm.expectRevert(ISpoke.InvalidAddress.selector); - vm.prank(_getProxyAdminAddress(address(spokeProxy))); + vm.prank(ProxyHelper.getProxyAdmin(address(spokeProxy))); spokeProxy.upgradeToAndCall(address(spokeImpl2), _getInitializeCalldata(address(0))); } @@ -200,11 +201,6 @@ contract SpokeUpgradeableTest is SpokeBase { ); } - function _getProxyInitializedVersion(address proxy) internal view returns (uint64) { - bytes32 slotData = vm.load(proxy, INITIALIZABLE_STORAGE); - return uint64(uint256(slotData) & ((1 << 64) - 1)); - } - function _getInitializeCalldata(address manager) internal pure returns (bytes memory) { return abi.encodeCall(Spoke.initialize, manager); } diff --git a/tests/unit/Spoke/SpokeBase.t.sol b/tests/unit/Spoke/SpokeBase.t.sol index b3044ee8a..9b9b771ed 100644 --- a/tests/unit/Spoke/SpokeBase.t.sol +++ b/tests/unit/Spoke/SpokeBase.t.sol @@ -158,7 +158,7 @@ contract SpokeBase is Base { function setUp() public virtual override { super.setUp(); - initEnvironment(); + _initEnvironment(); } /// @dev Opens a supply position for a random user @@ -1104,15 +1104,15 @@ contract SpokeBase is Base { ) internal { address mockSpoke = address(new MockSpoke(spoke.ORACLE())); - address implementation = _getImplementationAddress(address(spoke)); + address implementation = ProxyHelper.getImplementation(address(spoke)); - vm.prank(_getProxyAdminAddress(address(spoke))); + vm.prank(ProxyHelper.getProxyAdmin(address(spoke))); ITransparentUpgradeableProxy(address(spoke)).upgradeToAndCall(address(mockSpoke), ''); vm.prank(user); MockSpoke(address(spoke)).borrowWithoutHfCheck(reserveId, debtAmount, user); - vm.prank(_getProxyAdminAddress(address(spoke))); + vm.prank(ProxyHelper.getProxyAdmin(address(spoke))); ITransparentUpgradeableProxy(address(spoke)).upgradeToAndCall(implementation, ''); } diff --git a/tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateUser.t.sol b/tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateUser.t.sol index ac2ee59a3..63699feb2 100644 --- a/tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateUser.t.sol +++ b/tests/unit/libraries/LiquidationLogic/LiquidationLogic.LiquidateUser.t.sol @@ -28,7 +28,7 @@ contract LiquidationLogicLiquidateUserTest is LiquidationLogicBaseTest { // collateral to liquidator = 6000 - 100 = 5900 function setUp() public override { super.setUp(); - (hub2, ) = hub2Fixture(); + (hub2, ) = _hub2Fixture(); _mockInterestRateBps(hub2.getAsset(wethAssetId).irStrategy, 5_00); diff --git a/tests/unit/misc/GatewayBase.t.sol b/tests/unit/misc/GatewayBase.t.sol index 8a39b0377..a09f26e53 100644 --- a/tests/unit/misc/GatewayBase.t.sol +++ b/tests/unit/misc/GatewayBase.t.sol @@ -9,7 +9,7 @@ contract GatewayBaseTest is Base { function setUp() public virtual override { super.setUp(); - initEnvironment(); + _initEnvironment(); gateway = new GatewayBaseWrapper(address(ADMIN)); diff --git a/tests/unit/misc/SignatureGateway/SignatureGateway.Base.t.sol b/tests/unit/misc/SignatureGateway/SignatureGateway.Base.t.sol index 7fad83c12..c573970f9 100644 --- a/tests/unit/misc/SignatureGateway/SignatureGateway.Base.t.sol +++ b/tests/unit/misc/SignatureGateway/SignatureGateway.Base.t.sol @@ -9,8 +9,8 @@ contract SignatureGatewayBaseTest is SpokeBase { uint256 public alicePk; function setUp() public virtual override { - deployFixtures(); - initEnvironment(); + _setupFixtures(); + _initEnvironment(); gateway = ISignatureGateway(new SignatureGateway(ADMIN)); (alice, alicePk) = makeAddrAndKey('alice'); diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 1631ffd9c..75f580ab2 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -33,12 +33,10 @@ import {IHub} from 'src/hub/interfaces/IHub.sol'; import {ITreasurySpoke} from 'src/spoke/interfaces/ITreasurySpoke.sol'; import {IAaveOracle} from 'src/spoke/interfaces/IAaveOracle.sol'; -contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { - bytes32 internal constant ERC1967_ADMIN_SLOT = - 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; - bytes32 internal constant IMPLEMENTATION_SLOT = - 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; +import {ProxyHelper} from 'tests/utils/ProxyHelper.sol'; +import {AaveV4TestOrchestration} from 'tests/deployments/orchestration/AaveV4TestOrchestration.sol'; +contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { bytes4[] public spokeAdminRoleSelectors; bytes4[] public spokeConfiguratorRoleSelectors; bytes4[] public hubAdminRoleSelectors; @@ -453,7 +451,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { address accessManagerAddress, string memory label ) internal view { - address proxyAdminOwner = Ownable(_getProxyAdminAddress(report.report.spokeProxyAddress)) + address proxyAdminOwner = Ownable(ProxyHelper.getProxyAdmin(report.report.spokeProxyAddress)) .owner(); if (inputs.admin != address(0)) { assertEq(proxyAdminOwner, inputs.admin, string.concat(label, ' proxy admin owner')); @@ -461,7 +459,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { assertEq(proxyAdminOwner, deployer, string.concat(label, ' proxy admin owner')); } assertEq( - _getImplementationAddress(report.report.spokeProxyAddress), + ProxyHelper.getImplementation(report.report.spokeProxyAddress), report.report.spokeImplementationAddress, string.concat(label, ' implementation') ); @@ -564,14 +562,4 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { assertEq(treasurySpokeOwner, deployer, string.concat(label, ' treasury spoke owner')); } } - - function _getProxyAdminAddress(address proxy) internal view returns (address) { - bytes32 slotData = vm.load(proxy, ERC1967_ADMIN_SLOT); - return address(uint160(uint256(slotData))); - } - - function _getImplementationAddress(address proxy) internal view returns (address) { - bytes32 slotData = vm.load(proxy, IMPLEMENTATION_SLOT); - return address(uint160(uint256(slotData))); - } } diff --git a/tests/utils/ProxyHelper.sol b/tests/utils/ProxyHelper.sol new file mode 100644 index 000000000..1cc5b5c17 --- /dev/null +++ b/tests/utils/ProxyHelper.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Vm} from 'forge-std/Vm.sol'; + +library ProxyHelper { + Vm internal constant vm = Vm(address(uint160(uint256(keccak256('hevm cheat code'))))); + + bytes32 internal constant ERC1967_ADMIN_SLOT = + 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + bytes32 internal constant IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + bytes32 internal constant INITIALIZABLE_STORAGE = + 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; + + function getProxyAdmin(address proxy) internal view returns (address) { + bytes32 slotData = vm.load(proxy, ERC1967_ADMIN_SLOT); + return address(uint160(uint256(slotData))); + } + + function getImplementation(address proxy) internal view returns (address) { + bytes32 slotData = vm.load(proxy, IMPLEMENTATION_SLOT); + return address(uint160(uint256(slotData))); + } + + function getProxyInitializedVersion(address proxy) internal view returns (uint64) { + bytes32 slotData = vm.load(proxy, INITIALIZABLE_STORAGE); + return uint64(uint256(slotData) & ((1 << 64) - 1)); + } +} diff --git a/tests/utils/TestTypes.sol b/tests/utils/TestTypes.sol new file mode 100644 index 000000000..024664195 --- /dev/null +++ b/tests/utils/TestTypes.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {WETH9} from 'src/dependencies/weth/WETH9.sol'; +import {TestnetERC20} from 'tests/mocks/TestnetERC20.sol'; + +library TestTypes { + struct TokenList { + WETH9 weth; + TestnetERC20 usdx; + TestnetERC20 dai; + TestnetERC20 wbtc; + TestnetERC20 usdy; + TestnetERC20 usdz; + } + + struct SpokeReserveId { + address spoke; + uint256 reserveId; + } +} From 6c5c0b5734736fdc1ad2f28a6fb3f7bb9452db67 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 12 Dec 2025 21:18:26 -0600 Subject: [PATCH 44/62] fix: rename roles for clarity --- .../AaveV4DeployOrchestration.sol | 16 ++++---- .../roles/AaveV4HubRolesProcedure.sol | 29 ++++++------- .../roles/AaveV4SpokeRolesProcedure.sol | 32 ++++++++------- src/libraries/types/Roles.sol | 8 ++-- tests/Base.t.sol | 14 +++++-- tests/unit/Hub/Hub.Access.t.sol | 24 +++++------ tests/unit/Spoke/Spoke.Access.t.sol | 14 +++++-- tests/unit/Spoke/Spoke.MultipleHub.Base.t.sol | 26 ++++++++---- tests/utils/BatchTestProcedures.sol | 41 +++++++++++-------- 9 files changed, 118 insertions(+), 86 deletions(-) diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index cd03f0f6c..2489141c2 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -107,10 +107,10 @@ library AaveV4DeployOrchestration { AaveV4HubRolesProcedure.grantHubAdminRole(report.accessBatchReport.accessManagerAddress, admin); logger.log('...Granting Hub Configurator roles...'); - AaveV4HubRolesProcedure.grantHubConfiguratorRole({ - accessManagerAddress: report.accessBatchReport.accessManagerAddress, - hubConfiguratorAddress: report.configuratorBatchReport.hubConfiguratorAddress - }); + AaveV4HubRolesProcedure.grantHubConfiguratorRole( + report.accessBatchReport.accessManagerAddress, + report.configuratorBatchReport.hubConfiguratorAddress + ); } function _grantSpokeRoles( @@ -125,10 +125,10 @@ library AaveV4DeployOrchestration { ); logger.log('...Granting Spoke Configurator roles...'); - AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole({ - accessManagerAddress: report.accessBatchReport.accessManagerAddress, - spokeConfiguratorAddress: report.configuratorBatchReport.spokeConfiguratorAddress - }); + AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole( + report.accessBatchReport.accessManagerAddress, + report.configuratorBatchReport.spokeConfiguratorAddress + ); } function _deployAccessBatch( diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol index 5559b6028..60ad01376 100644 --- a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -8,37 +8,38 @@ import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; import {IHub} from 'src/hub/interfaces/IHub.sol'; library AaveV4HubRolesProcedure { - function grantHubAdminRole(address accessManagerAddress, address hubAdminAddress) internal { + function grantHubAdminRole(address accessManagerAddress, address admin) internal { + grantHubFeeMinterRole(accessManagerAddress, admin); + grantHubConfiguratorRole(accessManagerAddress, admin); + } + + function grantHubFeeMinterRole(address accessManagerAddress, address admin) internal { IAccessManager(accessManagerAddress).grantRole({ - roleId: Roles.HUB_ADMIN_ROLE, - account: hubAdminAddress, + roleId: Roles.HUB_FEE_MINTER_ROLE, + account: admin, executionDelay: 0 }); - grantHubConfiguratorRole(accessManagerAddress, hubAdminAddress); } - function grantHubConfiguratorRole( - address accessManagerAddress, - address hubConfiguratorAddress - ) internal { + function grantHubConfiguratorRole(address accessManagerAddress, address admin) internal { IAccessManager(accessManagerAddress).grantRole({ roleId: Roles.HUB_CONFIGURATOR_ROLE, - account: hubConfiguratorAddress, + account: admin, executionDelay: 0 }); } function setHubRoles(address accessManagerAddress, address hubAddress) internal { - setHubAdminRole(accessManagerAddress, hubAddress); + setHubFeeMinterRole(accessManagerAddress, hubAddress); setHubConfiguratorRole(accessManagerAddress, hubAddress); } - function setHubAdminRole(address accessManagerAddress, address hubAddress) internal { - bytes4[] memory selectors = getHubAdminRoleSelectors(); + function setHubFeeMinterRole(address accessManagerAddress, address hubAddress) internal { + bytes4[] memory selectors = getHubFeeMinterRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( hubAddress, selectors, - Roles.HUB_ADMIN_ROLE + Roles.HUB_FEE_MINTER_ROLE ); } @@ -51,7 +52,7 @@ library AaveV4HubRolesProcedure { ); } - function getHubAdminRoleSelectors() internal pure returns (bytes4[] memory) { + function getHubFeeMinterRoleSelectors() internal pure returns (bytes4[] memory) { bytes4[] memory selectors = new bytes4[](1); selectors[0] = IHub.mintFeeShares.selector; return selectors; diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol index 95f978f69..e1f7535d6 100644 --- a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -7,37 +7,41 @@ import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; library AaveV4SpokeRolesProcedure { - function grantSpokeConfiguratorRole( - address accessManagerAddress, - address spokeConfiguratorAddress - ) internal { + function grantSpokeConfiguratorRole(address accessManagerAddress, address admin) internal { IAccessManager(accessManagerAddress).grantRole({ roleId: Roles.SPOKE_CONFIGURATOR_ROLE, - account: spokeConfiguratorAddress, + account: admin, executionDelay: 0 }); } - function grantSpokeAdminRole(address accessManagerAddress, address spokeAdminAddress) internal { + function grantSpokeAdminRole(address accessManagerAddress, address admin) internal { + grantSpokePositionUpdaterRole(accessManagerAddress, admin); + grantSpokeConfiguratorRole(accessManagerAddress, admin); + } + + function grantSpokePositionUpdaterRole(address accessManagerAddress, address admin) internal { IAccessManager(accessManagerAddress).grantRole({ - roleId: Roles.SPOKE_ADMIN_ROLE, - account: spokeAdminAddress, + roleId: Roles.SPOKE_POSITION_UPDATER_ROLE, + account: admin, executionDelay: 0 }); - grantSpokeConfiguratorRole(accessManagerAddress, spokeAdminAddress); } function setSpokeRoles(address accessManagerAddress, address spokeAddress) internal { - setSpokeAdminRole(accessManagerAddress, spokeAddress); + setSpokePositionUpdaterRole(accessManagerAddress, spokeAddress); setSpokeConfiguratorRole(accessManagerAddress, spokeAddress); } - function setSpokeAdminRole(address accessManagerAddress, address spokeAddress) internal { - bytes4[] memory selectors = getSpokeAdminRoleSelectors(); + function setSpokePositionUpdaterRole( + address accessManagerAddress, + address spokeAddress + ) internal { + bytes4[] memory selectors = getSpokePositionUpdaterRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( spokeAddress, selectors, - Roles.SPOKE_ADMIN_ROLE + Roles.SPOKE_POSITION_UPDATER_ROLE ); } @@ -50,7 +54,7 @@ library AaveV4SpokeRolesProcedure { ); } - function getSpokeAdminRoleSelectors() internal pure returns (bytes4[] memory) { + function getSpokePositionUpdaterRoleSelectors() internal pure returns (bytes4[] memory) { bytes4[] memory selectors = new bytes4[](2); selectors[0] = ISpoke.updateUserDynamicConfig.selector; selectors[1] = ISpoke.updateUserRiskPremium.selector; diff --git a/src/libraries/types/Roles.sol b/src/libraries/types/Roles.sol index 8063d49a1..fec1b9eb8 100644 --- a/src/libraries/types/Roles.sol +++ b/src/libraries/types/Roles.sol @@ -7,8 +7,8 @@ pragma solidity ^0.8.20; /// @notice Defines the different roles used by the protocol. library Roles { uint64 public constant DEFAULT_ADMIN_ROLE = 0; - uint64 public constant HUB_ADMIN_ROLE = 1; - uint64 public constant HUB_CONFIGURATOR_ROLE = 2; - uint64 public constant SPOKE_ADMIN_ROLE = 3; - uint64 public constant SPOKE_CONFIGURATOR_ROLE = 4; + uint64 public constant HUB_CONFIGURATOR_ROLE = 1; + uint64 public constant HUB_FEE_MINTER_ROLE = 2; + uint64 public constant SPOKE_CONFIGURATOR_ROLE = 3; + uint64 public constant SPOKE_POSITION_UPDATER_ROLE = 4; } diff --git a/tests/Base.t.sol b/tests/Base.t.sol index a4bc205c6..1a098471c 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -343,17 +343,23 @@ abstract contract Base is BatchTestProcedures { function _setupFixturesRoles(OrchestrationReports.TestEnvReport memory report) internal virtual { if (report.accessManagerAddress == address(0)) report.accessManagerAddress = address(accessManager); - IAccessManager accessManager = IAccessManager(report.accessManagerAddress); // temporary grant admin role to address(this) to execute setAndGrantRolesTestEnv from its context vm.startPrank(ADMIN); - accessManager.grantRole(Roles.DEFAULT_ADMIN_ROLE, address(this), 0); + IAccessManager(report.accessManagerAddress).grantRole( + Roles.DEFAULT_ADMIN_ROLE, + address(this), + 0 + ); vm.stopPrank(); AaveV4TestOrchestration.setRolesTestEnv(report); AaveV4TestOrchestration.grantRolesTestEnv(report, ADMIN, HUB_ADMIN, SPOKE_ADMIN); - accessManager.renounceRole(Roles.DEFAULT_ADMIN_ROLE, address(this)); + IAccessManager(report.accessManagerAddress).renounceRole( + Roles.DEFAULT_ADMIN_ROLE, + address(this) + ); } function _initEnvironment() internal { @@ -1060,7 +1066,7 @@ abstract contract Base is BatchTestProcedures { function _grantHubAdminRole(IHub hub, address admin) internal { vm.startPrank(ADMIN); // hub admin consists of hub admin role and hub configurator role - IAccessManager(hub.authority()).grantRole(Roles.HUB_ADMIN_ROLE, admin, 0); + IAccessManager(hub.authority()).grantRole(Roles.HUB_FEE_MINTER_ROLE, admin, 0); IAccessManager(hub.authority()).grantRole(Roles.HUB_CONFIGURATOR_ROLE, admin, 0); vm.stopPrank(); } diff --git a/tests/unit/Hub/Hub.Access.t.sol b/tests/unit/Hub/Hub.Access.t.sol index e6756a84f..d83252eaf 100644 --- a/tests/unit/Hub/Hub.Access.t.sol +++ b/tests/unit/Hub/Hub.Access.t.sol @@ -209,9 +209,9 @@ contract HubAccessTest is HubBase { // Alice, Bob, and Carol currently have both HUB_ADMIN and SET_INTEREST_RATE roles. IAccessManager accessManager = IAccessManager(hub1.authority()); - assertTrue(_hasRole(accessManager, Roles.HUB_ADMIN_ROLE, alice)); - assertTrue(_hasRole(accessManager, Roles.HUB_ADMIN_ROLE, bob)); - assertTrue(_hasRole(accessManager, Roles.HUB_ADMIN_ROLE, carol)); + assertTrue(_hasRole(accessManager, Roles.HUB_FEE_MINTER_ROLE, alice)); + assertTrue(_hasRole(accessManager, Roles.HUB_FEE_MINTER_ROLE, bob)); + assertTrue(_hasRole(accessManager, Roles.HUB_FEE_MINTER_ROLE, carol)); assertTrue(_hasRole(accessManager, SET_INTEREST_RATE_ROLE, alice)); assertTrue(_hasRole(accessManager, SET_INTEREST_RATE_ROLE, bob)); @@ -219,15 +219,15 @@ contract HubAccessTest is HubBase { // We can remove HUB_ADMIN role from Alice, Bob, and Carol. vm.startPrank(ADMIN); - accessManager.revokeRole(Roles.HUB_ADMIN_ROLE, alice); - accessManager.revokeRole(Roles.HUB_ADMIN_ROLE, bob); - accessManager.revokeRole(Roles.HUB_ADMIN_ROLE, carol); + accessManager.revokeRole(Roles.HUB_FEE_MINTER_ROLE, alice); + accessManager.revokeRole(Roles.HUB_FEE_MINTER_ROLE, bob); + accessManager.revokeRole(Roles.HUB_FEE_MINTER_ROLE, carol); vm.stopPrank(); // Alice, Bob, and Carol should no longer have HUB_ADMIN role. - assertFalse(_hasRole(accessManager, Roles.HUB_ADMIN_ROLE, alice)); - assertFalse(_hasRole(accessManager, Roles.HUB_ADMIN_ROLE, bob)); - assertFalse(_hasRole(accessManager, Roles.HUB_ADMIN_ROLE, carol)); + assertFalse(_hasRole(accessManager, Roles.HUB_FEE_MINTER_ROLE, alice)); + assertFalse(_hasRole(accessManager, Roles.HUB_FEE_MINTER_ROLE, bob)); + assertFalse(_hasRole(accessManager, Roles.HUB_FEE_MINTER_ROLE, carol)); // Can still call setInterestRateData since they have SET_INTEREST_RATE role. vm.prank(alice); @@ -265,10 +265,10 @@ contract HubAccessTest is HubBase { // Set up the role for hub admin to call update asset config vm.startPrank(NEW_ADMIN); - newAuthority.grantRole(Roles.HUB_ADMIN_ROLE, HUB_ADMIN, 0); + newAuthority.grantRole(Roles.HUB_FEE_MINTER_ROLE, HUB_ADMIN, 0); bytes4[] memory selectors = new bytes4[](1); selectors[0] = IHub.updateAssetConfig.selector; - newAuthority.setTargetFunctionRole(address(hub1), selectors, Roles.HUB_ADMIN_ROLE); + newAuthority.setTargetFunctionRole(address(hub1), selectors, Roles.HUB_FEE_MINTER_ROLE); vm.stopPrank(); // Only Admin can change the authority contract @@ -301,7 +301,7 @@ contract HubAccessTest is HubBase { // Now we also give the hub admin role capability to update spoke config on new authority selectors[0] = IHub.updateSpokeConfig.selector; vm.prank(NEW_ADMIN); - newAuthority.setTargetFunctionRole(address(hub1), selectors, Roles.HUB_ADMIN_ROLE); + newAuthority.setTargetFunctionRole(address(hub1), selectors, Roles.HUB_FEE_MINTER_ROLE); // Hub admin can now call update spoke config on the hub after authority change vm.prank(HUB_ADMIN); diff --git a/tests/unit/Spoke/Spoke.Access.t.sol b/tests/unit/Spoke/Spoke.Access.t.sol index 675ebebea..b7353f9d2 100644 --- a/tests/unit/Spoke/Spoke.Access.t.sol +++ b/tests/unit/Spoke/Spoke.Access.t.sol @@ -154,10 +154,14 @@ contract SpokeAccessTest is SpokeBase { // Set up the role for spoke admin to call update liquidation config vm.startPrank(NEW_ADMIN); - newAuthority.grantRole(Roles.SPOKE_ADMIN_ROLE, SPOKE_ADMIN, 0); + newAuthority.grantRole(Roles.SPOKE_POSITION_UPDATER_ROLE, SPOKE_ADMIN, 0); bytes4[] memory selectors = new bytes4[](1); selectors[0] = ISpoke.updateLiquidationConfig.selector; - newAuthority.setTargetFunctionRole(address(spoke1), selectors, Roles.SPOKE_ADMIN_ROLE); + newAuthority.setTargetFunctionRole( + address(spoke1), + selectors, + Roles.SPOKE_POSITION_UPDATER_ROLE + ); vm.stopPrank(); // Only Admin can change the authority contract @@ -207,7 +211,11 @@ contract SpokeAccessTest is SpokeBase { // Now we also give the spoke admin role capability to add reserve on new authority selectors[0] = ISpoke.addReserve.selector; vm.prank(NEW_ADMIN); - newAuthority.setTargetFunctionRole(address(spoke1), selectors, Roles.SPOKE_ADMIN_ROLE); + newAuthority.setTargetFunctionRole( + address(spoke1), + selectors, + Roles.SPOKE_POSITION_UPDATER_ROLE + ); // Spoke admin can now call add reserve on the spoke after authority change vm.prank(SPOKE_ADMIN); diff --git a/tests/unit/Spoke/Spoke.MultipleHub.Base.t.sol b/tests/unit/Spoke/Spoke.MultipleHub.Base.t.sol index a11e9afed..012cd160b 100644 --- a/tests/unit/Spoke/Spoke.MultipleHub.Base.t.sol +++ b/tests/unit/Spoke/Spoke.MultipleHub.Base.t.sol @@ -60,11 +60,11 @@ contract SpokeMultipleHubBase is SpokeBase { function setUpRoles() internal { vm.startPrank(ADMIN); // Grant roles with 0 delay - accessManager.grantRole(Roles.HUB_ADMIN_ROLE, ADMIN, 0); - accessManager.grantRole(Roles.SPOKE_ADMIN_ROLE, ADMIN, 0); - accessManager.grantRole(Roles.HUB_ADMIN_ROLE, HUB_ADMIN, 0); - accessManager.grantRole(Roles.SPOKE_ADMIN_ROLE, HUB_ADMIN, 0); - accessManager.grantRole(Roles.SPOKE_ADMIN_ROLE, SPOKE_ADMIN, 0); + accessManager.grantRole(Roles.HUB_FEE_MINTER_ROLE, ADMIN, 0); + accessManager.grantRole(Roles.SPOKE_POSITION_UPDATER_ROLE, ADMIN, 0); + accessManager.grantRole(Roles.HUB_FEE_MINTER_ROLE, HUB_ADMIN, 0); + accessManager.grantRole(Roles.SPOKE_POSITION_UPDATER_ROLE, HUB_ADMIN, 0); + accessManager.grantRole(Roles.SPOKE_POSITION_UPDATER_ROLE, SPOKE_ADMIN, 0); // Grant responsibilities to roles // Spoke Admin functionalities @@ -76,8 +76,16 @@ contract SpokeMultipleHubBase is SpokeBase { selectors[4] = ISpoke.addDynamicReserveConfig.selector; selectors[5] = ISpoke.updateUserRiskPremium.selector; - accessManager.setTargetFunctionRole(address(spoke1), selectors, Roles.SPOKE_ADMIN_ROLE); - accessManager.setTargetFunctionRole(address(newSpoke), selectors, Roles.SPOKE_ADMIN_ROLE); + accessManager.setTargetFunctionRole( + address(spoke1), + selectors, + Roles.SPOKE_POSITION_UPDATER_ROLE + ); + accessManager.setTargetFunctionRole( + address(newSpoke), + selectors, + Roles.SPOKE_POSITION_UPDATER_ROLE + ); // Hub Admin functionalities bytes4[] memory hubSelectors = new bytes4[](4); @@ -86,8 +94,8 @@ contract SpokeMultipleHubBase is SpokeBase { hubSelectors[2] = IHub.addSpoke.selector; hubSelectors[3] = IHub.updateSpokeConfig.selector; - accessManager.setTargetFunctionRole(address(hub1), hubSelectors, Roles.HUB_ADMIN_ROLE); - accessManager.setTargetFunctionRole(address(newHub), hubSelectors, Roles.HUB_ADMIN_ROLE); + accessManager.setTargetFunctionRole(address(hub1), hubSelectors, Roles.HUB_FEE_MINTER_ROLE); + accessManager.setTargetFunctionRole(address(newHub), hubSelectors, Roles.HUB_FEE_MINTER_ROLE); vm.stopPrank(); } } diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 75f580ab2..e642abd5c 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -37,17 +37,18 @@ import {ProxyHelper} from 'tests/utils/ProxyHelper.sol'; import {AaveV4TestOrchestration} from 'tests/deployments/orchestration/AaveV4TestOrchestration.sol'; contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { - bytes4[] public spokeAdminRoleSelectors; + bytes4[] public spokePositionUpdaterRoleSelectors; bytes4[] public spokeConfiguratorRoleSelectors; - bytes4[] public hubAdminRoleSelectors; + bytes4[] public hubFeeMinterRoleSelectors; bytes4[] public hubConfiguratorRoleSelectors; address public deployer; function setUp() public virtual { - spokeAdminRoleSelectors = AaveV4SpokeRolesProcedure.getSpokeAdminRoleSelectors(); + spokePositionUpdaterRoleSelectors = AaveV4SpokeRolesProcedure + .getSpokePositionUpdaterRoleSelectors(); spokeConfiguratorRoleSelectors = AaveV4SpokeRolesProcedure.getSpokeConfiguratorRoleSelectors(); - hubAdminRoleSelectors = AaveV4HubRolesProcedure.getHubAdminRoleSelectors(); + hubFeeMinterRoleSelectors = AaveV4HubRolesProcedure.getHubFeeMinterRoleSelectors(); hubConfiguratorRoleSelectors = AaveV4HubRolesProcedure.getHubConfiguratorRoleSelectors(); } @@ -272,25 +273,29 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ) internal view { if (inputs.spokeLabels.length > 0 && inputs.grantRoles) { assertEq( - accessManager.getRoleMemberCount(Roles.SPOKE_ADMIN_ROLE), + accessManager.getRoleMemberCount(Roles.SPOKE_POSITION_UPDATER_ROLE), 1, 'SpokeAdminRole member count' ); assertEq( - accessManager.getRoleMember(Roles.SPOKE_ADMIN_ROLE, 0), + accessManager.getRoleMember(Roles.SPOKE_POSITION_UPDATER_ROLE, 0), contractAdmin, 'SpokeAdminRole member - spoke admin' ); } else { - assertEq(accessManager.getRoleMemberCount(Roles.SPOKE_ADMIN_ROLE), 0, 'HubAdminRoleCount'); + assertEq( + accessManager.getRoleMemberCount(Roles.SPOKE_POSITION_UPDATER_ROLE), + 0, + 'HubAdminRoleCount' + ); } for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { - for (uint256 j = 0; j < spokeAdminRoleSelectors.length; j++) { + for (uint256 j = 0; j < spokePositionUpdaterRoleSelectors.length; j++) { (bool allowed, uint32 delay) = accessManager.canCall( contractAdmin, report.spokeInstanceBatchReports[i].report.spokeProxyAddress, - spokeAdminRoleSelectors[j] + spokePositionUpdaterRoleSelectors[j] ); assertEq(allowed, inputs.grantRoles ? true : false, 'SpokeAdminRole allowed'); assertEq(delay, 0, 'SpokeAdminRole delay'); @@ -298,9 +303,9 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { assertEq( accessManager.getTargetFunctionRole( report.spokeInstanceBatchReports[i].report.spokeProxyAddress, - spokeAdminRoleSelectors[j] + spokePositionUpdaterRoleSelectors[j] ), - Roles.SPOKE_ADMIN_ROLE, + Roles.SPOKE_POSITION_UPDATER_ROLE, 'SpokeAdminRole target function' ); } @@ -324,30 +329,30 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { address contractAdmin ) internal view { if (inputs.hubLabels.length > 0 && inputs.grantRoles) { - assertEq(accessManager.getRoleMemberCount(Roles.HUB_ADMIN_ROLE), 1, 'HubAdminRoleCount'); + assertEq(accessManager.getRoleMemberCount(Roles.HUB_FEE_MINTER_ROLE), 1, 'HubAdminRoleCount'); assertEq( - accessManager.getRoleMember(Roles.HUB_ADMIN_ROLE, 0), + accessManager.getRoleMember(Roles.HUB_FEE_MINTER_ROLE, 0), contractAdmin, 'HubAdminRole member - hub admin' ); } else { - assertEq(accessManager.getRoleMemberCount(Roles.HUB_ADMIN_ROLE), 0, 'HubAdminRoleCount'); + assertEq(accessManager.getRoleMemberCount(Roles.HUB_FEE_MINTER_ROLE), 0, 'HubAdminRoleCount'); } for (uint256 i = 0; i < inputs.hubLabels.length; i++) { - for (uint256 j = 0; j < hubAdminRoleSelectors.length; j++) { + for (uint256 j = 0; j < hubFeeMinterRoleSelectors.length; j++) { assertEq( accessManager.getTargetFunctionRole( report.hubBatchReports[i].report.hubAddress, - hubAdminRoleSelectors[j] + hubFeeMinterRoleSelectors[j] ), - Roles.HUB_ADMIN_ROLE, + Roles.HUB_FEE_MINTER_ROLE, 'HubAdminRole target function' ); (bool allowed, uint32 delay) = accessManager.canCall( contractAdmin, report.hubBatchReports[i].report.hubAddress, - hubAdminRoleSelectors[j] + hubFeeMinterRoleSelectors[j] ); assertEq(allowed, inputs.grantRoles ? true : false, 'HubAdminRole allowed'); assertEq(delay, 0, 'HubAdminRole delay'); From 70e45012dbaa388777833b00901147ad840c3a7e Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 12 Dec 2025 22:07:41 -0600 Subject: [PATCH 45/62] fix: specify admin inputs --- scripts/deploy/AaveV4DeployBatchBase.s.sol | 10 +- scripts/deploy/inputs/AaveV4DeployInput.json | 10 +- .../batches/AaveV4ConfiguratorBatch.sol | 14 +- .../batches/AaveV4GatewayBatch.sol | 9 +- src/deployments/batches/AaveV4HubBatch.sol | 16 +- .../batches/AaveV4SpokeInstanceBatch.sol | 4 +- .../orchestration/AaveV4DeployCore.sol | 27 +- .../AaveV4DeployOrchestration.sol | 197 ++++---- src/deployments/utils/InputUtils.sol | 28 +- tests/deployments/AaveV4BatchDeployment.t.sol | 84 +++- tests/utils/BatchTestProcedures.sol | 419 ++++++++++-------- 11 files changed, 512 insertions(+), 306 deletions(-) diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index d7edf5a96..2253d38a2 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -28,15 +28,7 @@ abstract contract AaveV4DeployBatchBaseScript is Script, DeployUtils, InputUtils address deployer = msg.sender; vm.startBroadcast(deployer); OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration - .deployAaveV4({ - logger: logger, - deployer: deployer, - admin: inputs.admin, - nativeWrapper: inputs.nativeWrapperAddress, - hubLabels: inputs.hubLabels, - spokeLabels: inputs.spokeLabels, - grantRoles: inputs.grantRoles - }); + .deployAaveV4({logger: logger, deployer: deployer, deployInputs: inputs}); vm.stopBroadcast(); logger.writeJsonReportMarket(report); logger.log('...Batch Deployment Completed...'); diff --git a/scripts/deploy/inputs/AaveV4DeployInput.json b/scripts/deploy/inputs/AaveV4DeployInput.json index e6fdb158f..d14a47011 100644 --- a/scripts/deploy/inputs/AaveV4DeployInput.json +++ b/scripts/deploy/inputs/AaveV4DeployInput.json @@ -1,6 +1,12 @@ { - "admin": "0x0000000000000000000000000000000000000001", - "nativeWrapperAddress": "0x0000000000000000000000000000000000000002", + "accessManagerAdmin": "0x0000000000000000000000000000000000000001", + "hubConfiguratorOwner": "0x0000000000000000000000000000000000000002", + "hubAdmin": "0x0000000000000000000000000000000000000003", + "treasurySpokeOwner": "0x0000000000000000000000000000000000000003", + "spokeConfiguratorOwner": "0x0000000000000000000000000000000000000004", + "spokeAdmin": "0x0000000000000000000000000000000000000005", + "spokeProxyAdminOwner": "0x0000000000000000000000000000000000000005", + "nativeWrapperAddress": "0x0000000000000000000000000000000000000006", "grantRoles": true, "hubLabels": ["Hub 1", "Hub 2", "Hub 3"], "spokeLabels": ["Spoke 1", "Spoke 2", "Spoke 3"] diff --git a/src/deployments/batches/AaveV4ConfiguratorBatch.sol b/src/deployments/batches/AaveV4ConfiguratorBatch.sol index 46c31e21b..1af16be99 100644 --- a/src/deployments/batches/AaveV4ConfiguratorBatch.sol +++ b/src/deployments/batches/AaveV4ConfiguratorBatch.sol @@ -3,8 +3,12 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; -import {AaveV4HubConfiguratorDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol'; -import {AaveV4SpokeConfiguratorDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol'; +import { + AaveV4HubConfiguratorDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol'; +import { + AaveV4SpokeConfiguratorDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol'; contract AaveV4ConfiguratorBatch is AaveV4HubConfiguratorDeployProcedure, @@ -12,9 +16,9 @@ contract AaveV4ConfiguratorBatch is { BatchReports.ConfiguratorBatchReport internal _report; - constructor(address admin_) { - address hubConfiguratorAddress = _deployHubConfigurator(admin_); - address spokeConfiguratorAddress = _deploySpokeConfigurator(admin_); + constructor(address hubConfiguratorOwner_, address spokeConfiguratorOwner_) { + address hubConfiguratorAddress = _deployHubConfigurator(hubConfiguratorOwner_); + address spokeConfiguratorAddress = _deploySpokeConfigurator(spokeConfiguratorOwner_); _report = BatchReports.ConfiguratorBatchReport({ hubConfiguratorAddress: hubConfiguratorAddress, diff --git a/src/deployments/batches/AaveV4GatewayBatch.sol b/src/deployments/batches/AaveV4GatewayBatch.sol index 1683711f4..d0d1d1cc9 100644 --- a/src/deployments/batches/AaveV4GatewayBatch.sol +++ b/src/deployments/batches/AaveV4GatewayBatch.sol @@ -16,12 +16,15 @@ contract AaveV4GatewayBatch is { BatchReports.GatewaysBatchReport internal _report; - constructor(address admin_, address nativeWrapper_) { + constructor(address owner_, address nativeWrapper_) { address nativeGatewayAddress; if (nativeWrapper_ != address(0)) { - nativeGatewayAddress = _deployNativeTokenGateway(nativeWrapper_, admin_); + nativeGatewayAddress = _deployNativeTokenGateway({ + nativeWrapper_: nativeWrapper_, + owner_: owner_ + }); } - address signatureGatewayAddress = _deploySignatureGateway(admin_); + address signatureGatewayAddress = _deploySignatureGateway(owner_); _report = BatchReports.GatewaysBatchReport({ nativeGatewayAddress: nativeGatewayAddress, diff --git a/src/deployments/batches/AaveV4HubBatch.sol b/src/deployments/batches/AaveV4HubBatch.sol index 3893d62b5..7af160274 100644 --- a/src/deployments/batches/AaveV4HubBatch.sol +++ b/src/deployments/batches/AaveV4HubBatch.sol @@ -3,9 +3,15 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; -import {AaveV4HubDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol'; -import {AaveV4InterestRateStrategyDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol'; -import {AaveV4TreasurySpokeDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol'; +import { + AaveV4HubDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol'; +import { + AaveV4InterestRateStrategyDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol'; +import { + AaveV4TreasurySpokeDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol'; contract AaveV4HubBatch is AaveV4HubDeployProcedure, @@ -14,10 +20,10 @@ contract AaveV4HubBatch is { BatchReports.HubBatchReport internal _report; - constructor(address admin_, address accessManagerAddress_) { + constructor(address treasurySpokeOwner_, address accessManagerAddress_) { address hubAddress = _deployHub(accessManagerAddress_); address irStrategyAddress = _deployInterestRateStrategy(hubAddress); - address treasurySpokeAddress = _deployTreasurySpoke(admin_, hubAddress); + address treasurySpokeAddress = _deployTreasurySpoke(treasurySpokeOwner_, hubAddress); _report = BatchReports.HubBatchReport({ hubAddress: hubAddress, diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 8b1933ac4..46ee15775 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -22,7 +22,7 @@ contract AaveV4SpokeInstanceBatch is BatchReports.SpokeInstanceBatchReport internal _report; constructor( - address admin_, + address spokeProxyAdminOwner_, address accessManagerAddress_, uint8 oracleDecimals_, string memory oracleDescription_ @@ -38,7 +38,7 @@ contract AaveV4SpokeInstanceBatch is address spokeImplementationAddress = _deploySpokeInstance(aaveOracleAddress); address spokeProxyAddress = _proxify( spokeImplementationAddress, - admin_, + spokeProxyAdminOwner_, abi.encodeWithSignature('initialize(address)', accessManagerAddress_) ); diff --git a/src/deployments/orchestration/AaveV4DeployCore.sol b/src/deployments/orchestration/AaveV4DeployCore.sol index f0d32ff7e..4e6ac8bb9 100644 --- a/src/deployments/orchestration/AaveV4DeployCore.sol +++ b/src/deployments/orchestration/AaveV4DeployCore.sol @@ -13,36 +13,40 @@ import {AaveV4GatewayBatch} from 'src/deployments/batches/AaveV4GatewayBatch.sol library AaveV4DeployCore { function deployAccessBatch( - address accessManagerAdmin + address admin ) internal returns (BatchReports.AccessBatchReport memory) { - AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(accessManagerAdmin); + AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin); return accessBatch.getReport(); } function deployConfiguratorBatch( - address admin + address hubConfiguratorOwner, + address spokeConfiguratorOwner ) internal returns (BatchReports.ConfiguratorBatchReport memory) { - AaveV4ConfiguratorBatch configuratorBatch = new AaveV4ConfiguratorBatch(admin); + AaveV4ConfiguratorBatch configuratorBatch = new AaveV4ConfiguratorBatch( + hubConfiguratorOwner, + spokeConfiguratorOwner + ); return configuratorBatch.getReport(); } function deployHubBatch( - address admin, + address treasurySpokeOwner, address accessManagerAddress ) internal returns (BatchReports.HubBatchReport memory) { - AaveV4HubBatch hubBatch = new AaveV4HubBatch(admin, accessManagerAddress); + AaveV4HubBatch hubBatch = new AaveV4HubBatch(treasurySpokeOwner, accessManagerAddress); return hubBatch.getReport(); } function deploySpokeInstanceBatch( - address admin, + address spokeProxyAdminOwner, address accessManagerAddress, uint8 oracleDecimals, string memory oracleSuffix, string memory label ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch( - admin, + spokeProxyAdminOwner, accessManagerAddress, oracleDecimals, string.concat(label, oracleSuffix) @@ -51,10 +55,13 @@ library AaveV4DeployCore { } function deployGatewaysBatch( - address admin, + address owner, address nativeWrapper ) internal returns (BatchReports.GatewaysBatchReport memory) { - AaveV4GatewayBatch gatewayBatch = new AaveV4GatewayBatch(admin, nativeWrapper); + AaveV4GatewayBatch gatewayBatch = new AaveV4GatewayBatch({ + owner_: owner, + nativeWrapper_: nativeWrapper + }); return gatewayBatch.getReport(); } } diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 2489141c2..2f9aaa85f 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -23,68 +23,89 @@ import { import { AaveV4SpokeRolesProcedure } from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; +import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; library AaveV4DeployOrchestration { - // Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); - uint8 private constant ORACLE_DECIMALS = 8; string private constant ORACLE_SUFFIX = ' (USD)'; function deployAaveV4( Logger logger, address deployer, - address admin, - address nativeWrapper, - string[] memory hubLabels, - string[] memory spokeLabels, - bool grantRoles + InputUtils.FullDeployInputs memory deployInputs ) internal returns (OrchestrationReports.FullDeploymentReport memory report) { // Deploy Access Batch - address accessManagerAdmin = deployer; - report.accessBatchReport = _deployAccessBatch(logger, accessManagerAdmin); - - // if admin is zero address, use deployer as contract admin - // spoke proxyAdmin owner; hubAdmin; spokeAdmin - address contractAdmin = admin != address(0) ? admin : deployer; + // initially with provided access manager admin (fallback to deployer if zero) + address initialAdmin = deployer; + report.accessBatchReport = _deployAccessBatch({ + logger: logger, + accessManagerAdmin: initialAdmin + }); + + // if any admin is zero address, default to deployer as admin + InputUtils.FullDeployInputs memory inputs = deployInputs; + inputs.accessManagerAdmin = deployInputs.accessManagerAdmin != address(0) + ? deployInputs.accessManagerAdmin + : deployer; + inputs.hubConfiguratorOwner = deployInputs.hubConfiguratorOwner != address(0) + ? deployInputs.hubConfiguratorOwner + : deployer; + inputs.treasurySpokeOwner = deployInputs.treasurySpokeOwner != address(0) + ? deployInputs.treasurySpokeOwner + : deployer; + inputs.spokeProxyAdminOwner = deployInputs.spokeProxyAdminOwner != address(0) + ? deployInputs.spokeProxyAdminOwner + : deployer; + inputs.spokeConfiguratorOwner = deployInputs.spokeConfiguratorOwner != address(0) + ? deployInputs.spokeConfiguratorOwner + : deployer; // Deploy Configurator Batch - report.configuratorBatchReport = _deployConfiguratorBatch(logger, contractAdmin); + report.configuratorBatchReport = _deployConfiguratorBatch({ + logger: logger, + hubConfiguratorOwner: inputs.hubConfiguratorOwner, + spokeConfiguratorOwner: inputs.spokeConfiguratorOwner + }); // Deploy Hub Batches - report.hubBatchReports = _deployHubs( - logger, - contractAdmin, - report.accessBatchReport.accessManagerAddress, - hubLabels - ); + report.hubBatchReports = _deployHubs({ + logger: logger, + treasurySpokeOwner: inputs.treasurySpokeOwner, + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + hubLabels: inputs.hubLabels + }); // Deploy Spoke Instance Batches - report.spokeInstanceBatchReports = _deploySpokes( - logger, - contractAdmin, - report.accessBatchReport.accessManagerAddress, - spokeLabels - ); + report.spokeInstanceBatchReports = _deploySpokes({ + logger: logger, + spokeProxyAdminOwner: inputs.spokeProxyAdminOwner, + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + spokeLabels: inputs.spokeLabels + }); // Deploy Gateways Batch - report.gatewaysBatchReport = _deployGatewayBatch(logger, contractAdmin, nativeWrapper); + report.gatewaysBatchReport = _deployGatewayBatch({ + logger: logger, + owner: inputs.spokeProxyAdminOwner, + nativeWrapper: inputs.nativeWrapperAddress + }); // Set Roles if needed - if (grantRoles) { - if (hubLabels.length > 0) { - _grantHubRoles(logger, report, contractAdmin); + if (inputs.grantRoles) { + if (inputs.hubLabels.length > 0) { + _grantHubRoles({logger: logger, report: report, hubAdmin: inputs.hubAdmin}); } - if (spokeLabels.length > 0) { - _grantSpokeRoles(logger, report, contractAdmin); + if (inputs.spokeLabels.length > 0) { + _grantSpokeRoles({logger: logger, report: report, spokeAdmin: inputs.spokeAdmin}); } - if (contractAdmin != deployer) { + if (inputs.accessManagerAdmin != initialAdmin) { logger.log('...Granting AccessManager Root Admin role...'); - AaveV4AccessManagerRolesProcedure.grantRootAdminRole( - report.accessBatchReport.accessManagerAddress, - contractAdmin, - deployer - ); + AaveV4AccessManagerRolesProcedure.grantRootAdminRole({ + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + newAdminAddress: inputs.accessManagerAdmin, + currentAdminAddress: initialAdmin + }); } } @@ -101,43 +122,46 @@ library AaveV4DeployOrchestration { function _grantHubRoles( Logger logger, OrchestrationReports.FullDeploymentReport memory report, - address admin + address hubAdmin ) internal { logger.log('...Granting Hub Admin role...'); - AaveV4HubRolesProcedure.grantHubAdminRole(report.accessBatchReport.accessManagerAddress, admin); + AaveV4HubRolesProcedure.grantHubAdminRole({ + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + admin: hubAdmin + }); logger.log('...Granting Hub Configurator roles...'); - AaveV4HubRolesProcedure.grantHubConfiguratorRole( - report.accessBatchReport.accessManagerAddress, - report.configuratorBatchReport.hubConfiguratorAddress - ); + AaveV4HubRolesProcedure.grantHubConfiguratorRole({ + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + admin: report.configuratorBatchReport.hubConfiguratorAddress + }); } function _grantSpokeRoles( Logger logger, OrchestrationReports.FullDeploymentReport memory report, - address admin + address spokeAdmin ) internal { logger.log('...Granting Spoke Admin role...'); - AaveV4SpokeRolesProcedure.grantSpokeAdminRole( - report.accessBatchReport.accessManagerAddress, - admin - ); + AaveV4SpokeRolesProcedure.grantSpokeAdminRole({ + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + admin: spokeAdmin + }); logger.log('...Granting Spoke Configurator roles...'); - AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole( - report.accessBatchReport.accessManagerAddress, - report.configuratorBatchReport.spokeConfiguratorAddress - ); + AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole({ + accessManagerAddress: report.accessBatchReport.accessManagerAddress, + admin: report.configuratorBatchReport.spokeConfiguratorAddress + }); } function _deployAccessBatch( Logger logger, - address admin + address accessManagerAdmin ) internal returns (BatchReports.AccessBatchReport memory report) { logger.log('...Deploying AccessBatch...'); - report = AaveV4DeployCore.deployAccessBatch(admin); + report = AaveV4DeployCore.deployAccessBatch({admin: accessManagerAdmin}); logger.log('AccessManager', report.accessManagerAddress); logger.log(''); @@ -146,11 +170,15 @@ library AaveV4DeployOrchestration { function _deployConfiguratorBatch( Logger logger, - address admin + address hubConfiguratorOwner, + address spokeConfiguratorOwner ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { logger.log('...Deploying ConfiguratorBatch...'); - report = AaveV4DeployCore.deployConfiguratorBatch(admin); + report = AaveV4DeployCore.deployConfiguratorBatch({ + hubConfiguratorOwner: hubConfiguratorOwner, + spokeConfiguratorOwner: spokeConfiguratorOwner + }); logger.log('HubConfigurator', report.hubConfiguratorAddress); logger.log('SpokeConfigurator', report.spokeConfiguratorAddress); @@ -160,14 +188,19 @@ library AaveV4DeployOrchestration { function _deployHubs( Logger logger, - address admin, + address treasurySpokeOwner, address accessManagerAddress, string[] memory hubLabels ) internal returns (OrchestrationReports.HubDeploymentReport[] memory hubBatchReports) { uint256 hubCount = hubLabels.length; hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); for (uint256 i; i < hubCount; ++i) { - hubBatchReports[i] = _deployHub(logger, admin, accessManagerAddress, hubLabels[i]); + hubBatchReports[i] = _deployHub( + logger, + treasurySpokeOwner, + accessManagerAddress, + hubLabels[i] + ); } logger.log(''); return hubBatchReports; @@ -175,13 +208,17 @@ library AaveV4DeployOrchestration { function _deployHub( Logger logger, - address admin, + address treasurySpokeOwner, address accessManagerAddress, string memory label ) internal returns (OrchestrationReports.HubDeploymentReport memory) { OrchestrationReports.HubDeploymentReport memory hubReport; hubReport.label = label; - hubReport.report = _deployHubBatch(logger, admin, accessManagerAddress); + hubReport.report = _deployHubBatch({ + logger: logger, + treasurySpokeOwner: treasurySpokeOwner, + accessManagerAddress: accessManagerAddress + }); logger.log(label); logger.log(' Hub', hubReport.report.hubAddress); @@ -196,14 +233,19 @@ library AaveV4DeployOrchestration { function _deploySpokes( Logger logger, - address admin, + address spokeProxyAdminOwner, address accessManagerAddress, string[] memory spokeLabels ) internal returns (OrchestrationReports.SpokeDeploymentReport[] memory spokeBatchReports) { uint256 spokeCount = spokeLabels.length; spokeBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); for (uint256 i; i < spokeCount; ++i) { - spokeBatchReports[i] = _deploySpoke(logger, admin, accessManagerAddress, spokeLabels[i]); + spokeBatchReports[i] = _deploySpoke({ + logger: logger, + spokeProxyAdminOwner: spokeProxyAdminOwner, + accessManagerAddress: accessManagerAddress, + label: spokeLabels[i] + }); } logger.log(''); return spokeBatchReports; @@ -211,14 +253,19 @@ library AaveV4DeployOrchestration { function _deploySpoke( Logger logger, - address admin, + address spokeProxyAdminOwner, address accessManagerAddress, string memory label ) internal returns (OrchestrationReports.SpokeDeploymentReport memory) { OrchestrationReports.SpokeDeploymentReport memory spokeReport; spokeReport.label = label; - spokeReport.report = _deploySpokeInstanceBatch(logger, admin, accessManagerAddress, label); + spokeReport.report = _deploySpokeInstanceBatch({ + logger: logger, + spokeProxyAdminOwner: spokeProxyAdminOwner, + accessManagerAddress: accessManagerAddress, + label: label + }); logger.log(label); logger.log(' SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); @@ -226,23 +273,23 @@ library AaveV4DeployOrchestration { logger.log(' AaveOracle', spokeReport.report.aaveOracleAddress); logger.log('...Setting Spoke roles...'); - AaveV4SpokeRolesProcedure.setSpokeRoles( - accessManagerAddress, - spokeReport.report.spokeProxyAddress - ); + AaveV4SpokeRolesProcedure.setSpokeRoles({ + accessManagerAddress: accessManagerAddress, + spokeAddress: spokeReport.report.spokeProxyAddress + }); return spokeReport; } function _deploySpokeInstanceBatch( Logger logger, - address admin, + address spokeProxyAdminOwner, address accessManagerAddress, string memory label ) internal returns (BatchReports.SpokeInstanceBatchReport memory report) { logger.log('...Deploying AaveV4SpokeInstanceBatch...'); report = AaveV4DeployCore.deploySpokeInstanceBatch( - admin, + spokeProxyAdminOwner, accessManagerAddress, ORACLE_DECIMALS, ORACLE_SUFFIX, @@ -253,21 +300,21 @@ library AaveV4DeployOrchestration { function _deployHubBatch( Logger logger, - address admin, + address treasurySpokeOwner, address accessManagerAddress ) internal returns (BatchReports.HubBatchReport memory report) { logger.log('...Deploying HubBatch...'); - report = AaveV4DeployCore.deployHubBatch(admin, accessManagerAddress); + report = AaveV4DeployCore.deployHubBatch(treasurySpokeOwner, accessManagerAddress); return report; } function _deployGatewayBatch( Logger logger, - address admin, + address owner, address nativeWrapper ) internal returns (BatchReports.GatewaysBatchReport memory report) { logger.log('...Deploying GatewayBatch...'); - report = AaveV4DeployCore.deployGatewaysBatch(admin, nativeWrapper); + report = AaveV4DeployCore.deployGatewaysBatch({owner: owner, nativeWrapper: nativeWrapper}); logger.log('NativeTokenGateway', report.nativeGatewayAddress); logger.log('SignatureGateway', report.signatureGatewayAddress); return report; diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index fda1700f6..5b2f82c09 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -8,8 +8,25 @@ import 'forge-std/Vm.sol'; contract InputUtils { using stdJson for string; + /// @dev accessManagerAdmin The default admin of the access manager. + /// @dev hubAdmin The admin of the hub. + /// @dev hubConfiguratorOwner The admin of the hub configurator. + /// @dev treasurySpokeOwner The owner of the treasury spoke. + /// @dev spokeAdmin The spoke admin. + /// @dev spokeProxyAdminOwner The owner of the spoke proxyAdmin. + /// @dev spokeConfiguratorOwner The admin of the spoke configurator. + /// @dev nativeWrapperAddress The address of the native wrapper. + /// @dev grantRoles A boolean indicating if roles should be granted. + /// @dev hubLabels An array of hub labels; the number of hub labels defines the number of hubs to deploy. + /// @dev spokeLabels An array of spoke labels; the number of spoke labels defines the number of spokes to deploy. struct FullDeployInputs { - address admin; + address accessManagerAdmin; + address hubAdmin; + address hubConfiguratorOwner; + address treasurySpokeOwner; + address spokeAdmin; + address spokeProxyAdminOwner; + address spokeConfiguratorOwner; address nativeWrapperAddress; bool grantRoles; string[] hubLabels; @@ -34,12 +51,17 @@ contract InputUtils { string memory inputPath ) public view returns (FullDeployInputs memory inputs) { string memory json = vm.readFile(inputPath); - inputs.admin = json.readAddress('.admin'); + inputs.accessManagerAdmin = json.readAddress('.accessManagerAdmin'); + inputs.hubAdmin = json.readAddress('.hubAdmin'); + inputs.hubConfiguratorOwner = json.readAddress('.hubConfiguratorOwner'); + inputs.treasurySpokeOwner = json.readAddress('.treasurySpokeOwner'); + inputs.spokeAdmin = json.readAddress('.spokeAdmin'); + inputs.spokeProxyAdminOwner = json.readAddress('.spokeProxyAdminOwner'); + inputs.spokeConfiguratorOwner = json.readAddress('.spokeConfiguratorOwner'); inputs.nativeWrapperAddress = json.readAddress('.nativeWrapperAddress'); inputs.grantRoles = json.readBool('.grantRoles'); inputs.hubLabels = json.readStringArray('.hubLabels'); inputs.spokeLabels = json.readStringArray('.spokeLabels'); - return inputs; } function loadSpokeDeployInputs( diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index 365a72c85..fd4844e9a 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -23,7 +23,13 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { spokeLabels = ['spoke1', 'spoke2', 'spoke3']; inputs = FullDeployInputs({ - admin: makeAddr('admin'), + accessManagerAdmin: makeAddr('accessManagerAdmin'), + hubConfiguratorOwner: makeAddr('hubConfiguratorOwner'), + hubAdmin: makeAddr('hubAdmin'), + treasurySpokeOwner: makeAddr('treasurySpokeOwner'), + spokeProxyAdminOwner: makeAddr('spokeProxyAdminOwner'), + spokeConfiguratorOwner: makeAddr('spokeConfiguratorOwner'), + spokeAdmin: makeAddr('spokeAdmin'), nativeWrapperAddress: weth9, grantRoles: true, hubLabels: hubLabels, @@ -68,16 +74,84 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { _checkRoles(report, inputs); } - function testAaveV4BatchDeployment_withZeroAdminAddress() public { - inputs.admin = address(0); + function testAaveV4BatchDeployment_withZeroAccessManagerAdminAddress() public { + inputs.accessManagerAdmin = address(0); OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); _checkDeployment(report, inputs); _checkRoles(report, inputs); } - function testAaveV4BatchDeployment_withZeroAdminAddress_withoutRoles() public { - inputs.admin = address(0); + function testAaveV4BatchDeployment_withZeroAccessManagerAdminAddress_withoutRoles() public { + inputs.accessManagerAdmin = address(0); + inputs.grantRoles = false; + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withZerohubConfiguratorOwnerAddress() public { + inputs.hubConfiguratorOwner = address(0); + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withZerohubConfiguratorOwnerAddress_withoutRoles() public { + inputs.hubConfiguratorOwner = address(0); + inputs.grantRoles = false; + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withZeroTreasurySpokeOwnerAddress() public { + inputs.treasurySpokeOwner = address(0); + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withZeroTreasurySpokeOwnerAddress_withoutRoles() public { + inputs.treasurySpokeOwner = address(0); + inputs.grantRoles = false; + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withZeroSpokeProxyAdminOwnerAddress() public { + inputs.spokeProxyAdminOwner = address(0); + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withZeroSpokeProxyAdminOwnerAddress_withoutRoles() public { + inputs.spokeProxyAdminOwner = address(0); + inputs.grantRoles = false; + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withZerospokeConfiguratorOwnerAddress() public { + inputs.spokeConfiguratorOwner = address(0); + + OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); + _checkDeployment(report, inputs); + _checkRoles(report, inputs); + } + + function testAaveV4BatchDeployment_withZerospokeConfiguratorOwnerAddress_withoutRoles() public { + inputs.spokeConfiguratorOwner = address(0); inputs.grantRoles = false; OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index e642abd5c..3ef89e845 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -58,15 +58,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ) public returns (OrchestrationReports.FullDeploymentReport memory) { vm.startPrank(deployer); OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration - .deployAaveV4( - logger, - deployer, - inputs.admin, - inputs.nativeWrapperAddress, - inputs.hubLabels, - inputs.spokeLabels, - inputs.grantRoles - ); + .deployAaveV4(logger, deployer, inputs); vm.stopPrank(); return report; } @@ -80,6 +72,46 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { _checkHubBatchDeployments(report, inputs); } + function _checkRoles( + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + inputs = _sanitizeInputs(inputs); + + IAccessManagerEnumerable accessManager = IAccessManagerEnumerable( + report.accessBatchReport.accessManagerAddress + ); + _checkAccessManagerRoles(accessManager, inputs); + _checkSpokeRoles(accessManager, report, inputs); + _checkHubRoles(accessManager, report, inputs); + _checkConfiguratorBatchRoles(report, inputs); + } + + /// @dev Sanitizes the inputs by defaulting to the deployer if the address is zero. + function _sanitizeInputs( + FullDeployInputs memory inputs + ) internal view returns (FullDeployInputs memory) { + inputs.accessManagerAdmin = inputs.accessManagerAdmin != address(0) + ? inputs.accessManagerAdmin + : deployer; + inputs.hubAdmin = inputs.hubAdmin != address(0) ? inputs.hubAdmin : deployer; + inputs.hubConfiguratorOwner = inputs.hubConfiguratorOwner != address(0) + ? inputs.hubConfiguratorOwner + : deployer; + inputs.treasurySpokeOwner = inputs.treasurySpokeOwner != address(0) + ? inputs.treasurySpokeOwner + : deployer; + inputs.spokeAdmin = inputs.spokeAdmin != address(0) ? inputs.spokeAdmin : deployer; + inputs.spokeProxyAdminOwner = inputs.spokeProxyAdminOwner != address(0) + ? inputs.spokeProxyAdminOwner + : deployer; + inputs.spokeConfiguratorOwner = inputs.spokeConfiguratorOwner != address(0) + ? inputs.spokeConfiguratorOwner + : deployer; + + return inputs; + } + function _checkFullReport( OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs @@ -147,28 +179,151 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ); } - function _checkRoles( + function _checkSpokeBatchDeployments( OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { - address contractAdmin = inputs.admin != address(0) ? inputs.admin : deployer; + string memory globalLabel = 'SpokeDeployment'; + for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { + _checkSpokeBatchDeployment( + report.spokeInstanceBatchReports[i], + inputs, + report.accessBatchReport.accessManagerAddress, + string.concat(globalLabel, ', ', inputs.spokeLabels[i]) + ); + } + } - IAccessManagerEnumerable accessManager = IAccessManagerEnumerable( - report.accessBatchReport.accessManagerAddress + function _checkSpokeBatchDeployment( + OrchestrationReports.SpokeDeploymentReport memory report, + FullDeployInputs memory inputs, + address accessManagerAddress, + string memory label + ) internal view { + _checkSpokeDeployment({ + report: report, + inputs: inputs, + accessManagerAddress: accessManagerAddress, + label: label + }); + _checkOracleDeployment({report: report, label: label}); + } + + function _checkSpokeDeployment( + OrchestrationReports.SpokeDeploymentReport memory report, + FullDeployInputs memory inputs, + address accessManagerAddress, + string memory label + ) internal view { + assertEq( + ProxyHelper.getImplementation(report.report.spokeProxyAddress), + report.report.spokeImplementationAddress, + string.concat(label, ' implementation') + ); + assertEq( + ISpoke(report.report.spokeProxyAddress).ORACLE(), + report.report.aaveOracleAddress, + string.concat(label, ' oracle on spoke') + ); + assertEq( + IAccessManaged(report.report.spokeProxyAddress).authority(), + accessManagerAddress, + string.concat(label, ' spoke authority') + ); + } + + function _checkOracleDeployment( + OrchestrationReports.SpokeDeploymentReport memory report, + string memory label + ) internal view { + assertEq( + IAaveOracle(report.report.aaveOracleAddress).SPOKE(), + report.report.spokeProxyAddress, + string.concat(label, ' spoke on oracle') + ); + assertEq( + IAaveOracle(report.report.aaveOracleAddress).DECIMALS(), + Constants.ORACLE_DECIMALS, + string.concat(label, ' oracle decimals') + ); + assertEq( + IAaveOracle(report.report.aaveOracleAddress).DESCRIPTION(), + string.concat(report.label, Constants.ORACLE_SUFFIX), + string.concat(label, ' oracle description') + ); + } + + function _checkHubBatchDeployments( + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + string memory label = 'HubDeployment'; + for (uint256 i = 0; i < inputs.hubLabels.length; i++) { + _checkHubBatchDeployment( + report, + report.hubBatchReports[i], + inputs, + string.concat(label, ', ', inputs.hubLabels[i]) + ); + } + } + + function _checkHubBatchDeployment( + OrchestrationReports.FullDeploymentReport memory fullReport, + OrchestrationReports.HubDeploymentReport memory report, + FullDeployInputs memory inputs, + string memory label + ) internal view { + _checkHubDeployment(report, fullReport.accessBatchReport.accessManagerAddress, label); + _checkInterestRateStrategyDeployment(report, label); + _checkTreasurySpokeDeployment(report, inputs, label); + } + + function _checkHubDeployment( + OrchestrationReports.HubDeploymentReport memory report, + address accessManagerAddress, + string memory label + ) internal view { + assertEq( + IAccessManaged(report.report.hubAddress).authority(), + accessManagerAddress, + string.concat(label, ' hub authority') + ); + } + + function _checkInterestRateStrategyDeployment( + OrchestrationReports.HubDeploymentReport memory report, + string memory label + ) internal view { + assertEq( + IAssetInterestRateStrategy(report.report.irStrategyAddress).HUB(), + report.report.hubAddress, + string.concat(label, ' hub on interest rate strategy') + ); + } + + function _checkTreasurySpokeDeployment( + OrchestrationReports.HubDeploymentReport memory report, + FullDeployInputs memory inputs, + string memory label + ) internal view { + assertEq( + address(ITreasurySpoke(report.report.treasurySpokeAddress).HUB()), + report.report.hubAddress, + string.concat(label, ' hub on treasury spoke') ); - _checkAccessManagerRoles(accessManager, inputs, contractAdmin); - _checkSpokeRoles(accessManager, report, inputs, contractAdmin); - _checkHubRoles(accessManager, report, inputs, contractAdmin); } function _checkAccessManagerRoles( IAccessManagerEnumerable accessManager, - FullDeployInputs memory inputs, - address contractAdmin + FullDeployInputs memory inputs ) internal view { + address expectedAdmin = (inputs.grantRoles && inputs.accessManagerAdmin != address(0)) + ? inputs.accessManagerAdmin + : deployer; assertEq( accessManager.getRoleMember(Roles.DEFAULT_ADMIN_ROLE, 0), - contractAdmin, + expectedAdmin, 'DefaultAdminRoleMember' ); assertEq( @@ -177,30 +332,23 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { 'DefaultAdminRoleCount' ); - (bool adminHasRole, ) = accessManager.hasRole(Roles.DEFAULT_ADMIN_ROLE, contractAdmin); - bool expectAdminHasRole = inputs.grantRoles || inputs.admin == address(0); - if (expectAdminHasRole) { - assertTrue(adminHasRole, 'contract admin has default admin role'); - } else { - assertFalse(adminHasRole, 'contract admin does not have default admin role'); - } + (bool adminHasRole, ) = accessManager.hasRole(Roles.DEFAULT_ADMIN_ROLE, expectedAdmin); + assertTrue(adminHasRole, 'access manager admin has default admin role'); } function _checkSpokeRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs, - address contractAdmin + FullDeployInputs memory inputs ) internal view { - _checkSpokeAdminRoles(accessManager, report, inputs, contractAdmin); - _checkSpokeConfiguratorRoles(accessManager, report, inputs, contractAdmin); + _checkSpokeAdminRoles(accessManager, report, inputs); + _checkSpokeConfiguratorRoles(accessManager, report, inputs); } function _checkSpokeConfiguratorRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs, - address contractAdmin + FullDeployInputs memory inputs ) internal view { if (inputs.spokeLabels.length > 0 && inputs.grantRoles) { assertEq( @@ -210,7 +358,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ); assertEq( accessManager.getRoleMember(Roles.SPOKE_CONFIGURATOR_ROLE, 0), - contractAdmin, + inputs.spokeAdmin, 'SpokeConfiguratorRole member - spoke admin' ); assertEq( @@ -251,16 +399,16 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { // spoke admin role encompasses spoke configurator role (allowed, delay) = accessManager.canCall( - contractAdmin, + inputs.spokeAdmin, report.spokeInstanceBatchReports[i].report.spokeProxyAddress, spokeConfiguratorRoleSelectors[j] ); assertEq( allowed, inputs.grantRoles ? true : false, - 'SpokeConfiguratorRole allowed - admin' + 'SpokeConfiguratorRole allowed - spoke admin' ); - assertEq(delay, 0, 'SpokeConfiguratorRole delay - admin'); + assertEq(delay, 0, 'SpokeConfiguratorRole delay - spoke admin'); } } } @@ -268,8 +416,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function _checkSpokeAdminRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs, - address contractAdmin + FullDeployInputs memory inputs ) internal view { if (inputs.spokeLabels.length > 0 && inputs.grantRoles) { assertEq( @@ -279,7 +426,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ); assertEq( accessManager.getRoleMember(Roles.SPOKE_POSITION_UPDATER_ROLE, 0), - contractAdmin, + inputs.spokeAdmin, 'SpokeAdminRole member - spoke admin' ); } else { @@ -291,9 +438,18 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { } for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { + address proxyAdminOwner = Ownable( + ProxyHelper.getProxyAdmin(report.spokeInstanceBatchReports[i].report.spokeProxyAddress) + ).owner(); + assertEq( + proxyAdminOwner, + inputs.spokeProxyAdminOwner, + string.concat(inputs.spokeLabels[i], ' proxy admin owner') + ); + for (uint256 j = 0; j < spokePositionUpdaterRoleSelectors.length; j++) { (bool allowed, uint32 delay) = accessManager.canCall( - contractAdmin, + inputs.spokeAdmin, report.spokeInstanceBatchReports[i].report.spokeProxyAddress, spokePositionUpdaterRoleSelectors[j] ); @@ -315,30 +471,34 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function _checkHubRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs, - address contractAdmin + FullDeployInputs memory inputs ) internal view { - _checkHubAdminRoles(accessManager, report, inputs, contractAdmin); - _checkHubConfiguratorRoles(accessManager, report, inputs, contractAdmin); + _checkHubBatchRoles(accessManager, report, inputs); + _checkHubConfiguratorRoles(accessManager, report, inputs); } - function _checkHubAdminRoles( + function _checkHubBatchRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs, - address contractAdmin + FullDeployInputs memory inputs ) internal view { if (inputs.hubLabels.length > 0 && inputs.grantRoles) { assertEq(accessManager.getRoleMemberCount(Roles.HUB_FEE_MINTER_ROLE), 1, 'HubAdminRoleCount'); assertEq( accessManager.getRoleMember(Roles.HUB_FEE_MINTER_ROLE, 0), - contractAdmin, + inputs.hubAdmin, 'HubAdminRole member - hub admin' ); } else { assertEq(accessManager.getRoleMemberCount(Roles.HUB_FEE_MINTER_ROLE), 0, 'HubAdminRoleCount'); } for (uint256 i = 0; i < inputs.hubLabels.length; i++) { + _checkTreasurySpokeRoles( + accessManager, + report.hubBatchReports[i].report.treasurySpokeAddress, + inputs, + inputs.hubLabels[i] + ); for (uint256 j = 0; j < hubFeeMinterRoleSelectors.length; j++) { assertEq( accessManager.getTargetFunctionRole( @@ -350,7 +510,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ); (bool allowed, uint32 delay) = accessManager.canCall( - contractAdmin, + inputs.hubAdmin, report.hubBatchReports[i].report.hubAddress, hubFeeMinterRoleSelectors[j] ); @@ -360,11 +520,23 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { } } + function _checkTreasurySpokeRoles( + IAccessManagerEnumerable accessManager, + address treasurySpokeAddress, + FullDeployInputs memory inputs, + string memory label + ) internal view { + assertEq( + Ownable(treasurySpokeAddress).owner(), + inputs.treasurySpokeOwner, + string.concat(label, ' treasury spoke owner') + ); + } + function _checkHubConfiguratorRoles( IAccessManagerEnumerable accessManager, OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs, - address contractAdmin + FullDeployInputs memory inputs ) internal view { if (inputs.hubLabels.length > 0 && inputs.grantRoles) { assertEq( @@ -374,7 +546,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ); assertEq( accessManager.getRoleMember(Roles.HUB_CONFIGURATOR_ROLE, 0), - contractAdmin, + inputs.hubAdmin, 'HubConfiguratorRole member - hub admin' ); assertEq( @@ -415,7 +587,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { assertEq(delay, 0, 'HubConfiguratorRole delay - configurator'); (allowed, delay) = accessManager.canCall( - contractAdmin, + inputs.hubAdmin, report.hubBatchReports[i].report.hubAddress, hubConfiguratorRoleSelectors[j] ); @@ -425,146 +597,19 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { } } - function _checkSpokeBatchDeployments( + function _checkConfiguratorBatchRoles( OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { - string memory globalLabel = 'SpokeDeployment'; - for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { - _checkSpokeBatchDeployment( - report.spokeInstanceBatchReports[i], - inputs, - report.accessBatchReport.accessManagerAddress, - string.concat(globalLabel, ', ', inputs.spokeLabels[i]) - ); - } - } - - function _checkSpokeBatchDeployment( - OrchestrationReports.SpokeDeploymentReport memory report, - FullDeployInputs memory inputs, - address accessManagerAddress, - string memory label - ) internal view { - _checkSpokeDeployment(report, inputs, accessManagerAddress, label); - _checkOracleDeployment(report, label); - } - - function _checkSpokeDeployment( - OrchestrationReports.SpokeDeploymentReport memory report, - FullDeployInputs memory inputs, - address accessManagerAddress, - string memory label - ) internal view { - address proxyAdminOwner = Ownable(ProxyHelper.getProxyAdmin(report.report.spokeProxyAddress)) - .owner(); - if (inputs.admin != address(0)) { - assertEq(proxyAdminOwner, inputs.admin, string.concat(label, ' proxy admin owner')); - } else { - assertEq(proxyAdminOwner, deployer, string.concat(label, ' proxy admin owner')); - } - assertEq( - ProxyHelper.getImplementation(report.report.spokeProxyAddress), - report.report.spokeImplementationAddress, - string.concat(label, ' implementation') - ); assertEq( - ISpoke(report.report.spokeProxyAddress).ORACLE(), - report.report.aaveOracleAddress, - string.concat(label, ' oracle on spoke') + Ownable(report.configuratorBatchReport.hubConfiguratorAddress).owner(), + inputs.hubConfiguratorOwner, + 'HubConfigurator owner' ); assertEq( - IAccessManaged(report.report.spokeProxyAddress).authority(), - accessManagerAddress, - string.concat(label, ' spoke authority') - ); - } - - function _checkOracleDeployment( - OrchestrationReports.SpokeDeploymentReport memory report, - string memory label - ) internal view { - assertEq( - IAaveOracle(report.report.aaveOracleAddress).SPOKE(), - report.report.spokeProxyAddress, - string.concat(label, ' spoke on oracle') + Ownable(report.configuratorBatchReport.spokeConfiguratorAddress).owner(), + inputs.spokeConfiguratorOwner, + 'SpokeConfigurator owner' ); - assertEq( - IAaveOracle(report.report.aaveOracleAddress).DECIMALS(), - Constants.ORACLE_DECIMALS, - string.concat(label, ' oracle decimals') - ); - assertEq( - IAaveOracle(report.report.aaveOracleAddress).DESCRIPTION(), - string.concat(report.label, Constants.ORACLE_SUFFIX), - string.concat(label, ' oracle description') - ); - } - - function _checkHubBatchDeployments( - OrchestrationReports.FullDeploymentReport memory report, - FullDeployInputs memory inputs - ) internal view { - string memory label = 'HubDeployment'; - for (uint256 i = 0; i < inputs.hubLabels.length; i++) { - _checkHubBatchDeployment( - report, - report.hubBatchReports[i], - inputs, - string.concat(label, ', ', inputs.hubLabels[i]) - ); - } - } - - function _checkHubBatchDeployment( - OrchestrationReports.FullDeploymentReport memory fullReport, - OrchestrationReports.HubDeploymentReport memory report, - FullDeployInputs memory inputs, - string memory label - ) internal view { - _checkHubDeployment(report, fullReport.accessBatchReport.accessManagerAddress, label); - _checkInterestRateStrategyDeployment(report, label); - _checkTreasurySpokeDeployment(report, inputs, label); - } - - function _checkHubDeployment( - OrchestrationReports.HubDeploymentReport memory report, - address accessManagerAddress, - string memory label - ) internal view { - assertEq( - IAccessManaged(report.report.hubAddress).authority(), - accessManagerAddress, - string.concat(label, ' hub authority') - ); - } - - function _checkInterestRateStrategyDeployment( - OrchestrationReports.HubDeploymentReport memory report, - string memory label - ) internal view { - assertEq( - IAssetInterestRateStrategy(report.report.irStrategyAddress).HUB(), - report.report.hubAddress, - string.concat(label, ' hub on interest rate strategy') - ); - } - - function _checkTreasurySpokeDeployment( - OrchestrationReports.HubDeploymentReport memory report, - FullDeployInputs memory inputs, - string memory label - ) internal view { - assertEq( - address(ITreasurySpoke(report.report.treasurySpokeAddress).HUB()), - report.report.hubAddress, - string.concat(label, ' hub on treasury spoke') - ); - address treasurySpokeOwner = Ownable(report.report.treasurySpokeAddress).owner(); - if (inputs.admin != address(0)) { - assertEq(treasurySpokeOwner, inputs.admin, string.concat(label, ' treasury spoke owner')); - } else { - assertEq(treasurySpokeOwner, deployer, string.concat(label, ' treasury spoke owner')); - } } } From 8f14c5102ab4ce2640020f99d98ae0fe561b841f Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 12 Dec 2025 22:26:02 -0600 Subject: [PATCH 46/62] fix: AaveV4DeployBatchScript configurable inputs --- scripts/deploy/AaveV4DeployBatch.s.sol | 6 ++- scripts/deploy/AaveV4DeployBatchBase.s.sol | 50 +++++++++++++++++++--- tests/utils/BatchTestProcedures.sol | 7 +-- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/scripts/deploy/AaveV4DeployBatch.s.sol b/scripts/deploy/AaveV4DeployBatch.s.sol index cf7ed14a8..b0a719202 100644 --- a/scripts/deploy/AaveV4DeployBatch.s.sol +++ b/scripts/deploy/AaveV4DeployBatch.s.sol @@ -4,4 +4,8 @@ pragma solidity ^0.8.0; import 'scripts/deploy/AaveV4DeployBatchBase.s.sol'; -contract AaveV4DeployBatchScript is AaveV4DeployBatchBaseScript {} +contract AaveV4DeployBatchScript is AaveV4DeployBatchBaseScript { + string internal constant INPUT_FILE = 'AaveV4DeployInput.json'; + string internal constant OUTPUT_FILE = 'AaveV4DeployBatch.json'; + constructor() AaveV4DeployBatchBaseScript(INPUT_FILE, OUTPUT_FILE) {} +} diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index 2253d38a2..334c5ba95 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -12,15 +12,26 @@ import { AaveV4DeployOrchestration } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; +import {console2 as console} from 'forge-std/console2.sol'; + abstract contract AaveV4DeployBatchBaseScript is Script, DeployUtils, InputUtils { - string internal constant INPUT_PATH = 'scripts/deploy/inputs/AaveV4DeployInput.json'; + string internal constant INPUT_PATH = 'scripts/deploy/inputs/'; string internal constant OUTPUT_DIR = 'output/reports/deployments/'; - string internal constant OUTPUT_FILE = 'AaveV4DeployBatch.json'; + + string internal _inputFileName; + string internal _outputFileName; + + constructor(string memory inputFileName_, string memory outputFileName_) { + _inputFileName = inputFileName_; + _outputFileName = outputFileName_; + } function run() external { vm.createDir(OUTPUT_DIR, true); MetadataLogger logger = new MetadataLogger(OUTPUT_DIR); - FullDeployInputs memory inputs = loadFullDeployInputs(INPUT_PATH); + FullDeployInputs memory inputs = loadFullDeployInputs( + string.concat(INPUT_PATH, _inputFileName) + ); _loadWarnings(logger, inputs); @@ -33,7 +44,7 @@ abstract contract AaveV4DeployBatchBaseScript is Script, DeployUtils, InputUtils logger.writeJsonReportMarket(report); logger.log('...Batch Deployment Completed...'); logger.log('...Saving Logs...'); - logger.save({fileName: OUTPUT_FILE, withTimestamp: true}); + logger.save({fileName: _outputFileName, withTimestamp: true}); } function _loadWarnings( @@ -42,8 +53,35 @@ abstract contract AaveV4DeployBatchBaseScript is Script, DeployUtils, InputUtils ) internal pure virtual { if (inputs.grantRoles) { logger.log('WARNING: Roles are being set'); - if (inputs.admin == address(0)) { - logger.log('WARNING: Admin is zero address; Roles can not be set'); + if (inputs.accessManagerAdmin == address(0)) { + logger.log( + 'WARNING: Access Manager Admin is zero address; admin roles will be granted to deployer by default' + ); + } + if (inputs.hubConfiguratorOwner == address(0)) { + logger.log( + 'WARNING: Hub Configurator Owner is zero address; configurator roles will be granted to deployer by default' + ); + } + if (inputs.spokeConfiguratorOwner == address(0)) { + logger.log( + 'WARNING: Spoke Configurator Owner is zero address; configurator roles will be granted to deployer by default' + ); + } + if (inputs.spokeProxyAdminOwner == address(0)) { + logger.log( + 'WARNING: Spoke Proxy Admin Owner is zero address; proxy admin roles will be granted to deployer by default' + ); + } + if (inputs.treasurySpokeOwner == address(0)) { + logger.log( + 'WARNING: Treasury Spoke Owner is zero address; treasury spoke roles will be granted to deployer by default' + ); + } + if (inputs.spokeAdmin == address(0)) { + logger.log( + 'WARNING: Spoke Admin is zero address; spoke admin roles will be granted to deployer by default' + ); } } if (inputs.hubLabels.length == 0) { diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 3ef89e845..6de0dda92 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -202,7 +202,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ) internal view { _checkSpokeDeployment({ report: report, - inputs: inputs, accessManagerAddress: accessManagerAddress, label: label }); @@ -211,7 +210,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function _checkSpokeDeployment( OrchestrationReports.SpokeDeploymentReport memory report, - FullDeployInputs memory inputs, address accessManagerAddress, string memory label ) internal view { @@ -276,7 +274,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ) internal view { _checkHubDeployment(report, fullReport.accessBatchReport.accessManagerAddress, label); _checkInterestRateStrategyDeployment(report, label); - _checkTreasurySpokeDeployment(report, inputs, label); + _checkTreasurySpokeDeployment(report, label); } function _checkHubDeployment( @@ -304,7 +302,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function _checkTreasurySpokeDeployment( OrchestrationReports.HubDeploymentReport memory report, - FullDeployInputs memory inputs, string memory label ) internal view { assertEq( @@ -494,7 +491,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { } for (uint256 i = 0; i < inputs.hubLabels.length; i++) { _checkTreasurySpokeRoles( - accessManager, report.hubBatchReports[i].report.treasurySpokeAddress, inputs, inputs.hubLabels[i] @@ -521,7 +517,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { } function _checkTreasurySpokeRoles( - IAccessManagerEnumerable accessManager, address treasurySpokeAddress, FullDeployInputs memory inputs, string memory label From e7f4ea56efa50aedaddf7a143e0071e1f34a43ce Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 12 Dec 2025 23:11:19 -0600 Subject: [PATCH 47/62] fix: user warnings prompt --- scripts/deploy/AaveV4DeployBatchBase.s.sol | 61 ++++++++++++++++--- scripts/deploy/inputs/AaveV4DeployInput.json | 1 + .../AaveV4DeployOrchestration.sol | 12 +++- src/deployments/utils/InputUtils.sol | 2 + tests/deployments/AaveV4BatchDeployment.t.sol | 1 + tests/utils/BatchTestProcedures.sol | 35 ++++++++--- 6 files changed, 92 insertions(+), 20 deletions(-) diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index 334c5ba95..5cdd2a5f9 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -47,52 +47,93 @@ abstract contract AaveV4DeployBatchBaseScript is Script, DeployUtils, InputUtils logger.save({fileName: _outputFileName, withTimestamp: true}); } - function _loadWarnings( - MetadataLogger logger, - FullDeployInputs memory inputs - ) internal pure virtual { + function _loadWarnings(MetadataLogger logger, FullDeployInputs memory inputs) internal virtual { + bool hadWarnings = false; + string memory warnings = ''; if (inputs.grantRoles) { logger.log('WARNING: Roles are being set'); + warnings = string.concat(warnings, 'WARNING: Roles are being set\n'); + hadWarnings = true; if (inputs.accessManagerAdmin == address(0)) { logger.log( - 'WARNING: Access Manager Admin is zero address; admin roles will be granted to deployer by default' + 'WARNING: Access Manager Admin is zero address; role will be granted to deployer by default' + ); + warnings = string.concat( + warnings, + 'WARNING: Access Manager Admin is zero address; role will be granted to deployer by default\n' ); } if (inputs.hubConfiguratorOwner == address(0)) { logger.log( - 'WARNING: Hub Configurator Owner is zero address; configurator roles will be granted to deployer by default' + 'WARNING: Hub Configurator Owner is zero address; role will be granted to deployer by default' + ); + warnings = string.concat( + warnings, + 'WARNING: Hub Configurator Owner is zero address; role will be granted to deployer by default\n' ); } if (inputs.spokeConfiguratorOwner == address(0)) { logger.log( - 'WARNING: Spoke Configurator Owner is zero address; configurator roles will be granted to deployer by default' + 'WARNING: Spoke Configurator Owner is zero address; role will be granted to deployer by default' + ); + warnings = string.concat( + warnings, + 'WARNING: Spoke Configurator Owner is zero address; role will be granted to deployer by default\n' ); } if (inputs.spokeProxyAdminOwner == address(0)) { logger.log( - 'WARNING: Spoke Proxy Admin Owner is zero address; proxy admin roles will be granted to deployer by default' + 'WARNING: Spoke Proxy Admin Owner is zero address; role will be granted to deployer by default' + ); + warnings = string.concat( + warnings, + 'WARNING: Spoke Proxy Admin Owner is zero address; role will be granted to deployer by default\n' ); } if (inputs.treasurySpokeOwner == address(0)) { logger.log( - 'WARNING: Treasury Spoke Owner is zero address; treasury spoke roles will be granted to deployer by default' + 'WARNING: Treasury Spoke Owner is zero address; role will be granted to deployer by default' + ); + warnings = string.concat( + warnings, + 'WARNING: Treasury Spoke Owner is zero address; role will be granted to deployer by default\n' ); } if (inputs.spokeAdmin == address(0)) { logger.log( - 'WARNING: Spoke Admin is zero address; spoke admin roles will be granted to deployer by default' + 'WARNING: Spoke Admin is zero address; role will be granted to deployer by default' + ); + warnings = string.concat( + warnings, + 'WARNING: Spoke Admin is zero address; spoke admin roles will be granted to deployer by default\n' ); } } if (inputs.hubLabels.length == 0) { logger.log('WARNING: Hub will not be deployed'); + hadWarnings = true; + warnings = string.concat(warnings, 'WARNING: Hub will not be deployed\n'); } if (inputs.spokeLabels.length == 0) { logger.log('WARNING: Spoke will not be deployed'); + hadWarnings = true; + warnings = string.concat(warnings, 'WARNING: Spoke will not be deployed\n'); } if (inputs.nativeWrapperAddress == address(0)) { logger.log('WARNING: Native wrapper zero address; NativeTokenGateway will not be deployed'); + hadWarnings = true; + warnings = string.concat( + warnings, + 'WARNING: Native wrapper zero address; NativeTokenGateway will not be deployed\n' + ); } logger.log(''); + + if (hadWarnings) { + string memory ack = vm.prompt(string.concat(warnings, "\nEnter 'y' to continue")); + if (keccak256(bytes(ack)) != keccak256(bytes('y'))) { + revert('User did not acknowledge warnings. Please try again.'); + } + } } } diff --git a/scripts/deploy/inputs/AaveV4DeployInput.json b/scripts/deploy/inputs/AaveV4DeployInput.json index d14a47011..41d529f5d 100644 --- a/scripts/deploy/inputs/AaveV4DeployInput.json +++ b/scripts/deploy/inputs/AaveV4DeployInput.json @@ -6,6 +6,7 @@ "spokeConfiguratorOwner": "0x0000000000000000000000000000000000000004", "spokeAdmin": "0x0000000000000000000000000000000000000005", "spokeProxyAdminOwner": "0x0000000000000000000000000000000000000005", + "gatewayOwner": "0x0000000000000000000000000000000000000005", "nativeWrapperAddress": "0x0000000000000000000000000000000000000006", "grantRoles": true, "hubLabels": ["Hub 1", "Hub 2", "Hub 3"], diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 2f9aaa85f..7255b7cc2 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -59,6 +59,9 @@ library AaveV4DeployOrchestration { inputs.spokeConfiguratorOwner = deployInputs.spokeConfiguratorOwner != address(0) ? deployInputs.spokeConfiguratorOwner : deployer; + inputs.gatewayOwner = deployInputs.gatewayOwner != address(0) + ? deployInputs.gatewayOwner + : deployer; // Deploy Configurator Batch report.configuratorBatchReport = _deployConfiguratorBatch({ @@ -86,7 +89,7 @@ library AaveV4DeployOrchestration { // Deploy Gateways Batch report.gatewaysBatchReport = _deployGatewayBatch({ logger: logger, - owner: inputs.spokeProxyAdminOwner, + gatewayOwner: inputs.gatewayOwner, nativeWrapper: inputs.nativeWrapperAddress }); @@ -310,11 +313,14 @@ library AaveV4DeployOrchestration { function _deployGatewayBatch( Logger logger, - address owner, + address gatewayOwner, address nativeWrapper ) internal returns (BatchReports.GatewaysBatchReport memory report) { logger.log('...Deploying GatewayBatch...'); - report = AaveV4DeployCore.deployGatewaysBatch({owner: owner, nativeWrapper: nativeWrapper}); + report = AaveV4DeployCore.deployGatewaysBatch({ + owner: gatewayOwner, + nativeWrapper: nativeWrapper + }); logger.log('NativeTokenGateway', report.nativeGatewayAddress); logger.log('SignatureGateway', report.signatureGatewayAddress); return report; diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index 5b2f82c09..242fa026e 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -15,6 +15,7 @@ contract InputUtils { /// @dev spokeAdmin The spoke admin. /// @dev spokeProxyAdminOwner The owner of the spoke proxyAdmin. /// @dev spokeConfiguratorOwner The admin of the spoke configurator. + /// @dev gatewayOwner The owner of the native token and signature gateways. /// @dev nativeWrapperAddress The address of the native wrapper. /// @dev grantRoles A boolean indicating if roles should be granted. /// @dev hubLabels An array of hub labels; the number of hub labels defines the number of hubs to deploy. @@ -27,6 +28,7 @@ contract InputUtils { address spokeAdmin; address spokeProxyAdminOwner; address spokeConfiguratorOwner; + address gatewayOwner; address nativeWrapperAddress; bool grantRoles; string[] hubLabels; diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index fd4844e9a..04e5f566c 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -30,6 +30,7 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { spokeProxyAdminOwner: makeAddr('spokeProxyAdminOwner'), spokeConfiguratorOwner: makeAddr('spokeConfiguratorOwner'), spokeAdmin: makeAddr('spokeAdmin'), + gatewayOwner: makeAddr('gatewayOwner'), nativeWrapperAddress: weth9, grantRoles: true, hubLabels: hubLabels, diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 6de0dda92..d41511de7 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -85,6 +85,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { _checkSpokeRoles(accessManager, report, inputs); _checkHubRoles(accessManager, report, inputs); _checkConfiguratorBatchRoles(report, inputs); + _checkGatewayRoles(report, inputs); } /// @dev Sanitizes the inputs by defaulting to the deployer if the address is zero. @@ -108,6 +109,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { inputs.spokeConfiguratorOwner = inputs.spokeConfiguratorOwner != address(0) ? inputs.spokeConfiguratorOwner : deployer; + inputs.gatewayOwner = inputs.gatewayOwner != address(0) ? inputs.gatewayOwner : deployer; return inputs; } @@ -129,6 +131,11 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { 'Zero NativeGatewayAddress' ); } + assertNotEq( + report.gatewaysBatchReport.signatureGatewayAddress, + address(0), + 'SignatureGatewayAddress' + ); assertNotEq(report.accessBatchReport.accessManagerAddress, address(0), 'AccessManagerAddress'); assertNotEq( @@ -187,7 +194,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { _checkSpokeBatchDeployment( report.spokeInstanceBatchReports[i], - inputs, report.accessBatchReport.accessManagerAddress, string.concat(globalLabel, ', ', inputs.spokeLabels[i]) ); @@ -196,7 +202,6 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { function _checkSpokeBatchDeployment( OrchestrationReports.SpokeDeploymentReport memory report, - FullDeployInputs memory inputs, address accessManagerAddress, string memory label ) internal view { @@ -258,21 +263,19 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { string memory label = 'HubDeployment'; for (uint256 i = 0; i < inputs.hubLabels.length; i++) { _checkHubBatchDeployment( - report, report.hubBatchReports[i], - inputs, + report.accessBatchReport.accessManagerAddress, string.concat(label, ', ', inputs.hubLabels[i]) ); } } function _checkHubBatchDeployment( - OrchestrationReports.FullDeploymentReport memory fullReport, OrchestrationReports.HubDeploymentReport memory report, - FullDeployInputs memory inputs, + address accessManagerAddress, string memory label ) internal view { - _checkHubDeployment(report, fullReport.accessBatchReport.accessManagerAddress, label); + _checkHubDeployment(report, accessManagerAddress, label); _checkInterestRateStrategyDeployment(report, label); _checkTreasurySpokeDeployment(report, label); } @@ -607,4 +610,22 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { 'SpokeConfigurator owner' ); } + + function _checkGatewayRoles( + OrchestrationReports.FullDeploymentReport memory report, + FullDeployInputs memory inputs + ) internal view { + if (inputs.nativeWrapperAddress != address(0)) { + assertEq( + Ownable(report.gatewaysBatchReport.nativeGatewayAddress).owner(), + inputs.gatewayOwner, + 'NativeGateway owner' + ); + } + assertEq( + Ownable(report.gatewaysBatchReport.signatureGatewayAddress).owner(), + inputs.gatewayOwner, + 'SignatureGateway owner' + ); + } } From f6787b9f9c8db53cc856ac4c9f13789a1a3ae95b Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Sat, 13 Dec 2025 00:15:54 -0600 Subject: [PATCH 48/62] test: computeCreateAddress; pr comments --- .../batches/AaveV4SpokeInstanceBatch.sol | 4 +- src/deployments/libraries/BatchReports.sol | 5 -- src/deployments/libraries/ConfigData.sol | 6 -- .../libraries/OrchestrationReports.sol | 22 ------ ...eV4DeployCore.sol => AaveV4DeployBase.sol} | 14 ++-- .../AaveV4DeployOrchestration.sol | 12 ++-- .../AaveV4AaveOracleDeployProcedure.sol | 5 +- ...AccessManagerEnumerableDeployProcedure.sol | 4 +- .../AaveV4HubConfiguratorDeployProcedure.sol | 4 +- .../deploy/AaveV4HubDeployProcedure.sol | 4 +- ...eV4InterestRateStrategyDeployProcedure.sol | 4 +- ...aveV4NativeTokenGatewayDeployProcedure.sol | 4 +- .../AaveV4SignatureGatewayDeployProcedure.sol | 4 +- ...AaveV4SpokeConfiguratorDeployProcedure.sol | 4 +- .../AaveV4SpokeInstanceDeployProcedure.sol | 4 +- ...sparentUpgradeableProxyDeployProcedure.sol | 11 +-- .../AaveV4TreasurySpokeDeployProcedure.sol | 4 +- .../procedures/deploy/WETHDeployProcedure.sol | 4 +- src/deployments/utils/libraries/Utils.sol | 7 +- tests/Base.t.sol | 24 +++---- tests/deployments/batches/TestTokensBatch.sol | 13 ++-- .../orchestration/AaveV4TestOrchestration.sol | 69 ++++++------------- .../TestnetERC20DeployProcedure.sol | 4 +- tests/deployments/utils/libraries/Utils.t.sol | 15 ++++ tests/unit/Spoke/Spoke.Getters.t.sol | 2 +- tests/unit/Spoke/Spoke.Upgradeable.t.sol | 4 +- tests/utils/TestTypes.sol | 33 +++++++++ 27 files changed, 134 insertions(+), 156 deletions(-) rename src/deployments/orchestration/{AaveV4DeployCore.sol => AaveV4DeployBase.sol} (89%) rename {src/deployments/procedures/deploy => tests/deployments/procedures}/TestnetERC20DeployProcedure.sol (75%) create mode 100644 tests/deployments/utils/libraries/Utils.t.sol diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 46ee15775..e17121343 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -27,7 +27,7 @@ contract AaveV4SpokeInstanceBatch is uint8 oracleDecimals_, string memory oracleDescription_ ) { - // additional 3 nonces for AaveOracle, SpokeInstance, and TransparentUpgradeableProxy + // additional 2 nonces for AaveOracle, SpokeInstance, starting from contract nonce of 1 address predictedSpokeInstanceAddress = Utils.computeCreateAddress(address(this), 3); address aaveOracleAddress = _deployAaveOracle( @@ -42,7 +42,7 @@ contract AaveV4SpokeInstanceBatch is abi.encodeWithSignature('initialize(address)', accessManagerAddress_) ); - require(spokeProxyAddress == predictedSpokeInstanceAddress, 'SpokeInstance address mismatch'); + assert(spokeProxyAddress == predictedSpokeInstanceAddress); _report = BatchReports.SpokeInstanceBatchReport({ aaveOracleAddress: aaveOracleAddress, diff --git a/src/deployments/libraries/BatchReports.sol b/src/deployments/libraries/BatchReports.sol index ca8643984..12689e35b 100644 --- a/src/deployments/libraries/BatchReports.sol +++ b/src/deployments/libraries/BatchReports.sol @@ -28,9 +28,4 @@ library BatchReports { address signatureGatewayAddress; address nativeGatewayAddress; } - - struct TestTokensBatchReport { - address wethAddress; - address[] tokenAddresses; - } } diff --git a/src/deployments/libraries/ConfigData.sol b/src/deployments/libraries/ConfigData.sol index 879ca1986..6916ebc81 100644 --- a/src/deployments/libraries/ConfigData.sol +++ b/src/deployments/libraries/ConfigData.sol @@ -50,10 +50,4 @@ library ConfigData { ISpoke.ReserveConfig config; ISpoke.DynamicReserveConfig dynamicConfig; } - - struct TestTokenInput { - string name; - string symbol; - uint8 decimals; - } } diff --git a/src/deployments/libraries/OrchestrationReports.sol b/src/deployments/libraries/OrchestrationReports.sol index a9a919cf1..8d956c8a1 100644 --- a/src/deployments/libraries/OrchestrationReports.sol +++ b/src/deployments/libraries/OrchestrationReports.sol @@ -22,26 +22,4 @@ library OrchestrationReports { HubDeploymentReport[] hubBatchReports; BatchReports.GatewaysBatchReport gatewaysBatchReport; } - - struct TestHubReport { - address hubAddress; - address irStrategyAddress; - address treasurySpokeAddress; - } - - struct TestSpokeReport { - address spokeAddress; - address aaveOracleAddress; - } - - struct TestEnvReport { - address accessManagerAddress; - TestHubReport[] hubReports; - TestSpokeReport[] spokeReports; - } - - struct TestTokensReport { - address wethAddress; - address[] testTokenAddresses; - } } diff --git a/src/deployments/orchestration/AaveV4DeployCore.sol b/src/deployments/orchestration/AaveV4DeployBase.sol similarity index 89% rename from src/deployments/orchestration/AaveV4DeployCore.sol rename to src/deployments/orchestration/AaveV4DeployBase.sol index 4e6ac8bb9..a5e122742 100644 --- a/src/deployments/orchestration/AaveV4DeployCore.sol +++ b/src/deployments/orchestration/AaveV4DeployBase.sol @@ -11,7 +11,7 @@ import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; import {AaveV4GatewayBatch} from 'src/deployments/batches/AaveV4GatewayBatch.sol'; -library AaveV4DeployCore { +library AaveV4DeployBase { function deployAccessBatch( address admin ) internal returns (BatchReports.AccessBatchReport memory) { @@ -45,12 +45,12 @@ library AaveV4DeployCore { string memory oracleSuffix, string memory label ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { - AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch( - spokeProxyAdminOwner, - accessManagerAddress, - oracleDecimals, - string.concat(label, oracleSuffix) - ); + AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch({ + spokeProxyAdminOwner_: spokeProxyAdminOwner, + accessManagerAddress_: accessManagerAddress, + oracleDecimals_: oracleDecimals, + oracleDescription_: string.concat(label, oracleSuffix) + }); return spokeInstanceBatch.getReport(); } diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 7255b7cc2..58f83f408 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -7,7 +7,7 @@ pragma solidity ^0.8.0; import {Logger} from 'src/deployments/utils/Logger.sol'; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; -import {AaveV4DeployCore} from 'src/deployments/orchestration/AaveV4DeployCore.sol'; +import {AaveV4DeployBase} from 'src/deployments/orchestration/AaveV4DeployBase.sol'; import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; import {AaveV4ConfiguratorBatch} from 'src/deployments/batches/AaveV4ConfiguratorBatch.sol'; import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; @@ -164,7 +164,7 @@ library AaveV4DeployOrchestration { ) internal returns (BatchReports.AccessBatchReport memory report) { logger.log('...Deploying AccessBatch...'); - report = AaveV4DeployCore.deployAccessBatch({admin: accessManagerAdmin}); + report = AaveV4DeployBase.deployAccessBatch({admin: accessManagerAdmin}); logger.log('AccessManager', report.accessManagerAddress); logger.log(''); @@ -178,7 +178,7 @@ library AaveV4DeployOrchestration { ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { logger.log('...Deploying ConfiguratorBatch...'); - report = AaveV4DeployCore.deployConfiguratorBatch({ + report = AaveV4DeployBase.deployConfiguratorBatch({ hubConfiguratorOwner: hubConfiguratorOwner, spokeConfiguratorOwner: spokeConfiguratorOwner }); @@ -291,7 +291,7 @@ library AaveV4DeployOrchestration { string memory label ) internal returns (BatchReports.SpokeInstanceBatchReport memory report) { logger.log('...Deploying AaveV4SpokeInstanceBatch...'); - report = AaveV4DeployCore.deploySpokeInstanceBatch( + report = AaveV4DeployBase.deploySpokeInstanceBatch( spokeProxyAdminOwner, accessManagerAddress, ORACLE_DECIMALS, @@ -307,7 +307,7 @@ library AaveV4DeployOrchestration { address accessManagerAddress ) internal returns (BatchReports.HubBatchReport memory report) { logger.log('...Deploying HubBatch...'); - report = AaveV4DeployCore.deployHubBatch(treasurySpokeOwner, accessManagerAddress); + report = AaveV4DeployBase.deployHubBatch(treasurySpokeOwner, accessManagerAddress); return report; } @@ -317,7 +317,7 @@ library AaveV4DeployOrchestration { address nativeWrapper ) internal returns (BatchReports.GatewaysBatchReport memory report) { logger.log('...Deploying GatewayBatch...'); - report = AaveV4DeployCore.deployGatewaysBatch({ + report = AaveV4DeployBase.deployGatewaysBatch({ owner: gatewayOwner, nativeWrapper: nativeWrapper }); diff --git a/src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol index f47581f9c..7728d9bce 100644 --- a/src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol @@ -10,8 +10,7 @@ contract AaveV4AaveOracleDeployProcedure { uint8 decimals_, string memory description_ ) internal returns (address) { - address oracle = address(new AaveOracle(spoke_, decimals_, description_)); - - return oracle; + return + address(new AaveOracle({spoke_: spoke_, decimals_: decimals_, description_: description_})); } } diff --git a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol index c37ea3fc7..1d0e40737 100644 --- a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol @@ -6,8 +6,6 @@ import {AccessManagerEnumerable} from 'src/access/AccessManagerEnumerable.sol'; contract AaveV4AccessManagerEnumerableDeployProcedure { function _deployAccessManagerEnumerable(address admin_) internal returns (address) { - address accessManager = address(new AccessManagerEnumerable(admin_)); - - return accessManager; + return address(new AccessManagerEnumerable({initialAdmin_: admin_})); } } diff --git a/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol index cc4894e08..6208c2041 100644 --- a/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol @@ -6,8 +6,6 @@ import {HubConfigurator} from 'src/hub/HubConfigurator.sol'; contract AaveV4HubConfiguratorDeployProcedure { function _deployHubConfigurator(address owner_) internal returns (address) { - address hubConfigurator = address(new HubConfigurator(owner_)); - - return hubConfigurator; + return address(new HubConfigurator({owner_: owner_})); } } diff --git a/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol index e6bcc05f8..57811d158 100644 --- a/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol @@ -6,8 +6,6 @@ import {Hub} from 'src/hub/Hub.sol'; contract AaveV4HubDeployProcedure { function _deployHub(address accessManager_) internal returns (address) { - address hub = address(new Hub(accessManager_)); - - return hub; + return address(new Hub({authority_: accessManager_})); } } diff --git a/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol index 70324733c..d24677054 100644 --- a/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol @@ -6,8 +6,6 @@ import {AssetInterestRateStrategy} from 'src/hub/AssetInterestRateStrategy.sol'; contract AaveV4InterestRateStrategyDeployProcedure { function _deployInterestRateStrategy(address hub_) internal returns (address) { - address interestRateStrategy = address(new AssetInterestRateStrategy(hub_)); - - return interestRateStrategy; + return address(new AssetInterestRateStrategy({hub_: hub_})); } } diff --git a/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol index 66c4304d4..f34bb80aa 100644 --- a/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol @@ -9,8 +9,6 @@ contract AaveV4NativeTokenGatewayDeployProcedure { address nativeWrapper_, address owner_ ) internal returns (address) { - address nativeTokenGateway = address(new NativeTokenGateway(nativeWrapper_, owner_)); - - return nativeTokenGateway; + return address(new NativeTokenGateway({nativeWrapper_: nativeWrapper_, initialOwner_: owner_})); } } diff --git a/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol index eab654ea2..71e76c08d 100644 --- a/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol @@ -6,8 +6,6 @@ import {SignatureGateway} from 'src/position-manager/SignatureGateway.sol'; contract AaveV4SignatureGatewayDeployProcedure { function _deploySignatureGateway(address owner_) internal returns (address) { - address signatureGateway = address(new SignatureGateway(owner_)); - - return signatureGateway; + return address(new SignatureGateway({initialOwner_: owner_})); } } diff --git a/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol index ac1906a83..5df172f0f 100644 --- a/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol @@ -6,8 +6,6 @@ import {SpokeConfigurator} from 'src/spoke/SpokeConfigurator.sol'; contract AaveV4SpokeConfiguratorDeployProcedure { function _deploySpokeConfigurator(address owner_) internal returns (address) { - address spokeConfigurator = address(new SpokeConfigurator(owner_)); - - return spokeConfigurator; + return address(new SpokeConfigurator({owner_: owner_})); } } diff --git a/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol index 9684c5c0d..58184bbc9 100644 --- a/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol @@ -6,8 +6,6 @@ import {SpokeInstance} from 'src/spoke/instances/SpokeInstance.sol'; contract AaveV4SpokeInstanceDeployProcedure { function _deploySpokeInstance(address oracle_) internal returns (address) { - address spokeInstance = address(new SpokeInstance(oracle_)); - - return spokeInstance; + return address(new SpokeInstance({oracle_: oracle_})); } } diff --git a/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol index f8509f5c7..f6700898a 100644 --- a/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol @@ -2,7 +2,9 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {TransparentUpgradeableProxy} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; +import { + TransparentUpgradeableProxy +} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; contract AaveV4TransparentUpgradeableProxyDeployProcedure { function _proxify( @@ -10,8 +12,9 @@ contract AaveV4TransparentUpgradeableProxyDeployProcedure { address initialOwner_, bytes memory data_ ) internal returns (address) { - address proxy = address(new TransparentUpgradeableProxy(logic_, initialOwner_, data_)); - - return proxy; + return + address( + new TransparentUpgradeableProxy({_logic: logic_, initialOwner: initialOwner_, _data: data_}) + ); } } diff --git a/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol index 9968db9db..0390f581d 100644 --- a/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol @@ -6,8 +6,6 @@ import {TreasurySpoke} from 'src/spoke/TreasurySpoke.sol'; contract AaveV4TreasurySpokeDeployProcedure { function _deployTreasurySpoke(address owner_, address hub_) internal returns (address) { - address treasurySpoke = address(new TreasurySpoke(owner_, hub_)); - - return treasurySpoke; + return address(new TreasurySpoke({owner_: owner_, hub_: hub_})); } } diff --git a/src/deployments/procedures/deploy/WETHDeployProcedure.sol b/src/deployments/procedures/deploy/WETHDeployProcedure.sol index 79b631cb0..d6d6b5e57 100644 --- a/src/deployments/procedures/deploy/WETHDeployProcedure.sol +++ b/src/deployments/procedures/deploy/WETHDeployProcedure.sol @@ -6,8 +6,6 @@ import {WETH9} from 'src/dependencies/weth/WETH9.sol'; contract WETHDeployProcedure { function _deployWETH() internal returns (address) { - address weth = address(new WETH9()); - - return weth; + return address(new WETH9()); } } diff --git a/src/deployments/utils/libraries/Utils.sol b/src/deployments/utils/libraries/Utils.sol index fdaafbe7f..8c9765f70 100644 --- a/src/deployments/utils/libraries/Utils.sol +++ b/src/deployments/utils/libraries/Utils.sol @@ -4,8 +4,11 @@ pragma solidity ^0.8.0; library Utils { function computeCreateAddress(address deployer, uint8 nonce) internal pure returns (address) { - // RLP([deployer, nonce]) for 1 <= nonce <= 0x7f - bytes memory rlp = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, nonce); + // RLP([deployer, nonce]) for 0 <= nonce <= 0x7f + // nonce == 0 is encoded as the empty string (0x80) in RLP + require(nonce < 0x80, 'Utils: nonce >= 0x80 not supported'); + bytes1 nonceRlp = nonce == 0 ? bytes1(0x80) : bytes1(nonce); + bytes memory rlp = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, nonceRlp); return address(uint160(uint256(keccak256(rlp)))); } } diff --git a/tests/Base.t.sol b/tests/Base.t.sol index 1a098471c..145c64954 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -284,7 +284,7 @@ abstract contract Base is BatchTestProcedures { } function _setupFixtures() internal virtual { - OrchestrationReports.TestEnvReport memory report = _deployFixtures({numHubs: 1, numSpokes: 3}); + TestTypes.TestEnvReport memory report = _deployFixtures({numHubs: 1, numSpokes: 3}); _setupFixturesRoles(report); // todo rm when tests adapted to multiple hubs and spokes @@ -303,7 +303,7 @@ abstract contract Base is BatchTestProcedures { function _deployFixtures( uint256 numHubs, uint256 numSpokes - ) internal virtual returns (OrchestrationReports.TestEnvReport memory report) { + ) internal virtual returns (TestTypes.TestEnvReport memory report) { report = AaveV4TestOrchestration.deployTestEnv({ admin: ADMIN, treasuryAdmin: TREASURY_ADMIN, @@ -340,7 +340,7 @@ abstract contract Base is BatchTestProcedures { return report; } - function _setupFixturesRoles(OrchestrationReports.TestEnvReport memory report) internal virtual { + function _setupFixturesRoles(TestTypes.TestEnvReport memory report) internal virtual { if (report.accessManagerAddress == address(0)) report.accessManagerAddress = address(accessManager); @@ -369,28 +369,28 @@ abstract contract Base is BatchTestProcedures { } function _initTokenList() internal { - ConfigData.TestTokenInput[] memory tokenInputs = new ConfigData.TestTokenInput[](5); - tokenInputs[0] = ConfigData.TestTokenInput({ + TestTypes.TestTokenInput[] memory tokenInputs = new TestTypes.TestTokenInput[](5); + tokenInputs[0] = TestTypes.TestTokenInput({ name: 'USDX', symbol: 'USDX', decimals: _decimals.usdx }); - tokenInputs[1] = ConfigData.TestTokenInput({ + tokenInputs[1] = TestTypes.TestTokenInput({ name: 'DAI', symbol: 'DAI', decimals: _decimals.dai }); - tokenInputs[2] = ConfigData.TestTokenInput({ + tokenInputs[2] = TestTypes.TestTokenInput({ name: 'WBTC', symbol: 'WBTC', decimals: _decimals.wbtc }); - tokenInputs[3] = ConfigData.TestTokenInput({ + tokenInputs[3] = TestTypes.TestTokenInput({ name: 'USDY', symbol: 'USDY', decimals: _decimals.usdy }); - tokenInputs[4] = ConfigData.TestTokenInput({ + tokenInputs[4] = TestTypes.TestTokenInput({ name: 'USDZ', symbol: 'USDZ', decimals: _decimals.usdz @@ -956,7 +956,7 @@ abstract contract Base is BatchTestProcedures { irData: abi.encode(_defaultIrData) }); - OrchestrationReports.TestEnvReport memory report = _addFixture('2', assetsList); + TestTypes.TestEnvReport memory report = _addFixture('2', assetsList); return ( IHub(report.hubReports[0].hubAddress), AssetInterestRateStrategy(report.hubReports[0].irStrategyAddress) @@ -992,7 +992,7 @@ abstract contract Base is BatchTestProcedures { irData: abi.encode(_defaultIrData) }); - OrchestrationReports.TestEnvReport memory report = _addFixture('3', assetsList); + TestTypes.TestEnvReport memory report = _addFixture('3', assetsList); return ( IHub(report.hubReports[0].hubAddress), AssetInterestRateStrategy(report.hubReports[0].irStrategyAddress) @@ -1002,7 +1002,7 @@ abstract contract Base is BatchTestProcedures { function _addFixture( string memory label, FixtureAssetList[] memory assetsList - ) internal returns (OrchestrationReports.TestEnvReport memory report) { + ) internal returns (TestTypes.TestEnvReport memory report) { report = _deployFixtures({numHubs: 1, numSpokes: 0}); _setupFixturesRoles(report); diff --git a/tests/deployments/batches/TestTokensBatch.sol b/tests/deployments/batches/TestTokensBatch.sol index 0f52ab711..241c3e9e7 100644 --- a/tests/deployments/batches/TestTokensBatch.sol +++ b/tests/deployments/batches/TestTokensBatch.sol @@ -6,23 +6,26 @@ import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; -import {TestnetERC20DeployProcedure} from 'src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol'; +import { + TestnetERC20DeployProcedure +} from 'tests/deployments/procedures/TestnetERC20DeployProcedure.sol'; +import {TestTypes} from 'tests/utils/TestTypes.sol'; contract TestTokensBatch is WETHDeployProcedure, TestnetERC20DeployProcedure { - BatchReports.TestTokensBatchReport internal _report; + TestTypes.TestTokensBatchReport internal _report; - constructor(ConfigData.TestTokenInput[] memory inputs_) { + constructor(TestTypes.TestTokenInput[] memory inputs_) { _report.tokenAddresses = new address[](inputs_.length); _report.wethAddress = _deployWETH(); for (uint256 i; i < inputs_.length; i++) { - ConfigData.TestTokenInput memory input = inputs_[i]; + TestTypes.TestTokenInput memory input = inputs_[i]; address tokenAddress = _deployTestnetERC20(input.name, input.symbol, input.decimals); _report.tokenAddresses[i] = tokenAddress; } } - function getReport() external view returns (BatchReports.TestTokensBatchReport memory) { + function getReport() external view returns (TestTypes.TestTokensBatchReport memory) { return _report; } } diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol index 1e45a9a71..7cb3d058b 100644 --- a/tests/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -31,7 +31,7 @@ import { AaveV4SpokeConfigProcedures } from 'src/deployments/procedures/config/AaveV4SpokeConfigProcedures.sol'; -import {AaveV4DeployCore} from 'src/deployments/orchestration/AaveV4DeployCore.sol'; +import {AaveV4DeployBase} from 'src/deployments/orchestration/AaveV4DeployBase.sol'; import {TestTypes} from 'tests/utils/TestTypes.sol'; import {WETH9} from 'src/dependencies/weth/WETH9.sol'; @@ -45,9 +45,9 @@ library AaveV4TestOrchestration { Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); function deployTestTokens( - ConfigData.TestTokenInput[] memory tokenInputs + TestTypes.TestTokenInput[] memory tokenInputs ) external returns (TestTypes.TokenList memory) { - OrchestrationReports.TestTokensReport memory tokensReport = _deployTestTokensBatch(tokenInputs); + TestTypes.TestTokensReport memory tokensReport = _deployTestTokensBatch(tokenInputs); TestTypes.TokenList memory tokenList; tokenList.weth = WETH9(payable(tokensReport.wethAddress)); @@ -64,18 +64,18 @@ library AaveV4TestOrchestration { address treasuryAdmin, uint256 hubCount, uint256 spokeCount - ) external returns (OrchestrationReports.TestEnvReport memory) { - OrchestrationReports.TestEnvReport memory report; + ) external returns (TestTypes.TestEnvReport memory) { + TestTypes.TestEnvReport memory report; - report.hubReports = new OrchestrationReports.TestHubReport[](hubCount); - report.spokeReports = new OrchestrationReports.TestSpokeReport[](spokeCount); + report.hubReports = new TestTypes.TestHubReport[](hubCount); + report.spokeReports = new TestTypes.TestSpokeReport[](spokeCount); // Deploy Access Batch - report.accessManagerAddress = AaveV4DeployCore.deployAccessBatch(admin).accessManagerAddress; + report.accessManagerAddress = AaveV4DeployBase.deployAccessBatch(admin).accessManagerAddress; // Deploy Hub Batches for (uint256 i; i < hubCount; ++i) { - BatchReports.HubBatchReport memory hubReport = AaveV4DeployCore.deployHubBatch( + BatchReports.HubBatchReport memory hubReport = AaveV4DeployBase.deployHubBatch( treasuryAdmin, report.accessManagerAddress ); @@ -86,7 +86,7 @@ library AaveV4TestOrchestration { // Deploy Spoke Instance Batches for (uint256 i; i < spokeCount; ++i) { - BatchReports.SpokeInstanceBatchReport memory spokeReport = AaveV4DeployCore + BatchReports.SpokeInstanceBatchReport memory spokeReport = AaveV4DeployBase .deploySpokeInstanceBatch( admin, report.accessManagerAddress, @@ -101,7 +101,7 @@ library AaveV4TestOrchestration { return report; } - function setRolesTestEnv(OrchestrationReports.TestEnvReport memory report) public { + function setRolesTestEnv(TestTypes.TestEnvReport memory report) public { // Set Hub Roles for (uint256 i; i < report.hubReports.length; ++i) { AaveV4HubRolesProcedure.setHubRoles( @@ -120,7 +120,7 @@ library AaveV4TestOrchestration { } function grantRolesTestEnv( - OrchestrationReports.TestEnvReport memory report, + TestTypes.TestEnvReport memory report, address admin, address hubAdmin, address spokeAdmin @@ -130,7 +130,7 @@ library AaveV4TestOrchestration { } // function grantAccessManagerRolesTestEnv( - // OrchestrationReports.TestEnvReport memory report, + // TestTypes.TestEnvReport memory report, // address admin // ) external { // // grant RootAdmin Role @@ -142,7 +142,7 @@ library AaveV4TestOrchestration { // } function grantHubRolesTestEnv( - OrchestrationReports.TestEnvReport memory report, + TestTypes.TestEnvReport memory report, address admin, address hubAdmin ) public { @@ -152,7 +152,7 @@ library AaveV4TestOrchestration { } function grantSpokeRolesTestEnv( - OrchestrationReports.TestEnvReport memory report, + TestTypes.TestEnvReport memory report, address admin, address spokeAdmin ) public { @@ -161,33 +161,6 @@ library AaveV4TestOrchestration { AaveV4SpokeRolesProcedure.grantSpokeAdminRole(report.accessManagerAddress, spokeAdmin); } - // function deployTestHub( - // address admin, - // address treasuryAdmin, - // ConfigData.AddAssetParams[] memory paramsList - // ) external returns (address, OrchestrationReports.TestHubReport memory) { - // OrchestrationReports.TestHubReport memory report; - - // address accessManagerAddress = AaveV4DeployCore.deployAccessBatch(admin).accessManagerAddress; - - // // Deploy Hub Batch - // BatchReports.HubBatchReport memory hubReport = AaveV4DeployCore.deployHubBatch( - // treasuryAdmin, - // accessManagerAddress - // ); - // report.hubAddress = hubReport.hubAddress; - // report.irStrategyAddress = hubReport.irStrategyAddress; - // report.treasurySpokeAddress = hubReport.treasurySpokeAddress; - - // // Set Hub Roles - // AaveV4HubRolesProcedure.setHubAdminRole(accessManagerAddress, report.hubAddress); - - // // Configure Hub Assets - // configureHubsAssets(paramsList); - - // return (accessManagerAddress, report); - // } - function configureHubsAssets( ConfigData.AddAssetParams[] memory paramsList ) public returns (uint256[] memory) { @@ -224,14 +197,14 @@ library AaveV4TestOrchestration { } function _deployTestTokensBatch( - ConfigData.TestTokenInput[] memory tokenInputs - ) internal returns (OrchestrationReports.TestTokensReport memory) { - OrchestrationReports.TestTokensReport memory report; + TestTypes.TestTokenInput[] memory tokenInputs + ) internal returns (TestTypes.TestTokensReport memory) { + TestTypes.TestTokensReport memory report; report.testTokenAddresses = new address[](tokenInputs.length); // Deploy Test Tokens Batch - BatchReports.TestTokensBatchReport memory tokensReport = _deployTokensBatch(tokenInputs); + TestTypes.TestTokensBatchReport memory tokensReport = _deployTokensBatch(tokenInputs); report.wethAddress = tokensReport.wethAddress; report.testTokenAddresses = tokensReport.tokenAddresses; @@ -239,8 +212,8 @@ library AaveV4TestOrchestration { } function _deployTokensBatch( - ConfigData.TestTokenInput[] memory tokenInputs - ) internal returns (BatchReports.TestTokensBatchReport memory) { + TestTypes.TestTokenInput[] memory tokenInputs + ) internal returns (TestTypes.TestTokensBatchReport memory) { TestTokensBatch tokensBatch = new TestTokensBatch(tokenInputs); return tokensBatch.getReport(); } diff --git a/src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol b/tests/deployments/procedures/TestnetERC20DeployProcedure.sol similarity index 75% rename from src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol rename to tests/deployments/procedures/TestnetERC20DeployProcedure.sol index 866ecaf0e..982f917ed 100644 --- a/src/deployments/procedures/deploy/TestnetERC20DeployProcedure.sol +++ b/tests/deployments/procedures/TestnetERC20DeployProcedure.sol @@ -10,7 +10,9 @@ contract TestnetERC20DeployProcedure { string memory symbol_, uint8 decimals_ ) internal returns (address) { - address token = address(new TestnetERC20(name_, symbol_, decimals_)); + address token = address( + new TestnetERC20({name_: name_, symbol_: symbol_, decimals_: decimals_}) + ); return token; } diff --git a/tests/deployments/utils/libraries/Utils.t.sol b/tests/deployments/utils/libraries/Utils.t.sol new file mode 100644 index 000000000..795f4e8de --- /dev/null +++ b/tests/deployments/utils/libraries/Utils.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; +import {Test} from 'forge-std/Test.sol'; + +contract UtilsTest is Test { + function testComputeCreateAddress_fuzz(address deployer, uint8 nonce) public { + vm.assume(deployer != address(0)); + vm.assume(nonce < 0x80); + address expected = vm.computeCreateAddress(deployer, nonce); + assertEq(Utils.computeCreateAddress(deployer, nonce), expected); + } +} diff --git a/tests/unit/Spoke/Spoke.Getters.t.sol b/tests/unit/Spoke/Spoke.Getters.t.sol index c10d0b0e5..c9fc279fa 100644 --- a/tests/unit/Spoke/Spoke.Getters.t.sol +++ b/tests/unit/Spoke/Spoke.Getters.t.sol @@ -16,7 +16,7 @@ contract SpokeGettersTest is SpokeBase { super.setUp(); // Deploy new spoke without setting the liquidation config - OrchestrationReports.TestEnvReport memory report = _deployFixtures({numHubs: 0, numSpokes: 1}); + TestTypes.TestEnvReport memory report = _deployFixtures({numHubs: 0, numSpokes: 1}); _setupFixturesRoles(report); spoke = ISpoke(report.spokeReports[0].spokeAddress); diff --git a/tests/unit/Spoke/Spoke.Upgradeable.t.sol b/tests/unit/Spoke/Spoke.Upgradeable.t.sol index 4145005a1..909cf43e5 100644 --- a/tests/unit/Spoke/Spoke.Upgradeable.t.sol +++ b/tests/unit/Spoke/Spoke.Upgradeable.t.sol @@ -86,8 +86,8 @@ contract SpokeUpgradeableTest is SpokeBase { ) ); - OrchestrationReports.TestEnvReport memory report; - report.spokeReports = new OrchestrationReports.TestSpokeReport[](1); + TestTypes.TestEnvReport memory report; + report.spokeReports = new TestTypes.TestSpokeReport[](1); report.spokeReports[0].spokeAddress = address(spokeProxy); _setupFixturesRoles(report); diff --git a/tests/utils/TestTypes.sol b/tests/utils/TestTypes.sol index 024664195..38ae84d32 100644 --- a/tests/utils/TestTypes.sol +++ b/tests/utils/TestTypes.sol @@ -19,4 +19,37 @@ library TestTypes { address spoke; uint256 reserveId; } + + struct TestTokensBatchReport { + address wethAddress; + address[] tokenAddresses; + } + + struct TestTokenInput { + string name; + string symbol; + uint8 decimals; + } + + struct TestHubReport { + address hubAddress; + address irStrategyAddress; + address treasurySpokeAddress; + } + + struct TestSpokeReport { + address spokeAddress; + address aaveOracleAddress; + } + + struct TestEnvReport { + address accessManagerAddress; + TestHubReport[] hubReports; + TestSpokeReport[] spokeReports; + } + + struct TestTokensReport { + address wethAddress; + address[] testTokenAddresses; + } } From 27260d08a9c358e3bd6bd0bff9dc51a5142a1c8a Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Sat, 13 Dec 2025 00:37:44 -0600 Subject: [PATCH 49/62] fix: pr comments; re-order imports --- scripts/deploy/AaveV4DeployBatchBase.s.sol | 6 ++-- .../batches/AaveV4SpokeInstanceBatch.sol | 9 +++--- .../orchestration/AaveV4DeployBase.sol | 2 +- .../AaveV4DeployOrchestration.sol | 14 ++++++---- .../AaveV4AccessManagerRolesProcedure.sol | 2 +- .../roles/AaveV4HubRolesProcedure.sol | 13 ++++----- .../roles/AaveV4SpokeRolesProcedure.sol | 28 +++++++++---------- .../procedures/roles}/Roles.sol | 0 src/deployments/utils/DeployUtils.sol | 9 ------ src/deployments/utils/Logger.sol | 8 ++---- tests/Base.t.sol | 2 +- .../orchestration/AaveV4TestOrchestration.sol | 4 +-- tests/utils/BatchTestProcedures.sol | 2 +- 13 files changed, 44 insertions(+), 55 deletions(-) rename src/{libraries/types => deployments/procedures/roles}/Roles.sol (100%) delete mode 100644 src/deployments/utils/DeployUtils.sol diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index 5cdd2a5f9..e96c5970e 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -2,19 +2,17 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {Script} from 'forge-std/Script.sol'; - import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; -import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; import {MetadataLogger} from 'src/deployments/utils/MetadataLogger.sol'; import { AaveV4DeployOrchestration } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; +import {Script} from 'forge-std/Script.sol'; import {console2 as console} from 'forge-std/console2.sol'; -abstract contract AaveV4DeployBatchBaseScript is Script, DeployUtils, InputUtils { +abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { string internal constant INPUT_PATH = 'scripts/deploy/inputs/'; string internal constant OUTPUT_DIR = 'output/reports/deployments/'; diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index e17121343..4a8e05779 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -3,16 +3,17 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; +import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; + +import { + AaveV4AaveOracleDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol'; import { AaveV4SpokeInstanceDeployProcedure } from 'src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol'; import { AaveV4TransparentUpgradeableProxyDeployProcedure } from 'src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol'; -import { - AaveV4AaveOracleDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol'; -import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; contract AaveV4SpokeInstanceBatch is AaveV4SpokeInstanceDeployProcedure, diff --git a/src/deployments/orchestration/AaveV4DeployBase.sol b/src/deployments/orchestration/AaveV4DeployBase.sol index a5e122742..65a556c36 100644 --- a/src/deployments/orchestration/AaveV4DeployBase.sol +++ b/src/deployments/orchestration/AaveV4DeployBase.sol @@ -7,9 +7,9 @@ import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationRepor import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; import {AaveV4ConfiguratorBatch} from 'src/deployments/batches/AaveV4ConfiguratorBatch.sol'; +import {AaveV4GatewayBatch} from 'src/deployments/batches/AaveV4GatewayBatch.sol'; import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; -import {AaveV4GatewayBatch} from 'src/deployments/batches/AaveV4GatewayBatch.sol'; library AaveV4DeployBase { function deployAccessBatch( diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 58f83f408..225281149 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -2,17 +2,17 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -// import 'forge-std/Vm.sol'; - -import {Logger} from 'src/deployments/utils/Logger.sol'; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; + +import {AaveV4DeployBase} from 'src/deployments/orchestration/AaveV4DeployBase.sol'; + import {AaveV4DeployBase} from 'src/deployments/orchestration/AaveV4DeployBase.sol'; import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; import {AaveV4ConfiguratorBatch} from 'src/deployments/batches/AaveV4ConfiguratorBatch.sol'; -import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol'; import {AaveV4GatewayBatch} from 'src/deployments/batches/AaveV4GatewayBatch.sol'; +import {AaveV4HubBatch} from 'src/deployments/batches/AaveV4HubBatch.sol'; import { AaveV4AccessManagerRolesProcedure @@ -23,7 +23,9 @@ import { import { AaveV4SpokeRolesProcedure } from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; + import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; +import {Logger} from 'src/deployments/utils/Logger.sol'; library AaveV4DeployOrchestration { uint8 private constant ORACLE_DECIMALS = 8; @@ -229,7 +231,7 @@ library AaveV4DeployOrchestration { logger.log(' TreasurySpoke', hubReport.report.treasurySpokeAddress); logger.log('...Setting Hub roles...'); - AaveV4HubRolesProcedure.setHubRoles(accessManagerAddress, hubReport.report.hubAddress); + AaveV4HubRolesProcedure.setupHubRoles(accessManagerAddress, hubReport.report.hubAddress); return hubReport; } @@ -276,7 +278,7 @@ library AaveV4DeployOrchestration { logger.log(' AaveOracle', spokeReport.report.aaveOracleAddress); logger.log('...Setting Spoke roles...'); - AaveV4SpokeRolesProcedure.setSpokeRoles({ + AaveV4SpokeRolesProcedure.setupSpokeRoles({ accessManagerAddress: accessManagerAddress, spokeAddress: spokeReport.report.spokeProxyAddress }); diff --git a/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol index 600376144..714b196ab 100644 --- a/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol @@ -2,8 +2,8 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {Roles} from 'src/libraries/types/Roles.sol'; import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; +import {Roles} from 'src/deployments/procedures/roles/Roles.sol'; library AaveV4AccessManagerRolesProcedure { function grantRootAdminRole( diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol index 60ad01376..c14d33e3c 100644 --- a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -2,9 +2,8 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {Roles} from 'src/libraries/types/Roles.sol'; - import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; +import {Roles} from 'src/deployments/procedures/roles/Roles.sol'; import {IHub} from 'src/hub/interfaces/IHub.sol'; library AaveV4HubRolesProcedure { @@ -29,12 +28,12 @@ library AaveV4HubRolesProcedure { }); } - function setHubRoles(address accessManagerAddress, address hubAddress) internal { - setHubFeeMinterRole(accessManagerAddress, hubAddress); - setHubConfiguratorRole(accessManagerAddress, hubAddress); + function setupHubRoles(address accessManagerAddress, address hubAddress) internal { + setupHubFeeMinterRole(accessManagerAddress, hubAddress); + setupHubConfiguratorRole(accessManagerAddress, hubAddress); } - function setHubFeeMinterRole(address accessManagerAddress, address hubAddress) internal { + function setupHubFeeMinterRole(address accessManagerAddress, address hubAddress) internal { bytes4[] memory selectors = getHubFeeMinterRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( hubAddress, @@ -43,7 +42,7 @@ library AaveV4HubRolesProcedure { ); } - function setHubConfiguratorRole(address accessManagerAddress, address hubAddress) internal { + function setupHubConfiguratorRole(address accessManagerAddress, address hubAddress) internal { bytes4[] memory selectors = getHubConfiguratorRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( hubAddress, diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol index e1f7535d6..3041b4d10 100644 --- a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -2,19 +2,11 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {Roles} from 'src/libraries/types/Roles.sol'; import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; +import {Roles} from 'src/deployments/procedures/roles/Roles.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; library AaveV4SpokeRolesProcedure { - function grantSpokeConfiguratorRole(address accessManagerAddress, address admin) internal { - IAccessManager(accessManagerAddress).grantRole({ - roleId: Roles.SPOKE_CONFIGURATOR_ROLE, - account: admin, - executionDelay: 0 - }); - } - function grantSpokeAdminRole(address accessManagerAddress, address admin) internal { grantSpokePositionUpdaterRole(accessManagerAddress, admin); grantSpokeConfiguratorRole(accessManagerAddress, admin); @@ -28,12 +20,20 @@ library AaveV4SpokeRolesProcedure { }); } - function setSpokeRoles(address accessManagerAddress, address spokeAddress) internal { - setSpokePositionUpdaterRole(accessManagerAddress, spokeAddress); - setSpokeConfiguratorRole(accessManagerAddress, spokeAddress); + function grantSpokeConfiguratorRole(address accessManagerAddress, address admin) internal { + IAccessManager(accessManagerAddress).grantRole({ + roleId: Roles.SPOKE_CONFIGURATOR_ROLE, + account: admin, + executionDelay: 0 + }); + } + + function setupSpokeRoles(address accessManagerAddress, address spokeAddress) internal { + setupSpokePositionUpdaterRole(accessManagerAddress, spokeAddress); + setupSpokeConfiguratorRole(accessManagerAddress, spokeAddress); } - function setSpokePositionUpdaterRole( + function setupSpokePositionUpdaterRole( address accessManagerAddress, address spokeAddress ) internal { @@ -45,7 +45,7 @@ library AaveV4SpokeRolesProcedure { ); } - function setSpokeConfiguratorRole(address accessManagerAddress, address spokeAddress) internal { + function setupSpokeConfiguratorRole(address accessManagerAddress, address spokeAddress) internal { bytes4[] memory selectors = getSpokeConfiguratorRoleSelectors(); IAccessManager(accessManagerAddress).setTargetFunctionRole( spokeAddress, diff --git a/src/libraries/types/Roles.sol b/src/deployments/procedures/roles/Roles.sol similarity index 100% rename from src/libraries/types/Roles.sol rename to src/deployments/procedures/roles/Roles.sol diff --git a/src/deployments/utils/DeployUtils.sol b/src/deployments/utils/DeployUtils.sol deleted file mode 100644 index c3770cce3..000000000 --- a/src/deployments/utils/DeployUtils.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.0; - -import 'forge-std/Vm.sol'; - -contract DeployUtils { - Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); -} diff --git a/src/deployments/utils/Logger.sol b/src/deployments/utils/Logger.sol index 3c0d3765c..649d32a41 100644 --- a/src/deployments/utils/Logger.sol +++ b/src/deployments/utils/Logger.sol @@ -4,12 +4,12 @@ pragma solidity ^0.8.0; import 'forge-std/StdJson.sol'; import 'forge-std/Vm.sol'; -import {console} from 'forge-std/console.sol'; -import {DeployUtils} from 'src/deployments/utils/DeployUtils.sol'; +import {console2 as console} from 'forge-std/console2.sol'; -contract Logger is DeployUtils { +contract Logger { using stdJson for string; + Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); struct AddressEntry { string label; address value; @@ -20,8 +20,6 @@ contract Logger is DeployUtils { uint256 value; } - Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); - string internal _outputPath; string internal _root; string internal _json; diff --git a/tests/Base.t.sol b/tests/Base.t.sol index 145c64954..dae9944fb 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -36,7 +36,7 @@ import {WadRayMath} from 'src/libraries/math/WadRayMath.sol'; import {MathUtils} from 'src/libraries/math/MathUtils.sol'; import {PercentageMath} from 'src/libraries/math/PercentageMath.sol'; import {EIP712Types} from 'src/libraries/types/EIP712Types.sol'; -import {Roles} from 'src/libraries/types/Roles.sol'; +import {Roles} from 'src/deployments/procedures/roles/Roles.sol'; import {Rescuable, IRescuable} from 'src/utils/Rescuable.sol'; import {NoncesKeyed, INoncesKeyed} from 'src/utils/NoncesKeyed.sol'; import {UnitPriceFeed} from 'src/misc/UnitPriceFeed.sol'; diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol index 7cb3d058b..04d549737 100644 --- a/tests/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -104,7 +104,7 @@ library AaveV4TestOrchestration { function setRolesTestEnv(TestTypes.TestEnvReport memory report) public { // Set Hub Roles for (uint256 i; i < report.hubReports.length; ++i) { - AaveV4HubRolesProcedure.setHubRoles( + AaveV4HubRolesProcedure.setupHubRoles( report.accessManagerAddress, report.hubReports[i].hubAddress ); @@ -112,7 +112,7 @@ library AaveV4TestOrchestration { // Set Spoke Roles for (uint256 i; i < report.spokeReports.length; ++i) { - AaveV4SpokeRolesProcedure.setSpokeRoles( + AaveV4SpokeRolesProcedure.setupSpokeRoles( report.accessManagerAddress, report.spokeReports[i].spokeAddress ); diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index d41511de7..ac40d898d 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -25,7 +25,7 @@ import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; import {Constants} from 'tests/Constants.sol'; -import {Roles} from 'src/libraries/types/Roles.sol'; +import {Roles} from 'src/deployments/procedures/roles/Roles.sol'; import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; import {IAssetInterestRateStrategy} from 'src/hub/interfaces/IAssetInterestRateStrategy.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; From 8c26cf3f05fb32095f649a48157376c9d0d84ba1 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Sat, 13 Dec 2025 01:33:26 -0600 Subject: [PATCH 50/62] test: fix --- tests/unit/Hub/Hub.Config.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/Hub/Hub.Config.t.sol b/tests/unit/Hub/Hub.Config.t.sol index 8428a31c7..4f1d492e3 100644 --- a/tests/unit/Hub/Hub.Config.t.sol +++ b/tests/unit/Hub/Hub.Config.t.sol @@ -806,7 +806,7 @@ contract HubConfigTest is HubBase { function _assumeValidAssetConfig(IHub.AssetConfig memory newConfig) internal pure { newConfig.liquidityFee = bound(newConfig.liquidityFee, 0, PercentageMath.PERCENTAGE_FACTOR) .toUint16(); - vm.assume(address(newConfig.feeReceiver) != address(0) || newConfig.liquidityFee == 0); + vm.assume(address(newConfig.feeReceiver) != address(0)); assumeNotPrecompile(newConfig.feeReceiver); assumeNotForgeAddress(newConfig.feeReceiver); assumeNotZeroAddress(newConfig.irStrategy); From 0ad7618625bc9473d3af30b63d26d10aade831de Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:35:42 -0600 Subject: [PATCH 51/62] fix: pr comments --- scripts/deploy/AaveV4DeployBatchBase.s.sol | 123 +++++---- scripts/deploy/inputs/AaveV4DeployInput.json | 2 +- snapshots/Hub.Operations.json | 8 +- snapshots/NativeTokenGateway.Operations.json | 12 +- snapshots/SignatureGateway.Operations.json | 16 +- .../Spoke.Operations.ZeroRiskPremium.json | 4 +- snapshots/Spoke.Operations.json | 4 +- src/deployments/batches/AaveV4AccessBatch.sol | 9 +- .../batches/AaveV4ConfiguratorBatch.sol | 15 +- .../batches/AaveV4GatewayBatch.sol | 24 +- src/deployments/batches/AaveV4HubBatch.sol | 23 +- .../batches/AaveV4SpokeInstanceBatch.sol | 53 ++-- src/deployments/libraries/BatchReports.sol | 22 +- src/deployments/libraries/ConfigData.sol | 1 + .../orchestration/AaveV4DeployBase.sol | 8 +- .../AaveV4DeployOrchestration.sol | 140 ++++------ .../config/AaveV4HubConfigProcedures.sol | 8 +- ...AccessManagerEnumerableDeployProcedure.sol | 4 +- .../AaveV4SpokeInstanceDeployProcedure.sol | 11 - ...sparentUpgradeableProxyDeployProcedure.sol | 20 -- .../AaveV4HubConfiguratorDeployProcedure.sol | 4 +- .../{ => hub}/AaveV4HubDeployProcedure.sol | 4 +- ...eV4InterestRateStrategyDeployProcedure.sol | 4 +- ...aveV4NativeTokenGatewayDeployProcedure.sol | 6 +- .../AaveV4SignatureGatewayDeployProcedure.sol | 4 +- .../AaveV4AaveOracleDeployProcedure.sol | 0 ...AaveV4SpokeConfiguratorDeployProcedure.sol | 4 +- .../spoke/AaveV4SpokeDeployProcedure.sol | 21 ++ .../AaveV4TreasurySpokeDeployProcedure.sol | 4 +- .../AaveV4AccessManagerRolesProcedure.sol | 17 +- .../roles/AaveV4HubRolesProcedure.sol | 37 ++- .../roles/AaveV4SpokeRolesProcedure.sol | 42 +-- src/deployments/utils/InputUtils.sol | 6 +- src/deployments/utils/Logger.sol | 42 +-- src/deployments/utils/MetadataLogger.sol | 22 +- .../roles => utils/libraries}/Roles.sol | 0 src/deployments/utils/libraries/Utils.sol | 15 + tests/Base.t.sol | 134 +++++---- tests/deployments/AaveV4BatchDeployment.t.sol | 259 +++++++++++++----- tests/deployments/batches/TestTokensBatch.sol | 10 +- .../orchestration/AaveV4TestOrchestration.sol | 125 ++++----- .../procedures/ProceduresBase.t.sol | 86 ++++++ .../procedures}/WETHDeployProcedure.sol | 0 ...cessManagerEnumerableDeployProcedure.t.sol | 28 ++ ...AaveV4HubConfiguratorDeployProcedure.t.sol | 22 ++ .../deploy/hub/AaveV4HubDeployProcedure.t.sol | 20 ++ ...4InterestRateStrategyDeployProcedure.t.sol | 22 ++ ...eV4NativeTokenGatewayDeployProcedure.t.sol | 22 ++ ...aveV4SignatureGatewayDeployProcedure.t.sol | 22 ++ .../AaveV4AccessManagerRolesProcedure.t.sol | 47 ++++ .../roles/AaveV4HubRolesProcedure.t.sol | 14 + .../roles/AaveV4SpokeRolesProcedure.t.sol | 14 + .../AaveV4AaveOracleDeployProcedure.t.sol | 25 ++ ...veV4SpokeConfiguratorDeployProcedure.t.sol | 22 ++ .../spoke/AaveV4SpokeDeployProcedure.t.sol | 24 ++ .../AaveV4TreasurySpokeDeployProcedure.t.sol | 27 ++ tests/deployments/utils/libraries/Utils.t.sol | 2 +- tests/gas/Base.gas.t.sol | 13 + tests/gas/Gateways.Operations.gas.t.sol | 6 +- tests/gas/Hub.Operations.gas.t.sol | 9 +- tests/gas/Spoke.Getters.gas.t.sol | 9 +- tests/gas/Spoke.Operations.gas.t.sol | 3 +- ...AaveV4AaveOracleDeployProcedureWrapper.sol | 17 ++ ...anagerEnumerableDeployProcedureWrapper.sol | 15 + ...veV4AccessManagerRolesProcedureWrapper.sol | 17 ++ ...4HubConfiguratorDeployProcedureWrapper.sol | 13 + .../AaveV4HubDeployProcedureWrapper.sol | 13 + .../AaveV4HubRolesProcedureWrapper.sol | 41 +++ ...restRateStrategyDeployProcedureWrapper.sol | 15 + ...tiveTokenGatewayDeployProcedureWrapper.sol | 16 ++ ...SignatureGatewayDeployProcedureWrapper.sol | 13 + ...pokeConfiguratorDeployProcedureWrapper.sol | 13 + .../AaveV4SpokeDeployProcedureWrapper.sol | 17 ++ .../AaveV4SpokeRolesProcedureWrapper.sol | 40 +++ ...eV4TreasurySpokeDeployProcedureWrapper.sol | 13 + tests/unit/AaveOracle.t.sol | 2 +- tests/unit/AssetInterestRateStrategy.t.sol | 2 +- tests/unit/Spoke/Spoke.Getters.t.sol | 2 +- tests/unit/Spoke/Spoke.Upgradeable.t.sol | 2 +- .../SignatureGateway.Base.t.sol | 3 +- tests/utils/BatchTestProcedures.sol | 248 +++++++---------- tests/utils/TestTypes.sol | 26 +- 82 files changed, 1466 insertions(+), 766 deletions(-) delete mode 100644 src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol delete mode 100644 src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol rename src/deployments/procedures/deploy/{ => hub}/AaveV4HubConfiguratorDeployProcedure.sol (60%) rename src/deployments/procedures/deploy/{ => hub}/AaveV4HubDeployProcedure.sol (56%) rename src/deployments/procedures/deploy/{ => hub}/AaveV4InterestRateStrategyDeployProcedure.sol (61%) rename src/deployments/procedures/deploy/{ => position-manager}/AaveV4NativeTokenGatewayDeployProcedure.sol (81%) rename src/deployments/procedures/deploy/{ => position-manager}/AaveV4SignatureGatewayDeployProcedure.sol (60%) rename src/deployments/procedures/deploy/{ => spoke}/AaveV4AaveOracleDeployProcedure.sol (100%) rename src/deployments/procedures/deploy/{ => spoke}/AaveV4SpokeConfiguratorDeployProcedure.sol (60%) create mode 100644 src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol rename src/deployments/procedures/deploy/{ => spoke}/AaveV4TreasurySpokeDeployProcedure.sol (56%) rename src/deployments/{procedures/roles => utils/libraries}/Roles.sol (100%) create mode 100644 tests/deployments/procedures/ProceduresBase.t.sol rename {src/deployments/procedures/deploy => tests/deployments/procedures}/WETHDeployProcedure.sol (100%) create mode 100644 tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol create mode 100644 tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol create mode 100644 tests/gas/Base.gas.t.sol create mode 100644 tests/mocks/deployments/AaveV4AaveOracleDeployProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4AccessManagerRolesProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4HubConfiguratorDeployProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4HubDeployProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4HubRolesProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4InterestRateStrategyDeployProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4SignatureGatewayDeployProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4SpokeDeployProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4SpokeRolesProcedureWrapper.sol create mode 100644 tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index e96c5970e..47a92cf0f 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -10,7 +10,6 @@ import { } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; import {Script} from 'forge-std/Script.sol'; -import {console2 as console} from 'forge-std/console2.sol'; abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { string internal constant INPUT_PATH = 'scripts/deploy/inputs/'; @@ -24,17 +23,17 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { _outputFileName = outputFileName_; } - function run() external { + function run() external virtual { vm.createDir(OUTPUT_DIR, true); MetadataLogger logger = new MetadataLogger(OUTPUT_DIR); FullDeployInputs memory inputs = loadFullDeployInputs( string.concat(INPUT_PATH, _inputFileName) ); - + (, address deployer, ) = vm.readCallers(); _loadWarnings(logger, inputs); + inputs = _sanitizeInputs(inputs, deployer); logger.log('...Starting Aave V4 Batch Deployment...'); - address deployer = msg.sender; vm.startBroadcast(deployer); OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration .deployAaveV4({logger: logger, deployer: deployer, deployInputs: inputs}); @@ -49,89 +48,115 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { bool hadWarnings = false; string memory warnings = ''; if (inputs.grantRoles) { - logger.log('WARNING: Roles are being set'); - warnings = string.concat(warnings, 'WARNING: Roles are being set\n'); + warnings = _logAndAppend(logger, warnings, 'WARNING: Roles are being set'); hadWarnings = true; if (inputs.accessManagerAdmin == address(0)) { - logger.log( - 'WARNING: Access Manager Admin is zero address; role will be granted to deployer by default' - ); - warnings = string.concat( + warnings = _logAndAppend( + logger, warnings, - 'WARNING: Access Manager Admin is zero address; role will be granted to deployer by default\n' + 'WARNING: Access Manager Admin is zero address; role will be granted to deployer by default' ); } if (inputs.hubConfiguratorOwner == address(0)) { - logger.log( - 'WARNING: Hub Configurator Owner is zero address; role will be granted to deployer by default' - ); - warnings = string.concat( + warnings = _logAndAppend( + logger, warnings, - 'WARNING: Hub Configurator Owner is zero address; role will be granted to deployer by default\n' + 'WARNING: Hub Configurator Owner is zero address; role will be granted to deployer by default' ); } if (inputs.spokeConfiguratorOwner == address(0)) { - logger.log( - 'WARNING: Spoke Configurator Owner is zero address; role will be granted to deployer by default' - ); - warnings = string.concat( + warnings = _logAndAppend( + logger, warnings, - 'WARNING: Spoke Configurator Owner is zero address; role will be granted to deployer by default\n' + 'WARNING: Spoke Configurator Owner is zero address; role will be granted to deployer by default' ); } if (inputs.spokeProxyAdminOwner == address(0)) { - logger.log( - 'WARNING: Spoke Proxy Admin Owner is zero address; role will be granted to deployer by default' - ); - warnings = string.concat( + warnings = _logAndAppend( + logger, warnings, - 'WARNING: Spoke Proxy Admin Owner is zero address; role will be granted to deployer by default\n' + 'WARNING: Spoke Proxy Admin Owner is zero address; role will be granted to deployer by default' ); } if (inputs.treasurySpokeOwner == address(0)) { - logger.log( - 'WARNING: Treasury Spoke Owner is zero address; role will be granted to deployer by default' - ); - warnings = string.concat( + warnings = _logAndAppend( + logger, warnings, - 'WARNING: Treasury Spoke Owner is zero address; role will be granted to deployer by default\n' + 'WARNING: Treasury Spoke Owner is zero address; role will be granted to deployer by default' ); } if (inputs.spokeAdmin == address(0)) { - logger.log( - 'WARNING: Spoke Admin is zero address; role will be granted to deployer by default' - ); - warnings = string.concat( + warnings = _logAndAppend( + logger, warnings, - 'WARNING: Spoke Admin is zero address; spoke admin roles will be granted to deployer by default\n' + 'WARNING: Spoke Admin is zero address; spoke admin roles will be granted to deployer by default' ); } } if (inputs.hubLabels.length == 0) { - logger.log('WARNING: Hub will not be deployed'); + warnings = _logAndAppend(logger, warnings, 'WARNING: Hub will not be deployed'); hadWarnings = true; - warnings = string.concat(warnings, 'WARNING: Hub will not be deployed\n'); } if (inputs.spokeLabels.length == 0) { - logger.log('WARNING: Spoke will not be deployed'); + warnings = _logAndAppend(logger, warnings, 'WARNING: Spoke will not be deployed'); hadWarnings = true; - warnings = string.concat(warnings, 'WARNING: Spoke will not be deployed\n'); } - if (inputs.nativeWrapperAddress == address(0)) { - logger.log('WARNING: Native wrapper zero address; NativeTokenGateway will not be deployed'); - hadWarnings = true; - warnings = string.concat( + if (inputs.nativeWrapper == address(0)) { + warnings = _logAndAppend( + logger, warnings, - 'WARNING: Native wrapper zero address; NativeTokenGateway will not be deployed\n' + 'WARNING: Native wrapper zero address; NativeTokenGateway & SignatureGateway will not be deployed' ); + hadWarnings = true; } logger.log(''); if (hadWarnings) { - string memory ack = vm.prompt(string.concat(warnings, "\nEnter 'y' to continue")); - if (keccak256(bytes(ack)) != keccak256(bytes('y'))) { - revert('User did not acknowledge warnings. Please try again.'); - } + _executeUserPrompt(warnings); + } + } + + function _executeUserPrompt(string memory warnings) internal virtual { + string memory ack = vm.prompt(string.concat(warnings, "\nEnter 'y' to continue")); + if (keccak256(bytes(ack)) != keccak256(bytes('y'))) { + revert('User did not acknowledge warnings. Please try again.'); } } + + function _sanitizeInputs( + FullDeployInputs memory deployInputs, + address deployer + ) internal view virtual returns (FullDeployInputs memory) { + // if any admin is zero address, default to deployer as admin + InputUtils.FullDeployInputs memory sanitizedInputs = deployInputs; + sanitizedInputs.accessManagerAdmin = deployInputs.accessManagerAdmin != address(0) + ? deployInputs.accessManagerAdmin + : deployer; + sanitizedInputs.hubConfiguratorOwner = deployInputs.hubConfiguratorOwner != address(0) + ? deployInputs.hubConfiguratorOwner + : deployer; + sanitizedInputs.treasurySpokeOwner = deployInputs.treasurySpokeOwner != address(0) + ? deployInputs.treasurySpokeOwner + : deployer; + sanitizedInputs.spokeProxyAdminOwner = deployInputs.spokeProxyAdminOwner != address(0) + ? deployInputs.spokeProxyAdminOwner + : deployer; + sanitizedInputs.spokeConfiguratorOwner = deployInputs.spokeConfiguratorOwner != address(0) + ? deployInputs.spokeConfiguratorOwner + : deployer; + sanitizedInputs.gatewayOwner = deployInputs.gatewayOwner != address(0) + ? deployInputs.gatewayOwner + : deployer; + + return sanitizedInputs; + } + + function _logAndAppend( + MetadataLogger logger, + string memory warnings, + string memory warning + ) internal virtual returns (string memory) { + logger.log(warning); + return string.concat(warnings, warning, '\n'); + } } diff --git a/scripts/deploy/inputs/AaveV4DeployInput.json b/scripts/deploy/inputs/AaveV4DeployInput.json index 41d529f5d..6dbfb8b7b 100644 --- a/scripts/deploy/inputs/AaveV4DeployInput.json +++ b/scripts/deploy/inputs/AaveV4DeployInput.json @@ -7,7 +7,7 @@ "spokeAdmin": "0x0000000000000000000000000000000000000005", "spokeProxyAdminOwner": "0x0000000000000000000000000000000000000005", "gatewayOwner": "0x0000000000000000000000000000000000000005", - "nativeWrapperAddress": "0x0000000000000000000000000000000000000006", + "nativeWrapper": "0x0000000000000000000000000000000000000006", "grantRoles": true, "hubLabels": ["Hub 1", "Hub 2", "Hub 3"], "spokeLabels": ["Spoke 1", "Spoke 2", "Spoke 3"] diff --git a/snapshots/Hub.Operations.json b/snapshots/Hub.Operations.json index c43282a8f..3a96ead80 100644 --- a/snapshots/Hub.Operations.json +++ b/snapshots/Hub.Operations.json @@ -2,8 +2,8 @@ "add": "88006", "add: with transfer": "109642", "draw": "105931", - "eliminateDeficit: full": "59769", - "eliminateDeficit: partial": "69417", + "eliminateDeficit: full": "59781", + "eliminateDeficit: partial": "69429", "mintFeeShares": "84007", "payFee": "72302", "refreshPremium": "71999", @@ -11,8 +11,8 @@ "remove: partial": "81640", "reportDeficit": "115225", "restore: full": "80471", - "restore: full - with transfer": "173397", + "restore: full - with transfer": "173405", "restore: partial": "89137", "restore: partial - with transfer": "147429", - "transferShares": "71192" + "transferShares": "71180" } \ No newline at end of file diff --git a/snapshots/NativeTokenGateway.Operations.json b/snapshots/NativeTokenGateway.Operations.json index ec7958115..45aeca137 100644 --- a/snapshots/NativeTokenGateway.Operations.json +++ b/snapshots/NativeTokenGateway.Operations.json @@ -1,8 +1,8 @@ { - "borrowNative": "229304", - "repayNative": "168012", - "supplyAsCollateralNative": "160361", - "supplyNative": "136467", - "withdrawNative: full": "125611", - "withdrawNative: partial": "136813" + "borrowNative": "229316", + "repayNative": "168024", + "supplyAsCollateralNative": "160373", + "supplyNative": "136476", + "withdrawNative: full": "125620", + "withdrawNative: partial": "136825" } \ No newline at end of file diff --git a/snapshots/SignatureGateway.Operations.json b/snapshots/SignatureGateway.Operations.json index c8f045985..9bb7d4757 100644 --- a/snapshots/SignatureGateway.Operations.json +++ b/snapshots/SignatureGateway.Operations.json @@ -1,10 +1,10 @@ { - "borrowWithSig": "215593", - "repayWithSig": "188848", - "setSelfAsUserPositionManagerWithSig": "75390", - "setUsingAsCollateralWithSig": "85041", - "supplyWithSig": "153196", - "updateUserDynamicConfigWithSig": "62757", - "updateUserRiskPremiumWithSig": "61567", - "withdrawWithSig": "131686" + "borrowWithSig": "215605", + "repayWithSig": "188872", + "setSelfAsUserPositionManagerWithSig": "75402", + "setUsingAsCollateralWithSig": "85065", + "supplyWithSig": "153205", + "updateUserDynamicConfigWithSig": "62769", + "updateUserRiskPremiumWithSig": "61579", + "withdrawWithSig": "131696" } \ No newline at end of file diff --git a/snapshots/Spoke.Operations.ZeroRiskPremium.json b/snapshots/Spoke.Operations.ZeroRiskPremium.json index 8e8cdc94f..352760025 100644 --- a/snapshots/Spoke.Operations.ZeroRiskPremium.json +++ b/snapshots/Spoke.Operations.ZeroRiskPremium.json @@ -6,11 +6,11 @@ "liquidationCall: full": "310468", "liquidationCall: partial": "310186", "permitReserve + repay (multicall)": "166029", - "permitReserve + supply (multicall)": "146862", + "permitReserve + supply (multicall)": "146850", "permitReserve + supply + enable collateral (multicall)": "160573", "repay: full": "126094", "repay: partial": "130983", - "setUserPositionManagerWithSig: disable": "44834", + "setUserPositionManagerWithSig: disable": "44846", "setUserPositionManagerWithSig: enable": "68875", "supply + enable collateral (multicall)": "140624", "supply: 0 borrows, collateral disabled": "123679", diff --git a/snapshots/Spoke.Operations.json b/snapshots/Spoke.Operations.json index d5986df06..2ce1b424f 100644 --- a/snapshots/Spoke.Operations.json +++ b/snapshots/Spoke.Operations.json @@ -6,11 +6,11 @@ "liquidationCall: full": "344031", "liquidationCall: partial": "343749", "permitReserve + repay (multicall)": "163273", - "permitReserve + supply (multicall)": "146862", + "permitReserve + supply (multicall)": "146850", "permitReserve + supply + enable collateral (multicall)": "160573", "repay: full": "120256", "repay: partial": "139545", - "setUserPositionManagerWithSig: disable": "44834", + "setUserPositionManagerWithSig: disable": "44846", "setUserPositionManagerWithSig: enable": "68875", "supply + enable collateral (multicall)": "140624", "supply: 0 borrows, collateral disabled": "123679", diff --git a/src/deployments/batches/AaveV4AccessBatch.sol b/src/deployments/batches/AaveV4AccessBatch.sol index 4b1052cbd..b109a91d4 100644 --- a/src/deployments/batches/AaveV4AccessBatch.sol +++ b/src/deployments/batches/AaveV4AccessBatch.sol @@ -3,14 +3,17 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; -import {AaveV4AccessManagerEnumerableDeployProcedure} from 'src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol'; +import { + AaveV4AccessManagerEnumerableDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol'; contract AaveV4AccessBatch is AaveV4AccessManagerEnumerableDeployProcedure { BatchReports.AccessBatchReport internal _report; constructor(address admin_) { - address accessManagerAddress = _deployAccessManagerEnumerable(admin_); - _report = BatchReports.AccessBatchReport({accessManagerAddress: accessManagerAddress}); + assert(admin_ != address(0)); + address accessManager = _deployAccessManagerEnumerable(admin_); + _report = BatchReports.AccessBatchReport({accessManager: accessManager}); } function getReport() external view returns (BatchReports.AccessBatchReport memory) { diff --git a/src/deployments/batches/AaveV4ConfiguratorBatch.sol b/src/deployments/batches/AaveV4ConfiguratorBatch.sol index 1af16be99..134ebe989 100644 --- a/src/deployments/batches/AaveV4ConfiguratorBatch.sol +++ b/src/deployments/batches/AaveV4ConfiguratorBatch.sol @@ -5,10 +5,10 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import { AaveV4HubConfiguratorDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol'; +} from 'src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol'; import { AaveV4SpokeConfiguratorDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol'; +} from 'src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol'; contract AaveV4ConfiguratorBatch is AaveV4HubConfiguratorDeployProcedure, @@ -17,12 +17,15 @@ contract AaveV4ConfiguratorBatch is BatchReports.ConfiguratorBatchReport internal _report; constructor(address hubConfiguratorOwner_, address spokeConfiguratorOwner_) { - address hubConfiguratorAddress = _deployHubConfigurator(hubConfiguratorOwner_); - address spokeConfiguratorAddress = _deploySpokeConfigurator(spokeConfiguratorOwner_); + assert(hubConfiguratorOwner_ != address(0)); + assert(spokeConfiguratorOwner_ != address(0)); + + address hubConfigurator = _deployHubConfigurator(hubConfiguratorOwner_); + address spokeConfigurator = _deploySpokeConfigurator(spokeConfiguratorOwner_); _report = BatchReports.ConfiguratorBatchReport({ - hubConfiguratorAddress: hubConfiguratorAddress, - spokeConfiguratorAddress: spokeConfiguratorAddress + hubConfigurator: hubConfigurator, + spokeConfigurator: spokeConfigurator }); } diff --git a/src/deployments/batches/AaveV4GatewayBatch.sol b/src/deployments/batches/AaveV4GatewayBatch.sol index d0d1d1cc9..3741306db 100644 --- a/src/deployments/batches/AaveV4GatewayBatch.sol +++ b/src/deployments/batches/AaveV4GatewayBatch.sol @@ -5,10 +5,10 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import { AaveV4NativeTokenGatewayDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol'; +} from 'src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol'; import { AaveV4SignatureGatewayDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol'; +} from 'src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol'; contract AaveV4GatewayBatch is AaveV4NativeTokenGatewayDeployProcedure, @@ -17,18 +17,18 @@ contract AaveV4GatewayBatch is BatchReports.GatewaysBatchReport internal _report; constructor(address owner_, address nativeWrapper_) { - address nativeGatewayAddress; - if (nativeWrapper_ != address(0)) { - nativeGatewayAddress = _deployNativeTokenGateway({ - nativeWrapper_: nativeWrapper_, - owner_: owner_ - }); - } - address signatureGatewayAddress = _deploySignatureGateway(owner_); + assert(owner_ != address(0)); + assert(nativeWrapper_ != address(0)); + + address nativeGateway = _deployNativeTokenGateway({ + nativeWrapper: nativeWrapper_, + owner: owner_ + }); + address signatureGateway = _deploySignatureGateway(owner_); _report = BatchReports.GatewaysBatchReport({ - nativeGatewayAddress: nativeGatewayAddress, - signatureGatewayAddress: signatureGatewayAddress + nativeGateway: nativeGateway, + signatureGateway: signatureGateway }); } diff --git a/src/deployments/batches/AaveV4HubBatch.sol b/src/deployments/batches/AaveV4HubBatch.sol index 7af160274..f25bc67d7 100644 --- a/src/deployments/batches/AaveV4HubBatch.sol +++ b/src/deployments/batches/AaveV4HubBatch.sol @@ -5,13 +5,13 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import { AaveV4HubDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol'; +} from 'src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol'; import { AaveV4InterestRateStrategyDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol'; +} from 'src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol'; import { AaveV4TreasurySpokeDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol'; +} from 'src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol'; contract AaveV4HubBatch is AaveV4HubDeployProcedure, @@ -20,15 +20,18 @@ contract AaveV4HubBatch is { BatchReports.HubBatchReport internal _report; - constructor(address treasurySpokeOwner_, address accessManagerAddress_) { - address hubAddress = _deployHub(accessManagerAddress_); - address irStrategyAddress = _deployInterestRateStrategy(hubAddress); - address treasurySpokeAddress = _deployTreasurySpoke(treasurySpokeOwner_, hubAddress); + constructor(address treasurySpokeOwner_, address accessManager_) { + assert(treasurySpokeOwner_ != address(0)); + assert(accessManager_ != address(0)); + + address hub = _deployHub(accessManager_); + address irStrategy = _deployInterestRateStrategy(hub); + address treasurySpoke = _deployTreasurySpoke(treasurySpokeOwner_, hub); _report = BatchReports.HubBatchReport({ - hubAddress: hubAddress, - irStrategyAddress: irStrategyAddress, - treasurySpokeAddress: treasurySpokeAddress + hub: hub, + irStrategy: irStrategy, + treasurySpoke: treasurySpoke }); } diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 4a8e05779..6bce4532f 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -4,51 +4,52 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; - import { AaveV4AaveOracleDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol'; -import { - AaveV4SpokeInstanceDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol'; +} from 'src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol'; import { - AaveV4TransparentUpgradeableProxyDeployProcedure -} from 'src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol'; + AaveV4SpokeDeployProcedure +} from 'src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol'; -contract AaveV4SpokeInstanceBatch is - AaveV4SpokeInstanceDeployProcedure, - AaveV4TransparentUpgradeableProxyDeployProcedure, - AaveV4AaveOracleDeployProcedure -{ +import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; +import {IAaveOracle} from 'src/spoke/interfaces/IAaveOracle.sol'; + +contract AaveV4SpokeInstanceBatch is AaveV4SpokeDeployProcedure, AaveV4AaveOracleDeployProcedure { BatchReports.SpokeInstanceBatchReport internal _report; constructor( address spokeProxyAdminOwner_, - address accessManagerAddress_, + address accessManager_, uint8 oracleDecimals_, string memory oracleDescription_ ) { + assert(spokeProxyAdminOwner_ != address(0)); + assert(accessManager_ != address(0)); + assert(oracleDecimals_ > 0); + assert(bytes(oracleDescription_).length > 0); + // additional 2 nonces for AaveOracle, SpokeInstance, starting from contract nonce of 1 - address predictedSpokeInstanceAddress = Utils.computeCreateAddress(address(this), 3); + address predictedSpokeInstance = Utils.computeCreateAddress(address(this), 3); - address aaveOracleAddress = _deployAaveOracle( - predictedSpokeInstanceAddress, + address aaveOracle = _deployAaveOracle( + predictedSpokeInstance, oracleDecimals_, oracleDescription_ ); - address spokeImplementationAddress = _deploySpokeInstance(aaveOracleAddress); - address spokeProxyAddress = _proxify( - spokeImplementationAddress, - spokeProxyAdminOwner_, - abi.encodeWithSignature('initialize(address)', accessManagerAddress_) - ); + (address spokeProxy, address spokeImplementation) = _deployUpgradableSpokeInstance({ + spokeProxyAdminOwner: spokeProxyAdminOwner_, + accessManager: accessManager_, + oracle: aaveOracle + }); - assert(spokeProxyAddress == predictedSpokeInstanceAddress); + assert(spokeProxy == predictedSpokeInstance); + assert(ISpoke(spokeProxy).ORACLE() == aaveOracle); + assert(IAaveOracle(aaveOracle).SPOKE() == spokeProxy); _report = BatchReports.SpokeInstanceBatchReport({ - aaveOracleAddress: aaveOracleAddress, - spokeImplementationAddress: spokeImplementationAddress, - spokeProxyAddress: spokeProxyAddress + aaveOracle: aaveOracle, + spokeImplementation: spokeImplementation, + spokeProxy: spokeProxy }); } diff --git a/src/deployments/libraries/BatchReports.sol b/src/deployments/libraries/BatchReports.sol index 12689e35b..9c12db59f 100644 --- a/src/deployments/libraries/BatchReports.sol +++ b/src/deployments/libraries/BatchReports.sol @@ -4,28 +4,28 @@ pragma solidity ^0.8.0; library BatchReports { struct AccessBatchReport { - address accessManagerAddress; + address accessManager; } struct ConfiguratorBatchReport { - address hubConfiguratorAddress; - address spokeConfiguratorAddress; + address hubConfigurator; + address spokeConfigurator; } struct SpokeInstanceBatchReport { - address spokeImplementationAddress; - address spokeProxyAddress; - address aaveOracleAddress; + address spokeImplementation; + address spokeProxy; + address aaveOracle; } struct HubBatchReport { - address hubAddress; - address irStrategyAddress; - address treasurySpokeAddress; + address hub; + address irStrategy; + address treasurySpoke; } struct GatewaysBatchReport { - address signatureGatewayAddress; - address nativeGatewayAddress; + address signatureGateway; + address nativeGateway; } } diff --git a/src/deployments/libraries/ConfigData.sol b/src/deployments/libraries/ConfigData.sol index 6916ebc81..7ec7e5bb8 100644 --- a/src/deployments/libraries/ConfigData.sol +++ b/src/deployments/libraries/ConfigData.sol @@ -13,6 +13,7 @@ library ConfigData { address feeReceiver; uint16 liquidityFee; address irStrategy; + address reinvestmentController; bytes irData; } diff --git a/src/deployments/orchestration/AaveV4DeployBase.sol b/src/deployments/orchestration/AaveV4DeployBase.sol index 65a556c36..1084f22ad 100644 --- a/src/deployments/orchestration/AaveV4DeployBase.sol +++ b/src/deployments/orchestration/AaveV4DeployBase.sol @@ -32,22 +32,22 @@ library AaveV4DeployBase { function deployHubBatch( address treasurySpokeOwner, - address accessManagerAddress + address accessManager ) internal returns (BatchReports.HubBatchReport memory) { - AaveV4HubBatch hubBatch = new AaveV4HubBatch(treasurySpokeOwner, accessManagerAddress); + AaveV4HubBatch hubBatch = new AaveV4HubBatch(treasurySpokeOwner, accessManager); return hubBatch.getReport(); } function deploySpokeInstanceBatch( address spokeProxyAdminOwner, - address accessManagerAddress, + address accessManager, uint8 oracleDecimals, string memory oracleSuffix, string memory label ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch({ spokeProxyAdminOwner_: spokeProxyAdminOwner, - accessManagerAddress_: accessManagerAddress, + accessManager_: accessManager, oracleDecimals_: oracleDecimals, oracleDescription_: string.concat(label, oracleSuffix) }); diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 225281149..a66a25f8b 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -37,79 +37,60 @@ library AaveV4DeployOrchestration { InputUtils.FullDeployInputs memory deployInputs ) internal returns (OrchestrationReports.FullDeploymentReport memory report) { // Deploy Access Batch - // initially with provided access manager admin (fallback to deployer if zero) + // initialize with deployer as access manager admin address initialAdmin = deployer; report.accessBatchReport = _deployAccessBatch({ logger: logger, accessManagerAdmin: initialAdmin }); - // if any admin is zero address, default to deployer as admin - InputUtils.FullDeployInputs memory inputs = deployInputs; - inputs.accessManagerAdmin = deployInputs.accessManagerAdmin != address(0) - ? deployInputs.accessManagerAdmin - : deployer; - inputs.hubConfiguratorOwner = deployInputs.hubConfiguratorOwner != address(0) - ? deployInputs.hubConfiguratorOwner - : deployer; - inputs.treasurySpokeOwner = deployInputs.treasurySpokeOwner != address(0) - ? deployInputs.treasurySpokeOwner - : deployer; - inputs.spokeProxyAdminOwner = deployInputs.spokeProxyAdminOwner != address(0) - ? deployInputs.spokeProxyAdminOwner - : deployer; - inputs.spokeConfiguratorOwner = deployInputs.spokeConfiguratorOwner != address(0) - ? deployInputs.spokeConfiguratorOwner - : deployer; - inputs.gatewayOwner = deployInputs.gatewayOwner != address(0) - ? deployInputs.gatewayOwner - : deployer; - // Deploy Configurator Batch report.configuratorBatchReport = _deployConfiguratorBatch({ logger: logger, - hubConfiguratorOwner: inputs.hubConfiguratorOwner, - spokeConfiguratorOwner: inputs.spokeConfiguratorOwner + hubConfiguratorOwner: deployInputs.hubConfiguratorOwner, + spokeConfiguratorOwner: deployInputs.spokeConfiguratorOwner }); // Deploy Hub Batches report.hubBatchReports = _deployHubs({ logger: logger, - treasurySpokeOwner: inputs.treasurySpokeOwner, - accessManagerAddress: report.accessBatchReport.accessManagerAddress, - hubLabels: inputs.hubLabels + treasurySpokeOwner: deployInputs.treasurySpokeOwner, + accessManager: report.accessBatchReport.accessManager, + hubLabels: deployInputs.hubLabels }); // Deploy Spoke Instance Batches report.spokeInstanceBatchReports = _deploySpokes({ logger: logger, - spokeProxyAdminOwner: inputs.spokeProxyAdminOwner, - accessManagerAddress: report.accessBatchReport.accessManagerAddress, - spokeLabels: inputs.spokeLabels + spokeProxyAdminOwner: deployInputs.spokeProxyAdminOwner, + accessManager: report.accessBatchReport.accessManager, + spokeLabels: deployInputs.spokeLabels }); - // Deploy Gateways Batch - report.gatewaysBatchReport = _deployGatewayBatch({ - logger: logger, - gatewayOwner: inputs.gatewayOwner, - nativeWrapper: inputs.nativeWrapperAddress - }); + // Deploy Gateways Batch if native wrapper is not zero address + if (deployInputs.nativeWrapper != address(0)) { + report.gatewaysBatchReport = _deployGatewayBatch({ + logger: logger, + gatewayOwner: deployInputs.gatewayOwner, + nativeWrapper: deployInputs.nativeWrapper + }); + } // Set Roles if needed - if (inputs.grantRoles) { - if (inputs.hubLabels.length > 0) { - _grantHubRoles({logger: logger, report: report, hubAdmin: inputs.hubAdmin}); + if (deployInputs.grantRoles) { + if (deployInputs.hubLabels.length > 0) { + _grantHubRoles({logger: logger, report: report, hubAdmin: deployInputs.hubAdmin}); } - if (inputs.spokeLabels.length > 0) { - _grantSpokeRoles({logger: logger, report: report, spokeAdmin: inputs.spokeAdmin}); + if (deployInputs.spokeLabels.length > 0) { + _grantSpokeRoles({logger: logger, report: report, spokeAdmin: deployInputs.spokeAdmin}); } - if (inputs.accessManagerAdmin != initialAdmin) { + if (deployInputs.accessManagerAdmin != initialAdmin) { logger.log('...Granting AccessManager Root Admin role...'); AaveV4AccessManagerRolesProcedure.grantRootAdminRole({ - accessManagerAddress: report.accessBatchReport.accessManagerAddress, - newAdminAddress: inputs.accessManagerAdmin, - currentAdminAddress: initialAdmin + accessManager: report.accessBatchReport.accessManager, + adminToAdd: deployInputs.accessManagerAdmin, + adminToRemove: initialAdmin }); } } @@ -131,14 +112,14 @@ library AaveV4DeployOrchestration { ) internal { logger.log('...Granting Hub Admin role...'); AaveV4HubRolesProcedure.grantHubAdminRole({ - accessManagerAddress: report.accessBatchReport.accessManagerAddress, + accessManager: report.accessBatchReport.accessManager, admin: hubAdmin }); logger.log('...Granting Hub Configurator roles...'); AaveV4HubRolesProcedure.grantHubConfiguratorRole({ - accessManagerAddress: report.accessBatchReport.accessManagerAddress, - admin: report.configuratorBatchReport.hubConfiguratorAddress + accessManager: report.accessBatchReport.accessManager, + admin: report.configuratorBatchReport.hubConfigurator }); } @@ -149,14 +130,14 @@ library AaveV4DeployOrchestration { ) internal { logger.log('...Granting Spoke Admin role...'); AaveV4SpokeRolesProcedure.grantSpokeAdminRole({ - accessManagerAddress: report.accessBatchReport.accessManagerAddress, + accessManager: report.accessBatchReport.accessManager, admin: spokeAdmin }); logger.log('...Granting Spoke Configurator roles...'); AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole({ - accessManagerAddress: report.accessBatchReport.accessManagerAddress, - admin: report.configuratorBatchReport.spokeConfiguratorAddress + accessManager: report.accessBatchReport.accessManager, + admin: report.configuratorBatchReport.spokeConfigurator }); } @@ -168,7 +149,7 @@ library AaveV4DeployOrchestration { report = AaveV4DeployBase.deployAccessBatch({admin: accessManagerAdmin}); - logger.log('AccessManager', report.accessManagerAddress); + logger.log('AccessManager', report.accessManager); logger.log(''); return report; } @@ -185,8 +166,8 @@ library AaveV4DeployOrchestration { spokeConfiguratorOwner: spokeConfiguratorOwner }); - logger.log('HubConfigurator', report.hubConfiguratorAddress); - logger.log('SpokeConfigurator', report.spokeConfiguratorAddress); + logger.log('HubConfigurator', report.hubConfigurator); + logger.log('SpokeConfigurator', report.spokeConfigurator); logger.log(''); return report; } @@ -194,18 +175,13 @@ library AaveV4DeployOrchestration { function _deployHubs( Logger logger, address treasurySpokeOwner, - address accessManagerAddress, + address accessManager, string[] memory hubLabels ) internal returns (OrchestrationReports.HubDeploymentReport[] memory hubBatchReports) { uint256 hubCount = hubLabels.length; hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); for (uint256 i; i < hubCount; ++i) { - hubBatchReports[i] = _deployHub( - logger, - treasurySpokeOwner, - accessManagerAddress, - hubLabels[i] - ); + hubBatchReports[i] = _deployHub(logger, treasurySpokeOwner, accessManager, hubLabels[i]); } logger.log(''); return hubBatchReports; @@ -214,7 +190,7 @@ library AaveV4DeployOrchestration { function _deployHub( Logger logger, address treasurySpokeOwner, - address accessManagerAddress, + address accessManager, string memory label ) internal returns (OrchestrationReports.HubDeploymentReport memory) { OrchestrationReports.HubDeploymentReport memory hubReport; @@ -222,16 +198,16 @@ library AaveV4DeployOrchestration { hubReport.report = _deployHubBatch({ logger: logger, treasurySpokeOwner: treasurySpokeOwner, - accessManagerAddress: accessManagerAddress + accessManager: accessManager }); logger.log(label); - logger.log(' Hub', hubReport.report.hubAddress); - logger.log(' InterestRateStrategy', hubReport.report.irStrategyAddress); - logger.log(' TreasurySpoke', hubReport.report.treasurySpokeAddress); + logger.log(' Hub', hubReport.report.hub); + logger.log(' InterestRateStrategy', hubReport.report.irStrategy); + logger.log(' TreasurySpoke', hubReport.report.treasurySpoke); logger.log('...Setting Hub roles...'); - AaveV4HubRolesProcedure.setupHubRoles(accessManagerAddress, hubReport.report.hubAddress); + AaveV4HubRolesProcedure.setupHubRoles(accessManager, hubReport.report.hub); return hubReport; } @@ -239,7 +215,7 @@ library AaveV4DeployOrchestration { function _deploySpokes( Logger logger, address spokeProxyAdminOwner, - address accessManagerAddress, + address accessManager, string[] memory spokeLabels ) internal returns (OrchestrationReports.SpokeDeploymentReport[] memory spokeBatchReports) { uint256 spokeCount = spokeLabels.length; @@ -248,7 +224,7 @@ library AaveV4DeployOrchestration { spokeBatchReports[i] = _deploySpoke({ logger: logger, spokeProxyAdminOwner: spokeProxyAdminOwner, - accessManagerAddress: accessManagerAddress, + accessManager: accessManager, label: spokeLabels[i] }); } @@ -259,7 +235,7 @@ library AaveV4DeployOrchestration { function _deploySpoke( Logger logger, address spokeProxyAdminOwner, - address accessManagerAddress, + address accessManager, string memory label ) internal returns (OrchestrationReports.SpokeDeploymentReport memory) { OrchestrationReports.SpokeDeploymentReport memory spokeReport; @@ -268,19 +244,19 @@ library AaveV4DeployOrchestration { spokeReport.report = _deploySpokeInstanceBatch({ logger: logger, spokeProxyAdminOwner: spokeProxyAdminOwner, - accessManagerAddress: accessManagerAddress, + accessManager: accessManager, label: label }); logger.log(label); - logger.log(' SpokeInstance Proxy', spokeReport.report.spokeProxyAddress); - logger.log(' SpokeInstance Implementation', spokeReport.report.spokeImplementationAddress); - logger.log(' AaveOracle', spokeReport.report.aaveOracleAddress); + logger.log(' SpokeInstance Proxy', spokeReport.report.spokeProxy); + logger.log(' SpokeInstance Implementation', spokeReport.report.spokeImplementation); + logger.log(' AaveOracle', spokeReport.report.aaveOracle); logger.log('...Setting Spoke roles...'); AaveV4SpokeRolesProcedure.setupSpokeRoles({ - accessManagerAddress: accessManagerAddress, - spokeAddress: spokeReport.report.spokeProxyAddress + accessManager: accessManager, + spoke: spokeReport.report.spokeProxy }); return spokeReport; @@ -289,13 +265,13 @@ library AaveV4DeployOrchestration { function _deploySpokeInstanceBatch( Logger logger, address spokeProxyAdminOwner, - address accessManagerAddress, + address accessManager, string memory label ) internal returns (BatchReports.SpokeInstanceBatchReport memory report) { logger.log('...Deploying AaveV4SpokeInstanceBatch...'); report = AaveV4DeployBase.deploySpokeInstanceBatch( spokeProxyAdminOwner, - accessManagerAddress, + accessManager, ORACLE_DECIMALS, ORACLE_SUFFIX, label @@ -306,10 +282,10 @@ library AaveV4DeployOrchestration { function _deployHubBatch( Logger logger, address treasurySpokeOwner, - address accessManagerAddress + address accessManager ) internal returns (BatchReports.HubBatchReport memory report) { logger.log('...Deploying HubBatch...'); - report = AaveV4DeployBase.deployHubBatch(treasurySpokeOwner, accessManagerAddress); + report = AaveV4DeployBase.deployHubBatch(treasurySpokeOwner, accessManager); return report; } @@ -323,8 +299,8 @@ library AaveV4DeployOrchestration { owner: gatewayOwner, nativeWrapper: nativeWrapper }); - logger.log('NativeTokenGateway', report.nativeGatewayAddress); - logger.log('SignatureGateway', report.signatureGatewayAddress); + logger.log('NativeTokenGateway', report.nativeGateway); + logger.log('SignatureGateway', report.signatureGateway); return report; } diff --git a/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol b/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol index 6a87e6604..2b4038ed0 100644 --- a/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol +++ b/src/deployments/procedures/config/AaveV4HubConfigProcedures.sol @@ -16,16 +16,16 @@ library AaveV4HubConfigProcedures { params.irStrategy, params.irData ); - if (params.liquidityFee > 0) { + if (params.liquidityFee > 0 || params.reinvestmentController != address(0)) { IHub(params.hub).updateAssetConfig( assetId, IHub.AssetConfig({ liquidityFee: params.liquidityFee, feeReceiver: params.feeReceiver, irStrategy: params.irStrategy, - reinvestmentController: address(0) + reinvestmentController: params.reinvestmentController }), - new bytes(0) + bytes('') ); } return assetId; @@ -67,7 +67,7 @@ library AaveV4HubConfigProcedures { ); } - function addSpokeToAssets( + function addSpokeToAssetsViaConfigurator( address configurator, ConfigData.AddSpokeToAssetsParams memory params ) internal { diff --git a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol index 1d0e40737..319b62449 100644 --- a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import {AccessManagerEnumerable} from 'src/access/AccessManagerEnumerable.sol'; contract AaveV4AccessManagerEnumerableDeployProcedure { - function _deployAccessManagerEnumerable(address admin_) internal returns (address) { - return address(new AccessManagerEnumerable({initialAdmin_: admin_})); + function _deployAccessManagerEnumerable(address admin) internal returns (address) { + return address(new AccessManagerEnumerable({initialAdmin_: admin})); } } diff --git a/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol deleted file mode 100644 index 58184bbc9..000000000 --- a/src/deployments/procedures/deploy/AaveV4SpokeInstanceDeployProcedure.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.0; - -import {SpokeInstance} from 'src/spoke/instances/SpokeInstance.sol'; - -contract AaveV4SpokeInstanceDeployProcedure { - function _deploySpokeInstance(address oracle_) internal returns (address) { - return address(new SpokeInstance({oracle_: oracle_})); - } -} diff --git a/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol deleted file mode 100644 index f6700898a..000000000 --- a/src/deployments/procedures/deploy/AaveV4TransparentUpgradeableProxyDeployProcedure.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.0; - -import { - TransparentUpgradeableProxy -} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; - -contract AaveV4TransparentUpgradeableProxyDeployProcedure { - function _proxify( - address logic_, - address initialOwner_, - bytes memory data_ - ) internal returns (address) { - return - address( - new TransparentUpgradeableProxy({_logic: logic_, initialOwner: initialOwner_, _data: data_}) - ); - } -} diff --git a/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol similarity index 60% rename from src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol rename to src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol index 6208c2041..8ca1bd4be 100644 --- a/src/deployments/procedures/deploy/AaveV4HubConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import {HubConfigurator} from 'src/hub/HubConfigurator.sol'; contract AaveV4HubConfiguratorDeployProcedure { - function _deployHubConfigurator(address owner_) internal returns (address) { - return address(new HubConfigurator({owner_: owner_})); + function _deployHubConfigurator(address owner) internal returns (address) { + return address(new HubConfigurator({owner_: owner})); } } diff --git a/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol similarity index 56% rename from src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol rename to src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol index 57811d158..c5e84f4ca 100644 --- a/src/deployments/procedures/deploy/AaveV4HubDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import {Hub} from 'src/hub/Hub.sol'; contract AaveV4HubDeployProcedure { - function _deployHub(address accessManager_) internal returns (address) { - return address(new Hub({authority_: accessManager_})); + function _deployHub(address accessManager) internal returns (address) { + return address(new Hub({authority_: accessManager})); } } diff --git a/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol similarity index 61% rename from src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol rename to src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol index d24677054..fe45c61d0 100644 --- a/src/deployments/procedures/deploy/AaveV4InterestRateStrategyDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import {AssetInterestRateStrategy} from 'src/hub/AssetInterestRateStrategy.sol'; contract AaveV4InterestRateStrategyDeployProcedure { - function _deployInterestRateStrategy(address hub_) internal returns (address) { - return address(new AssetInterestRateStrategy({hub_: hub_})); + function _deployInterestRateStrategy(address hub) internal returns (address) { + return address(new AssetInterestRateStrategy({hub_: hub})); } } diff --git a/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol similarity index 81% rename from src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol rename to src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol index f34bb80aa..4e698b640 100644 --- a/src/deployments/procedures/deploy/AaveV4NativeTokenGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol @@ -6,9 +6,9 @@ import {NativeTokenGateway} from 'src/position-manager/NativeTokenGateway.sol'; contract AaveV4NativeTokenGatewayDeployProcedure { function _deployNativeTokenGateway( - address nativeWrapper_, - address owner_ + address nativeWrapper, + address owner ) internal returns (address) { - return address(new NativeTokenGateway({nativeWrapper_: nativeWrapper_, initialOwner_: owner_})); + return address(new NativeTokenGateway({nativeWrapper_: nativeWrapper, initialOwner_: owner})); } } diff --git a/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol similarity index 60% rename from src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol rename to src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol index 71e76c08d..a7e7d8d44 100644 --- a/src/deployments/procedures/deploy/AaveV4SignatureGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import {SignatureGateway} from 'src/position-manager/SignatureGateway.sol'; contract AaveV4SignatureGatewayDeployProcedure { - function _deploySignatureGateway(address owner_) internal returns (address) { - return address(new SignatureGateway({initialOwner_: owner_})); + function _deploySignatureGateway(address owner) internal returns (address) { + return address(new SignatureGateway({initialOwner_: owner})); } } diff --git a/src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/deploy/AaveV4AaveOracleDeployProcedure.sol rename to src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol diff --git a/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol similarity index 60% rename from src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol rename to src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol index 5df172f0f..aae93d507 100644 --- a/src/deployments/procedures/deploy/AaveV4SpokeConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import {SpokeConfigurator} from 'src/spoke/SpokeConfigurator.sol'; contract AaveV4SpokeConfiguratorDeployProcedure { - function _deploySpokeConfigurator(address owner_) internal returns (address) { - return address(new SpokeConfigurator({owner_: owner_})); + function _deploySpokeConfigurator(address owner) internal returns (address) { + return address(new SpokeConfigurator({owner_: owner})); } } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol new file mode 100644 index 000000000..23b514315 --- /dev/null +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; +import {SpokeInstance} from 'src/spoke/instances/SpokeInstance.sol'; + +contract AaveV4SpokeDeployProcedure { + function _deployUpgradableSpokeInstance( + address spokeProxyAdminOwner, + address accessManager, + address oracle + ) internal returns (address spokeProxy, address spokeImplementation) { + spokeImplementation = address(new SpokeInstance({oracle_: oracle})); + spokeProxy = Utils.proxify( + spokeImplementation, + spokeProxyAdminOwner, + abi.encodeCall(SpokeInstance.initialize, (accessManager)) + ); + } +} diff --git a/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol similarity index 56% rename from src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol rename to src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol index 0390f581d..a6f66a001 100644 --- a/src/deployments/procedures/deploy/AaveV4TreasurySpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import {TreasurySpoke} from 'src/spoke/TreasurySpoke.sol'; contract AaveV4TreasurySpokeDeployProcedure { - function _deployTreasurySpoke(address owner_, address hub_) internal returns (address) { - return address(new TreasurySpoke({owner_: owner_, hub_: hub_})); + function _deployTreasurySpoke(address owner, address hub) internal returns (address) { + return address(new TreasurySpoke({owner_: owner, hub_: hub})); } } diff --git a/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol index 714b196ab..c4aa66cc9 100644 --- a/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol @@ -3,22 +3,23 @@ pragma solidity ^0.8.0; import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; -import {Roles} from 'src/deployments/procedures/roles/Roles.sol'; +import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; library AaveV4AccessManagerRolesProcedure { function grantRootAdminRole( - address accessManagerAddress, - address newAdminAddress, - address currentAdminAddress + address accessManager, + address adminToAdd, + address adminToRemove ) internal { - IAccessManager(accessManagerAddress).grantRole({ + assert(adminToAdd != address(0)); + IAccessManager(accessManager).grantRole({ roleId: Roles.DEFAULT_ADMIN_ROLE, - account: newAdminAddress, + account: adminToAdd, executionDelay: 0 }); - IAccessManager(accessManagerAddress).renounceRole({ + IAccessManager(accessManager).renounceRole({ roleId: Roles.DEFAULT_ADMIN_ROLE, - callerConfirmation: currentAdminAddress + callerConfirmation: adminToRemove }); } } diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol index c14d33e3c..3529c1e0a 100644 --- a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -3,49 +3,46 @@ pragma solidity ^0.8.0; import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; -import {Roles} from 'src/deployments/procedures/roles/Roles.sol'; +import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; import {IHub} from 'src/hub/interfaces/IHub.sol'; library AaveV4HubRolesProcedure { - function grantHubAdminRole(address accessManagerAddress, address admin) internal { - grantHubFeeMinterRole(accessManagerAddress, admin); - grantHubConfiguratorRole(accessManagerAddress, admin); + function grantHubAdminRole(address accessManager, address admin) internal { + assert(admin != address(0)); + grantHubFeeMinterRole(accessManager, admin); + grantHubConfiguratorRole(accessManager, admin); } - function grantHubFeeMinterRole(address accessManagerAddress, address admin) internal { - IAccessManager(accessManagerAddress).grantRole({ + function grantHubFeeMinterRole(address accessManager, address admin) internal { + IAccessManager(accessManager).grantRole({ roleId: Roles.HUB_FEE_MINTER_ROLE, account: admin, executionDelay: 0 }); } - function grantHubConfiguratorRole(address accessManagerAddress, address admin) internal { - IAccessManager(accessManagerAddress).grantRole({ + function grantHubConfiguratorRole(address accessManager, address admin) internal { + IAccessManager(accessManager).grantRole({ roleId: Roles.HUB_CONFIGURATOR_ROLE, account: admin, executionDelay: 0 }); } - function setupHubRoles(address accessManagerAddress, address hubAddress) internal { - setupHubFeeMinterRole(accessManagerAddress, hubAddress); - setupHubConfiguratorRole(accessManagerAddress, hubAddress); + function setupHubRoles(address accessManager, address hub) internal { + setupHubFeeMinterRole(accessManager, hub); + setupHubConfiguratorRole(accessManager, hub); } - function setupHubFeeMinterRole(address accessManagerAddress, address hubAddress) internal { + function setupHubFeeMinterRole(address accessManager, address hub) internal { bytes4[] memory selectors = getHubFeeMinterRoleSelectors(); - IAccessManager(accessManagerAddress).setTargetFunctionRole( - hubAddress, - selectors, - Roles.HUB_FEE_MINTER_ROLE - ); + IAccessManager(accessManager).setTargetFunctionRole(hub, selectors, Roles.HUB_FEE_MINTER_ROLE); } - function setupHubConfiguratorRole(address accessManagerAddress, address hubAddress) internal { + function setupHubConfiguratorRole(address accessManager, address hub) internal { bytes4[] memory selectors = getHubConfiguratorRoleSelectors(); - IAccessManager(accessManagerAddress).setTargetFunctionRole( - hubAddress, + IAccessManager(accessManager).setTargetFunctionRole( + hub, selectors, Roles.HUB_CONFIGURATOR_ROLE ); diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol index 3041b4d10..87a1038fe 100644 --- a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -3,52 +3,54 @@ pragma solidity ^0.8.0; import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; -import {Roles} from 'src/deployments/procedures/roles/Roles.sol'; +import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; library AaveV4SpokeRolesProcedure { - function grantSpokeAdminRole(address accessManagerAddress, address admin) internal { - grantSpokePositionUpdaterRole(accessManagerAddress, admin); - grantSpokeConfiguratorRole(accessManagerAddress, admin); + function grantSpokeAdminRole(address accessManager, address admin) internal { + assert(admin != address(0)); + grantSpokePositionUpdaterRole(accessManager, admin); + grantSpokeConfiguratorRole(accessManager, admin); } - function grantSpokePositionUpdaterRole(address accessManagerAddress, address admin) internal { - IAccessManager(accessManagerAddress).grantRole({ + function grantSpokePositionUpdaterRole(address accessManager, address admin) internal { + assert(admin != address(0)); + IAccessManager(accessManager).grantRole({ roleId: Roles.SPOKE_POSITION_UPDATER_ROLE, account: admin, executionDelay: 0 }); } - function grantSpokeConfiguratorRole(address accessManagerAddress, address admin) internal { - IAccessManager(accessManagerAddress).grantRole({ + function grantSpokeConfiguratorRole(address accessManager, address admin) internal { + assert(admin != address(0)); + IAccessManager(accessManager).grantRole({ roleId: Roles.SPOKE_CONFIGURATOR_ROLE, account: admin, executionDelay: 0 }); } - function setupSpokeRoles(address accessManagerAddress, address spokeAddress) internal { - setupSpokePositionUpdaterRole(accessManagerAddress, spokeAddress); - setupSpokeConfiguratorRole(accessManagerAddress, spokeAddress); + function setupSpokeRoles(address accessManager, address spoke) internal { + setupSpokePositionUpdaterRole(accessManager, spoke); + setupSpokeConfiguratorRole(accessManager, spoke); } - function setupSpokePositionUpdaterRole( - address accessManagerAddress, - address spokeAddress - ) internal { + function setupSpokePositionUpdaterRole(address accessManager, address spoke) internal { + assert(spoke != address(0)); bytes4[] memory selectors = getSpokePositionUpdaterRoleSelectors(); - IAccessManager(accessManagerAddress).setTargetFunctionRole( - spokeAddress, + IAccessManager(accessManager).setTargetFunctionRole( + spoke, selectors, Roles.SPOKE_POSITION_UPDATER_ROLE ); } - function setupSpokeConfiguratorRole(address accessManagerAddress, address spokeAddress) internal { + function setupSpokeConfiguratorRole(address accessManager, address spoke) internal { + assert(spoke != address(0)); bytes4[] memory selectors = getSpokeConfiguratorRoleSelectors(); - IAccessManager(accessManagerAddress).setTargetFunctionRole( - spokeAddress, + IAccessManager(accessManager).setTargetFunctionRole( + spoke, selectors, Roles.SPOKE_CONFIGURATOR_ROLE ); diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index 242fa026e..93148be29 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -16,7 +16,7 @@ contract InputUtils { /// @dev spokeProxyAdminOwner The owner of the spoke proxyAdmin. /// @dev spokeConfiguratorOwner The admin of the spoke configurator. /// @dev gatewayOwner The owner of the native token and signature gateways. - /// @dev nativeWrapperAddress The address of the native wrapper. + /// @dev nativeWrapper The address of the native wrapper. /// @dev grantRoles A boolean indicating if roles should be granted. /// @dev hubLabels An array of hub labels; the number of hub labels defines the number of hubs to deploy. /// @dev spokeLabels An array of spoke labels; the number of spoke labels defines the number of spokes to deploy. @@ -29,7 +29,7 @@ contract InputUtils { address spokeProxyAdminOwner; address spokeConfiguratorOwner; address gatewayOwner; - address nativeWrapperAddress; + address nativeWrapper; bool grantRoles; string[] hubLabels; string[] spokeLabels; @@ -60,7 +60,7 @@ contract InputUtils { inputs.spokeAdmin = json.readAddress('.spokeAdmin'); inputs.spokeProxyAdminOwner = json.readAddress('.spokeProxyAdminOwner'); inputs.spokeConfiguratorOwner = json.readAddress('.spokeConfiguratorOwner'); - inputs.nativeWrapperAddress = json.readAddress('.nativeWrapperAddress'); + inputs.nativeWrapper = json.readAddress('.nativeWrapper'); inputs.grantRoles = json.readBool('.grantRoles'); inputs.hubLabels = json.readStringArray('.hubLabels'); inputs.spokeLabels = json.readStringArray('.spokeLabels'); diff --git a/src/deployments/utils/Logger.sol b/src/deployments/utils/Logger.sol index 649d32a41..898e7db4d 100644 --- a/src/deployments/utils/Logger.sol +++ b/src/deployments/utils/Logger.sol @@ -30,18 +30,6 @@ contract Logger { _json = _root; } - function log(string memory label, address value) public pure { - _log(label, value); - } - - function log(string memory label, uint256 value) public pure { - _log(label, value); - } - - function log(string memory value) public pure { - _log(value); - } - function write(string memory label, address value) public { _write(label, value); } @@ -65,20 +53,20 @@ contract Logger { function save(string memory fileName, bool withTimestamp) public { console.log(); console.log('Saving log to %s', _outputPath); - string memory appendedMetadata = withTimestamp ? string.concat(getTimestamp(), '-') : ''; + string memory appendedMetadata = withTimestamp ? string.concat(_getTimestamp(), '-') : ''; vm.writeJson(_json, string.concat(_outputPath, appendedMetadata, fileName)); } - function _log(string memory label, address value) internal pure { - console.log('%s: %s', label, value); + function log(string memory label, address value) public pure { + _log(label, value); } - function _log(string memory label, uint256 value) internal pure { - console.log('%s: %s', label, value); + function log(string memory label, uint256 value) public pure { + _log(label, value); } - function _log(string memory value) internal pure { - console.log(value); + function log(string memory value) public pure { + _log(value); } function _write(string memory label, address value) internal { @@ -86,7 +74,7 @@ contract Logger { } function _write(string memory label, uint256 value) internal { - _json = vm.serializeString(_root, label, vm.toString(value)); + _json = vm.serializeUint(_root, label, value); } function _write(string memory value) internal { @@ -109,7 +97,7 @@ contract Logger { _json = vm.serializeString(_root, groupLabel, group); } - function getTimestamp() public returns (string memory result) { + function _getTimestamp() internal returns (string memory result) { string[] memory command = new string[](3); command[0] = 'bash'; @@ -120,4 +108,16 @@ contract Logger { return result; } + + function _log(string memory label, address value) internal pure { + console.log('%s: %s', label, value); + } + + function _log(string memory label, uint256 value) internal pure { + console.log('%s: %s', label, value); + } + + function _log(string memory value) internal pure { + console.log(value); + } } diff --git a/src/deployments/utils/MetadataLogger.sol b/src/deployments/utils/MetadataLogger.sol index 19fbc0e82..86c33934c 100644 --- a/src/deployments/utils/MetadataLogger.sol +++ b/src/deployments/utils/MetadataLogger.sol @@ -9,23 +9,23 @@ contract MetadataLogger is Logger { constructor(string memory outputPath_) Logger(outputPath_) {} function writeJsonReportMarket(OrchestrationReports.FullDeploymentReport memory report) public { - _write('AccessBatchReport', report.accessBatchReport.accessManagerAddress); - _write('HubConfigurator', report.configuratorBatchReport.hubConfiguratorAddress); - _write('SpokeConfigurator', report.configuratorBatchReport.spokeConfiguratorAddress); + _write('AccessBatchReport', report.accessBatchReport.accessManager); + _write('HubConfigurator', report.configuratorBatchReport.hubConfigurator); + _write('SpokeConfigurator', report.configuratorBatchReport.spokeConfigurator); for (uint256 i; i < report.hubBatchReports.length; i++) { Logger.AddressEntry[] memory hubEntries = new Logger.AddressEntry[](3); hubEntries[0] = Logger.AddressEntry({ label: 'Hub', - value: report.hubBatchReports[i].report.hubAddress + value: report.hubBatchReports[i].report.hub }); hubEntries[1] = Logger.AddressEntry({ label: 'InterestRateStrategy', - value: report.hubBatchReports[i].report.hubAddress + value: report.hubBatchReports[i].report.hub }); hubEntries[2] = Logger.AddressEntry({ label: 'TreasurySpoke', - value: report.hubBatchReports[i].report.treasurySpokeAddress + value: report.hubBatchReports[i].report.treasurySpoke }); _writeGroup(report.hubBatchReports[i].label, hubEntries); } @@ -34,20 +34,20 @@ contract MetadataLogger is Logger { Logger.AddressEntry[] memory spokeInstanceEntries = new Logger.AddressEntry[](3); spokeInstanceEntries[0] = Logger.AddressEntry({ label: 'SpokeInstance Proxy', - value: report.spokeInstanceBatchReports[i].report.spokeProxyAddress + value: report.spokeInstanceBatchReports[i].report.spokeProxy }); spokeInstanceEntries[1] = Logger.AddressEntry({ label: 'SpokeInstance Implementation', - value: report.spokeInstanceBatchReports[i].report.spokeImplementationAddress + value: report.spokeInstanceBatchReports[i].report.spokeImplementation }); spokeInstanceEntries[2] = Logger.AddressEntry({ label: 'AaveOracle', - value: report.spokeInstanceBatchReports[i].report.aaveOracleAddress + value: report.spokeInstanceBatchReports[i].report.aaveOracle }); _writeGroup(report.spokeInstanceBatchReports[i].label, spokeInstanceEntries); } - _write('SignatureGateway', report.gatewaysBatchReport.signatureGatewayAddress); - _write('NativeTokenGateway', report.gatewaysBatchReport.nativeGatewayAddress); + _write('SignatureGateway', report.gatewaysBatchReport.signatureGateway); + _write('NativeTokenGateway', report.gatewaysBatchReport.nativeGateway); } } diff --git a/src/deployments/procedures/roles/Roles.sol b/src/deployments/utils/libraries/Roles.sol similarity index 100% rename from src/deployments/procedures/roles/Roles.sol rename to src/deployments/utils/libraries/Roles.sol diff --git a/src/deployments/utils/libraries/Utils.sol b/src/deployments/utils/libraries/Utils.sol index 8c9765f70..76f97a4f2 100644 --- a/src/deployments/utils/libraries/Utils.sol +++ b/src/deployments/utils/libraries/Utils.sol @@ -2,6 +2,10 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import { + TransparentUpgradeableProxy +} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; + library Utils { function computeCreateAddress(address deployer, uint8 nonce) internal pure returns (address) { // RLP([deployer, nonce]) for 0 <= nonce <= 0x7f @@ -11,4 +15,15 @@ library Utils { bytes memory rlp = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, nonceRlp); return address(uint160(uint256(keccak256(rlp)))); } + + function proxify( + address logic_, + address initialOwner_, + bytes memory data_ + ) internal returns (address) { + return + address( + new TransparentUpgradeableProxy({_logic: logic_, initialOwner: initialOwner_, _data: data_}) + ); + } } diff --git a/tests/Base.t.sol b/tests/Base.t.sol index dae9944fb..7c9ea9db9 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -36,7 +36,6 @@ import {WadRayMath} from 'src/libraries/math/WadRayMath.sol'; import {MathUtils} from 'src/libraries/math/MathUtils.sol'; import {PercentageMath} from 'src/libraries/math/PercentageMath.sol'; import {EIP712Types} from 'src/libraries/types/EIP712Types.sol'; -import {Roles} from 'src/deployments/procedures/roles/Roles.sol'; import {Rescuable, IRescuable} from 'src/utils/Rescuable.sol'; import {NoncesKeyed, INoncesKeyed} from 'src/utils/NoncesKeyed.sol'; import {UnitPriceFeed} from 'src/misc/UnitPriceFeed.sol'; @@ -78,6 +77,7 @@ import {TestTypes} from 'tests/utils/TestTypes.sol'; // orchestration import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; +import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; // mocks import {TestnetERC20} from 'tests/mocks/TestnetERC20.sol'; @@ -129,7 +129,6 @@ abstract contract Base is BatchTestProcedures { PercentageMath.PERCENTAGE_FACTOR; IHubBase.PremiumDelta internal ZERO_PREMIUM_DELTA = ZERO_PREMIUM_DELTA; - /// IHub[] internal _hubs; ISpoke[] internal _spokes; IAaveOracle[] internal _oracles; @@ -213,6 +212,7 @@ abstract contract Base is BatchTestProcedures { struct FixtureAssetList { IERC20Metadata underlying; uint16 liquidityFee; + address reinvestmentController; bytes irData; } @@ -280,6 +280,7 @@ abstract contract Base is BatchTestProcedures { }); function setUp() public virtual override { + _initTokenList(); _setupFixtures(); } @@ -288,84 +289,72 @@ abstract contract Base is BatchTestProcedures { _setupFixturesRoles(report); // todo rm when tests adapted to multiple hubs and spokes - hub1 = IHub(report.hubReports[0].hubAddress); - irStrategy = AssetInterestRateStrategy(report.hubReports[0].irStrategyAddress); - treasurySpoke = ITreasurySpoke(report.hubReports[0].treasurySpokeAddress); - spoke1 = ISpoke(report.spokeReports[0].spokeAddress); - spoke2 = ISpoke(report.spokeReports[1].spokeAddress); - spoke3 = ISpoke(report.spokeReports[2].spokeAddress); - oracle1 = IAaveOracle(report.spokeReports[0].aaveOracleAddress); - oracle2 = IAaveOracle(report.spokeReports[1].aaveOracleAddress); - oracle3 = IAaveOracle(report.spokeReports[2].aaveOracleAddress); - accessManager = IAccessManager(report.accessManagerAddress); + hub1 = IHub(report.hubReports[0].hub); + irStrategy = AssetInterestRateStrategy(report.hubReports[0].irStrategy); + treasurySpoke = ITreasurySpoke(report.hubReports[0].treasurySpoke); + spoke1 = ISpoke(report.spokeReports[0].spoke); + spoke2 = ISpoke(report.spokeReports[1].spoke); + spoke3 = ISpoke(report.spokeReports[2].spoke); + oracle1 = IAaveOracle(report.spokeReports[0].aaveOracle); + oracle2 = IAaveOracle(report.spokeReports[1].aaveOracle); + oracle3 = IAaveOracle(report.spokeReports[2].aaveOracle); + accessManager = IAccessManager(report.accessManager); } function _deployFixtures( uint256 numHubs, uint256 numSpokes ) internal virtual returns (TestTypes.TestEnvReport memory report) { + // console.log('weth', address(tokenList.weth)); + // revert('testing env'); report = AaveV4TestOrchestration.deployTestEnv({ admin: ADMIN, treasuryAdmin: TREASURY_ADMIN, hubCount: numHubs, - spokeCount: numSpokes + spokeCount: numSpokes, + nativeWrapper: address(tokenList.weth) }); for (uint256 i; i < numHubs; ++i) { - _hubs.push(IHub(report.hubReports[i].hubAddress)); - _irStrategies.push(AssetInterestRateStrategy(report.hubReports[i].irStrategyAddress)); - _treasurySpokes.push(ITreasurySpoke(report.hubReports[i].treasurySpokeAddress)); + _hubs.push(IHub(report.hubReports[i].hub)); + _irStrategies.push(AssetInterestRateStrategy(report.hubReports[i].irStrategy)); + _treasurySpokes.push(ITreasurySpoke(report.hubReports[i].treasurySpoke)); - vm.label(report.hubReports[i].hubAddress, string.concat('hub', string(abi.encode(i)))); - vm.label( - report.hubReports[i].irStrategyAddress, - string.concat('irStrategy', string(abi.encode(i))) - ); + vm.label(report.hubReports[i].hub, string.concat('hub', string(abi.encode(i)))); + vm.label(report.hubReports[i].irStrategy, string.concat('irStrategy', string(abi.encode(i)))); vm.label( - report.hubReports[i].treasurySpokeAddress, + report.hubReports[i].treasurySpoke, string.concat('treasurySpoke', string(abi.encode(i))) ); } for (uint256 i; i < numSpokes; ++i) { - _spokes.push(ISpoke(report.spokeReports[i].spokeAddress)); - _oracles.push(IAaveOracle(report.spokeReports[i].aaveOracleAddress)); + _spokes.push(ISpoke(report.spokeReports[i].spoke)); + _oracles.push(IAaveOracle(report.spokeReports[i].aaveOracle)); - vm.label(report.spokeReports[i].spokeAddress, string.concat('spoke', string(abi.encode(i)))); - vm.label( - report.spokeReports[i].aaveOracleAddress, - string.concat('oracle', string(abi.encode(i))) - ); + vm.label(report.spokeReports[i].spoke, string.concat('spoke', string(abi.encode(i)))); + vm.label(report.spokeReports[i].aaveOracle, string.concat('oracle', string(abi.encode(i)))); } return report; } function _setupFixturesRoles(TestTypes.TestEnvReport memory report) internal virtual { - if (report.accessManagerAddress == address(0)) - report.accessManagerAddress = address(accessManager); + if (report.accessManager == address(0)) report.accessManager = address(accessManager); // temporary grant admin role to address(this) to execute setAndGrantRolesTestEnv from its context vm.startPrank(ADMIN); - IAccessManager(report.accessManagerAddress).grantRole( - Roles.DEFAULT_ADMIN_ROLE, - address(this), - 0 - ); + IAccessManager(report.accessManager).grantRole(Roles.DEFAULT_ADMIN_ROLE, address(this), 0); vm.stopPrank(); AaveV4TestOrchestration.setRolesTestEnv(report); AaveV4TestOrchestration.grantRolesTestEnv(report, ADMIN, HUB_ADMIN, SPOKE_ADMIN); - IAccessManager(report.accessManagerAddress).renounceRole( - Roles.DEFAULT_ADMIN_ROLE, - address(this) - ); + IAccessManager(report.accessManager).renounceRole(Roles.DEFAULT_ADMIN_ROLE, address(this)); } function _initEnvironment() internal { - _initTokenList(); _mintAndApproveTokenList(); - _configureTokenList(); + _configureHubsAndSpokes(); } function _initTokenList() internal { @@ -482,7 +471,7 @@ abstract contract Base is BatchTestProcedures { } } - function _configureTokenList() internal { + function _configureHubsAndSpokes() internal { vm.startPrank(ADMIN); accessManager.grantRole(Roles.HUB_CONFIGURATOR_ROLE, address(this), 0); accessManager.grantRole(Roles.SPOKE_CONFIGURATOR_ROLE, address(this), 0); @@ -877,6 +866,7 @@ abstract contract Base is BatchTestProcedures { feeReceiver: address(treasurySpoke), liquidityFee: 10_00, irStrategy: address(irStrategy), + reinvestmentController: address(0), irData: encodedIrData }); assetParams[1] = ConfigData.AddAssetParams({ @@ -886,6 +876,7 @@ abstract contract Base is BatchTestProcedures { feeReceiver: address(treasurySpoke), liquidityFee: 5_00, irStrategy: address(irStrategy), + reinvestmentController: address(0), irData: encodedIrData }); assetParams[2] = ConfigData.AddAssetParams({ @@ -895,6 +886,7 @@ abstract contract Base is BatchTestProcedures { feeReceiver: address(treasurySpoke), liquidityFee: 5_00, irStrategy: address(irStrategy), + reinvestmentController: address(0), irData: encodedIrData }); assetParams[3] = ConfigData.AddAssetParams({ @@ -904,6 +896,7 @@ abstract contract Base is BatchTestProcedures { feeReceiver: address(treasurySpoke), liquidityFee: 10_00, irStrategy: address(irStrategy), + reinvestmentController: address(0), irData: encodedIrData }); assetParams[4] = ConfigData.AddAssetParams({ @@ -913,6 +906,7 @@ abstract contract Base is BatchTestProcedures { feeReceiver: address(treasurySpoke), liquidityFee: 10_00, irStrategy: address(irStrategy), + reinvestmentController: address(0), irData: encodedIrData }); assetParams[5] = ConfigData.AddAssetParams({ @@ -922,6 +916,7 @@ abstract contract Base is BatchTestProcedures { feeReceiver: address(treasurySpoke), liquidityFee: 5_00, irStrategy: address(irStrategy), + reinvestmentController: address(0), irData: encodedIrData }); return assetParams; @@ -938,28 +933,32 @@ abstract contract Base is BatchTestProcedures { assetsList[0] = FixtureAssetList({ underlying: IERC20Metadata(address(tokenList.weth)), liquidityFee: 0, + reinvestmentController: address(0), irData: abi.encode(_defaultIrData) }); assetsList[1] = FixtureAssetList({ underlying: IERC20Metadata(address(tokenList.usdx)), liquidityFee: 0, + reinvestmentController: address(0), irData: abi.encode(_defaultIrData) }); assetsList[2] = FixtureAssetList({ underlying: IERC20Metadata(address(tokenList.dai)), liquidityFee: 0, + reinvestmentController: address(0), irData: abi.encode(_defaultIrData) }); assetsList[3] = FixtureAssetList({ underlying: IERC20Metadata(address(tokenList.wbtc)), liquidityFee: 0, + reinvestmentController: address(0), irData: abi.encode(_defaultIrData) }); TestTypes.TestEnvReport memory report = _addFixture('2', assetsList); return ( - IHub(report.hubReports[0].hubAddress), - AssetInterestRateStrategy(report.hubReports[0].irStrategyAddress) + IHub(report.hubReports[0].hub), + AssetInterestRateStrategy(report.hubReports[0].irStrategy) ); } @@ -974,28 +973,32 @@ abstract contract Base is BatchTestProcedures { assetsList[0] = FixtureAssetList({ underlying: IERC20Metadata(address(tokenList.dai)), liquidityFee: 0, + reinvestmentController: address(0), irData: abi.encode(_defaultIrData) }); assetsList[1] = FixtureAssetList({ underlying: IERC20Metadata(address(tokenList.usdx)), liquidityFee: 0, + reinvestmentController: address(0), irData: abi.encode(_defaultIrData) }); assetsList[2] = FixtureAssetList({ underlying: IERC20Metadata(address(tokenList.wbtc)), liquidityFee: 0, + reinvestmentController: address(0), irData: abi.encode(_defaultIrData) }); assetsList[3] = FixtureAssetList({ underlying: IERC20Metadata(address(tokenList.weth)), liquidityFee: 0, + reinvestmentController: address(0), irData: abi.encode(_defaultIrData) }); TestTypes.TestEnvReport memory report = _addFixture('3', assetsList); return ( - IHub(report.hubReports[0].hubAddress), - AssetInterestRateStrategy(report.hubReports[0].irStrategyAddress) + IHub(report.hubReports[0].hub), + AssetInterestRateStrategy(report.hubReports[0].irStrategy) ); } @@ -1011,44 +1014,31 @@ abstract contract Base is BatchTestProcedures { ); for (uint256 i; i < assetsList.length; ++i) { assetParams[i] = ConfigData.AddAssetParams({ - hub: report.hubReports[0].hubAddress, + hub: report.hubReports[0].hub, underlying: address(assetsList[i].underlying), decimals: assetsList[i].underlying.decimals(), - feeReceiver: report.hubReports[0].treasurySpokeAddress, + feeReceiver: report.hubReports[0].treasurySpoke, liquidityFee: assetsList[i].liquidityFee, - irStrategy: report.hubReports[0].irStrategyAddress, - irData: assetsList[i].irData + irStrategy: report.hubReports[0].irStrategy, + irData: assetsList[i].irData, + reinvestmentController: assetsList[i].reinvestmentController }); } vm.startPrank(ADMIN); - IAccessManager(report.accessManagerAddress).grantRole( - Roles.HUB_CONFIGURATOR_ROLE, - address(this), - 0 - ); - IAccessManager(report.accessManagerAddress).grantRole( - Roles.SPOKE_CONFIGURATOR_ROLE, - address(this), - 0 - ); + IAccessManager(report.accessManager).grantRole(Roles.HUB_CONFIGURATOR_ROLE, address(this), 0); + IAccessManager(report.accessManager).grantRole(Roles.SPOKE_CONFIGURATOR_ROLE, address(this), 0); vm.stopPrank(); AaveV4TestOrchestration.configureHubsAssets(assetParams); // Renounce temporary roles - IAccessManager(report.accessManagerAddress).renounceRole( - Roles.HUB_CONFIGURATOR_ROLE, - address(this) - ); - IAccessManager(report.accessManagerAddress).renounceRole( - Roles.SPOKE_CONFIGURATOR_ROLE, - address(this) - ); + IAccessManager(report.accessManager).renounceRole(Roles.HUB_CONFIGURATOR_ROLE, address(this)); + IAccessManager(report.accessManager).renounceRole(Roles.SPOKE_CONFIGURATOR_ROLE, address(this)); - vm.label(report.hubReports[0].hubAddress, string.concat('Hub', label)); - vm.label(report.hubReports[0].irStrategyAddress, string.concat('IrStrategy', label)); - vm.label(report.hubReports[0].treasurySpokeAddress, string.concat('TreasurySpoke', label)); + vm.label(report.hubReports[0].hub, string.concat('Hub', label)); + vm.label(report.hubReports[0].irStrategy, string.concat('IrStrategy', label)); + vm.label(report.hubReports[0].treasurySpoke, string.concat('TreasurySpoke', label)); return report; } diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index 04e5f566c..a80f8e46b 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.0; import 'tests/utils/BatchTestProcedures.sol'; +import {stdError} from 'forge-std/StdError.sol'; contract AaveV4BatchDeploymentTest is BatchTestProcedures { Logger public logger; @@ -31,7 +32,7 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { spokeConfiguratorOwner: makeAddr('spokeConfiguratorOwner'), spokeAdmin: makeAddr('spokeAdmin'), gatewayOwner: makeAddr('gatewayOwner'), - nativeWrapperAddress: weth9, + nativeWrapper: weth9, grantRoles: true, hubLabels: hubLabels, spokeLabels: spokeLabels @@ -39,124 +40,234 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { } function testAaveV4BatchDeployment() public { - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + checkedV4Deployment(logger, inputs); } function testAaveV4BatchDeployment_withoutRoles() public { inputs.grantRoles = false; - - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); + checkedV4Deployment(logger, inputs); } function testAaveV4BatchDeployment_withoutNativeGateway() public { - inputs.nativeWrapperAddress = address(0); - - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + inputs.nativeWrapper = address(0); + checkedV4Deployment(logger, inputs); } function testAaveV4BatchDeployment_withoutHubs() public { inputs.hubLabels = new string[](0); - - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + checkedV4Deployment(logger, inputs); } function testAaveV4BatchDeployment_withoutSpokes() public { inputs.spokeLabels = new string[](0); - - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + checkedV4Deployment(logger, inputs); } - function testAaveV4BatchDeployment_withZeroAccessManagerAdminAddress() public { + function testAaveV4BatchDeployment_withZeroAccessManagerAdmin_withRoles_revertsWithAssertionError() + public + { + // only reverts if grantRoles is true, as access manager admin replaces deployer as default admin inputs.accessManagerAdmin = address(0); + inputs.grantRoles = true; - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + // reverts in AaveV4AccessBatch + vm.expectRevert(stdError.assertionError); + this.checkedV4Deployment(logger, inputs); } - function testAaveV4BatchDeployment_withZeroAccessManagerAdminAddress_withoutRoles() public { + function testAaveV4BatchDeployment_withZeroAccessManagerAdmin_withoutRoles() public { inputs.accessManagerAdmin = address(0); inputs.grantRoles = false; - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); - } - - function testAaveV4BatchDeployment_withZerohubConfiguratorOwnerAddress() public { - inputs.hubConfiguratorOwner = address(0); - - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + checkedV4Deployment(logger, inputs); } - function testAaveV4BatchDeployment_withZerohubConfiguratorOwnerAddress_withoutRoles() public { + /// @dev Reverts as hubConfigurator is always deployed + /// and owners are needed on initial deployment + function testAaveV4BatchDeployment_withZeroHubConfiguratorOwner() public { inputs.hubConfiguratorOwner = address(0); - inputs.grantRoles = false; + inputs.grantRoles = vm.randomBool(); - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + // reverts in AaveV4ConfiguratorBatch + vm.expectRevert(stdError.assertionError); + this.checkedV4Deployment(logger, inputs); } - function testAaveV4BatchDeployment_withZeroTreasurySpokeOwnerAddress() public { + /// @dev Reverts as treasurySpoke is always deployed if hubs are being deployed + /// and owner is needed on initial deployment + function testAaveV4BatchDeployment_fuzz_withZeroTreasurySpokeOwner( + bool withoutHubs, + bool grantRoles + ) public { inputs.treasurySpokeOwner = address(0); - - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + inputs.grantRoles = grantRoles; + + if (withoutHubs) { + inputs.hubLabels = new string[](0); + } + + if (_isExpectAssertionError(inputs, deployer)) { + // reverts in AaveV4HubBatch + vm.expectRevert(stdError.assertionError); + this.checkedV4Deployment(logger, inputs); + } else { + checkedV4Deployment(logger, inputs); + } } - function testAaveV4BatchDeployment_withZeroTreasurySpokeOwnerAddress_withoutRoles() public { - inputs.treasurySpokeOwner = address(0); - inputs.grantRoles = false; - - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + function testAaveV4BatchDeployment_fuzz_withZeroSpokeProxyAdminOwner( + bool withoutSpokes, + bool grantRoles + ) public { + inputs.spokeProxyAdminOwner = address(0); + inputs.grantRoles = grantRoles; + if (withoutSpokes) { + inputs.spokeLabels = new string[](0); + } + + if (_isExpectAssertionError(inputs, deployer)) { + // reverts in AaveV4SpokeInstanceBatch + vm.expectRevert(stdError.assertionError); + this.checkedV4Deployment(logger, inputs); + } else { + checkedV4Deployment(logger, inputs); + } } - function testAaveV4BatchDeployment_withZeroSpokeProxyAdminOwnerAddress() public { - inputs.spokeProxyAdminOwner = address(0); + function testAaveV4BatchDeployment_withZeroSpokeConfiguratorOwner() public { + inputs.spokeConfiguratorOwner = address(0); + inputs.grantRoles = vm.randomBool(); - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + // reverts in AaveV4ConfiguratorBatch + vm.expectRevert(stdError.assertionError); + this.checkedV4Deployment(logger, inputs); } - function testAaveV4BatchDeployment_withZeroSpokeProxyAdminOwnerAddress_withoutRoles() public { - inputs.spokeProxyAdminOwner = address(0); + function testAaveV4BatchDeployment_withZeroSpokeConfiguratorOwner_withoutRoles_revertsWithAssertionError() + public + { + inputs.spokeConfiguratorOwner = address(0); inputs.grantRoles = false; - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + // reverts in AaveV4ConfiguratorBatch + vm.expectRevert(stdError.assertionError); + this.checkedV4Deployment(logger, inputs); } - function testAaveV4BatchDeployment_withZerospokeConfiguratorOwnerAddress() public { - inputs.spokeConfiguratorOwner = address(0); + function testAaveV4BatchDeployment_fuzz_withoutRoles( + FullDeployInputs memory deployInputs, + address deployer, + bool withoutHubs, + bool withoutSpokes, + bool withoutNativeWrapper + ) public { + deployInputs.grantRoles = false; + if (withoutNativeWrapper) { + deployInputs.nativeWrapper = address(0); + } else { + deployInputs.nativeWrapper = inputs.nativeWrapper; + } + if (withoutHubs) { + deployInputs.hubLabels = new string[](0); + } else { + deployInputs.hubLabels = inputs.hubLabels; + } + if (withoutSpokes) { + deployInputs.spokeLabels = new string[](0); + } else { + deployInputs.spokeLabels = inputs.spokeLabels; + } + + if (_isExpectAssertionError(deployInputs, deployer)) { + vm.expectRevert(stdError.assertionError); + this.checkedV4Deployment(logger, deployInputs); + } else { + checkedV4Deployment(logger, deployInputs); + } + } - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + function testAaveV4BatchDeployment_fuzz_withRoles( + FullDeployInputs memory deployInputs, + address deployer, + bool withoutHubs, + bool withoutSpokes, + bool withoutNativeWrapper + ) public { + deployInputs.grantRoles = true; + if (withoutNativeWrapper) { + deployInputs.nativeWrapper = address(0); + } else { + deployInputs.nativeWrapper = inputs.nativeWrapper; + } + deployInputs.nativeWrapper = inputs.nativeWrapper; + if (withoutHubs) { + deployInputs.hubLabels = new string[](0); + } else { + deployInputs.hubLabels = inputs.hubLabels; + } + if (withoutSpokes) { + deployInputs.spokeLabels = new string[](0); + } else { + deployInputs.spokeLabels = inputs.spokeLabels; + } + + if (_isExpectAssertionError(deployInputs, deployer)) { + vm.expectRevert(stdError.assertionError); + this.checkedV4Deployment(logger, deployInputs); + } else { + checkedV4Deployment(logger, deployInputs); + } } - function testAaveV4BatchDeployment_withZerospokeConfiguratorOwnerAddress_withoutRoles() public { - inputs.spokeConfiguratorOwner = address(0); - inputs.grantRoles = false; + /// @dev Sanitized inputs should never fail when deploying + function testAaveV4BatchDeployment_fuzz_sanitizedInputs( + FullDeployInputs memory deployInputs + ) public { + deployInputs = _sanitizeInputs(deployInputs); + + assertNotEq(deployInputs.accessManagerAdmin, address(0)); + assertNotEq(deployInputs.hubConfiguratorOwner, address(0)); + assertNotEq(deployInputs.treasurySpokeOwner, address(0)); + assertNotEq(deployInputs.spokeProxyAdminOwner, address(0)); + assertNotEq(deployInputs.spokeConfiguratorOwner, address(0)); + assertNotEq(deployInputs.gatewayOwner, address(0)); + assertNotEq(deployInputs.accessManagerAdmin, address(0)); + assertNotEq(deployInputs.hubAdmin, address(0)); + assertNotEq(deployInputs.spokeAdmin, address(0)); + + checkedV4Deployment(logger, deployInputs); + } - OrchestrationReports.FullDeploymentReport memory report = deployAaveV4Testnet(logger, inputs); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + function _isExpectAssertionError( + FullDeployInputs memory deployInputs, + address deployer + ) internal pure returns (bool isExpectedError) { + // deployer is initial admin for access manager + if (deployer == address(0)) return true; + + // configurators always deployed + if (deployInputs.spokeConfiguratorOwner == address(0)) return true; + if (deployInputs.hubConfiguratorOwner == address(0)) return true; + + // gateways only when native wrapper is set + if (deployInputs.nativeWrapper != address(0) && deployInputs.gatewayOwner == address(0)) { + return true; + } + + // hubs require treasury owner when deployed + if (deployInputs.hubLabels.length > 0 && deployInputs.treasurySpokeOwner == address(0)) { + return true; + } + + // spokes require proxy admin owner when deployed + if (deployInputs.spokeLabels.length > 0 && deployInputs.spokeProxyAdminOwner == address(0)) { + return true; + } + + if (deployInputs.grantRoles) { + if (deployInputs.accessManagerAdmin == address(0)) return true; + if (deployInputs.hubLabels.length > 0 && deployInputs.hubAdmin == address(0)) return true; + if (deployInputs.spokeLabels.length > 0 && deployInputs.spokeAdmin == address(0)) return true; + } } } diff --git a/tests/deployments/batches/TestTokensBatch.sol b/tests/deployments/batches/TestTokensBatch.sol index 241c3e9e7..82d5de510 100644 --- a/tests/deployments/batches/TestTokensBatch.sol +++ b/tests/deployments/batches/TestTokensBatch.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; -import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; +import {WETHDeployProcedure} from 'tests/deployments/procedures/WETHDeployProcedure.sol'; import { TestnetERC20DeployProcedure } from 'tests/deployments/procedures/TestnetERC20DeployProcedure.sol'; @@ -15,13 +15,13 @@ contract TestTokensBatch is WETHDeployProcedure, TestnetERC20DeployProcedure { TestTypes.TestTokensBatchReport internal _report; constructor(TestTypes.TestTokenInput[] memory inputs_) { - _report.tokenAddresses = new address[](inputs_.length); - _report.wethAddress = _deployWETH(); + _report.tokens = new address[](inputs_.length); + _report.weth = _deployWETH(); for (uint256 i; i < inputs_.length; i++) { TestTypes.TestTokenInput memory input = inputs_[i]; - address tokenAddress = _deployTestnetERC20(input.name, input.symbol, input.decimals); - _report.tokenAddresses[i] = tokenAddress; + address token = _deployTestnetERC20(input.name, input.symbol, input.decimals); + _report.tokens[i] = token; } } diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol index 04d549737..dd834c658 100644 --- a/tests/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -50,12 +50,12 @@ library AaveV4TestOrchestration { TestTypes.TestTokensReport memory tokensReport = _deployTestTokensBatch(tokenInputs); TestTypes.TokenList memory tokenList; - tokenList.weth = WETH9(payable(tokensReport.wethAddress)); - tokenList.usdx = TestnetERC20(tokensReport.testTokenAddresses[0]); - tokenList.dai = TestnetERC20(tokensReport.testTokenAddresses[1]); - tokenList.wbtc = TestnetERC20(tokensReport.testTokenAddresses[2]); - tokenList.usdy = TestnetERC20(tokensReport.testTokenAddresses[3]); - tokenList.usdz = TestnetERC20(tokensReport.testTokenAddresses[4]); + tokenList.weth = WETH9(payable(tokensReport.weth)); + tokenList.usdx = TestnetERC20(tokensReport.testTokens[0]); + tokenList.dai = TestnetERC20(tokensReport.testTokens[1]); + tokenList.wbtc = TestnetERC20(tokensReport.testTokens[2]); + tokenList.usdy = TestnetERC20(tokensReport.testTokens[3]); + tokenList.usdz = TestnetERC20(tokensReport.testTokens[4]); return tokenList; } @@ -63,7 +63,8 @@ library AaveV4TestOrchestration { address admin, address treasuryAdmin, uint256 hubCount, - uint256 spokeCount + uint256 spokeCount, + address nativeWrapper ) external returns (TestTypes.TestEnvReport memory) { TestTypes.TestEnvReport memory report; @@ -71,17 +72,17 @@ library AaveV4TestOrchestration { report.spokeReports = new TestTypes.TestSpokeReport[](spokeCount); // Deploy Access Batch - report.accessManagerAddress = AaveV4DeployBase.deployAccessBatch(admin).accessManagerAddress; + report.accessManager = AaveV4DeployBase.deployAccessBatch(admin).accessManager; // Deploy Hub Batches for (uint256 i; i < hubCount; ++i) { BatchReports.HubBatchReport memory hubReport = AaveV4DeployBase.deployHubBatch( treasuryAdmin, - report.accessManagerAddress + report.accessManager ); - report.hubReports[i].hubAddress = hubReport.hubAddress; - report.hubReports[i].irStrategyAddress = hubReport.irStrategyAddress; - report.hubReports[i].treasurySpokeAddress = hubReport.treasurySpokeAddress; + report.hubReports[i].hub = hubReport.hub; + report.hubReports[i].irStrategy = hubReport.irStrategy; + report.hubReports[i].treasurySpoke = hubReport.treasurySpoke; } // Deploy Spoke Instance Batches @@ -89,33 +90,60 @@ library AaveV4TestOrchestration { BatchReports.SpokeInstanceBatchReport memory spokeReport = AaveV4DeployBase .deploySpokeInstanceBatch( admin, - report.accessManagerAddress, + report.accessManager, Constants.ORACLE_DECIMALS, Constants.ORACLE_SUFFIX, string.concat('Spoke ', string(abi.encode(i)), Constants.ORACLE_SUFFIX) ); - report.spokeReports[i].spokeAddress = spokeReport.spokeProxyAddress; - report.spokeReports[i].aaveOracleAddress = spokeReport.aaveOracleAddress; + report.spokeReports[i].spoke = spokeReport.spokeProxy; + report.spokeReports[i].aaveOracle = spokeReport.aaveOracle; } + // Deploy Gateways Batch + BatchReports.GatewaysBatchReport memory gatewaysReport = AaveV4DeployBase.deployGatewaysBatch({ + owner: admin, + nativeWrapper: nativeWrapper + }); + report.gatewaysReport.signatureGateway = gatewaysReport.signatureGateway; + report.gatewaysReport.nativeGateway = gatewaysReport.nativeGateway; + return report; } + function configureHubsSpokes(ConfigData.AddSpokeParams[] memory paramsList) external { + for (uint256 i; i < paramsList.length; ++i) { + AaveV4HubConfigProcedures.addSpoke(paramsList[i]); + } + } + + function configureSpokes( + ConfigData.UpdateLiquidationConfigParams[] memory liquidationParamsList, + ConfigData.AddReserveParams[] memory reserveParamsList + ) external returns (TestTypes.SpokeReserveId[] memory) { + for (uint256 i; i < liquidationParamsList.length; ++i) { + AaveV4SpokeConfigProcedures.updateLiquidationConfig(liquidationParamsList[i]); + } + TestTypes.SpokeReserveId[] memory spokeReserveIds = new TestTypes.SpokeReserveId[]( + reserveParamsList.length + ); + for (uint256 i; i < reserveParamsList.length; ++i) { + spokeReserveIds[i] = TestTypes.SpokeReserveId({ + spoke: reserveParamsList[i].spoke, + reserveId: AaveV4SpokeConfigProcedures.addReserve(reserveParamsList[i]) + }); + } + return spokeReserveIds; + } + function setRolesTestEnv(TestTypes.TestEnvReport memory report) public { // Set Hub Roles for (uint256 i; i < report.hubReports.length; ++i) { - AaveV4HubRolesProcedure.setupHubRoles( - report.accessManagerAddress, - report.hubReports[i].hubAddress - ); + AaveV4HubRolesProcedure.setupHubRoles(report.accessManager, report.hubReports[i].hub); } // Set Spoke Roles for (uint256 i; i < report.spokeReports.length; ++i) { - AaveV4SpokeRolesProcedure.setupSpokeRoles( - report.accessManagerAddress, - report.spokeReports[i].spokeAddress - ); + AaveV4SpokeRolesProcedure.setupSpokeRoles(report.accessManager, report.spokeReports[i].spoke); } } @@ -129,26 +157,14 @@ library AaveV4TestOrchestration { grantSpokeRolesTestEnv(report, admin, spokeAdmin); } - // function grantAccessManagerRolesTestEnv( - // TestTypes.TestEnvReport memory report, - // address admin - // ) external { - // // grant RootAdmin Role - // AaveV4AccessManagerRolesProcedure.grantRootAdminRole({ - // accessManagerAddress: report.accessManagerAddress, - // newAdminAddress: admin, - // currentAdminAddress: admin - // }); - // } - function grantHubRolesTestEnv( TestTypes.TestEnvReport memory report, address admin, address hubAdmin ) public { // grant Hub roles - AaveV4HubRolesProcedure.grantHubAdminRole(report.accessManagerAddress, admin); - AaveV4HubRolesProcedure.grantHubAdminRole(report.accessManagerAddress, hubAdmin); + AaveV4HubRolesProcedure.grantHubAdminRole(report.accessManager, admin); + AaveV4HubRolesProcedure.grantHubAdminRole(report.accessManager, hubAdmin); } function grantSpokeRolesTestEnv( @@ -157,8 +173,8 @@ library AaveV4TestOrchestration { address spokeAdmin ) public { // grant Spoke roles - AaveV4SpokeRolesProcedure.grantSpokeAdminRole(report.accessManagerAddress, admin); - AaveV4SpokeRolesProcedure.grantSpokeAdminRole(report.accessManagerAddress, spokeAdmin); + AaveV4SpokeRolesProcedure.grantSpokeAdminRole(report.accessManager, admin); + AaveV4SpokeRolesProcedure.grantSpokeAdminRole(report.accessManager, spokeAdmin); } function configureHubsAssets( @@ -171,42 +187,17 @@ library AaveV4TestOrchestration { return assetIds; } - function configureHubsSpokes(ConfigData.AddSpokeParams[] memory paramsList) external { - for (uint256 i; i < paramsList.length; ++i) { - AaveV4HubConfigProcedures.addSpoke(paramsList[i]); - } - } - - function configureSpokes( - ConfigData.UpdateLiquidationConfigParams[] memory liquidationParamsList, - ConfigData.AddReserveParams[] memory reserveParamsList - ) external returns (TestTypes.SpokeReserveId[] memory) { - for (uint256 i; i < liquidationParamsList.length; ++i) { - AaveV4SpokeConfigProcedures.updateLiquidationConfig(liquidationParamsList[i]); - } - TestTypes.SpokeReserveId[] memory spokeReserveIds = new TestTypes.SpokeReserveId[]( - reserveParamsList.length - ); - for (uint256 i; i < reserveParamsList.length; ++i) { - spokeReserveIds[i] = TestTypes.SpokeReserveId({ - spoke: reserveParamsList[i].spoke, - reserveId: AaveV4SpokeConfigProcedures.addReserve(reserveParamsList[i]) - }); - } - return spokeReserveIds; - } - function _deployTestTokensBatch( TestTypes.TestTokenInput[] memory tokenInputs ) internal returns (TestTypes.TestTokensReport memory) { TestTypes.TestTokensReport memory report; - report.testTokenAddresses = new address[](tokenInputs.length); + report.testTokens = new address[](tokenInputs.length); // Deploy Test Tokens Batch TestTypes.TestTokensBatchReport memory tokensReport = _deployTokensBatch(tokenInputs); - report.wethAddress = tokensReport.wethAddress; - report.testTokenAddresses = tokensReport.tokenAddresses; + report.weth = tokensReport.weth; + report.testTokens = tokensReport.tokens; return report; } diff --git a/tests/deployments/procedures/ProceduresBase.t.sol b/tests/deployments/procedures/ProceduresBase.t.sol new file mode 100644 index 000000000..d4ed381cc --- /dev/null +++ b/tests/deployments/procedures/ProceduresBase.t.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Test} from 'forge-std/Test.sol'; +import {stdError} from 'forge-std/Test.sol'; + +import {Ownable} from 'src/dependencies/openzeppelin/Ownable.sol'; +import { + AaveV4HubConfiguratorDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4HubConfiguratorDeployProcedureWrapper.sol'; +import { + AaveV4HubDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4HubDeployProcedureWrapper.sol'; +import { + AaveV4InterestRateStrategyDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4InterestRateStrategyDeployProcedureWrapper.sol'; +import { + AaveV4NativeTokenGatewayDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol'; +import { + AaveV4SignatureGatewayDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4SignatureGatewayDeployProcedureWrapper.sol'; +import { + AaveV4AccessManagerEnumerableDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol'; +import { + AaveV4AaveOracleDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4AaveOracleDeployProcedureWrapper.sol'; +import { + AaveV4SpokeDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4SpokeDeployProcedureWrapper.sol'; +import { + AaveV4TreasurySpokeDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol'; +import { + AaveV4SpokeConfiguratorDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol'; +import { + AaveV4AccessManagerRolesProcedureWrapper +} from 'tests/mocks/deployments/AaveV4AccessManagerRolesProcedureWrapper.sol'; +import { + AaveV4SpokeRolesProcedureWrapper +} from 'tests/mocks/deployments/AaveV4SpokeRolesProcedureWrapper.sol'; +import { + AaveV4HubRolesProcedureWrapper +} from 'tests/mocks/deployments/AaveV4HubRolesProcedureWrapper.sol'; + +import {AaveOracle} from 'src/spoke/AaveOracle.sol'; +import {AccessManagerEnumerable} from 'src/access/AccessManagerEnumerable.sol'; +import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; +import {ProxyHelper} from 'tests/utils/ProxyHelper.sol'; + +import {IHub} from 'src/hub/interfaces/IHub.sol'; +import {IAssetInterestRateStrategy} from 'src/hub/interfaces/IAssetInterestRateStrategy.sol'; +import {IAaveOracle} from 'src/spoke/interfaces/IAaveOracle.sol'; +import {ITreasurySpoke} from 'src/spoke/interfaces/ITreasurySpoke.sol'; +import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; +import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; +import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; + +contract ProceduresBase is Test { + address public owner; + address public accessManager; + address public hub; + address public nativeWrapper; + address public accessManagerAdmin; + uint8 public oracleDecimals; + string public oracleDescription; + address public spoke; + address public aaveOracle; + address public treasurySpoke; + + function setUp() public virtual { + owner = makeAddr('owner'); + accessManagerAdmin = makeAddr('accessManagerAdmin'); + accessManager = address(new AccessManagerEnumerable(accessManagerAdmin)); + hub = makeAddr('hub'); + nativeWrapper = makeAddr('nativeWrapper'); + oracleDecimals = 8; + oracleDescription = 'Oracle Description'; + spoke = makeAddr('spoke'); + aaveOracle = address(new AaveOracle(spoke, oracleDecimals, oracleDescription)); + treasurySpoke = makeAddr('treasurySpoke'); + } +} diff --git a/src/deployments/procedures/deploy/WETHDeployProcedure.sol b/tests/deployments/procedures/WETHDeployProcedure.sol similarity index 100% rename from src/deployments/procedures/deploy/WETHDeployProcedure.sol rename to tests/deployments/procedures/WETHDeployProcedure.sol diff --git a/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol b/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol new file mode 100644 index 000000000..7c5333809 --- /dev/null +++ b/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4AccessManagerEnumerableDeployProcedureTest is ProceduresBase { + AaveV4AccessManagerEnumerableDeployProcedureWrapper + public aaveV4AccessManagerEnumerableDeployProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4AccessManagerEnumerableDeployProcedureWrapper = new AaveV4AccessManagerEnumerableDeployProcedureWrapper(); + } + + function test_deployAccessManagerEnumerable() public { + address accessManagerEnumerable = aaveV4AccessManagerEnumerableDeployProcedureWrapper + .deployAccessManagerEnumerable(accessManagerAdmin); + assertNotEq(accessManagerEnumerable, address(0)); + (bool hasRole, uint32 executionDelay) = IAccessManagerEnumerable(accessManagerEnumerable) + .hasRole( + uint64(AccessManagerEnumerable(accessManagerEnumerable).ADMIN_ROLE()), + accessManagerAdmin + ); + assertTrue(hasRole); + assertEq(executionDelay, 0); + } +} diff --git a/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol new file mode 100644 index 000000000..c0b9a9732 --- /dev/null +++ b/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4HubConfiguratorDeployProcedureTest is ProceduresBase { + AaveV4HubConfiguratorDeployProcedureWrapper public aaveV4HubConfiguratorDeployProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4HubConfiguratorDeployProcedureWrapper = new AaveV4HubConfiguratorDeployProcedureWrapper(); + } + + function test_deployHubConfigurator() public { + address hubConfigurator = aaveV4HubConfiguratorDeployProcedureWrapper.deployHubConfigurator( + owner + ); + assertNotEq(hubConfigurator, address(0)); + assertEq(Ownable(hubConfigurator).owner(), owner); + } +} diff --git a/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol new file mode 100644 index 000000000..f6bbb447c --- /dev/null +++ b/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4HubDeployProcedureTest is ProceduresBase { + AaveV4HubDeployProcedureWrapper public aaveV4HubDeployProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4HubDeployProcedureWrapper = new AaveV4HubDeployProcedureWrapper(); + } + + function test_deployHub() public { + address hub = aaveV4HubDeployProcedureWrapper.deployHub(accessManager); + assertNotEq(hub, address(0)); + assertEq(IHub(hub).authority(), accessManager); + } +} diff --git a/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol new file mode 100644 index 000000000..06529dd7d --- /dev/null +++ b/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4InterestRateStrategyDeployProcedureTest is ProceduresBase { + AaveV4InterestRateStrategyDeployProcedureWrapper + public aaveV4InterestRateStrategyDeployProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4InterestRateStrategyDeployProcedureWrapper = new AaveV4InterestRateStrategyDeployProcedureWrapper(); + } + + function test_deployInterestRateStrategy() public { + address interestRateStrategy = aaveV4InterestRateStrategyDeployProcedureWrapper + .deployInterestRateStrategy(hub); + assertNotEq(interestRateStrategy, address(0)); + assertEq(IAssetInterestRateStrategy(interestRateStrategy).HUB(), hub); + } +} diff --git a/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol b/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol new file mode 100644 index 000000000..6c68f20b0 --- /dev/null +++ b/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4NativeTokenGatewayDeployProcedureTest is ProceduresBase { + AaveV4NativeTokenGatewayDeployProcedureWrapper + public aaveV4NativeTokenGatewayDeployProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4NativeTokenGatewayDeployProcedureWrapper = new AaveV4NativeTokenGatewayDeployProcedureWrapper(); + } + + function test_deployHubConfigurator() public { + address nativeTokenGateway = aaveV4NativeTokenGatewayDeployProcedureWrapper + .deployNativeTokenGateway(nativeWrapper, owner); + assertNotEq(nativeTokenGateway, address(0)); + assertEq(Ownable(nativeTokenGateway).owner(), owner); + } +} diff --git a/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol b/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol new file mode 100644 index 000000000..680d8ac7c --- /dev/null +++ b/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4SignatureGatewayDeployProcedureTest is ProceduresBase { + AaveV4SignatureGatewayDeployProcedureWrapper public aaveV4SignatureGatewayDeployProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4SignatureGatewayDeployProcedureWrapper = new AaveV4SignatureGatewayDeployProcedureWrapper(); + } + + function test_deploySignatureGateway() public { + address signatureGateway = aaveV4SignatureGatewayDeployProcedureWrapper.deploySignatureGateway( + owner + ); + assertNotEq(signatureGateway, address(0)); + assertEq(Ownable(signatureGateway).owner(), owner); + } +} diff --git a/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol b/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol new file mode 100644 index 000000000..ca5a2a8b6 --- /dev/null +++ b/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4AccessManagerRolesProcedureTest is ProceduresBase { + AaveV4AccessManagerRolesProcedureWrapper public aaveV4AccessManagerRolesProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4AccessManagerRolesProcedureWrapper = new AaveV4AccessManagerRolesProcedureWrapper(); + } + + function test_grantRootAdminRole() public { + address newAdmin = makeAddr('newAdmin'); + + _grantTmpRootAdminRole(newAdmin); + (bool hasRole, uint32 executionDelay) = IAccessManagerEnumerable(accessManager).hasRole( + Roles.DEFAULT_ADMIN_ROLE, + newAdmin + ); + assertTrue(hasRole); + assertEq(executionDelay, 0); + } + + function test_grantRootAdminRole_reverts() public { + vm.expectRevert(stdError.assertionError); + aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole(accessManager, address(0), owner); + } + + /// @dev Grants a temporary root admin role to the wrapper contract to execute the procedure. + function _grantTmpRootAdminRole(address newAdmin) internal { + vm.startPrank(accessManagerAdmin); + IAccessManager(accessManager).grantRole( + Roles.DEFAULT_ADMIN_ROLE, + address(aaveV4AccessManagerRolesProcedureWrapper), + 0 + ); + aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole( + accessManager, + newAdmin, + address(aaveV4AccessManagerRolesProcedureWrapper) + ); + vm.stopPrank(); + } +} diff --git a/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol b/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol new file mode 100644 index 000000000..5ca2886a4 --- /dev/null +++ b/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4HubRolesProcedureTest is ProceduresBase { + AaveV4HubRolesProcedureWrapper public aaveV4HubRolesProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4HubRolesProcedureWrapper = new AaveV4HubRolesProcedureWrapper(); + } +} diff --git a/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol b/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol new file mode 100644 index 000000000..fd74cb524 --- /dev/null +++ b/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4SpokeRolesProcedureTest is ProceduresBase { + AaveV4SpokeRolesProcedureWrapper public aaveV4SpokeRolesProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4SpokeRolesProcedureWrapper = new AaveV4SpokeRolesProcedureWrapper(); + } +} diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol new file mode 100644 index 000000000..8b03860d5 --- /dev/null +++ b/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4AaveOracleDeployProcedureTest is ProceduresBase { + AaveV4AaveOracleDeployProcedureWrapper public aaveV4AaveOracleDeployProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4AaveOracleDeployProcedureWrapper = new AaveV4AaveOracleDeployProcedureWrapper(); + } + + function test_deployAaveOracle() public { + address aaveOracle = aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle( + spoke, + oracleDecimals, + oracleDescription + ); + assertNotEq(aaveOracle, address(0)); + assertEq(IAaveOracle(aaveOracle).DECIMALS(), oracleDecimals); + assertEq(IAaveOracle(aaveOracle).DESCRIPTION(), oracleDescription); + } +} diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol new file mode 100644 index 000000000..f6f8be75f --- /dev/null +++ b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4SpokeConfiguratorDeployProcedureTestTest is ProceduresBase { + AaveV4SpokeConfiguratorDeployProcedureWrapper + public aaveV4SpokeConfiguratorDeployProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4SpokeConfiguratorDeployProcedureWrapper = new AaveV4SpokeConfiguratorDeployProcedureWrapper(); + } + + function test_deploySpokeConfigurator() public { + address spokeConfigurator = aaveV4SpokeConfiguratorDeployProcedureWrapper + .deploySpokeConfigurator(owner); + assertNotEq(spokeConfigurator, address(0)); + assertEq(Ownable(spokeConfigurator).owner(), owner); + } +} diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol new file mode 100644 index 000000000..ef5729356 --- /dev/null +++ b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; + +contract AaveV4SpokeDeployProcedureTest is ProceduresBase { + AaveV4SpokeDeployProcedureWrapper public aaveV4SpokeDeployProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4SpokeDeployProcedureWrapper = new AaveV4SpokeDeployProcedureWrapper(); + } + + function test_deployUpgradableSpokeInstance() public { + (address spokeProxy, address spokeImplementation) = aaveV4SpokeDeployProcedureWrapper + .deployUpgradableSpokeInstance(owner, accessManager, aaveOracle); + assertNotEq(spokeProxy, address(0)); + assertNotEq(spokeImplementation, address(0)); + assertEq(Ownable(ProxyHelper.getProxyAdmin(spokeProxy)).owner(), owner); + assertEq(ProxyHelper.getImplementation(spokeProxy), spokeImplementation); + assertEq(ISpoke(spokeProxy).ORACLE(), aaveOracle); + } +} diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol new file mode 100644 index 000000000..e1c0c4f2a --- /dev/null +++ b/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/procedures/ProceduresBase.t.sol'; +import { + AaveV4TreasurySpokeDeployProcedureWrapper +} from 'tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol'; + +contract AaveV4TreasurySpokeDeployProcedureTest is ProceduresBase { + AaveV4TreasurySpokeDeployProcedureWrapper public aaveV4TreasurySpokeDeployProcedureWrapper; + function setUp() public override { + super.setUp(); + + aaveV4TreasurySpokeDeployProcedureWrapper = new AaveV4TreasurySpokeDeployProcedureWrapper(); + } + + function test_deployTreasurySpoke() public { + address treasurySpoke = aaveV4TreasurySpokeDeployProcedureWrapper.deployTreasurySpoke( + owner, + hub + ); + assertNotEq(treasurySpoke, address(0)); + assertEq(Ownable(treasurySpoke).owner(), owner); + assertEq(address(ITreasurySpoke(treasurySpoke).HUB()), hub); + } +} diff --git a/tests/deployments/utils/libraries/Utils.t.sol b/tests/deployments/utils/libraries/Utils.t.sol index 795f4e8de..e79014d09 100644 --- a/tests/deployments/utils/libraries/Utils.t.sol +++ b/tests/deployments/utils/libraries/Utils.t.sol @@ -6,7 +6,7 @@ import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; import {Test} from 'forge-std/Test.sol'; contract UtilsTest is Test { - function testComputeCreateAddress_fuzz(address deployer, uint8 nonce) public { + function testComputeCreateAddress_fuzz(address deployer, uint8 nonce) public pure { vm.assume(deployer != address(0)); vm.assume(nonce < 0x80); address expected = vm.computeCreateAddress(deployer, nonce); diff --git a/tests/gas/Base.gas.t.sol b/tests/gas/Base.gas.t.sol new file mode 100644 index 000000000..d85199dca --- /dev/null +++ b/tests/gas/Base.gas.t.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/Base.t.sol'; + +/// forge-config: default.isolate = true +contract BaseGasTest is Base { + function setUp() public virtual override { + super.setUp(); + _initEnvironment(); + } +} diff --git a/tests/gas/Gateways.Operations.gas.t.sol b/tests/gas/Gateways.Operations.gas.t.sol index 078908309..f19eeb5c8 100644 --- a/tests/gas/Gateways.Operations.gas.t.sol +++ b/tests/gas/Gateways.Operations.gas.t.sol @@ -2,19 +2,17 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import 'tests/Base.t.sol'; +import 'tests/gas/Base.gas.t.sol'; import 'tests/unit/misc/SignatureGateway/SignatureGateway.Base.t.sol'; /// forge-config: default.isolate = true -contract NativeTokenGateway_Gas_Tests is Base { +contract NativeTokenGateway_Gas_Tests is BaseGasTest { string internal NAMESPACE = 'NativeTokenGateway.Operations'; NativeTokenGateway public nativeTokenGateway; function setUp() public virtual override { super.setUp(); - _initEnvironment(); - nativeTokenGateway = new NativeTokenGateway(address(tokenList.weth), address(ADMIN)); vm.prank(SPOKE_ADMIN); diff --git a/tests/gas/Hub.Operations.gas.t.sol b/tests/gas/Hub.Operations.gas.t.sol index 3c375dd9f..b1fd17805 100644 --- a/tests/gas/Hub.Operations.gas.t.sol +++ b/tests/gas/Hub.Operations.gas.t.sol @@ -2,18 +2,13 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import 'tests/Base.t.sol'; +import 'tests/gas/Base.gas.t.sol'; /// forge-config: default.isolate = true -contract HubOperations_Gas_Tests is Base { +contract HubOperations_Gas_Tests is BaseGasTest { using SafeCast for *; using WadRayMath for uint256; - function setUp() public override { - _setupFixtures(); - _initEnvironment(); - } - function test_add() public { vm.startPrank(address(spoke1)); tokenList.usdx.transferFrom(alice, address(hub1), 1000e6); diff --git a/tests/gas/Spoke.Getters.gas.t.sol b/tests/gas/Spoke.Getters.gas.t.sol index e114e7ce2..ccfb30f86 100644 --- a/tests/gas/Spoke.Getters.gas.t.sol +++ b/tests/gas/Spoke.Getters.gas.t.sol @@ -2,15 +2,10 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import 'tests/Base.t.sol'; +import 'tests/gas/Base.gas.t.sol'; /// forge-config: default.isolate = true -contract SpokeGetters_Gas_Tests is Base { - function setUp() public override { - _setupFixtures(); - _initEnvironment(); - } - +contract SpokeGetters_Gas_Tests is BaseGasTest { function test_getUserAccountData() external { spoke1.getUserAccountData(alice); vm.snapshotGasLastCall('Spoke.Getters', 'getUserAccountData: supplies: 0, borrows: 0'); diff --git a/tests/gas/Spoke.Operations.gas.t.sol b/tests/gas/Spoke.Operations.gas.t.sol index b84af1fec..78ca96303 100644 --- a/tests/gas/Spoke.Operations.gas.t.sol +++ b/tests/gas/Spoke.Operations.gas.t.sol @@ -11,8 +11,7 @@ contract SpokeOperations_Gas_Tests is SpokeBase { ISpoke internal spoke; function setUp() public virtual override { - _setupFixtures(); - _initEnvironment(); + super.setUp(); spoke = spoke1; reserveId = _getReserveIds(spoke); _seed(); diff --git a/tests/mocks/deployments/AaveV4AaveOracleDeployProcedureWrapper.sol b/tests/mocks/deployments/AaveV4AaveOracleDeployProcedureWrapper.sol new file mode 100644 index 000000000..cfe50bdf1 --- /dev/null +++ b/tests/mocks/deployments/AaveV4AaveOracleDeployProcedureWrapper.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4AaveOracleDeployProcedure +} from 'src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol'; + +contract AaveV4AaveOracleDeployProcedureWrapper is AaveV4AaveOracleDeployProcedure { + function deployAaveOracle( + address spoke, + uint8 decimals, + string memory description + ) external returns (address) { + return _deployAaveOracle(spoke, decimals, description); + } +} diff --git a/tests/mocks/deployments/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol b/tests/mocks/deployments/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol new file mode 100644 index 000000000..02c4d72d6 --- /dev/null +++ b/tests/mocks/deployments/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4AccessManagerEnumerableDeployProcedure +} from 'src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol'; + +contract AaveV4AccessManagerEnumerableDeployProcedureWrapper is + AaveV4AccessManagerEnumerableDeployProcedure +{ + function deployAccessManagerEnumerable(address admin) external returns (address) { + return _deployAccessManagerEnumerable(admin); + } +} diff --git a/tests/mocks/deployments/AaveV4AccessManagerRolesProcedureWrapper.sol b/tests/mocks/deployments/AaveV4AccessManagerRolesProcedureWrapper.sol new file mode 100644 index 000000000..8314adcd7 --- /dev/null +++ b/tests/mocks/deployments/AaveV4AccessManagerRolesProcedureWrapper.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4AccessManagerRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol'; + +contract AaveV4AccessManagerRolesProcedureWrapper { + function grantRootAdminRole( + address accessManager, + address adminToAdd, + address adminToRemove + ) external { + AaveV4AccessManagerRolesProcedure.grantRootAdminRole(accessManager, adminToAdd, adminToRemove); + } +} diff --git a/tests/mocks/deployments/AaveV4HubConfiguratorDeployProcedureWrapper.sol b/tests/mocks/deployments/AaveV4HubConfiguratorDeployProcedureWrapper.sol new file mode 100644 index 000000000..34120441c --- /dev/null +++ b/tests/mocks/deployments/AaveV4HubConfiguratorDeployProcedureWrapper.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4HubConfiguratorDeployProcedure +} from 'src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol'; + +contract AaveV4HubConfiguratorDeployProcedureWrapper is AaveV4HubConfiguratorDeployProcedure { + function deployHubConfigurator(address owner) external returns (address) { + return _deployHubConfigurator(owner); + } +} diff --git a/tests/mocks/deployments/AaveV4HubDeployProcedureWrapper.sol b/tests/mocks/deployments/AaveV4HubDeployProcedureWrapper.sol new file mode 100644 index 000000000..c06b41dac --- /dev/null +++ b/tests/mocks/deployments/AaveV4HubDeployProcedureWrapper.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4HubDeployProcedure +} from 'src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol'; + +contract AaveV4HubDeployProcedureWrapper is AaveV4HubDeployProcedure { + function deployHub(address accessManager) external returns (address) { + return _deployHub(accessManager); + } +} diff --git a/tests/mocks/deployments/AaveV4HubRolesProcedureWrapper.sol b/tests/mocks/deployments/AaveV4HubRolesProcedureWrapper.sol new file mode 100644 index 000000000..035675f40 --- /dev/null +++ b/tests/mocks/deployments/AaveV4HubRolesProcedureWrapper.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4HubRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; + +contract AaveV4HubRolesProcedureWrapper { + function grantHubAdminRole(address accessManager, address admin) external { + AaveV4HubRolesProcedure.grantHubAdminRole(accessManager, admin); + } + + function grantHubFeeMinterRole(address accessManager, address admin) external { + AaveV4HubRolesProcedure.grantHubFeeMinterRole(accessManager, admin); + } + + function grantHubConfiguratorRole(address accessManager, address admin) external { + AaveV4HubRolesProcedure.grantHubConfiguratorRole(accessManager, admin); + } + + function setupHubRoles(address accessManager, address hub) external { + AaveV4HubRolesProcedure.setupHubRoles(accessManager, hub); + } + + function setupHubFeeMinterRole(address accessManager, address hub) external { + AaveV4HubRolesProcedure.setupHubFeeMinterRole(accessManager, hub); + } + + function setupHubConfiguratorRole(address accessManager, address hub) external { + AaveV4HubRolesProcedure.setupHubConfiguratorRole(accessManager, hub); + } + + function getHubFeeMinterRoleSelectors() external pure returns (bytes4[] memory) { + return AaveV4HubRolesProcedure.getHubFeeMinterRoleSelectors(); + } + + function getHubConfiguratorRoleSelectors() external pure returns (bytes4[] memory) { + return AaveV4HubRolesProcedure.getHubConfiguratorRoleSelectors(); + } +} diff --git a/tests/mocks/deployments/AaveV4InterestRateStrategyDeployProcedureWrapper.sol b/tests/mocks/deployments/AaveV4InterestRateStrategyDeployProcedureWrapper.sol new file mode 100644 index 000000000..db7fbcaa5 --- /dev/null +++ b/tests/mocks/deployments/AaveV4InterestRateStrategyDeployProcedureWrapper.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4InterestRateStrategyDeployProcedure +} from 'src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol'; + +contract AaveV4InterestRateStrategyDeployProcedureWrapper is + AaveV4InterestRateStrategyDeployProcedure +{ + function deployInterestRateStrategy(address hub) external returns (address) { + return _deployInterestRateStrategy(hub); + } +} diff --git a/tests/mocks/deployments/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol b/tests/mocks/deployments/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol new file mode 100644 index 000000000..8b4dd92f0 --- /dev/null +++ b/tests/mocks/deployments/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4NativeTokenGatewayDeployProcedure +} from 'src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol'; + +contract AaveV4NativeTokenGatewayDeployProcedureWrapper is AaveV4NativeTokenGatewayDeployProcedure { + function deployNativeTokenGateway( + address nativeWrapper, + address owner + ) external returns (address) { + return _deployNativeTokenGateway(nativeWrapper, owner); + } +} diff --git a/tests/mocks/deployments/AaveV4SignatureGatewayDeployProcedureWrapper.sol b/tests/mocks/deployments/AaveV4SignatureGatewayDeployProcedureWrapper.sol new file mode 100644 index 000000000..f43f808fe --- /dev/null +++ b/tests/mocks/deployments/AaveV4SignatureGatewayDeployProcedureWrapper.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4SignatureGatewayDeployProcedure +} from 'src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol'; + +contract AaveV4SignatureGatewayDeployProcedureWrapper is AaveV4SignatureGatewayDeployProcedure { + function deploySignatureGateway(address owner) external returns (address) { + return _deploySignatureGateway(owner); + } +} diff --git a/tests/mocks/deployments/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol b/tests/mocks/deployments/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol new file mode 100644 index 000000000..d80b690df --- /dev/null +++ b/tests/mocks/deployments/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4SpokeConfiguratorDeployProcedure +} from 'src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol'; + +contract AaveV4SpokeConfiguratorDeployProcedureWrapper is AaveV4SpokeConfiguratorDeployProcedure { + function deploySpokeConfigurator(address owner) external returns (address) { + return _deploySpokeConfigurator(owner); + } +} diff --git a/tests/mocks/deployments/AaveV4SpokeDeployProcedureWrapper.sol b/tests/mocks/deployments/AaveV4SpokeDeployProcedureWrapper.sol new file mode 100644 index 000000000..a321081af --- /dev/null +++ b/tests/mocks/deployments/AaveV4SpokeDeployProcedureWrapper.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4SpokeDeployProcedure +} from 'src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol'; + +contract AaveV4SpokeDeployProcedureWrapper is AaveV4SpokeDeployProcedure { + function deployUpgradableSpokeInstance( + address spokeProxyAdminOwner, + address accessManager, + address oracle + ) external returns (address spokeProxy, address spokeImplementation) { + return _deployUpgradableSpokeInstance(spokeProxyAdminOwner, accessManager, oracle); + } +} diff --git a/tests/mocks/deployments/AaveV4SpokeRolesProcedureWrapper.sol b/tests/mocks/deployments/AaveV4SpokeRolesProcedureWrapper.sol new file mode 100644 index 000000000..6a65e6d2a --- /dev/null +++ b/tests/mocks/deployments/AaveV4SpokeRolesProcedureWrapper.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4SpokeRolesProcedure +} from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; + +contract AaveV4SpokeRolesProcedureWrapper { + function grantSpokeAdminRole(address accessManager, address admin) external { + AaveV4SpokeRolesProcedure.grantSpokeAdminRole(accessManager, admin); + } + + function grantSpokePositionUpdaterRole(address accessManager, address admin) internal { + AaveV4SpokeRolesProcedure.grantSpokePositionUpdaterRole(accessManager, admin); + } + + function grantSpokeConfiguratorRole(address accessManager, address admin) external { + AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole(accessManager, admin); + } + + function setupSpokeRoles(address accessManager, address spoke) external { + AaveV4SpokeRolesProcedure.setupSpokeRoles(accessManager, spoke); + } + + function setupSpokePositionUpdaterRole(address accessManager, address spoke) external { + AaveV4SpokeRolesProcedure.setupSpokePositionUpdaterRole(accessManager, spoke); + } + + function setupSpokeConfiguratorRole(address accessManager, address spoke) external { + AaveV4SpokeRolesProcedure.setupSpokeConfiguratorRole(accessManager, spoke); + } + function getSpokePositionUpdaterRoleSelectors() external pure returns (bytes4[] memory) { + return AaveV4SpokeRolesProcedure.getSpokePositionUpdaterRoleSelectors(); + } + + function getSpokeConfiguratorRoleSelectors() external pure returns (bytes4[] memory) { + return AaveV4SpokeRolesProcedure.getSpokeConfiguratorRoleSelectors(); + } +} diff --git a/tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol b/tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol new file mode 100644 index 000000000..f89728c47 --- /dev/null +++ b/tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import { + AaveV4TreasurySpokeDeployProcedure +} from 'src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol'; + +contract AaveV4TreasurySpokeDeployProcedureWrapper is AaveV4TreasurySpokeDeployProcedure { + function deployTreasurySpoke(address owner, address hub) external returns (address) { + return _deployTreasurySpoke(owner, hub); + } +} diff --git a/tests/unit/AaveOracle.t.sol b/tests/unit/AaveOracle.t.sol index a38361cdd..aa159ae4e 100644 --- a/tests/unit/AaveOracle.t.sol +++ b/tests/unit/AaveOracle.t.sol @@ -21,7 +21,7 @@ contract AaveOracleTest is Base { uint256 private constant reserveId2 = 1; function setUp() public override { - _setupFixtures(); + super.setUp(); oracle = new AaveOracle(address(spoke1), _oracleDecimals, _description); } diff --git a/tests/unit/AssetInterestRateStrategy.t.sol b/tests/unit/AssetInterestRateStrategy.t.sol index 4ae40d8c2..cccca25e0 100644 --- a/tests/unit/AssetInterestRateStrategy.t.sol +++ b/tests/unit/AssetInterestRateStrategy.t.sol @@ -15,7 +15,7 @@ contract AssetInterestRateStrategyTest is Base { bytes public encodedRateData; function setUp() public override { - _setupFixtures(); + super.setUp(); rateStrategy = new AssetInterestRateStrategy(address(hub1)); rateData = IAssetInterestRateStrategy.InterestRateData({ diff --git a/tests/unit/Spoke/Spoke.Getters.t.sol b/tests/unit/Spoke/Spoke.Getters.t.sol index c9fc279fa..a4ba510d8 100644 --- a/tests/unit/Spoke/Spoke.Getters.t.sol +++ b/tests/unit/Spoke/Spoke.Getters.t.sol @@ -18,7 +18,7 @@ contract SpokeGettersTest is SpokeBase { // Deploy new spoke without setting the liquidation config TestTypes.TestEnvReport memory report = _deployFixtures({numHubs: 0, numSpokes: 1}); _setupFixturesRoles(report); - spoke = ISpoke(report.spokeReports[0].spokeAddress); + spoke = ISpoke(report.spokeReports[0].spoke); IHub.SpokeConfig memory spokeConfig = IHub.SpokeConfig({ active: true, diff --git a/tests/unit/Spoke/Spoke.Upgradeable.t.sol b/tests/unit/Spoke/Spoke.Upgradeable.t.sol index 909cf43e5..d8b3612bb 100644 --- a/tests/unit/Spoke/Spoke.Upgradeable.t.sol +++ b/tests/unit/Spoke/Spoke.Upgradeable.t.sol @@ -88,7 +88,7 @@ contract SpokeUpgradeableTest is SpokeBase { TestTypes.TestEnvReport memory report; report.spokeReports = new TestTypes.TestSpokeReport[](1); - report.spokeReports[0].spokeAddress = address(spokeProxy); + report.spokeReports[0].spoke = address(spokeProxy); _setupFixturesRoles(report); uint128 targetHealthFactor = 1.05e18; diff --git a/tests/unit/misc/SignatureGateway/SignatureGateway.Base.t.sol b/tests/unit/misc/SignatureGateway/SignatureGateway.Base.t.sol index c573970f9..3a5f72380 100644 --- a/tests/unit/misc/SignatureGateway/SignatureGateway.Base.t.sol +++ b/tests/unit/misc/SignatureGateway/SignatureGateway.Base.t.sol @@ -9,8 +9,7 @@ contract SignatureGatewayBaseTest is SpokeBase { uint256 public alicePk; function setUp() public virtual override { - _setupFixtures(); - _initEnvironment(); + super.setUp(); gateway = ISignatureGateway(new SignatureGateway(ADMIN)); (alice, alicePk) = makeAddrAndKey('alice'); diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index ac40d898d..417e5748c 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -13,7 +13,7 @@ import {IAccessManaged} from 'src/dependencies/openzeppelin/IAccessManaged.sol'; import { AaveV4DeployOrchestration } from 'src/deployments/orchestration/AaveV4DeployOrchestration.sol'; -import {WETHDeployProcedure} from 'src/deployments/procedures/deploy/WETHDeployProcedure.sol'; +import {WETHDeployProcedure} from 'tests/deployments/procedures/WETHDeployProcedure.sol'; import { AaveV4SpokeRolesProcedure } from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; @@ -25,7 +25,7 @@ import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; import {Constants} from 'tests/Constants.sol'; -import {Roles} from 'src/deployments/procedures/roles/Roles.sol'; +import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; import {IAssetInterestRateStrategy} from 'src/hub/interfaces/IAssetInterestRateStrategy.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; @@ -52,15 +52,13 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { hubConfiguratorRoleSelectors = AaveV4HubRolesProcedure.getHubConfiguratorRoleSelectors(); } - function deployAaveV4Testnet( - Logger logger, - FullDeployInputs memory inputs - ) public returns (OrchestrationReports.FullDeploymentReport memory) { + function checkedV4Deployment(Logger logger, FullDeployInputs memory inputs) public { vm.startPrank(deployer); OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration .deployAaveV4(logger, deployer, inputs); vm.stopPrank(); - return report; + _checkDeployment(report, inputs); + _checkRoles(report, inputs); } function _checkDeployment( @@ -76,10 +74,8 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { - inputs = _sanitizeInputs(inputs); - IAccessManagerEnumerable accessManager = IAccessManagerEnumerable( - report.accessBatchReport.accessManagerAddress + report.accessBatchReport.accessManager ); _checkAccessManagerRoles(accessManager, inputs); _checkSpokeRoles(accessManager, report, inputs); @@ -118,65 +114,25 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal pure { - if (inputs.nativeWrapperAddress != address(0)) { - assertNotEq( - report.gatewaysBatchReport.nativeGatewayAddress, - address(0), - 'NativeGatewayAddress' - ); + if (inputs.nativeWrapper != address(0)) { + assertNotEq(report.gatewaysBatchReport.nativeGateway, address(0), 'NativeGateway'); + assertNotEq(report.gatewaysBatchReport.signatureGateway, address(0), 'SignatureGateway'); } else { - assertEq( - report.gatewaysBatchReport.nativeGatewayAddress, - address(0), - 'Zero NativeGatewayAddress' - ); + assertEq(report.gatewaysBatchReport.nativeGateway, address(0), 'Zero NativeGateway'); + assertEq(report.gatewaysBatchReport.signatureGateway, address(0), 'Zero SignatureGateway'); } - assertNotEq( - report.gatewaysBatchReport.signatureGatewayAddress, - address(0), - 'SignatureGatewayAddress' - ); - assertNotEq(report.accessBatchReport.accessManagerAddress, address(0), 'AccessManagerAddress'); - assertNotEq( - report.configuratorBatchReport.spokeConfiguratorAddress, - address(0), - 'SpokeConfiguratorAddress' - ); - assertNotEq( - report.configuratorBatchReport.hubConfiguratorAddress, - address(0), - 'HubConfiguratorAddress' - ); - assertNotEq( - report.gatewaysBatchReport.signatureGatewayAddress, - address(0), - 'SignatureGatewayAddress' - ); + assertNotEq(report.accessBatchReport.accessManager, address(0), 'AccessManager'); + assertNotEq(report.configuratorBatchReport.spokeConfigurator, address(0), 'SpokeConfigurator'); + assertNotEq(report.configuratorBatchReport.hubConfigurator, address(0), 'HubConfigurator'); for (uint256 i = 0; i < report.hubBatchReports.length; i++) { - assertNotEq(report.hubBatchReports[i].report.hubAddress, address(0), 'HubAddress'); - assertNotEq( - report.hubBatchReports[i].report.irStrategyAddress, - address(0), - 'IRStrategyAddress' - ); - assertNotEq( - report.hubBatchReports[i].report.treasurySpokeAddress, - address(0), - 'TreasurySpokeAddress' - ); + assertNotEq(report.hubBatchReports[i].report.hub, address(0), 'Hub'); + assertNotEq(report.hubBatchReports[i].report.irStrategy, address(0), 'IRStrategy'); + assertNotEq(report.hubBatchReports[i].report.treasurySpoke, address(0), 'TreasurySpoke'); } for (uint256 i = 0; i < report.spokeInstanceBatchReports.length; i++) { - assertNotEq( - report.spokeInstanceBatchReports[i].report.spokeProxyAddress, - address(0), - 'SpokeProxyAddress' - ); - assertNotEq( - report.spokeInstanceBatchReports[i].report.aaveOracleAddress, - address(0), - 'AaveOracleAddress' - ); + assertNotEq(report.spokeInstanceBatchReports[i].report.spokeProxy, address(0), 'SpokeProxy'); + assertNotEq(report.spokeInstanceBatchReports[i].report.aaveOracle, address(0), 'AaveOracle'); } assertEq(report.hubBatchReports.length, inputs.hubLabels.length, 'HubBatchReportsLength'); assertEq( @@ -192,45 +148,36 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ) internal view { string memory globalLabel = 'SpokeDeployment'; for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { - _checkSpokeBatchDeployment( - report.spokeInstanceBatchReports[i], - report.accessBatchReport.accessManagerAddress, - string.concat(globalLabel, ', ', inputs.spokeLabels[i]) - ); + string memory label = string.concat(globalLabel, ', ', inputs.spokeLabels[i]); + OrchestrationReports.SpokeDeploymentReport memory spokeReport = report + .spokeInstanceBatchReports[i]; + _checkSpokeDeployment({ + report: spokeReport, + accessManager: report.accessBatchReport.accessManager, + label: label + }); + _checkOracleDeployment({report: spokeReport, label: label}); } } - function _checkSpokeBatchDeployment( - OrchestrationReports.SpokeDeploymentReport memory report, - address accessManagerAddress, - string memory label - ) internal view { - _checkSpokeDeployment({ - report: report, - accessManagerAddress: accessManagerAddress, - label: label - }); - _checkOracleDeployment({report: report, label: label}); - } - function _checkSpokeDeployment( OrchestrationReports.SpokeDeploymentReport memory report, - address accessManagerAddress, + address accessManager, string memory label ) internal view { assertEq( - ProxyHelper.getImplementation(report.report.spokeProxyAddress), - report.report.spokeImplementationAddress, + ProxyHelper.getImplementation(report.report.spokeProxy), + report.report.spokeImplementation, string.concat(label, ' implementation') ); assertEq( - ISpoke(report.report.spokeProxyAddress).ORACLE(), - report.report.aaveOracleAddress, + ISpoke(report.report.spokeProxy).ORACLE(), + report.report.aaveOracle, string.concat(label, ' oracle on spoke') ); assertEq( - IAccessManaged(report.report.spokeProxyAddress).authority(), - accessManagerAddress, + IAccessManaged(report.report.spokeProxy).authority(), + accessManager, string.concat(label, ' spoke authority') ); } @@ -240,17 +187,17 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { string memory label ) internal view { assertEq( - IAaveOracle(report.report.aaveOracleAddress).SPOKE(), - report.report.spokeProxyAddress, + IAaveOracle(report.report.aaveOracle).SPOKE(), + report.report.spokeProxy, string.concat(label, ' spoke on oracle') ); assertEq( - IAaveOracle(report.report.aaveOracleAddress).DECIMALS(), + IAaveOracle(report.report.aaveOracle).DECIMALS(), Constants.ORACLE_DECIMALS, string.concat(label, ' oracle decimals') ); assertEq( - IAaveOracle(report.report.aaveOracleAddress).DESCRIPTION(), + IAaveOracle(report.report.aaveOracle).DESCRIPTION(), string.concat(report.label, Constants.ORACLE_SUFFIX), string.concat(label, ' oracle description') ); @@ -260,34 +207,29 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { - string memory label = 'HubDeployment'; + string memory globalLabel = 'HubDeployment'; for (uint256 i = 0; i < inputs.hubLabels.length; i++) { - _checkHubBatchDeployment( - report.hubBatchReports[i], - report.accessBatchReport.accessManagerAddress, - string.concat(label, ', ', inputs.hubLabels[i]) - ); + string memory label = string.concat(globalLabel, ', ', inputs.hubLabels[i]); + OrchestrationReports.HubDeploymentReport memory hubReport = report.hubBatchReports[i]; + + _checkHubDeployment({ + report: hubReport, + accessManager: report.accessBatchReport.accessManager, + label: label + }); + _checkInterestRateStrategyDeployment({report: hubReport, label: label}); + _checkTreasurySpokeDeployment({report: hubReport, label: label}); } } - function _checkHubBatchDeployment( - OrchestrationReports.HubDeploymentReport memory report, - address accessManagerAddress, - string memory label - ) internal view { - _checkHubDeployment(report, accessManagerAddress, label); - _checkInterestRateStrategyDeployment(report, label); - _checkTreasurySpokeDeployment(report, label); - } - function _checkHubDeployment( OrchestrationReports.HubDeploymentReport memory report, - address accessManagerAddress, + address accessManager, string memory label ) internal view { assertEq( - IAccessManaged(report.report.hubAddress).authority(), - accessManagerAddress, + IAccessManaged(report.report.hub).authority(), + accessManager, string.concat(label, ' hub authority') ); } @@ -297,8 +239,8 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { string memory label ) internal view { assertEq( - IAssetInterestRateStrategy(report.report.irStrategyAddress).HUB(), - report.report.hubAddress, + IAssetInterestRateStrategy(report.report.irStrategy).HUB(), + report.report.hub, string.concat(label, ' hub on interest rate strategy') ); } @@ -308,8 +250,8 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { string memory label ) internal view { assertEq( - address(ITreasurySpoke(report.report.treasurySpokeAddress).HUB()), - report.report.hubAddress, + address(ITreasurySpoke(report.report.treasurySpoke).HUB()), + report.report.hub, string.concat(label, ' hub on treasury spoke') ); } @@ -363,7 +305,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ); assertEq( accessManager.getRoleMember(Roles.SPOKE_CONFIGURATOR_ROLE, 1), - report.configuratorBatchReport.spokeConfiguratorAddress, + report.configuratorBatchReport.spokeConfigurator, 'SpokeConfiguratorRole member - spoke configurator' ); } else { @@ -378,7 +320,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { for (uint256 j = 0; j < spokeConfiguratorRoleSelectors.length; j++) { assertEq( accessManager.getTargetFunctionRole( - report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + report.spokeInstanceBatchReports[i].report.spokeProxy, spokeConfiguratorRoleSelectors[j] ), Roles.SPOKE_CONFIGURATOR_ROLE, @@ -386,8 +328,8 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ); (bool allowed, uint32 delay) = accessManager.canCall( - report.configuratorBatchReport.spokeConfiguratorAddress, - report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + report.configuratorBatchReport.spokeConfigurator, + report.spokeInstanceBatchReports[i].report.spokeProxy, spokeConfiguratorRoleSelectors[j] ); assertEq( @@ -400,7 +342,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { // spoke admin role encompasses spoke configurator role (allowed, delay) = accessManager.canCall( inputs.spokeAdmin, - report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + report.spokeInstanceBatchReports[i].report.spokeProxy, spokeConfiguratorRoleSelectors[j] ); assertEq( @@ -439,7 +381,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { address proxyAdminOwner = Ownable( - ProxyHelper.getProxyAdmin(report.spokeInstanceBatchReports[i].report.spokeProxyAddress) + ProxyHelper.getProxyAdmin(report.spokeInstanceBatchReports[i].report.spokeProxy) ).owner(); assertEq( proxyAdminOwner, @@ -450,7 +392,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { for (uint256 j = 0; j < spokePositionUpdaterRoleSelectors.length; j++) { (bool allowed, uint32 delay) = accessManager.canCall( inputs.spokeAdmin, - report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + report.spokeInstanceBatchReports[i].report.spokeProxy, spokePositionUpdaterRoleSelectors[j] ); assertEq(allowed, inputs.grantRoles ? true : false, 'SpokeAdminRole allowed'); @@ -458,7 +400,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { assertEq( accessManager.getTargetFunctionRole( - report.spokeInstanceBatchReports[i].report.spokeProxyAddress, + report.spokeInstanceBatchReports[i].report.spokeProxy, spokePositionUpdaterRoleSelectors[j] ), Roles.SPOKE_POSITION_UPDATER_ROLE, @@ -494,14 +436,14 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { } for (uint256 i = 0; i < inputs.hubLabels.length; i++) { _checkTreasurySpokeRoles( - report.hubBatchReports[i].report.treasurySpokeAddress, + report.hubBatchReports[i].report.treasurySpoke, inputs, inputs.hubLabels[i] ); for (uint256 j = 0; j < hubFeeMinterRoleSelectors.length; j++) { assertEq( accessManager.getTargetFunctionRole( - report.hubBatchReports[i].report.hubAddress, + report.hubBatchReports[i].report.hub, hubFeeMinterRoleSelectors[j] ), Roles.HUB_FEE_MINTER_ROLE, @@ -510,7 +452,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { (bool allowed, uint32 delay) = accessManager.canCall( inputs.hubAdmin, - report.hubBatchReports[i].report.hubAddress, + report.hubBatchReports[i].report.hub, hubFeeMinterRoleSelectors[j] ); assertEq(allowed, inputs.grantRoles ? true : false, 'HubAdminRole allowed'); @@ -520,12 +462,12 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { } function _checkTreasurySpokeRoles( - address treasurySpokeAddress, + address treasurySpoke, FullDeployInputs memory inputs, string memory label ) internal view { assertEq( - Ownable(treasurySpokeAddress).owner(), + Ownable(treasurySpoke).owner(), inputs.treasurySpokeOwner, string.concat(label, ' treasury spoke owner') ); @@ -549,7 +491,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ); assertEq( accessManager.getRoleMember(Roles.HUB_CONFIGURATOR_ROLE, 1), - report.configuratorBatchReport.hubConfiguratorAddress, + report.configuratorBatchReport.hubConfigurator, 'HubConfiguratorRole member - hub configurator' ); } else { @@ -563,7 +505,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { for (uint256 j = 0; j < hubConfiguratorRoleSelectors.length; j++) { assertEq( accessManager.getTargetFunctionRole( - report.hubBatchReports[i].report.hubAddress, + report.hubBatchReports[i].report.hub, hubConfiguratorRoleSelectors[j] ), Roles.HUB_CONFIGURATOR_ROLE, @@ -573,8 +515,8 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { uint32 delay; (allowed, delay) = accessManager.canCall( - report.configuratorBatchReport.hubConfiguratorAddress, - report.hubBatchReports[i].report.hubAddress, + report.configuratorBatchReport.hubConfigurator, + report.hubBatchReports[i].report.hub, hubConfiguratorRoleSelectors[j] ); assertEq( @@ -586,7 +528,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { (allowed, delay) = accessManager.canCall( inputs.hubAdmin, - report.hubBatchReports[i].report.hubAddress, + report.hubBatchReports[i].report.hub, hubConfiguratorRoleSelectors[j] ); assertEq(allowed, inputs.grantRoles ? true : false, 'HubConfiguratorRole allowed - admin'); @@ -599,33 +541,39 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { - assertEq( - Ownable(report.configuratorBatchReport.hubConfiguratorAddress).owner(), - inputs.hubConfiguratorOwner, - 'HubConfigurator owner' - ); - assertEq( - Ownable(report.configuratorBatchReport.spokeConfiguratorAddress).owner(), - inputs.spokeConfiguratorOwner, - 'SpokeConfigurator owner' - ); + if (inputs.grantRoles) { + if (inputs.hubLabels.length > 0 && inputs.hubConfiguratorOwner != address(0)) { + assertEq( + Ownable(report.configuratorBatchReport.hubConfigurator).owner(), + inputs.hubConfiguratorOwner, + 'HubConfigurator owner' + ); + } + if (inputs.spokeLabels.length > 0 && inputs.spokeConfiguratorOwner != address(0)) { + assertEq( + Ownable(report.configuratorBatchReport.spokeConfigurator).owner(), + inputs.spokeConfiguratorOwner, + 'SpokeConfigurator owner' + ); + } + } } function _checkGatewayRoles( OrchestrationReports.FullDeploymentReport memory report, FullDeployInputs memory inputs ) internal view { - if (inputs.nativeWrapperAddress != address(0)) { + if (inputs.nativeWrapper != address(0)) { assertEq( - Ownable(report.gatewaysBatchReport.nativeGatewayAddress).owner(), + Ownable(report.gatewaysBatchReport.nativeGateway).owner(), inputs.gatewayOwner, 'NativeGateway owner' ); + assertEq( + Ownable(report.gatewaysBatchReport.signatureGateway).owner(), + inputs.gatewayOwner, + 'SignatureGateway owner' + ); } - assertEq( - Ownable(report.gatewaysBatchReport.signatureGatewayAddress).owner(), - inputs.gatewayOwner, - 'SignatureGateway owner' - ); } } diff --git a/tests/utils/TestTypes.sol b/tests/utils/TestTypes.sol index 38ae84d32..9bd838c77 100644 --- a/tests/utils/TestTypes.sol +++ b/tests/utils/TestTypes.sol @@ -21,8 +21,8 @@ library TestTypes { } struct TestTokensBatchReport { - address wethAddress; - address[] tokenAddresses; + address weth; + address[] tokens; } struct TestTokenInput { @@ -32,24 +32,30 @@ library TestTypes { } struct TestHubReport { - address hubAddress; - address irStrategyAddress; - address treasurySpokeAddress; + address hub; + address irStrategy; + address treasurySpoke; } struct TestSpokeReport { - address spokeAddress; - address aaveOracleAddress; + address spoke; + address aaveOracle; + } + + struct TestGatewaysReport { + address signatureGateway; + address nativeGateway; } struct TestEnvReport { - address accessManagerAddress; + address accessManager; TestHubReport[] hubReports; TestSpokeReport[] spokeReports; + TestGatewaysReport gatewaysReport; } struct TestTokensReport { - address wethAddress; - address[] testTokenAddresses; + address weth; + address[] testTokens; } } From 198fc50ced6cc26e9d5c225f30c8d329f22b4222 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:37:54 -0600 Subject: [PATCH 52/62] fix: rm named arg --- scripts/deploy/AaveV4DeployBatchBase.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index 47a92cf0f..2840280be 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -36,7 +36,7 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { logger.log('...Starting Aave V4 Batch Deployment...'); vm.startBroadcast(deployer); OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration - .deployAaveV4({logger: logger, deployer: deployer, deployInputs: inputs}); + .deployAaveV4(logger, deployer, inputs); vm.stopBroadcast(); logger.writeJsonReportMarket(report); logger.log('...Batch Deployment Completed...'); From 5b13830f5a38fd7f9e1da8b209961f4a515981bf Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Tue, 16 Dec 2025 20:52:10 -0600 Subject: [PATCH 53/62] fix: pr comments --- .../inputs => config}/AaveV4DeployInput.json | 0 foundry.toml | 3 +- scripts/deploy/AaveV4DeployBatchBase.s.sol | 118 +++++---- snapshots/Hub.Operations.json | 6 +- snapshots/SignatureGateway.Operations.json | 2 +- src/deployments/batches/AaveV4AccessBatch.sol | 1 - .../batches/AaveV4ConfiguratorBatch.sol | 3 - .../batches/AaveV4GatewayBatch.sol | 3 - src/deployments/batches/AaveV4HubBatch.sol | 3 - .../batches/AaveV4SpokeInstanceBatch.sol | 11 +- .../AaveV4DeployOrchestration.sol | 2 +- .../procedures/AaveV4DeployProcedureBase.sol | 10 + ...AccessManagerEnumerableDeployProcedure.sol | 4 +- .../AaveV4HubConfiguratorDeployProcedure.sol | 5 +- .../deploy/hub/AaveV4HubDeployProcedure.sol | 5 +- ...eV4InterestRateStrategyDeployProcedure.sol | 5 +- ...aveV4NativeTokenGatewayDeployProcedure.sol | 6 +- .../AaveV4SignatureGatewayDeployProcedure.sol | 5 +- .../spoke/AaveV4AaveOracleDeployProcedure.sol | 7 +- ...AaveV4SpokeConfiguratorDeployProcedure.sol | 4 +- .../spoke/AaveV4SpokeDeployProcedure.sol | 7 +- .../AaveV4TreasurySpokeDeployProcedure.sol | 5 +- .../AaveV4AccessManagerRolesProcedure.sol | 7 +- .../roles/AaveV4HubRolesProcedure.sol | 16 +- .../roles/AaveV4SpokeRolesProcedure.sol | 20 +- src/deployments/utils/InputUtils.sol | 5 +- tests/Base.t.sol | 21 +- tests/Config.sol | 13 - tests/deployments/AaveV4BatchDeployment.t.sol | 233 ++++++++++-------- .../batches/AaveV4AccessBatch.t.sol | 25 ++ tests/deployments/batches/BatchBase.t.sol | 17 ++ .../orchestration/AaveV4TestOrchestration.sol | 39 ++- .../procedures/ProceduresBase.t.sol | 54 ++-- ...cessManagerEnumerableDeployProcedure.t.sol | 8 +- ...AaveV4HubConfiguratorDeployProcedure.t.sol | 8 +- .../deploy/hub/AaveV4HubDeployProcedure.t.sol | 8 +- ...4InterestRateStrategyDeployProcedure.t.sol | 6 +- ...eV4NativeTokenGatewayDeployProcedure.t.sol | 16 +- ...aveV4SignatureGatewayDeployProcedure.t.sol | 7 + .../AaveV4AccessManagerRolesProcedure.t.sol | 32 ++- .../roles/AaveV4HubRolesProcedure.t.sol | 101 +++++++- .../roles/AaveV4SpokeRolesProcedure.t.sol | 124 +++++++++- .../AaveV4AaveOracleDeployProcedure.t.sol | 30 ++- ...veV4SpokeConfiguratorDeployProcedure.t.sol | 10 +- .../spoke/AaveV4SpokeDeployProcedure.t.sol | 33 ++- .../AaveV4TreasurySpokeDeployProcedure.t.sol | 14 +- tests/mocks/GatewayBaseWrapper.sol | 2 + tests/mocks/LiquidationLogicWrapper.sol | 2 + ...AaveV4AaveOracleDeployProcedureWrapper.sol | 2 + ...anagerEnumerableDeployProcedureWrapper.sol | 1 + ...veV4AccessManagerRolesProcedureWrapper.sol | 8 +- ...4HubConfiguratorDeployProcedureWrapper.sol | 2 + .../AaveV4HubDeployProcedureWrapper.sol | 2 + .../AaveV4HubRolesProcedureWrapper.sol | 2 + ...restRateStrategyDeployProcedureWrapper.sol | 2 + ...tiveTokenGatewayDeployProcedureWrapper.sol | 2 + ...SignatureGatewayDeployProcedureWrapper.sol | 2 + ...pokeConfiguratorDeployProcedureWrapper.sol | 2 + .../AaveV4SpokeDeployProcedureWrapper.sol | 2 + .../AaveV4SpokeRolesProcedureWrapper.sol | 4 +- ...eV4TreasurySpokeDeployProcedureWrapper.sol | 2 + .../scripts/AaveV4DeployBatchBaseScript.t.sol | 193 +++++++++++++++ tests/unit/Hub/Hub.Restore.t.sol | 12 - tests/unit/HubConfigurator.t.sol | 4 - tests/unit/Spoke/Spoke.Upgradeable.t.sol | 3 + tests/unit/SpokeConfigurator.t.sol | 7 - tests/utils/BatchTestProcedures.sol | 95 ++++--- tests/utils/TestTypes.sol | 6 + 68 files changed, 1071 insertions(+), 348 deletions(-) rename {scripts/deploy/inputs => config}/AaveV4DeployInput.json (100%) create mode 100644 src/deployments/procedures/AaveV4DeployProcedureBase.sol delete mode 100644 tests/Config.sol create mode 100644 tests/deployments/batches/AaveV4AccessBatch.t.sol create mode 100644 tests/deployments/batches/BatchBase.t.sol rename tests/mocks/deployments/{ => procedures}/AaveV4AaveOracleDeployProcedureWrapper.sol (94%) rename tests/mocks/deployments/{ => procedures}/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol (94%) rename tests/mocks/deployments/{ => procedures}/AaveV4AccessManagerRolesProcedureWrapper.sol (71%) rename tests/mocks/deployments/{ => procedures}/AaveV4HubConfiguratorDeployProcedureWrapper.sol (93%) rename tests/mocks/deployments/{ => procedures}/AaveV4HubDeployProcedureWrapper.sol (92%) rename tests/mocks/deployments/{ => procedures}/AaveV4HubRolesProcedureWrapper.sol (97%) rename tests/mocks/deployments/{ => procedures}/AaveV4InterestRateStrategyDeployProcedureWrapper.sol (93%) rename tests/mocks/deployments/{ => procedures}/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol (94%) rename tests/mocks/deployments/{ => procedures}/AaveV4SignatureGatewayDeployProcedureWrapper.sol (93%) rename tests/mocks/deployments/{ => procedures}/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol (93%) rename tests/mocks/deployments/{ => procedures}/AaveV4SpokeDeployProcedureWrapper.sol (94%) rename tests/mocks/deployments/{ => procedures}/AaveV4SpokeRolesProcedureWrapper.sol (96%) rename tests/mocks/deployments/{ => procedures}/AaveV4TreasurySpokeDeployProcedureWrapper.sol (93%) create mode 100644 tests/scripts/AaveV4DeployBatchBaseScript.t.sol diff --git a/scripts/deploy/inputs/AaveV4DeployInput.json b/config/AaveV4DeployInput.json similarity index 100% rename from scripts/deploy/inputs/AaveV4DeployInput.json rename to config/AaveV4DeployInput.json diff --git a/foundry.toml b/foundry.toml index adec3f2db..4a6d7e00a 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,8 +6,7 @@ libs = ['lib'] fs_permissions = [ { access = "read", path = "tests/mocks/JsonBindings.sol" }, { access = "read", path = "./config" }, - { access = "read-write", path = "./output" }, - { access = "read-write", path = "./scripts/deploy/inputs" } + { access = "read-write", path = "./output" } ] solc_version = "0.8.28" evm_version = "cancun" diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index 2840280be..d69916600 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -12,11 +12,15 @@ import { import {Script} from 'forge-std/Script.sol'; abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { - string internal constant INPUT_PATH = 'scripts/deploy/inputs/'; - string internal constant OUTPUT_DIR = 'output/reports/deployments/'; + struct Warnings { + string[] s; + } + string internal constant INPUT_PATH = 'config/'; + string internal constant OUTPUT_DIR = 'output/reports/deployments/'; string internal _inputFileName; string internal _outputFileName; + Warnings internal _warnings; constructor(string memory inputFileName_, string memory outputFileName_) { _inputFileName = inputFileName_; @@ -30,8 +34,7 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { string.concat(INPUT_PATH, _inputFileName) ); (, address deployer, ) = vm.readCallers(); - _loadWarnings(logger, inputs); - inputs = _sanitizeInputs(inputs, deployer); + inputs = _loadWarningsAndSanitizeInputs(logger, inputs, deployer); logger.log('...Starting Aave V4 Batch Deployment...'); vm.startBroadcast(deployer); @@ -44,119 +47,112 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { logger.save({fileName: _outputFileName, withTimestamp: true}); } - function _loadWarnings(MetadataLogger logger, FullDeployInputs memory inputs) internal virtual { + function _loadWarningsAndSanitizeInputs( + MetadataLogger logger, + FullDeployInputs memory inputs, + address deployer + ) internal virtual returns (FullDeployInputs memory) { + FullDeployInputs memory sanitizedInputs = inputs; bool hadWarnings = false; - string memory warnings = ''; if (inputs.grantRoles) { - warnings = _logAndAppend(logger, warnings, 'WARNING: Roles are being set'); + _logAndAppend(logger, 'WARNING: Roles are being set'); hadWarnings = true; if (inputs.accessManagerAdmin == address(0)) { - warnings = _logAndAppend( + _logAndAppend( logger, - warnings, 'WARNING: Access Manager Admin is zero address; role will be granted to deployer by default' ); + sanitizedInputs.accessManagerAdmin = deployer; } if (inputs.hubConfiguratorOwner == address(0)) { - warnings = _logAndAppend( + _logAndAppend( logger, - warnings, 'WARNING: Hub Configurator Owner is zero address; role will be granted to deployer by default' ); + sanitizedInputs.hubConfiguratorOwner = deployer; } if (inputs.spokeConfiguratorOwner == address(0)) { - warnings = _logAndAppend( + _logAndAppend( logger, - warnings, 'WARNING: Spoke Configurator Owner is zero address; role will be granted to deployer by default' ); + sanitizedInputs.spokeConfiguratorOwner = deployer; } if (inputs.spokeProxyAdminOwner == address(0)) { - warnings = _logAndAppend( + _logAndAppend( logger, - warnings, 'WARNING: Spoke Proxy Admin Owner is zero address; role will be granted to deployer by default' ); + sanitizedInputs.spokeProxyAdminOwner = deployer; } if (inputs.treasurySpokeOwner == address(0)) { - warnings = _logAndAppend( + _logAndAppend( logger, - warnings, 'WARNING: Treasury Spoke Owner is zero address; role will be granted to deployer by default' ); + sanitizedInputs.treasurySpokeOwner = deployer; } if (inputs.spokeAdmin == address(0)) { - warnings = _logAndAppend( + _logAndAppend( logger, - warnings, 'WARNING: Spoke Admin is zero address; spoke admin roles will be granted to deployer by default' ); + sanitizedInputs.spokeAdmin = deployer; } } if (inputs.hubLabels.length == 0) { - warnings = _logAndAppend(logger, warnings, 'WARNING: Hub will not be deployed'); + _logAndAppend(logger, 'WARNING: Hub will not be deployed'); hadWarnings = true; + sanitizedInputs.hubLabels = new string[](0); } if (inputs.spokeLabels.length == 0) { - warnings = _logAndAppend(logger, warnings, 'WARNING: Spoke will not be deployed'); + _logAndAppend(logger, 'WARNING: Spoke will not be deployed'); hadWarnings = true; + sanitizedInputs.spokeLabels = new string[](0); } if (inputs.nativeWrapper == address(0)) { - warnings = _logAndAppend( + _logAndAppend( logger, - warnings, 'WARNING: Native wrapper zero address; NativeTokenGateway & SignatureGateway will not be deployed' ); hadWarnings = true; + sanitizedInputs.nativeWrapper = address(0); + } + if (inputs.gatewayOwner == address(0)) { + _logAndAppend( + logger, + 'WARNING: Gateway owner zero address; role will be granted to deployer by default' + ); + hadWarnings = true; + sanitizedInputs.gatewayOwner = deployer; } - logger.log(''); - if (hadWarnings) { - _executeUserPrompt(warnings); + _executeUserPrompt(); } + return sanitizedInputs; } - function _executeUserPrompt(string memory warnings) internal virtual { - string memory ack = vm.prompt(string.concat(warnings, "\nEnter 'y' to continue")); + function _executeUserPrompt() internal virtual { + string memory ack = vm.prompt( + string.concat(_joinWarnings(_warnings), "\nEnter 'y' to continue") + ); if (keccak256(bytes(ack)) != keccak256(bytes('y'))) { revert('User did not acknowledge warnings. Please try again.'); } } - function _sanitizeInputs( - FullDeployInputs memory deployInputs, - address deployer - ) internal view virtual returns (FullDeployInputs memory) { - // if any admin is zero address, default to deployer as admin - InputUtils.FullDeployInputs memory sanitizedInputs = deployInputs; - sanitizedInputs.accessManagerAdmin = deployInputs.accessManagerAdmin != address(0) - ? deployInputs.accessManagerAdmin - : deployer; - sanitizedInputs.hubConfiguratorOwner = deployInputs.hubConfiguratorOwner != address(0) - ? deployInputs.hubConfiguratorOwner - : deployer; - sanitizedInputs.treasurySpokeOwner = deployInputs.treasurySpokeOwner != address(0) - ? deployInputs.treasurySpokeOwner - : deployer; - sanitizedInputs.spokeProxyAdminOwner = deployInputs.spokeProxyAdminOwner != address(0) - ? deployInputs.spokeProxyAdminOwner - : deployer; - sanitizedInputs.spokeConfiguratorOwner = deployInputs.spokeConfiguratorOwner != address(0) - ? deployInputs.spokeConfiguratorOwner - : deployer; - sanitizedInputs.gatewayOwner = deployInputs.gatewayOwner != address(0) - ? deployInputs.gatewayOwner - : deployer; - - return sanitizedInputs; + function _logAndAppend(MetadataLogger logger, string memory warning) internal virtual { + logger.log(warning); + _warnings.s.push(warning); } - function _logAndAppend( - MetadataLogger logger, - string memory warnings, - string memory warning - ) internal virtual returns (string memory) { - logger.log(warning); - return string.concat(warnings, warning, '\n'); + function _joinWarnings(Warnings storage warnings) internal view virtual returns (string memory) { + uint256 n = warnings.s.length; + if (n == 0) return ''; + string memory out = warnings.s[0]; + for (uint256 i = 1; i < n; i++) { + out = string.concat(out, '\n', warnings.s[i]); + } + return string.concat(out, '\n'); } } diff --git a/snapshots/Hub.Operations.json b/snapshots/Hub.Operations.json index 3a96ead80..255fcfc37 100644 --- a/snapshots/Hub.Operations.json +++ b/snapshots/Hub.Operations.json @@ -1,6 +1,6 @@ { "add": "88006", - "add: with transfer": "109642", + "add: with transfer": "109652", "draw": "105931", "eliminateDeficit: full": "59781", "eliminateDeficit: partial": "69429", @@ -11,8 +11,8 @@ "remove: partial": "81640", "reportDeficit": "115225", "restore: full": "80471", - "restore: full - with transfer": "173405", + "restore: full - with transfer": "173415", "restore: partial": "89137", - "restore: partial - with transfer": "147429", + "restore: partial - with transfer": "147439", "transferShares": "71180" } \ No newline at end of file diff --git a/snapshots/SignatureGateway.Operations.json b/snapshots/SignatureGateway.Operations.json index 9bb7d4757..96eb0ef3e 100644 --- a/snapshots/SignatureGateway.Operations.json +++ b/snapshots/SignatureGateway.Operations.json @@ -2,7 +2,7 @@ "borrowWithSig": "215605", "repayWithSig": "188872", "setSelfAsUserPositionManagerWithSig": "75402", - "setUsingAsCollateralWithSig": "85065", + "setUsingAsCollateralWithSig": "85053", "supplyWithSig": "153205", "updateUserDynamicConfigWithSig": "62769", "updateUserRiskPremiumWithSig": "61579", diff --git a/src/deployments/batches/AaveV4AccessBatch.sol b/src/deployments/batches/AaveV4AccessBatch.sol index b109a91d4..ba49a42c0 100644 --- a/src/deployments/batches/AaveV4AccessBatch.sol +++ b/src/deployments/batches/AaveV4AccessBatch.sol @@ -11,7 +11,6 @@ contract AaveV4AccessBatch is AaveV4AccessManagerEnumerableDeployProcedure { BatchReports.AccessBatchReport internal _report; constructor(address admin_) { - assert(admin_ != address(0)); address accessManager = _deployAccessManagerEnumerable(admin_); _report = BatchReports.AccessBatchReport({accessManager: accessManager}); } diff --git a/src/deployments/batches/AaveV4ConfiguratorBatch.sol b/src/deployments/batches/AaveV4ConfiguratorBatch.sol index 134ebe989..11737720a 100644 --- a/src/deployments/batches/AaveV4ConfiguratorBatch.sol +++ b/src/deployments/batches/AaveV4ConfiguratorBatch.sol @@ -17,9 +17,6 @@ contract AaveV4ConfiguratorBatch is BatchReports.ConfiguratorBatchReport internal _report; constructor(address hubConfiguratorOwner_, address spokeConfiguratorOwner_) { - assert(hubConfiguratorOwner_ != address(0)); - assert(spokeConfiguratorOwner_ != address(0)); - address hubConfigurator = _deployHubConfigurator(hubConfiguratorOwner_); address spokeConfigurator = _deploySpokeConfigurator(spokeConfiguratorOwner_); diff --git a/src/deployments/batches/AaveV4GatewayBatch.sol b/src/deployments/batches/AaveV4GatewayBatch.sol index 3741306db..328c662ba 100644 --- a/src/deployments/batches/AaveV4GatewayBatch.sol +++ b/src/deployments/batches/AaveV4GatewayBatch.sol @@ -17,9 +17,6 @@ contract AaveV4GatewayBatch is BatchReports.GatewaysBatchReport internal _report; constructor(address owner_, address nativeWrapper_) { - assert(owner_ != address(0)); - assert(nativeWrapper_ != address(0)); - address nativeGateway = _deployNativeTokenGateway({ nativeWrapper: nativeWrapper_, owner: owner_ diff --git a/src/deployments/batches/AaveV4HubBatch.sol b/src/deployments/batches/AaveV4HubBatch.sol index f25bc67d7..d879c1184 100644 --- a/src/deployments/batches/AaveV4HubBatch.sol +++ b/src/deployments/batches/AaveV4HubBatch.sol @@ -21,9 +21,6 @@ contract AaveV4HubBatch is BatchReports.HubBatchReport internal _report; constructor(address treasurySpokeOwner_, address accessManager_) { - assert(treasurySpokeOwner_ != address(0)); - assert(accessManager_ != address(0)); - address hub = _deployHub(accessManager_); address irStrategy = _deployInterestRateStrategy(hub); address treasurySpoke = _deployTreasurySpoke(treasurySpokeOwner_, hub); diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 6bce4532f..904f913d3 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -23,11 +23,6 @@ contract AaveV4SpokeInstanceBatch is AaveV4SpokeDeployProcedure, AaveV4AaveOracl uint8 oracleDecimals_, string memory oracleDescription_ ) { - assert(spokeProxyAdminOwner_ != address(0)); - assert(accessManager_ != address(0)); - assert(oracleDecimals_ > 0); - assert(bytes(oracleDescription_).length > 0); - // additional 2 nonces for AaveOracle, SpokeInstance, starting from contract nonce of 1 address predictedSpokeInstance = Utils.computeCreateAddress(address(this), 3); @@ -42,9 +37,9 @@ contract AaveV4SpokeInstanceBatch is AaveV4SpokeDeployProcedure, AaveV4AaveOracl oracle: aaveOracle }); - assert(spokeProxy == predictedSpokeInstance); - assert(ISpoke(spokeProxy).ORACLE() == aaveOracle); - assert(IAaveOracle(aaveOracle).SPOKE() == spokeProxy); + require(spokeProxy == predictedSpokeInstance, InvalidParam('predicted spoke instance')); + require(ISpoke(spokeProxy).ORACLE() == aaveOracle, InvalidParam('spoke oracle')); + require(IAaveOracle(aaveOracle).SPOKE() == spokeProxy, InvalidParam('aave oracle spoke')); _report = BatchReports.SpokeInstanceBatchReport({ aaveOracle: aaveOracle, diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index a66a25f8b..9fe0351b9 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -87,7 +87,7 @@ library AaveV4DeployOrchestration { if (deployInputs.accessManagerAdmin != initialAdmin) { logger.log('...Granting AccessManager Root Admin role...'); - AaveV4AccessManagerRolesProcedure.grantRootAdminRole({ + AaveV4AccessManagerRolesProcedure.replaceDefaultAdminRole({ accessManager: report.accessBatchReport.accessManager, adminToAdd: deployInputs.accessManagerAdmin, adminToRemove: initialAdmin diff --git a/src/deployments/procedures/AaveV4DeployProcedureBase.sol b/src/deployments/procedures/AaveV4DeployProcedureBase.sol new file mode 100644 index 000000000..cd8160b00 --- /dev/null +++ b/src/deployments/procedures/AaveV4DeployProcedureBase.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +contract AaveV4DeployProcedureBase { + error InvalidParam(string errorMessage); + function _validateAddress(address addr, string memory errorMessage) internal pure { + require(addr != address(0), InvalidParam(errorMessage)); + } +} diff --git a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol index 319b62449..64096aea0 100644 --- a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol @@ -3,9 +3,11 @@ pragma solidity ^0.8.0; import {AccessManagerEnumerable} from 'src/access/AccessManagerEnumerable.sol'; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; -contract AaveV4AccessManagerEnumerableDeployProcedure { +contract AaveV4AccessManagerEnumerableDeployProcedure is AaveV4DeployProcedureBase { function _deployAccessManagerEnumerable(address admin) internal returns (address) { + _validateAddress(admin, 'admin'); return address(new AccessManagerEnumerable({initialAdmin_: admin})); } } diff --git a/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol index 8ca1bd4be..d7a47412c 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol @@ -3,9 +3,10 @@ pragma solidity ^0.8.0; import {HubConfigurator} from 'src/hub/HubConfigurator.sol'; - -contract AaveV4HubConfiguratorDeployProcedure { +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +contract AaveV4HubConfiguratorDeployProcedure is AaveV4DeployProcedureBase { function _deployHubConfigurator(address owner) internal returns (address) { + _validateAddress(owner, 'owner'); return address(new HubConfigurator({owner_: owner})); } } diff --git a/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol index c5e84f4ca..51cc9f089 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol @@ -3,9 +3,10 @@ pragma solidity ^0.8.0; import {Hub} from 'src/hub/Hub.sol'; - -contract AaveV4HubDeployProcedure { +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +contract AaveV4HubDeployProcedure is AaveV4DeployProcedureBase { function _deployHub(address accessManager) internal returns (address) { + _validateAddress(accessManager, 'access manager'); return address(new Hub({authority_: accessManager})); } } diff --git a/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol index fe45c61d0..7d9caece9 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol @@ -3,9 +3,10 @@ pragma solidity ^0.8.0; import {AssetInterestRateStrategy} from 'src/hub/AssetInterestRateStrategy.sol'; - -contract AaveV4InterestRateStrategyDeployProcedure { +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +contract AaveV4InterestRateStrategyDeployProcedure is AaveV4DeployProcedureBase { function _deployInterestRateStrategy(address hub) internal returns (address) { + require(hub != address(0), InvalidParam('hub')); return address(new AssetInterestRateStrategy({hub_: hub})); } } diff --git a/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol index 4e698b640..5577ea77c 100644 --- a/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol @@ -3,12 +3,14 @@ pragma solidity ^0.8.0; import {NativeTokenGateway} from 'src/position-manager/NativeTokenGateway.sol'; - -contract AaveV4NativeTokenGatewayDeployProcedure { +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +contract AaveV4NativeTokenGatewayDeployProcedure is AaveV4DeployProcedureBase { function _deployNativeTokenGateway( address nativeWrapper, address owner ) internal returns (address) { + _validateAddress(nativeWrapper, 'native wrapper'); + _validateAddress(owner, 'owner'); return address(new NativeTokenGateway({nativeWrapper_: nativeWrapper, initialOwner_: owner})); } } diff --git a/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol index a7e7d8d44..63d88c51d 100644 --- a/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol @@ -3,9 +3,10 @@ pragma solidity ^0.8.0; import {SignatureGateway} from 'src/position-manager/SignatureGateway.sol'; - -contract AaveV4SignatureGatewayDeployProcedure { +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +contract AaveV4SignatureGatewayDeployProcedure is AaveV4DeployProcedureBase { function _deploySignatureGateway(address owner) internal returns (address) { + _validateAddress(owner, 'owner'); return address(new SignatureGateway({initialOwner_: owner})); } } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol index 7728d9bce..3e8aa10ea 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol @@ -3,13 +3,16 @@ pragma solidity ^0.8.0; import {AaveOracle} from 'src/spoke/AaveOracle.sol'; - -contract AaveV4AaveOracleDeployProcedure { +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +contract AaveV4AaveOracleDeployProcedure is AaveV4DeployProcedureBase { function _deployAaveOracle( address spoke_, uint8 decimals_, string memory description_ ) internal returns (address) { + _validateAddress(spoke_, 'spoke'); + require(decimals_ > 0, InvalidParam('oracle decimals')); + require(bytes(description_).length > 0, InvalidParam('oracle description')); return address(new AaveOracle({spoke_: spoke_, decimals_: decimals_, description_: description_})); } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol index aae93d507..45c96642b 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol @@ -3,9 +3,11 @@ pragma solidity ^0.8.0; import {SpokeConfigurator} from 'src/spoke/SpokeConfigurator.sol'; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; -contract AaveV4SpokeConfiguratorDeployProcedure { +contract AaveV4SpokeConfiguratorDeployProcedure is AaveV4DeployProcedureBase { function _deploySpokeConfigurator(address owner) internal returns (address) { + _validateAddress(owner, 'owner'); return address(new SpokeConfigurator({owner_: owner})); } } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol index 23b514315..fbd7670e2 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol @@ -4,18 +4,23 @@ pragma solidity ^0.8.0; import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; import {SpokeInstance} from 'src/spoke/instances/SpokeInstance.sol'; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; -contract AaveV4SpokeDeployProcedure { +contract AaveV4SpokeDeployProcedure is AaveV4DeployProcedureBase { function _deployUpgradableSpokeInstance( address spokeProxyAdminOwner, address accessManager, address oracle ) internal returns (address spokeProxy, address spokeImplementation) { + _validateAddress(spokeProxyAdminOwner, 'spoke proxy admin owner'); + _validateAddress(accessManager, 'access manager'); + _validateAddress(oracle, 'oracle'); spokeImplementation = address(new SpokeInstance({oracle_: oracle})); spokeProxy = Utils.proxify( spokeImplementation, spokeProxyAdminOwner, abi.encodeCall(SpokeInstance.initialize, (accessManager)) ); + return (spokeProxy, spokeImplementation); } } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol index a6f66a001..177fc731a 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol @@ -3,9 +3,12 @@ pragma solidity ^0.8.0; import {TreasurySpoke} from 'src/spoke/TreasurySpoke.sol'; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; -contract AaveV4TreasurySpokeDeployProcedure { +contract AaveV4TreasurySpokeDeployProcedure is AaveV4DeployProcedureBase { function _deployTreasurySpoke(address owner, address hub) internal returns (address) { + _validateAddress(owner, 'owner'); + _validateAddress(hub, 'hub'); return address(new TreasurySpoke({owner_: owner, hub_: hub})); } } diff --git a/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol index c4aa66cc9..f1db0eccb 100644 --- a/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol @@ -2,16 +2,19 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; library AaveV4AccessManagerRolesProcedure { - function grantRootAdminRole( + function replaceDefaultAdminRole( address accessManager, address adminToAdd, address adminToRemove ) internal { - assert(adminToAdd != address(0)); + require(accessManager != address(0), AaveV4DeployProcedureBase.InvalidParam('access manager')); + require(adminToAdd != address(0), AaveV4DeployProcedureBase.InvalidParam('admin to add')); + require(adminToRemove != address(0), AaveV4DeployProcedureBase.InvalidParam('admin to remove')); IAccessManager(accessManager).grantRole({ roleId: Roles.DEFAULT_ADMIN_ROLE, account: adminToAdd, diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol index 3529c1e0a..3512f21c7 100644 --- a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -2,18 +2,19 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; import {IHub} from 'src/hub/interfaces/IHub.sol'; library AaveV4HubRolesProcedure { function grantHubAdminRole(address accessManager, address admin) internal { - assert(admin != address(0)); grantHubFeeMinterRole(accessManager, admin); grantHubConfiguratorRole(accessManager, admin); } function grantHubFeeMinterRole(address accessManager, address admin) internal { + _validateAccessManagerAndAdmin(accessManager, admin); IAccessManager(accessManager).grantRole({ roleId: Roles.HUB_FEE_MINTER_ROLE, account: admin, @@ -22,6 +23,7 @@ library AaveV4HubRolesProcedure { } function grantHubConfiguratorRole(address accessManager, address admin) internal { + _validateAccessManagerAndAdmin(accessManager, admin); IAccessManager(accessManager).grantRole({ roleId: Roles.HUB_CONFIGURATOR_ROLE, account: admin, @@ -35,11 +37,13 @@ library AaveV4HubRolesProcedure { } function setupHubFeeMinterRole(address accessManager, address hub) internal { + _validateAccessManagerAndHub(accessManager, hub); bytes4[] memory selectors = getHubFeeMinterRoleSelectors(); IAccessManager(accessManager).setTargetFunctionRole(hub, selectors, Roles.HUB_FEE_MINTER_ROLE); } function setupHubConfiguratorRole(address accessManager, address hub) internal { + _validateAccessManagerAndHub(accessManager, hub); bytes4[] memory selectors = getHubConfiguratorRoleSelectors(); IAccessManager(accessManager).setTargetFunctionRole( hub, @@ -63,4 +67,14 @@ library AaveV4HubRolesProcedure { selectors[4] = IHub.setInterestRateData.selector; return selectors; } + + function _validateAccessManagerAndHub(address accessManager, address hub) private pure { + require(accessManager != address(0), AaveV4DeployProcedureBase.InvalidParam('access manager')); + require(hub != address(0), AaveV4DeployProcedureBase.InvalidParam('hub')); + } + + function _validateAccessManagerAndAdmin(address accessManager, address admin) private pure { + require(accessManager != address(0), AaveV4DeployProcedureBase.InvalidParam('access manager')); + require(admin != address(0), AaveV4DeployProcedureBase.InvalidParam('admin')); + } } diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol index 87a1038fe..8f122afed 100644 --- a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -2,19 +2,19 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; library AaveV4SpokeRolesProcedure { function grantSpokeAdminRole(address accessManager, address admin) internal { - assert(admin != address(0)); grantSpokePositionUpdaterRole(accessManager, admin); grantSpokeConfiguratorRole(accessManager, admin); } function grantSpokePositionUpdaterRole(address accessManager, address admin) internal { - assert(admin != address(0)); + _validateAccessManagerAndAdmin(accessManager, admin); IAccessManager(accessManager).grantRole({ roleId: Roles.SPOKE_POSITION_UPDATER_ROLE, account: admin, @@ -23,7 +23,7 @@ library AaveV4SpokeRolesProcedure { } function grantSpokeConfiguratorRole(address accessManager, address admin) internal { - assert(admin != address(0)); + _validateAccessManagerAndAdmin(accessManager, admin); IAccessManager(accessManager).grantRole({ roleId: Roles.SPOKE_CONFIGURATOR_ROLE, account: admin, @@ -37,7 +37,7 @@ library AaveV4SpokeRolesProcedure { } function setupSpokePositionUpdaterRole(address accessManager, address spoke) internal { - assert(spoke != address(0)); + _validateAccessManagerAndSpoke(accessManager, spoke); bytes4[] memory selectors = getSpokePositionUpdaterRoleSelectors(); IAccessManager(accessManager).setTargetFunctionRole( spoke, @@ -47,7 +47,7 @@ library AaveV4SpokeRolesProcedure { } function setupSpokeConfiguratorRole(address accessManager, address spoke) internal { - assert(spoke != address(0)); + _validateAccessManagerAndSpoke(accessManager, spoke); bytes4[] memory selectors = getSpokeConfiguratorRoleSelectors(); IAccessManager(accessManager).setTargetFunctionRole( spoke, @@ -74,4 +74,14 @@ library AaveV4SpokeRolesProcedure { selectors[6] = ISpoke.updateReservePriceSource.selector; return selectors; } + + function _validateAccessManagerAndSpoke(address accessManager, address spoke) private pure { + require(accessManager != address(0), AaveV4DeployProcedureBase.InvalidParam('access manager')); + require(spoke != address(0), AaveV4DeployProcedureBase.InvalidParam('spoke')); + } + + function _validateAccessManagerAndAdmin(address accessManager, address admin) private pure { + require(accessManager != address(0), AaveV4DeployProcedureBase.InvalidParam('access manager')); + require(admin != address(0), AaveV4DeployProcedureBase.InvalidParam('admin')); + } } diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index 93148be29..e66662b68 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -8,6 +8,8 @@ import 'forge-std/Vm.sol'; contract InputUtils { using stdJson for string; + Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); + /// @dev accessManagerAdmin The default admin of the access manager. /// @dev hubAdmin The admin of the hub. /// @dev hubConfiguratorOwner The admin of the hub configurator. @@ -47,8 +49,6 @@ contract InputUtils { string hubLabel; } - Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); - function loadFullDeployInputs( string memory inputPath ) public view returns (FullDeployInputs memory inputs) { @@ -60,6 +60,7 @@ contract InputUtils { inputs.spokeAdmin = json.readAddress('.spokeAdmin'); inputs.spokeProxyAdminOwner = json.readAddress('.spokeProxyAdminOwner'); inputs.spokeConfiguratorOwner = json.readAddress('.spokeConfiguratorOwner'); + inputs.gatewayOwner = json.readAddress('.gatewayOwner'); inputs.nativeWrapper = json.readAddress('.nativeWrapper'); inputs.grantRoles = json.readBool('.grantRoles'); inputs.hubLabels = json.readStringArray('.hubLabels'); diff --git a/tests/Base.t.sol b/tests/Base.t.sol index 7c9ea9db9..f69902030 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -146,6 +146,8 @@ abstract contract Base is BatchTestProcedures { ISpoke internal spoke3; AssetInterestRateStrategy internal irStrategy; IAccessManager internal accessManager; + IHubConfigurator internal hubConfigurator; + ISpokeConfigurator internal spokeConfigurator; address internal alice = makeAddr('alice'); address internal bob = makeAddr('bob'); @@ -159,6 +161,8 @@ abstract contract Base is BatchTestProcedures { address internal TREASURY_ADMIN = makeAddr('TREASURY_ADMIN'); address internal LIQUIDATOR = makeAddr('LIQUIDATOR'); address internal POSITION_MANAGER = makeAddr('POSITION_MANAGER'); + address internal HUB_CONFIGURATOR_ADMIN = makeAddr('HUB_CONFIGURATOR_ADMIN'); + address internal SPOKE_CONFIGURATOR_ADMIN = makeAddr('SPOKE_CONFIGURATOR_ADMIN'); TestTypes.TokenList internal tokenList; uint256 internal wethAssetId = 0; @@ -299,17 +303,19 @@ abstract contract Base is BatchTestProcedures { oracle2 = IAaveOracle(report.spokeReports[1].aaveOracle); oracle3 = IAaveOracle(report.spokeReports[2].aaveOracle); accessManager = IAccessManager(report.accessManager); + hubConfigurator = IHubConfigurator(report.configuratorReport.hubConfigurator); + spokeConfigurator = ISpokeConfigurator(report.configuratorReport.spokeConfigurator); } function _deployFixtures( uint256 numHubs, uint256 numSpokes ) internal virtual returns (TestTypes.TestEnvReport memory report) { - // console.log('weth', address(tokenList.weth)); - // revert('testing env'); report = AaveV4TestOrchestration.deployTestEnv({ admin: ADMIN, treasuryAdmin: TREASURY_ADMIN, + hubConfiguratorAdmin: HUB_CONFIGURATOR_ADMIN, + spokeConfiguratorAdmin: SPOKE_CONFIGURATOR_ADMIN, hubCount: numHubs, spokeCount: numSpokes, nativeWrapper: address(tokenList.weth) @@ -335,6 +341,9 @@ abstract contract Base is BatchTestProcedures { vm.label(report.spokeReports[i].aaveOracle, string.concat('oracle', string(abi.encode(i)))); } + vm.label(report.configuratorReport.hubConfigurator, 'hubConfigurator'); + vm.label(report.configuratorReport.spokeConfigurator, 'spokeConfigurator'); + return report; } @@ -1043,13 +1052,9 @@ abstract contract Base is BatchTestProcedures { return report; } - function _grantSpokeConfiguratorRole(ISpoke spoke, address spokeConfigurator) internal { + function _grantSpokeConfiguratorRole(ISpoke spoke, address configurator) internal { vm.startPrank(ADMIN); - IAccessManager(spoke.authority()).grantRole( - Roles.SPOKE_CONFIGURATOR_ROLE, - spokeConfigurator, - 0 - ); + IAccessManager(spoke.authority()).grantRole(Roles.SPOKE_CONFIGURATOR_ROLE, configurator, 0); vm.stopPrank(); } diff --git a/tests/Config.sol b/tests/Config.sol deleted file mode 100644 index d63d641b9..000000000 --- a/tests/Config.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.0; - -import {IHub} from 'src/hub/interfaces/IHub.sol'; -import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; -import {ConfigData} from 'src/deployments/libraries/ConfigData.sol'; - -library Config { - // get Hub test configs - // get Spokes test liquidation configs - // get Spokes test reserve configs -} diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index a80f8e46b..55798b5ef 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -3,27 +3,12 @@ pragma solidity ^0.8.0; import 'tests/utils/BatchTestProcedures.sol'; -import {stdError} from 'forge-std/StdError.sol'; contract AaveV4BatchDeploymentTest is BatchTestProcedures { - Logger public logger; - FullDeployInputs public inputs; - address public weth9; - - string[] public hubLabels; - string[] public spokeLabels; - function setUp() public override { super.setUp(); - deployer = makeAddr('deployer'); - logger = new Logger('dummy/path'); - weth9 = _deployWETH(); - - hubLabels = ['hub1', 'hub2', 'hub3']; - spokeLabels = ['spoke1', 'spoke2', 'spoke3']; - - inputs = FullDeployInputs({ + _inputs = FullDeployInputs({ accessManagerAdmin: makeAddr('accessManagerAdmin'), hubConfiguratorOwner: makeAddr('hubConfiguratorOwner'), hubAdmin: makeAddr('hubAdmin'), @@ -32,65 +17,67 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { spokeConfiguratorOwner: makeAddr('spokeConfiguratorOwner'), spokeAdmin: makeAddr('spokeAdmin'), gatewayOwner: makeAddr('gatewayOwner'), - nativeWrapper: weth9, + nativeWrapper: _weth9, grantRoles: true, - hubLabels: hubLabels, - spokeLabels: spokeLabels + hubLabels: _hubLabels, + spokeLabels: _spokeLabels }); } function testAaveV4BatchDeployment() public { - checkedV4Deployment(logger, inputs); + checkedV4Deployment(); } function testAaveV4BatchDeployment_withoutRoles() public { - inputs.grantRoles = false; - checkedV4Deployment(logger, inputs); + _inputs.grantRoles = false; + checkedV4Deployment(); } function testAaveV4BatchDeployment_withoutNativeGateway() public { - inputs.nativeWrapper = address(0); - checkedV4Deployment(logger, inputs); + _inputs.nativeWrapper = address(0); + checkedV4Deployment(); } function testAaveV4BatchDeployment_withoutHubs() public { - inputs.hubLabels = new string[](0); - checkedV4Deployment(logger, inputs); + _inputs.hubLabels = new string[](0); + checkedV4Deployment(); } function testAaveV4BatchDeployment_withoutSpokes() public { - inputs.spokeLabels = new string[](0); - checkedV4Deployment(logger, inputs); + _inputs.spokeLabels = new string[](0); + checkedV4Deployment(); } function testAaveV4BatchDeployment_withZeroAccessManagerAdmin_withRoles_revertsWithAssertionError() public { // only reverts if grantRoles is true, as access manager admin replaces deployer as default admin - inputs.accessManagerAdmin = address(0); - inputs.grantRoles = true; + _inputs.accessManagerAdmin = address(0); + _inputs.grantRoles = true; - // reverts in AaveV4AccessBatch - vm.expectRevert(stdError.assertionError); - this.checkedV4Deployment(logger, inputs); + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin to add') + ); + this.checkedV4Deployment(); } function testAaveV4BatchDeployment_withZeroAccessManagerAdmin_withoutRoles() public { - inputs.accessManagerAdmin = address(0); - inputs.grantRoles = false; + _inputs.accessManagerAdmin = address(0); + _inputs.grantRoles = false; - checkedV4Deployment(logger, inputs); + checkedV4Deployment(); } /// @dev Reverts as hubConfigurator is always deployed /// and owners are needed on initial deployment function testAaveV4BatchDeployment_withZeroHubConfiguratorOwner() public { - inputs.hubConfiguratorOwner = address(0); - inputs.grantRoles = vm.randomBool(); + _inputs.hubConfiguratorOwner = address(0); + _inputs.grantRoles = vm.randomBool(); - // reverts in AaveV4ConfiguratorBatch - vm.expectRevert(stdError.assertionError); - this.checkedV4Deployment(logger, inputs); + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); + this.checkedV4Deployment(); } /// @dev Reverts as treasurySpoke is always deployed if hubs are being deployed @@ -99,19 +86,19 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { bool withoutHubs, bool grantRoles ) public { - inputs.treasurySpokeOwner = address(0); - inputs.grantRoles = grantRoles; + _inputs.treasurySpokeOwner = address(0); + _inputs.grantRoles = grantRoles; if (withoutHubs) { - inputs.hubLabels = new string[](0); + _inputs.hubLabels = new string[](0); } - if (_isExpectAssertionError(inputs, deployer)) { - // reverts in AaveV4HubBatch - vm.expectRevert(stdError.assertionError); - this.checkedV4Deployment(logger, inputs); + (bool isExpectedError, bytes memory errorSelector) = _getExpectedError(); + if (isExpectedError) { + vm.expectRevert(errorSelector); + this.checkedV4Deployment(); } else { - checkedV4Deployment(logger, inputs); + checkedV4Deployment(); } } @@ -119,39 +106,41 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { bool withoutSpokes, bool grantRoles ) public { - inputs.spokeProxyAdminOwner = address(0); - inputs.grantRoles = grantRoles; + _inputs.spokeProxyAdminOwner = address(0); + _inputs.grantRoles = grantRoles; if (withoutSpokes) { - inputs.spokeLabels = new string[](0); + _inputs.spokeLabels = new string[](0); } - if (_isExpectAssertionError(inputs, deployer)) { - // reverts in AaveV4SpokeInstanceBatch - vm.expectRevert(stdError.assertionError); - this.checkedV4Deployment(logger, inputs); + (bool isExpectedError, bytes memory errorSelector) = _getExpectedError(); + if (isExpectedError) { + vm.expectRevert(errorSelector); + this.checkedV4Deployment(); } else { - checkedV4Deployment(logger, inputs); + checkedV4Deployment(); } } function testAaveV4BatchDeployment_withZeroSpokeConfiguratorOwner() public { - inputs.spokeConfiguratorOwner = address(0); - inputs.grantRoles = vm.randomBool(); + _inputs.spokeConfiguratorOwner = address(0); + _inputs.grantRoles = vm.randomBool(); - // reverts in AaveV4ConfiguratorBatch - vm.expectRevert(stdError.assertionError); - this.checkedV4Deployment(logger, inputs); + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); + this.checkedV4Deployment(); } function testAaveV4BatchDeployment_withZeroSpokeConfiguratorOwner_withoutRoles_revertsWithAssertionError() public { - inputs.spokeConfiguratorOwner = address(0); - inputs.grantRoles = false; + _inputs.spokeConfiguratorOwner = address(0); + _inputs.grantRoles = false; - // reverts in AaveV4ConfiguratorBatch - vm.expectRevert(stdError.assertionError); - this.checkedV4Deployment(logger, inputs); + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); + this.checkedV4Deployment(); } function testAaveV4BatchDeployment_fuzz_withoutRoles( @@ -165,24 +154,27 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { if (withoutNativeWrapper) { deployInputs.nativeWrapper = address(0); } else { - deployInputs.nativeWrapper = inputs.nativeWrapper; + deployInputs.nativeWrapper = _inputs.nativeWrapper; } if (withoutHubs) { deployInputs.hubLabels = new string[](0); } else { - deployInputs.hubLabels = inputs.hubLabels; + deployInputs.hubLabels = _inputs.hubLabels; } if (withoutSpokes) { deployInputs.spokeLabels = new string[](0); } else { - deployInputs.spokeLabels = inputs.spokeLabels; + deployInputs.spokeLabels = _inputs.spokeLabels; } + _deployer = deployer; + _inputs = deployInputs; - if (_isExpectAssertionError(deployInputs, deployer)) { - vm.expectRevert(stdError.assertionError); - this.checkedV4Deployment(logger, deployInputs); + (bool isExpectedError, bytes memory errorSelector) = _getExpectedError(); + if (isExpectedError) { + vm.expectRevert(errorSelector); + this.checkedV4Deployment(); } else { - checkedV4Deployment(logger, deployInputs); + checkedV4Deployment(); } } @@ -197,25 +189,28 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { if (withoutNativeWrapper) { deployInputs.nativeWrapper = address(0); } else { - deployInputs.nativeWrapper = inputs.nativeWrapper; + deployInputs.nativeWrapper = _inputs.nativeWrapper; } - deployInputs.nativeWrapper = inputs.nativeWrapper; + deployInputs.nativeWrapper = _inputs.nativeWrapper; if (withoutHubs) { deployInputs.hubLabels = new string[](0); } else { - deployInputs.hubLabels = inputs.hubLabels; + deployInputs.hubLabels = _inputs.hubLabels; } if (withoutSpokes) { deployInputs.spokeLabels = new string[](0); } else { - deployInputs.spokeLabels = inputs.spokeLabels; + deployInputs.spokeLabels = _inputs.spokeLabels; } + _deployer = deployer; + _inputs = deployInputs; - if (_isExpectAssertionError(deployInputs, deployer)) { - vm.expectRevert(stdError.assertionError); - this.checkedV4Deployment(logger, deployInputs); + (bool isExpectedError, bytes memory errorSelector) = _getExpectedError(); + if (isExpectedError) { + vm.expectRevert(errorSelector); + this.checkedV4Deployment(); } else { - checkedV4Deployment(logger, deployInputs); + checkedV4Deployment(); } } @@ -235,39 +230,77 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { assertNotEq(deployInputs.hubAdmin, address(0)); assertNotEq(deployInputs.spokeAdmin, address(0)); - checkedV4Deployment(logger, deployInputs); + checkedV4Deployment(); } - function _isExpectAssertionError( - FullDeployInputs memory deployInputs, - address deployer - ) internal pure returns (bool isExpectedError) { + function _getExpectedError() + internal + view + returns (bool isExpectedError, bytes memory errorSelector) + { // deployer is initial admin for access manager - if (deployer == address(0)) return true; + if (_deployer == address(0)) return (true, abi.encodePacked('')); // configurators always deployed - if (deployInputs.spokeConfiguratorOwner == address(0)) return true; - if (deployInputs.hubConfiguratorOwner == address(0)) return true; + if (_inputs.spokeConfiguratorOwner == address(0)) { + return ( + true, + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); + } + if (_inputs.hubConfiguratorOwner == address(0)) { + return ( + true, + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); + } // gateways only when native wrapper is set - if (deployInputs.nativeWrapper != address(0) && deployInputs.gatewayOwner == address(0)) { - return true; + if (_inputs.nativeWrapper != address(0) && _inputs.gatewayOwner == address(0)) { + return ( + true, + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); } // hubs require treasury owner when deployed - if (deployInputs.hubLabels.length > 0 && deployInputs.treasurySpokeOwner == address(0)) { - return true; + if (_inputs.hubLabels.length > 0 && _inputs.treasurySpokeOwner == address(0)) { + return ( + true, + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); } // spokes require proxy admin owner when deployed - if (deployInputs.spokeLabels.length > 0 && deployInputs.spokeProxyAdminOwner == address(0)) { - return true; + if (_inputs.spokeLabels.length > 0 && _inputs.spokeProxyAdminOwner == address(0)) { + return ( + true, + abi.encodeWithSelector( + AaveV4DeployProcedureBase.InvalidParam.selector, + 'spoke proxy admin owner' + ) + ); } - if (deployInputs.grantRoles) { - if (deployInputs.accessManagerAdmin == address(0)) return true; - if (deployInputs.hubLabels.length > 0 && deployInputs.hubAdmin == address(0)) return true; - if (deployInputs.spokeLabels.length > 0 && deployInputs.spokeAdmin == address(0)) return true; + if (_inputs.grantRoles) { + if (_inputs.accessManagerAdmin == address(0)) { + return ( + true, + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') + ); + } + if (_inputs.hubLabels.length > 0 && _inputs.hubAdmin == address(0)) { + return ( + true, + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') + ); + } + if (_inputs.spokeLabels.length > 0 && _inputs.spokeAdmin == address(0)) { + return ( + true, + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') + ); + } } } } diff --git a/tests/deployments/batches/AaveV4AccessBatch.t.sol b/tests/deployments/batches/AaveV4AccessBatch.t.sol new file mode 100644 index 000000000..69adf37b3 --- /dev/null +++ b/tests/deployments/batches/AaveV4AccessBatch.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import 'tests/deployments/batches/BatchBase.t.sol'; + +contract AaveV4AccessBatchTest is BatchBaseTest { + AaveV4AccessBatch public aaveV4AccessBatch; + function setUp() public override { + super.setUp(); + aaveV4AccessBatch = new AaveV4AccessBatch(admin); + } + + function test_getReport() public view { + BatchReports.AccessBatchReport memory report = aaveV4AccessBatch.getReport(); + assertNotEq(report.accessManager, address(0)); + + (bool hasRole, uint32 executionDelay) = IAccessManagerEnumerable(report.accessManager).hasRole( + Roles.DEFAULT_ADMIN_ROLE, + admin + ); + assertTrue(hasRole); + assertEq(executionDelay, 0); + } +} diff --git a/tests/deployments/batches/BatchBase.t.sol b/tests/deployments/batches/BatchBase.t.sol new file mode 100644 index 000000000..0aac98a43 --- /dev/null +++ b/tests/deployments/batches/BatchBase.t.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Test} from 'forge-std/Test.sol'; + +import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; +import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; +import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; + +import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; + +contract BatchBaseTest is Test { + address public admin = makeAddr('admin'); + + function setUp() public virtual {} +} diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol index dd834c658..e7044f20e 100644 --- a/tests/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -62,6 +62,8 @@ library AaveV4TestOrchestration { function deployTestEnv( address admin, address treasuryAdmin, + address hubConfiguratorAdmin, + address spokeConfiguratorAdmin, uint256 hubCount, uint256 spokeCount, address nativeWrapper @@ -99,6 +101,15 @@ library AaveV4TestOrchestration { report.spokeReports[i].aaveOracle = spokeReport.aaveOracle; } + // Deploy Configurator Batches + BatchReports.ConfiguratorBatchReport memory configuratorReport = AaveV4DeployBase + .deployConfiguratorBatch({ + hubConfiguratorOwner: hubConfiguratorAdmin, + spokeConfiguratorOwner: spokeConfiguratorAdmin + }); + report.configuratorReport.hubConfigurator = configuratorReport.hubConfigurator; + report.configuratorReport.spokeConfigurator = configuratorReport.spokeConfigurator; + // Deploy Gateways Batch BatchReports.GatewaysBatchReport memory gatewaysReport = AaveV4DeployBase.deployGatewaysBatch({ owner: admin, @@ -162,9 +173,15 @@ library AaveV4TestOrchestration { address admin, address hubAdmin ) public { - // grant Hub roles + // grant Hub Admin roles AaveV4HubRolesProcedure.grantHubAdminRole(report.accessManager, admin); AaveV4HubRolesProcedure.grantHubAdminRole(report.accessManager, hubAdmin); + + // grant Hub Configurator roles + AaveV4HubRolesProcedure.grantHubConfiguratorRole( + report.accessManager, + report.configuratorReport.hubConfigurator + ); } function grantSpokeRolesTestEnv( @@ -175,6 +192,12 @@ library AaveV4TestOrchestration { // grant Spoke roles AaveV4SpokeRolesProcedure.grantSpokeAdminRole(report.accessManager, admin); AaveV4SpokeRolesProcedure.grantSpokeAdminRole(report.accessManager, spokeAdmin); + + // grant Spoke Configurator roles + AaveV4SpokeRolesProcedure.grantSpokeConfiguratorRole( + report.accessManager, + report.configuratorReport.spokeConfigurator + ); } function configureHubsAssets( @@ -187,6 +210,20 @@ library AaveV4TestOrchestration { return assetIds; } + function configureHubsAssetsViaConfigurator( + ConfigData.AddAssetParams[] memory paramsList, + address hubConfigurator + ) public returns (uint256[] memory) { + uint256[] memory assetIds = new uint256[](paramsList.length); + for (uint256 i; i < paramsList.length; ++i) { + assetIds[i] = AaveV4HubConfigProcedures.addAssetViaConfigurator( + hubConfigurator, + paramsList[i] + ); + } + return assetIds; + } + function _deployTestTokensBatch( TestTypes.TestTokenInput[] memory tokenInputs ) internal returns (TestTypes.TestTokensReport memory) { diff --git a/tests/deployments/procedures/ProceduresBase.t.sol b/tests/deployments/procedures/ProceduresBase.t.sol index d4ed381cc..d5fdc0798 100644 --- a/tests/deployments/procedures/ProceduresBase.t.sol +++ b/tests/deployments/procedures/ProceduresBase.t.sol @@ -3,48 +3,49 @@ pragma solidity ^0.8.0; import {Test} from 'forge-std/Test.sol'; -import {stdError} from 'forge-std/Test.sol'; import {Ownable} from 'src/dependencies/openzeppelin/Ownable.sol'; import { AaveV4HubConfiguratorDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4HubConfiguratorDeployProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4HubConfiguratorDeployProcedureWrapper.sol'; import { AaveV4HubDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4HubDeployProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4HubDeployProcedureWrapper.sol'; import { AaveV4InterestRateStrategyDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4InterestRateStrategyDeployProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4InterestRateStrategyDeployProcedureWrapper.sol'; import { AaveV4NativeTokenGatewayDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol'; import { AaveV4SignatureGatewayDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4SignatureGatewayDeployProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4SignatureGatewayDeployProcedureWrapper.sol'; import { AaveV4AccessManagerEnumerableDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol'; import { AaveV4AaveOracleDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4AaveOracleDeployProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4AaveOracleDeployProcedureWrapper.sol'; import { AaveV4SpokeDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4SpokeDeployProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4SpokeDeployProcedureWrapper.sol'; import { AaveV4TreasurySpokeDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4TreasurySpokeDeployProcedureWrapper.sol'; import { AaveV4SpokeConfiguratorDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol'; import { AaveV4AccessManagerRolesProcedureWrapper -} from 'tests/mocks/deployments/AaveV4AccessManagerRolesProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4AccessManagerRolesProcedureWrapper.sol'; import { AaveV4SpokeRolesProcedureWrapper -} from 'tests/mocks/deployments/AaveV4SpokeRolesProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4SpokeRolesProcedureWrapper.sol'; import { AaveV4HubRolesProcedureWrapper -} from 'tests/mocks/deployments/AaveV4HubRolesProcedureWrapper.sol'; +} from 'tests/mocks/deployments/procedures/AaveV4HubRolesProcedureWrapper.sol'; + +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; import {AaveOracle} from 'src/spoke/AaveOracle.sol'; import {AccessManagerEnumerable} from 'src/access/AccessManagerEnumerable.sol'; @@ -60,27 +61,20 @@ import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnum import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; contract ProceduresBase is Test { - address public owner; + address public owner = makeAddr('owner'); address public accessManager; - address public hub; - address public nativeWrapper; - address public accessManagerAdmin; - uint8 public oracleDecimals; - string public oracleDescription; - address public spoke; + address public hub = makeAddr('hub'); + address public nativeWrapper = makeAddr('nativeWrapper'); + address public accessManagerAdmin = makeAddr('accessManagerAdmin'); + uint8 public oracleDecimals = 8; + string public oracleDescription = 'Oracle Description'; + address public spoke = makeAddr('spoke'); address public aaveOracle; - address public treasurySpoke; + address public treasurySpoke = makeAddr('treasurySpoke'); + address public admin = makeAddr('admin'); function setUp() public virtual { - owner = makeAddr('owner'); - accessManagerAdmin = makeAddr('accessManagerAdmin'); accessManager = address(new AccessManagerEnumerable(accessManagerAdmin)); - hub = makeAddr('hub'); - nativeWrapper = makeAddr('nativeWrapper'); - oracleDecimals = 8; - oracleDescription = 'Oracle Description'; - spoke = makeAddr('spoke'); aaveOracle = address(new AaveOracle(spoke, oracleDecimals, oracleDescription)); - treasurySpoke = makeAddr('treasurySpoke'); } } diff --git a/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol b/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol index 7c5333809..2d2928327 100644 --- a/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol @@ -9,7 +9,6 @@ contract AaveV4AccessManagerEnumerableDeployProcedureTest is ProceduresBase { public aaveV4AccessManagerEnumerableDeployProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4AccessManagerEnumerableDeployProcedureWrapper = new AaveV4AccessManagerEnumerableDeployProcedureWrapper(); } @@ -25,4 +24,11 @@ contract AaveV4AccessManagerEnumerableDeployProcedureTest is ProceduresBase { assertTrue(hasRole); assertEq(executionDelay, 0); } + + function test_deployAccessManagerEnumerable_reverts() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') + ); + aaveV4AccessManagerEnumerableDeployProcedureWrapper.deployAccessManagerEnumerable(address(0)); + } } diff --git a/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol index c0b9a9732..f12eef96e 100644 --- a/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol @@ -8,7 +8,6 @@ contract AaveV4HubConfiguratorDeployProcedureTest is ProceduresBase { AaveV4HubConfiguratorDeployProcedureWrapper public aaveV4HubConfiguratorDeployProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4HubConfiguratorDeployProcedureWrapper = new AaveV4HubConfiguratorDeployProcedureWrapper(); } @@ -19,4 +18,11 @@ contract AaveV4HubConfiguratorDeployProcedureTest is ProceduresBase { assertNotEq(hubConfigurator, address(0)); assertEq(Ownable(hubConfigurator).owner(), owner); } + + function test_deployHubConfigurator_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); + aaveV4HubConfiguratorDeployProcedureWrapper.deployHubConfigurator(address(0)); + } } diff --git a/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol index f6bbb447c..936bf86ce 100644 --- a/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol @@ -8,7 +8,6 @@ contract AaveV4HubDeployProcedureTest is ProceduresBase { AaveV4HubDeployProcedureWrapper public aaveV4HubDeployProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4HubDeployProcedureWrapper = new AaveV4HubDeployProcedureWrapper(); } @@ -17,4 +16,11 @@ contract AaveV4HubDeployProcedureTest is ProceduresBase { assertNotEq(hub, address(0)); assertEq(IHub(hub).authority(), accessManager); } + + function test_deployHub_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4HubDeployProcedureWrapper.deployHub(address(0)); + } } diff --git a/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol index 06529dd7d..4e0bbbcc4 100644 --- a/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol @@ -9,7 +9,6 @@ contract AaveV4InterestRateStrategyDeployProcedureTest is ProceduresBase { public aaveV4InterestRateStrategyDeployProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4InterestRateStrategyDeployProcedureWrapper = new AaveV4InterestRateStrategyDeployProcedureWrapper(); } @@ -19,4 +18,9 @@ contract AaveV4InterestRateStrategyDeployProcedureTest is ProceduresBase { assertNotEq(interestRateStrategy, address(0)); assertEq(IAssetInterestRateStrategy(interestRateStrategy).HUB(), hub); } + + function test_deployInterestRateStrategy_revertsWithInvalidParam() public { + vm.expectRevert(abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'hub')); + aaveV4InterestRateStrategyDeployProcedureWrapper.deployInterestRateStrategy(address(0)); + } } diff --git a/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol b/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol index 6c68f20b0..6f76affa1 100644 --- a/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol @@ -9,7 +9,6 @@ contract AaveV4NativeTokenGatewayDeployProcedureTest is ProceduresBase { public aaveV4NativeTokenGatewayDeployProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4NativeTokenGatewayDeployProcedureWrapper = new AaveV4NativeTokenGatewayDeployProcedureWrapper(); } @@ -19,4 +18,19 @@ contract AaveV4NativeTokenGatewayDeployProcedureTest is ProceduresBase { assertNotEq(nativeTokenGateway, address(0)); assertEq(Ownable(nativeTokenGateway).owner(), owner); } + + function test_deployNativeTokenGateway_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'native wrapper') + ); + aaveV4NativeTokenGatewayDeployProcedureWrapper.deployNativeTokenGateway(address(0), owner); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); + aaveV4NativeTokenGatewayDeployProcedureWrapper.deployNativeTokenGateway( + nativeWrapper, + address(0) + ); + } } diff --git a/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol b/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol index 680d8ac7c..05963faeb 100644 --- a/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol @@ -19,4 +19,11 @@ contract AaveV4SignatureGatewayDeployProcedureTest is ProceduresBase { assertNotEq(signatureGateway, address(0)); assertEq(Ownable(signatureGateway).owner(), owner); } + + function test_deploySignatureGateway_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); + aaveV4SignatureGatewayDeployProcedureWrapper.deploySignatureGateway(address(0)); + } } diff --git a/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol b/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol index ca5a2a8b6..38f87c192 100644 --- a/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol +++ b/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol @@ -8,7 +8,6 @@ contract AaveV4AccessManagerRolesProcedureTest is ProceduresBase { AaveV4AccessManagerRolesProcedureWrapper public aaveV4AccessManagerRolesProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4AccessManagerRolesProcedureWrapper = new AaveV4AccessManagerRolesProcedureWrapper(); } @@ -24,9 +23,34 @@ contract AaveV4AccessManagerRolesProcedureTest is ProceduresBase { assertEq(executionDelay, 0); } - function test_grantRootAdminRole_reverts() public { - vm.expectRevert(stdError.assertionError); - aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole(accessManager, address(0), owner); + function test_grantRootAdminRole_revertsWithInvalidParam() public { + address newAdmin = makeAddr('newAdmin'); + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole({ + accessManager: address(0), + adminToAdd: newAdmin, + adminToRemove: address(0) + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin to add') + ); + aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole({ + accessManager: accessManager, + adminToAdd: address(0), + adminToRemove: newAdmin + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin to remove') + ); + aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole({ + accessManager: accessManager, + adminToAdd: newAdmin, + adminToRemove: address(0) + }); } /// @dev Grants a temporary root admin role to the wrapper contract to execute the procedure. diff --git a/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol b/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol index 5ca2886a4..9dafc985b 100644 --- a/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol +++ b/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol @@ -8,7 +8,106 @@ contract AaveV4HubRolesProcedureTest is ProceduresBase { AaveV4HubRolesProcedureWrapper public aaveV4HubRolesProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4HubRolesProcedureWrapper = new AaveV4HubRolesProcedureWrapper(); } + + function test_grantHubAdminRole_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4HubRolesProcedureWrapper.grantHubAdminRole({accessManager: address(0), admin: admin}); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') + ); + aaveV4HubRolesProcedureWrapper.grantHubAdminRole({ + accessManager: accessManager, + admin: address(0) + }); + } + + function test_grantHubFeeMinterRole_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4HubRolesProcedureWrapper.grantHubFeeMinterRole({accessManager: address(0), admin: admin}); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') + ); + aaveV4HubRolesProcedureWrapper.grantHubFeeMinterRole({ + accessManager: accessManager, + admin: address(0) + }); + } + + function test_grantHubConfiguratorRole_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4HubRolesProcedureWrapper.grantHubConfiguratorRole({ + accessManager: address(0), + admin: admin + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') + ); + aaveV4HubRolesProcedureWrapper.grantHubConfiguratorRole({ + accessManager: accessManager, + admin: address(0) + }); + } + + function test_setupHubRoles_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4HubRolesProcedureWrapper.setupHubRoles({accessManager: address(0), hub: hub}); + + vm.expectRevert(abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'hub')); + aaveV4HubRolesProcedureWrapper.setupHubRoles({accessManager: accessManager, hub: address(0)}); + } + + function test_setupHubFeeMinterRole_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4HubRolesProcedureWrapper.setupHubFeeMinterRole({accessManager: address(0), hub: hub}); + + vm.expectRevert(abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'hub')); + aaveV4HubRolesProcedureWrapper.setupHubFeeMinterRole({ + accessManager: accessManager, + hub: address(0) + }); + } + + function test_setupHubConfiguratorRole_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4HubRolesProcedureWrapper.setupHubConfiguratorRole({accessManager: address(0), hub: hub}); + + vm.expectRevert(abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'hub')); + aaveV4HubRolesProcedureWrapper.setupHubConfiguratorRole({ + accessManager: accessManager, + hub: address(0) + }); + } + + function test_getHubFeeMinterRoleSelectors() public view { + bytes4[] memory selectors = aaveV4HubRolesProcedureWrapper.getHubFeeMinterRoleSelectors(); + assertEq(selectors.length, 1); + assertEq(selectors[0], IHub.mintFeeShares.selector); + } + + function test_getHubConfiguratorRoleSelectors() public view { + bytes4[] memory selectors = aaveV4HubRolesProcedureWrapper.getHubConfiguratorRoleSelectors(); + assertEq(selectors.length, 5); + assertEq(selectors[0], IHub.addAsset.selector); + assertEq(selectors[1], IHub.updateAssetConfig.selector); + assertEq(selectors[2], IHub.addSpoke.selector); + assertEq(selectors[3], IHub.updateSpokeConfig.selector); + assertEq(selectors[4], IHub.setInterestRateData.selector); + } } diff --git a/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol b/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol index fd74cb524..6c4d6612a 100644 --- a/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol +++ b/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol @@ -8,7 +8,129 @@ contract AaveV4SpokeRolesProcedureTest is ProceduresBase { AaveV4SpokeRolesProcedureWrapper public aaveV4SpokeRolesProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4SpokeRolesProcedureWrapper = new AaveV4SpokeRolesProcedureWrapper(); } + + function test_grantSpokeAdminRole_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4SpokeRolesProcedureWrapper.grantSpokeAdminRole({accessManager: address(0), admin: admin}); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') + ); + aaveV4SpokeRolesProcedureWrapper.grantSpokeAdminRole({ + accessManager: accessManager, + admin: address(0) + }); + } + + function test_grantSpokePositionUpdaterRole_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4SpokeRolesProcedureWrapper.grantSpokePositionUpdaterRole({ + accessManager: address(0), + admin: admin + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') + ); + aaveV4SpokeRolesProcedureWrapper.grantSpokePositionUpdaterRole({ + accessManager: accessManager, + admin: address(0) + }); + } + + function test_grantSpokeConfiguratorRole_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4SpokeRolesProcedureWrapper.grantSpokeConfiguratorRole({ + accessManager: address(0), + admin: admin + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') + ); + aaveV4SpokeRolesProcedureWrapper.grantSpokeConfiguratorRole({ + accessManager: accessManager, + admin: address(0) + }); + } + + function test_setupSpokeRoles_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4SpokeRolesProcedureWrapper.setupSpokeRoles({accessManager: address(0), spoke: spoke}); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'spoke') + ); + aaveV4SpokeRolesProcedureWrapper.setupSpokeRoles({ + accessManager: accessManager, + spoke: address(0) + }); + } + + function test_setupSpokePositionUpdaterRole_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4SpokeRolesProcedureWrapper.setupSpokePositionUpdaterRole({ + accessManager: address(0), + spoke: spoke + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'spoke') + ); + aaveV4SpokeRolesProcedureWrapper.setupSpokePositionUpdaterRole({ + accessManager: accessManager, + spoke: address(0) + }); + } + + function test_setupSpokeConfiguratorRole_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4SpokeRolesProcedureWrapper.setupSpokeConfiguratorRole({ + accessManager: address(0), + spoke: spoke + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'spoke') + ); + aaveV4SpokeRolesProcedureWrapper.setupSpokeConfiguratorRole({ + accessManager: accessManager, + spoke: address(0) + }); + } + + function test_getSpokePositionUpdaterRoleSelectors() public view { + bytes4[] memory selectors = aaveV4SpokeRolesProcedureWrapper + .getSpokePositionUpdaterRoleSelectors(); + assertEq(selectors.length, 2); + assertEq(selectors[0], ISpoke.updateUserDynamicConfig.selector); + assertEq(selectors[1], ISpoke.updateUserRiskPremium.selector); + } + + function test_getSpokeConfiguratorRoleSelectors() public view { + bytes4[] memory selectors = aaveV4SpokeRolesProcedureWrapper + .getSpokeConfiguratorRoleSelectors(); + assertEq(selectors.length, 7); + assertEq(selectors[0], ISpoke.updateLiquidationConfig.selector); + assertEq(selectors[1], ISpoke.addReserve.selector); + assertEq(selectors[2], ISpoke.updateReserveConfig.selector); + assertEq(selectors[3], ISpoke.updateDynamicReserveConfig.selector); + assertEq(selectors[4], ISpoke.addDynamicReserveConfig.selector); + assertEq(selectors[5], ISpoke.updatePositionManager.selector); + assertEq(selectors[6], ISpoke.updateReservePriceSource.selector); + } } diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol index 8b03860d5..3db5f6f11 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol @@ -8,7 +8,6 @@ contract AaveV4AaveOracleDeployProcedureTest is ProceduresBase { AaveV4AaveOracleDeployProcedureWrapper public aaveV4AaveOracleDeployProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4AaveOracleDeployProcedureWrapper = new AaveV4AaveOracleDeployProcedureWrapper(); } @@ -22,4 +21,33 @@ contract AaveV4AaveOracleDeployProcedureTest is ProceduresBase { assertEq(IAaveOracle(aaveOracle).DECIMALS(), oracleDecimals); assertEq(IAaveOracle(aaveOracle).DESCRIPTION(), oracleDescription); } + + function test_deployAaveOracle_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'spoke') + ); + aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle({ + spoke: address(0), + decimals: oracleDecimals, + description: oracleDescription + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'oracle decimals') + ); + aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle({ + spoke: spoke, + decimals: 0, + description: oracleDescription + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'oracle description') + ); + aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle({ + spoke: spoke, + decimals: oracleDecimals, + description: '' + }); + } } diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol index f6f8be75f..3f65a8935 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol @@ -4,12 +4,11 @@ pragma solidity ^0.8.0; import 'tests/deployments/procedures/ProceduresBase.t.sol'; -contract AaveV4SpokeConfiguratorDeployProcedureTestTest is ProceduresBase { +contract AaveV4SpokeConfiguratorDeployProcedureTest is ProceduresBase { AaveV4SpokeConfiguratorDeployProcedureWrapper public aaveV4SpokeConfiguratorDeployProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4SpokeConfiguratorDeployProcedureWrapper = new AaveV4SpokeConfiguratorDeployProcedureWrapper(); } @@ -19,4 +18,11 @@ contract AaveV4SpokeConfiguratorDeployProcedureTestTest is ProceduresBase { assertNotEq(spokeConfigurator, address(0)); assertEq(Ownable(spokeConfigurator).owner(), owner); } + + function test_deploySpokeConfigurator_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); + aaveV4SpokeConfiguratorDeployProcedureWrapper.deploySpokeConfigurator(address(0)); + } } diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol index ef5729356..619a9e402 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol @@ -8,7 +8,6 @@ contract AaveV4SpokeDeployProcedureTest is ProceduresBase { AaveV4SpokeDeployProcedureWrapper public aaveV4SpokeDeployProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4SpokeDeployProcedureWrapper = new AaveV4SpokeDeployProcedureWrapper(); } @@ -21,4 +20,36 @@ contract AaveV4SpokeDeployProcedureTest is ProceduresBase { assertEq(ProxyHelper.getImplementation(spokeProxy), spokeImplementation); assertEq(ISpoke(spokeProxy).ORACLE(), aaveOracle); } + + function test_deployUpgradableSpokeInstance_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector( + AaveV4DeployProcedureBase.InvalidParam.selector, + 'spoke proxy admin owner' + ) + ); + aaveV4SpokeDeployProcedureWrapper.deployUpgradableSpokeInstance({ + spokeProxyAdminOwner: address(0), + accessManager: accessManager, + oracle: aaveOracle + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') + ); + aaveV4SpokeDeployProcedureWrapper.deployUpgradableSpokeInstance({ + spokeProxyAdminOwner: owner, + accessManager: address(0), + oracle: aaveOracle + }); + + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'oracle') + ); + aaveV4SpokeDeployProcedureWrapper.deployUpgradableSpokeInstance({ + spokeProxyAdminOwner: owner, + accessManager: accessManager, + oracle: address(0) + }); + } } diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol index e1c0c4f2a..30ed9275d 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol @@ -3,15 +3,11 @@ pragma solidity ^0.8.0; import 'tests/deployments/procedures/ProceduresBase.t.sol'; -import { - AaveV4TreasurySpokeDeployProcedureWrapper -} from 'tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol'; contract AaveV4TreasurySpokeDeployProcedureTest is ProceduresBase { AaveV4TreasurySpokeDeployProcedureWrapper public aaveV4TreasurySpokeDeployProcedureWrapper; function setUp() public override { super.setUp(); - aaveV4TreasurySpokeDeployProcedureWrapper = new AaveV4TreasurySpokeDeployProcedureWrapper(); } @@ -24,4 +20,14 @@ contract AaveV4TreasurySpokeDeployProcedureTest is ProceduresBase { assertEq(Ownable(treasurySpoke).owner(), owner); assertEq(address(ITreasurySpoke(treasurySpoke).HUB()), hub); } + + function test_deployTreasurySpoke_revertsWithInvalidParam() public { + vm.expectRevert( + abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') + ); + aaveV4TreasurySpokeDeployProcedureWrapper.deployTreasurySpoke({owner: address(0), hub: hub}); + + vm.expectRevert(abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'hub')); + aaveV4TreasurySpokeDeployProcedureWrapper.deployTreasurySpoke({owner: owner, hub: address(0)}); + } } diff --git a/tests/mocks/GatewayBaseWrapper.sol b/tests/mocks/GatewayBaseWrapper.sol index e35515108..5821be244 100644 --- a/tests/mocks/GatewayBaseWrapper.sol +++ b/tests/mocks/GatewayBaseWrapper.sol @@ -5,5 +5,7 @@ pragma solidity 0.8.28; import {GatewayBase} from 'src/position-manager/GatewayBase.sol'; contract GatewayBaseWrapper is GatewayBase { + bool public IS_TEST = true; + constructor(address initialOwner_) GatewayBase(initialOwner_) {} } diff --git a/tests/mocks/LiquidationLogicWrapper.sol b/tests/mocks/LiquidationLogicWrapper.sol index 8a765e6be..3a06ef84c 100644 --- a/tests/mocks/LiquidationLogicWrapper.sol +++ b/tests/mocks/LiquidationLogicWrapper.sol @@ -12,6 +12,8 @@ import {LiquidationLogic} from 'src/spoke/libraries/LiquidationLogic.sol'; import {ReserveFlags, ReserveFlagsMap} from 'src/spoke/libraries/ReserveFlagsMap.sol'; contract LiquidationLogicWrapper { + bool public IS_TEST = true; + using SafeCast for *; using SafeERC20 for IERC20; using PositionStatusMap for ISpoke.PositionStatus; diff --git a/tests/mocks/deployments/AaveV4AaveOracleDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4AaveOracleDeployProcedureWrapper.sol similarity index 94% rename from tests/mocks/deployments/AaveV4AaveOracleDeployProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4AaveOracleDeployProcedureWrapper.sol index cfe50bdf1..64b728e5c 100644 --- a/tests/mocks/deployments/AaveV4AaveOracleDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4AaveOracleDeployProcedureWrapper.sol @@ -7,6 +7,8 @@ import { } from 'src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol'; contract AaveV4AaveOracleDeployProcedureWrapper is AaveV4AaveOracleDeployProcedure { + bool public IS_TEST = true; + function deployAaveOracle( address spoke, uint8 decimals, diff --git a/tests/mocks/deployments/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol similarity index 94% rename from tests/mocks/deployments/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol index 02c4d72d6..5a76d95b6 100644 --- a/tests/mocks/deployments/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol @@ -9,6 +9,7 @@ import { contract AaveV4AccessManagerEnumerableDeployProcedureWrapper is AaveV4AccessManagerEnumerableDeployProcedure { + bool public IS_TEST = true; function deployAccessManagerEnumerable(address admin) external returns (address) { return _deployAccessManagerEnumerable(admin); } diff --git a/tests/mocks/deployments/AaveV4AccessManagerRolesProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4AccessManagerRolesProcedureWrapper.sol similarity index 71% rename from tests/mocks/deployments/AaveV4AccessManagerRolesProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4AccessManagerRolesProcedureWrapper.sol index 8314adcd7..994fac71e 100644 --- a/tests/mocks/deployments/AaveV4AccessManagerRolesProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4AccessManagerRolesProcedureWrapper.sol @@ -7,11 +7,17 @@ import { } from 'src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol'; contract AaveV4AccessManagerRolesProcedureWrapper { + bool public IS_TEST = true; + function grantRootAdminRole( address accessManager, address adminToAdd, address adminToRemove ) external { - AaveV4AccessManagerRolesProcedure.grantRootAdminRole(accessManager, adminToAdd, adminToRemove); + AaveV4AccessManagerRolesProcedure.replaceDefaultAdminRole( + accessManager, + adminToAdd, + adminToRemove + ); } } diff --git a/tests/mocks/deployments/AaveV4HubConfiguratorDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4HubConfiguratorDeployProcedureWrapper.sol similarity index 93% rename from tests/mocks/deployments/AaveV4HubConfiguratorDeployProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4HubConfiguratorDeployProcedureWrapper.sol index 34120441c..f76b0462a 100644 --- a/tests/mocks/deployments/AaveV4HubConfiguratorDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4HubConfiguratorDeployProcedureWrapper.sol @@ -7,6 +7,8 @@ import { } from 'src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol'; contract AaveV4HubConfiguratorDeployProcedureWrapper is AaveV4HubConfiguratorDeployProcedure { + bool public IS_TEST = true; + function deployHubConfigurator(address owner) external returns (address) { return _deployHubConfigurator(owner); } diff --git a/tests/mocks/deployments/AaveV4HubDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4HubDeployProcedureWrapper.sol similarity index 92% rename from tests/mocks/deployments/AaveV4HubDeployProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4HubDeployProcedureWrapper.sol index c06b41dac..d907be8ad 100644 --- a/tests/mocks/deployments/AaveV4HubDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4HubDeployProcedureWrapper.sol @@ -7,6 +7,8 @@ import { } from 'src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol'; contract AaveV4HubDeployProcedureWrapper is AaveV4HubDeployProcedure { + bool public IS_TEST = true; + function deployHub(address accessManager) external returns (address) { return _deployHub(accessManager); } diff --git a/tests/mocks/deployments/AaveV4HubRolesProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4HubRolesProcedureWrapper.sol similarity index 97% rename from tests/mocks/deployments/AaveV4HubRolesProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4HubRolesProcedureWrapper.sol index 035675f40..17b3a8d5c 100644 --- a/tests/mocks/deployments/AaveV4HubRolesProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4HubRolesProcedureWrapper.sol @@ -7,6 +7,8 @@ import { } from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; contract AaveV4HubRolesProcedureWrapper { + bool public IS_TEST = true; + function grantHubAdminRole(address accessManager, address admin) external { AaveV4HubRolesProcedure.grantHubAdminRole(accessManager, admin); } diff --git a/tests/mocks/deployments/AaveV4InterestRateStrategyDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4InterestRateStrategyDeployProcedureWrapper.sol similarity index 93% rename from tests/mocks/deployments/AaveV4InterestRateStrategyDeployProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4InterestRateStrategyDeployProcedureWrapper.sol index db7fbcaa5..dcbdfcecc 100644 --- a/tests/mocks/deployments/AaveV4InterestRateStrategyDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4InterestRateStrategyDeployProcedureWrapper.sol @@ -9,6 +9,8 @@ import { contract AaveV4InterestRateStrategyDeployProcedureWrapper is AaveV4InterestRateStrategyDeployProcedure { + bool public IS_TEST = true; + function deployInterestRateStrategy(address hub) external returns (address) { return _deployInterestRateStrategy(hub); } diff --git a/tests/mocks/deployments/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol similarity index 94% rename from tests/mocks/deployments/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol index 8b4dd92f0..0925ab00e 100644 --- a/tests/mocks/deployments/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol @@ -7,6 +7,8 @@ import { } from 'src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol'; contract AaveV4NativeTokenGatewayDeployProcedureWrapper is AaveV4NativeTokenGatewayDeployProcedure { + bool public IS_TEST = true; + function deployNativeTokenGateway( address nativeWrapper, address owner diff --git a/tests/mocks/deployments/AaveV4SignatureGatewayDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4SignatureGatewayDeployProcedureWrapper.sol similarity index 93% rename from tests/mocks/deployments/AaveV4SignatureGatewayDeployProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4SignatureGatewayDeployProcedureWrapper.sol index f43f808fe..65d4f514c 100644 --- a/tests/mocks/deployments/AaveV4SignatureGatewayDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4SignatureGatewayDeployProcedureWrapper.sol @@ -7,6 +7,8 @@ import { } from 'src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol'; contract AaveV4SignatureGatewayDeployProcedureWrapper is AaveV4SignatureGatewayDeployProcedure { + bool public IS_TEST = true; + function deploySignatureGateway(address owner) external returns (address) { return _deploySignatureGateway(owner); } diff --git a/tests/mocks/deployments/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol similarity index 93% rename from tests/mocks/deployments/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol index d80b690df..9f6cddd69 100644 --- a/tests/mocks/deployments/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol @@ -7,6 +7,8 @@ import { } from 'src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol'; contract AaveV4SpokeConfiguratorDeployProcedureWrapper is AaveV4SpokeConfiguratorDeployProcedure { + bool public IS_TEST = true; + function deploySpokeConfigurator(address owner) external returns (address) { return _deploySpokeConfigurator(owner); } diff --git a/tests/mocks/deployments/AaveV4SpokeDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4SpokeDeployProcedureWrapper.sol similarity index 94% rename from tests/mocks/deployments/AaveV4SpokeDeployProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4SpokeDeployProcedureWrapper.sol index a321081af..5773cdf65 100644 --- a/tests/mocks/deployments/AaveV4SpokeDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4SpokeDeployProcedureWrapper.sol @@ -7,6 +7,8 @@ import { } from 'src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol'; contract AaveV4SpokeDeployProcedureWrapper is AaveV4SpokeDeployProcedure { + bool public IS_TEST = true; + function deployUpgradableSpokeInstance( address spokeProxyAdminOwner, address accessManager, diff --git a/tests/mocks/deployments/AaveV4SpokeRolesProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4SpokeRolesProcedureWrapper.sol similarity index 96% rename from tests/mocks/deployments/AaveV4SpokeRolesProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4SpokeRolesProcedureWrapper.sol index 6a65e6d2a..93d95e363 100644 --- a/tests/mocks/deployments/AaveV4SpokeRolesProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4SpokeRolesProcedureWrapper.sol @@ -7,11 +7,13 @@ import { } from 'src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol'; contract AaveV4SpokeRolesProcedureWrapper { + bool public IS_TEST = true; + function grantSpokeAdminRole(address accessManager, address admin) external { AaveV4SpokeRolesProcedure.grantSpokeAdminRole(accessManager, admin); } - function grantSpokePositionUpdaterRole(address accessManager, address admin) internal { + function grantSpokePositionUpdaterRole(address accessManager, address admin) external { AaveV4SpokeRolesProcedure.grantSpokePositionUpdaterRole(accessManager, admin); } diff --git a/tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4TreasurySpokeDeployProcedureWrapper.sol similarity index 93% rename from tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol rename to tests/mocks/deployments/procedures/AaveV4TreasurySpokeDeployProcedureWrapper.sol index f89728c47..8632629c0 100644 --- a/tests/mocks/deployments/AaveV4TreasurySpokeDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4TreasurySpokeDeployProcedureWrapper.sol @@ -7,6 +7,8 @@ import { } from 'src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol'; contract AaveV4TreasurySpokeDeployProcedureWrapper is AaveV4TreasurySpokeDeployProcedure { + bool public IS_TEST = true; + function deployTreasurySpoke(address owner, address hub) external returns (address) { return _deployTreasurySpoke(owner, hub); } diff --git a/tests/scripts/AaveV4DeployBatchBaseScript.t.sol b/tests/scripts/AaveV4DeployBatchBaseScript.t.sol new file mode 100644 index 000000000..01de665f7 --- /dev/null +++ b/tests/scripts/AaveV4DeployBatchBaseScript.t.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Test} from 'forge-std/Test.sol'; +import {AaveV4DeployBatchBaseScript} from 'scripts/deploy/AaveV4DeployBatchBase.s.sol'; +import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; +import {MetadataLogger} from 'src/deployments/utils/MetadataLogger.sol'; + +// contract AaveV4DeployBatchBaseScriptHarness is AaveV4DeployBatchBaseScript { +// string public recordedWarnings; +// bool public promptCalled; + +// constructor() AaveV4DeployBatchBaseScript('in.json', 'out.json') {} + +// function exposedSanitize( +// InputUtils.FullDeployInputs memory inputs, +// address deployer +// ) external view returns (InputUtils.FullDeployInputs memory) { +// return _sanitizeInputs(inputs, deployer); +// } + +// function exposedLoadWarnings( +// InputUtils.FullDeployInputs memory inputs +// ) external returns (string memory warnings, bool promptWasCalled) { +// MetadataLogger logger = new MetadataLogger('output/'); +// recordedWarnings = ''; +// promptCalled = false; +// _loadWarnings(logger, inputs); +// return (recordedWarnings, promptCalled); +// } + +// function _logAndAppend( +// MetadataLogger, +// string memory warnings, +// string memory warning +// ) internal virtual override returns (string memory) { +// recordedWarnings = string.concat(warnings, warning, '\n'); +// return recordedWarnings; +// } + +// function _executeUserPrompt(string memory warnings) internal virtual override { +// promptCalled = true; +// recordedWarnings = warnings; +// } +// } + +// contract AaveV4DeployBatchBaseScriptTest is Test { +// AaveV4DeployBatchBaseScriptHarness internal harness; + +// function setUp() public { +// harness = new AaveV4DeployBatchBaseScriptHarness(); +// } + +// function _nonEmptyLabels() internal pure returns (string[] memory hubLabels, string[] memory spokeLabels) { +// hubLabels = new string[](1); +// hubLabels[0] = 'hub'; +// spokeLabels = new string[](1); +// spokeLabels[0] = 'spoke'; +// } + +// function test_sanitize_defaultsZeroAddressesToDeployer() public { +// (string[] memory hubLabels, string[] memory spokeLabels) = _nonEmptyLabels(); +// InputUtils.FullDeployInputs memory inputs = InputUtils.FullDeployInputs({ +// accessManagerAdmin: address(0), +// hubAdmin: address(0), +// hubConfiguratorOwner: address(0), +// treasurySpokeOwner: address(0), +// spokeAdmin: address(0), +// spokeProxyAdminOwner: address(0), +// spokeConfiguratorOwner: address(0), +// gatewayOwner: address(0), +// nativeWrapper: address(1), +// grantRoles: true, +// hubLabels: hubLabels, +// spokeLabels: spokeLabels +// }); +// address deployer = address(0xBEEF); + +// InputUtils.FullDeployInputs memory sanitized = harness.exposedSanitize(inputs, deployer); + +// assertEq(sanitized.accessManagerAdmin, deployer); +// assertEq(sanitized.hubConfiguratorOwner, deployer); +// assertEq(sanitized.treasurySpokeOwner, deployer); +// assertEq(sanitized.spokeProxyAdminOwner, deployer); +// assertEq(sanitized.spokeConfiguratorOwner, deployer); +// assertEq(sanitized.gatewayOwner, deployer); +// // untouched fields +// assertEq(sanitized.nativeWrapper, inputs.nativeWrapper); +// assertEq(sanitized.hubAdmin, inputs.hubAdmin); +// assertEq(sanitized.spokeAdmin, inputs.spokeAdmin); +// } + +// function test_sanitize_preservesNonZero() public { +// (string[] memory hubLabels, string[] memory spokeLabels) = _nonEmptyLabels(); +// InputUtils.FullDeployInputs memory inputs = InputUtils.FullDeployInputs({ +// accessManagerAdmin: address(1), +// hubAdmin: address(2), +// hubConfiguratorOwner: address(3), +// treasurySpokeOwner: address(4), +// spokeAdmin: address(5), +// spokeProxyAdminOwner: address(6), +// spokeConfiguratorOwner: address(7), +// gatewayOwner: address(8), +// nativeWrapper: address(9), +// grantRoles: true, +// hubLabels: hubLabels, +// spokeLabels: spokeLabels +// }); + +// InputUtils.FullDeployInputs memory sanitized = harness.exposedSanitize(inputs, address(0xBEEF)); + +// assertEq(sanitized.accessManagerAdmin, inputs.accessManagerAdmin); +// assertEq(sanitized.hubConfiguratorOwner, inputs.hubConfiguratorOwner); +// assertEq(sanitized.treasurySpokeOwner, inputs.treasurySpokeOwner); +// assertEq(sanitized.spokeProxyAdminOwner, inputs.spokeProxyAdminOwner); +// assertEq(sanitized.spokeConfiguratorOwner, inputs.spokeConfiguratorOwner); +// assertEq(sanitized.gatewayOwner, inputs.gatewayOwner); +// assertEq(sanitized.nativeWrapper, inputs.nativeWrapper); +// } + +// function test_loadWarnings_noWarnings_noPrompt() public { +// (string[] memory hubLabels, string[] memory spokeLabels) = _nonEmptyLabels(); +// InputUtils.FullDeployInputs memory inputs = InputUtils.FullDeployInputs({ +// accessManagerAdmin: address(1), +// hubAdmin: address(2), +// hubConfiguratorOwner: address(3), +// treasurySpokeOwner: address(4), +// spokeAdmin: address(5), +// spokeProxyAdminOwner: address(6), +// spokeConfiguratorOwner: address(7), +// gatewayOwner: address(8), +// nativeWrapper: address(9), +// grantRoles: false, +// hubLabels: hubLabels, +// spokeLabels: spokeLabels +// }); + +// (string memory warnings, bool promptCalled) = harness.exposedLoadWarnings(inputs); + +// assertEq(bytes(warnings).length, 0); +// assertFalse(promptCalled); +// } + +// function test_loadWarnings_withWarnings_triggersPrompt() public { +// string[] memory empty; +// InputUtils.FullDeployInputs memory inputs = InputUtils.FullDeployInputs({ +// accessManagerAdmin: address(0), +// hubAdmin: address(0), +// hubConfiguratorOwner: address(0), +// treasurySpokeOwner: address(0), +// spokeAdmin: address(0), +// spokeProxyAdminOwner: address(0), +// spokeConfiguratorOwner: address(0), +// gatewayOwner: address(0), +// nativeWrapper: address(0), +// grantRoles: true, +// hubLabels: empty, +// spokeLabels: empty +// }); + +// (string memory warnings, bool promptCalled) = harness.exposedLoadWarnings(inputs); + +// assertTrue(promptCalled); +// assertTrue(bytes(warnings).length > 0); +// // Should include at least one known warning +// assertTrue(_contains(warnings, 'Roles are being set')); +// assertTrue(_contains(warnings, 'Spoke will not be deployed')); +// } + +// function _contains(string memory haystack, string memory needle) internal pure returns (bool) { +// return bytes(haystack).length >= bytes(needle).length && +// bytes(haystack).length != 0 && +// bytes(needle).length != 0 && +// _indexOf(haystack, needle) != type(uint256).max; +// } + +// function _indexOf(string memory haystack, string memory needle) internal pure returns (uint256) { +// bytes memory h = bytes(haystack); +// bytes memory n = bytes(needle); +// if (n.length == 0 || n.length > h.length) return type(uint256).max; +// for (uint256 i; i <= h.length - n.length; ++i) { +// bool match = true; +// for (uint256 j; j < n.length; ++j) { +// if (h[i + j] != n[j]) { +// match = false; +// break; +// } +// } +// if (match) return i; +// } +// return type(uint256).max; +// } +// } diff --git a/tests/unit/Hub/Hub.Restore.t.sol b/tests/unit/Hub/Hub.Restore.t.sol index c78db366d..d1180cc4d 100644 --- a/tests/unit/Hub/Hub.Restore.t.sol +++ b/tests/unit/Hub/Hub.Restore.t.sol @@ -10,21 +10,9 @@ contract HubRestoreTest is HubBase { using PercentageMath for uint256; using SafeCast for *; - HubConfigurator public hubConfigurator; - address public HUB_CONFIGURATOR_ADMIN = makeAddr('HUB_CONFIGURATOR_ADMIN'); - - function setUp() public override { - super.setUp(); - - // Set up a hub configurator to test freezing and pausing assets - hubConfigurator = new HubConfigurator(HUB_CONFIGURATOR_ADMIN); - _grantHubConfiguratorRole(hub1, address(hubConfigurator)); - } - function test_restore_revertsWith_SurplusDrawnRestored() public { uint256 daiAmount = 100e18; uint256 wethAmount = 10e18; - uint256 drawAmount = daiAmount / 2; // spoke1 add weth diff --git a/tests/unit/HubConfigurator.t.sol b/tests/unit/HubConfigurator.t.sol index 28a6c0fd5..cbd038d75 100644 --- a/tests/unit/HubConfigurator.t.sol +++ b/tests/unit/HubConfigurator.t.sol @@ -7,9 +7,6 @@ import 'tests/unit/Hub/HubBase.t.sol'; contract HubConfiguratorTest is HubBase { using SafeCast for uint256; - HubConfigurator internal hubConfigurator; - - address internal HUB_CONFIGURATOR_ADMIN = makeAddr('HUB_CONFIGURATOR_ADMIN'); uint256 internal _assetId; bytes internal _encodedIrData; @@ -21,7 +18,6 @@ contract HubConfiguratorTest is HubBase { function setUp() public virtual override { super.setUp(); - hubConfigurator = new HubConfigurator(HUB_CONFIGURATOR_ADMIN); _grantHubConfiguratorRole(hub1, address(hubConfigurator)); _assetId = daiAssetId; _encodedIrData = abi.encode( diff --git a/tests/unit/Spoke/Spoke.Upgradeable.t.sol b/tests/unit/Spoke/Spoke.Upgradeable.t.sol index d8b3612bb..53ead43d6 100644 --- a/tests/unit/Spoke/Spoke.Upgradeable.t.sol +++ b/tests/unit/Spoke/Spoke.Upgradeable.t.sol @@ -89,6 +89,9 @@ contract SpokeUpgradeableTest is SpokeBase { TestTypes.TestEnvReport memory report; report.spokeReports = new TestTypes.TestSpokeReport[](1); report.spokeReports[0].spoke = address(spokeProxy); + report.configuratorReport.hubConfigurator = address(hubConfigurator); + report.configuratorReport.spokeConfigurator = address(spokeConfigurator); + _setupFixturesRoles(report); uint128 targetHealthFactor = 1.05e18; diff --git a/tests/unit/SpokeConfigurator.t.sol b/tests/unit/SpokeConfigurator.t.sol index 5bd959a67..581ec5a25 100644 --- a/tests/unit/SpokeConfigurator.t.sol +++ b/tests/unit/SpokeConfigurator.t.sol @@ -7,9 +7,6 @@ import 'tests/unit/Spoke/SpokeBase.t.sol'; contract SpokeConfiguratorTest is SpokeBase { using SafeCast for uint256; - SpokeConfigurator public spokeConfigurator; - address public SPOKE_CONFIGURATOR_ADMIN = makeAddr('SPOKE_CONFIGURATOR_ADMIN'); - address public spokeAddr; ISpoke public spoke; uint256 public _reserveId; @@ -18,14 +15,10 @@ contract SpokeConfiguratorTest is SpokeBase { function setUp() public virtual override { super.setUp(); - spokeConfigurator = new SpokeConfigurator(SPOKE_CONFIGURATOR_ADMIN); spokeAddr = address(spoke1); spoke = ISpoke(spokeAddr); _reserveId = 0; invalidReserveId = spoke.getReserveCount(); - - // Grant spokeConfigurator spoke admin role - _grantSpokeConfiguratorRole(spoke, address(spokeConfigurator)); } function test_updateReservePriceSource_revertsWith_OwnableUnauthorizedAccount() public { diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 417e5748c..6eb77204f 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -20,12 +20,19 @@ import { import { AaveV4HubRolesProcedure } from 'src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol'; +import {AaveV4TestOrchestration} from 'tests/deployments/orchestration/AaveV4TestOrchestration.sol'; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; + import {Logger} from 'src/deployments/utils/Logger.sol'; import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {OrchestrationReports} from 'src/deployments/libraries/OrchestrationReports.sol'; import {Constants} from 'tests/Constants.sol'; +// libraries import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; +import {ProxyHelper} from 'tests/utils/ProxyHelper.sol'; + +// interfaces import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; import {IAssetInterestRateStrategy} from 'src/hub/interfaces/IAssetInterestRateStrategy.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; @@ -33,32 +40,40 @@ import {IHub} from 'src/hub/interfaces/IHub.sol'; import {ITreasurySpoke} from 'src/spoke/interfaces/ITreasurySpoke.sol'; import {IAaveOracle} from 'src/spoke/interfaces/IAaveOracle.sol'; -import {ProxyHelper} from 'tests/utils/ProxyHelper.sol'; -import {AaveV4TestOrchestration} from 'tests/deployments/orchestration/AaveV4TestOrchestration.sol'; - contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { - bytes4[] public spokePositionUpdaterRoleSelectors; - bytes4[] public spokeConfiguratorRoleSelectors; - bytes4[] public hubFeeMinterRoleSelectors; - bytes4[] public hubConfiguratorRoleSelectors; - address public deployer; + Logger internal _logger; + FullDeployInputs internal _inputs; + address internal _weth9; + + string[] internal _hubLabels; + string[] internal _spokeLabels; + bytes4[] internal _spokePositionUpdaterRoleSelectors; + bytes4[] internal _spokeConfiguratorRoleSelectors; + bytes4[] internal _hubFeeMinterRoleSelectors; + bytes4[] internal _hubConfiguratorRoleSelectors; + address internal _deployer = makeAddr('deployer'); function setUp() public virtual { - spokePositionUpdaterRoleSelectors = AaveV4SpokeRolesProcedure + _spokePositionUpdaterRoleSelectors = AaveV4SpokeRolesProcedure .getSpokePositionUpdaterRoleSelectors(); - spokeConfiguratorRoleSelectors = AaveV4SpokeRolesProcedure.getSpokeConfiguratorRoleSelectors(); + _spokeConfiguratorRoleSelectors = AaveV4SpokeRolesProcedure.getSpokeConfiguratorRoleSelectors(); + + _hubFeeMinterRoleSelectors = AaveV4HubRolesProcedure.getHubFeeMinterRoleSelectors(); + _hubConfiguratorRoleSelectors = AaveV4HubRolesProcedure.getHubConfiguratorRoleSelectors(); - hubFeeMinterRoleSelectors = AaveV4HubRolesProcedure.getHubFeeMinterRoleSelectors(); - hubConfiguratorRoleSelectors = AaveV4HubRolesProcedure.getHubConfiguratorRoleSelectors(); + _weth9 = _deployWETH(); + _logger = new Logger('dummy/path'); + _hubLabels = ['hub1', 'hub2', 'hub3']; + _spokeLabels = ['spoke1', 'spoke2', 'spoke3']; } - function checkedV4Deployment(Logger logger, FullDeployInputs memory inputs) public { - vm.startPrank(deployer); + function checkedV4Deployment() public { + vm.startPrank(_deployer); OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration - .deployAaveV4(logger, deployer, inputs); + .deployAaveV4(_logger, _deployer, _inputs); vm.stopPrank(); - _checkDeployment(report, inputs); - _checkRoles(report, inputs); + _checkDeployment(report, _inputs); + _checkRoles(report, _inputs); } function _checkDeployment( @@ -90,22 +105,22 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ) internal view returns (FullDeployInputs memory) { inputs.accessManagerAdmin = inputs.accessManagerAdmin != address(0) ? inputs.accessManagerAdmin - : deployer; - inputs.hubAdmin = inputs.hubAdmin != address(0) ? inputs.hubAdmin : deployer; + : _deployer; + inputs.hubAdmin = inputs.hubAdmin != address(0) ? inputs.hubAdmin : _deployer; inputs.hubConfiguratorOwner = inputs.hubConfiguratorOwner != address(0) ? inputs.hubConfiguratorOwner - : deployer; + : _deployer; inputs.treasurySpokeOwner = inputs.treasurySpokeOwner != address(0) ? inputs.treasurySpokeOwner - : deployer; - inputs.spokeAdmin = inputs.spokeAdmin != address(0) ? inputs.spokeAdmin : deployer; + : _deployer; + inputs.spokeAdmin = inputs.spokeAdmin != address(0) ? inputs.spokeAdmin : _deployer; inputs.spokeProxyAdminOwner = inputs.spokeProxyAdminOwner != address(0) ? inputs.spokeProxyAdminOwner - : deployer; + : _deployer; inputs.spokeConfiguratorOwner = inputs.spokeConfiguratorOwner != address(0) ? inputs.spokeConfiguratorOwner - : deployer; - inputs.gatewayOwner = inputs.gatewayOwner != address(0) ? inputs.gatewayOwner : deployer; + : _deployer; + inputs.gatewayOwner = inputs.gatewayOwner != address(0) ? inputs.gatewayOwner : _deployer; return inputs; } @@ -262,7 +277,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ) internal view { address expectedAdmin = (inputs.grantRoles && inputs.accessManagerAdmin != address(0)) ? inputs.accessManagerAdmin - : deployer; + : _deployer; assertEq( accessManager.getRoleMember(Roles.DEFAULT_ADMIN_ROLE, 0), expectedAdmin, @@ -317,11 +332,11 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { } for (uint256 i = 0; i < inputs.spokeLabels.length; i++) { - for (uint256 j = 0; j < spokeConfiguratorRoleSelectors.length; j++) { + for (uint256 j = 0; j < _spokeConfiguratorRoleSelectors.length; j++) { assertEq( accessManager.getTargetFunctionRole( report.spokeInstanceBatchReports[i].report.spokeProxy, - spokeConfiguratorRoleSelectors[j] + _spokeConfiguratorRoleSelectors[j] ), Roles.SPOKE_CONFIGURATOR_ROLE, 'SpokeConfiguratorRole target function' @@ -330,7 +345,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { (bool allowed, uint32 delay) = accessManager.canCall( report.configuratorBatchReport.spokeConfigurator, report.spokeInstanceBatchReports[i].report.spokeProxy, - spokeConfiguratorRoleSelectors[j] + _spokeConfiguratorRoleSelectors[j] ); assertEq( allowed, @@ -343,7 +358,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { (allowed, delay) = accessManager.canCall( inputs.spokeAdmin, report.spokeInstanceBatchReports[i].report.spokeProxy, - spokeConfiguratorRoleSelectors[j] + _spokeConfiguratorRoleSelectors[j] ); assertEq( allowed, @@ -389,11 +404,11 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { string.concat(inputs.spokeLabels[i], ' proxy admin owner') ); - for (uint256 j = 0; j < spokePositionUpdaterRoleSelectors.length; j++) { + for (uint256 j = 0; j < _spokePositionUpdaterRoleSelectors.length; j++) { (bool allowed, uint32 delay) = accessManager.canCall( inputs.spokeAdmin, report.spokeInstanceBatchReports[i].report.spokeProxy, - spokePositionUpdaterRoleSelectors[j] + _spokePositionUpdaterRoleSelectors[j] ); assertEq(allowed, inputs.grantRoles ? true : false, 'SpokeAdminRole allowed'); assertEq(delay, 0, 'SpokeAdminRole delay'); @@ -401,7 +416,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { assertEq( accessManager.getTargetFunctionRole( report.spokeInstanceBatchReports[i].report.spokeProxy, - spokePositionUpdaterRoleSelectors[j] + _spokePositionUpdaterRoleSelectors[j] ), Roles.SPOKE_POSITION_UPDATER_ROLE, 'SpokeAdminRole target function' @@ -440,11 +455,11 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { inputs, inputs.hubLabels[i] ); - for (uint256 j = 0; j < hubFeeMinterRoleSelectors.length; j++) { + for (uint256 j = 0; j < _hubFeeMinterRoleSelectors.length; j++) { assertEq( accessManager.getTargetFunctionRole( report.hubBatchReports[i].report.hub, - hubFeeMinterRoleSelectors[j] + _hubFeeMinterRoleSelectors[j] ), Roles.HUB_FEE_MINTER_ROLE, 'HubAdminRole target function' @@ -453,7 +468,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { (bool allowed, uint32 delay) = accessManager.canCall( inputs.hubAdmin, report.hubBatchReports[i].report.hub, - hubFeeMinterRoleSelectors[j] + _hubFeeMinterRoleSelectors[j] ); assertEq(allowed, inputs.grantRoles ? true : false, 'HubAdminRole allowed'); assertEq(delay, 0, 'HubAdminRole delay'); @@ -502,11 +517,11 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { ); } for (uint256 i = 0; i < inputs.hubLabels.length; i++) { - for (uint256 j = 0; j < hubConfiguratorRoleSelectors.length; j++) { + for (uint256 j = 0; j < _hubConfiguratorRoleSelectors.length; j++) { assertEq( accessManager.getTargetFunctionRole( report.hubBatchReports[i].report.hub, - hubConfiguratorRoleSelectors[j] + _hubConfiguratorRoleSelectors[j] ), Roles.HUB_CONFIGURATOR_ROLE, 'HubConfiguratorRole target function' @@ -517,7 +532,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { (allowed, delay) = accessManager.canCall( report.configuratorBatchReport.hubConfigurator, report.hubBatchReports[i].report.hub, - hubConfiguratorRoleSelectors[j] + _hubConfiguratorRoleSelectors[j] ); assertEq( allowed, @@ -529,7 +544,7 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { (allowed, delay) = accessManager.canCall( inputs.hubAdmin, report.hubBatchReports[i].report.hub, - hubConfiguratorRoleSelectors[j] + _hubConfiguratorRoleSelectors[j] ); assertEq(allowed, inputs.grantRoles ? true : false, 'HubConfiguratorRole allowed - admin'); assertEq(delay, 0, 'HubConfiguratorRole delay - admin'); diff --git a/tests/utils/TestTypes.sol b/tests/utils/TestTypes.sol index 9bd838c77..c0226d145 100644 --- a/tests/utils/TestTypes.sol +++ b/tests/utils/TestTypes.sol @@ -47,11 +47,17 @@ library TestTypes { address nativeGateway; } + struct TestConfiguratorReport { + address hubConfigurator; + address spokeConfigurator; + } + struct TestEnvReport { address accessManager; TestHubReport[] hubReports; TestSpokeReport[] spokeReports; TestGatewaysReport gatewaysReport; + TestConfiguratorReport configuratorReport; } struct TestTokensReport { From 4358d33a5f169bfc85e06d687c0655fff78d63a9 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Tue, 16 Dec 2025 21:13:42 -0600 Subject: [PATCH 54/62] fix: rename validation func --- .../procedures/AaveV4DeployProcedureBase.sol | 2 +- .../AaveV4AccessManagerEnumerableDeployProcedure.sol | 2 +- .../hub/AaveV4HubConfiguratorDeployProcedure.sol | 2 +- .../procedures/deploy/hub/AaveV4HubDeployProcedure.sol | 2 +- .../AaveV4NativeTokenGatewayDeployProcedure.sol | 4 ++-- .../AaveV4SignatureGatewayDeployProcedure.sol | 2 +- .../deploy/spoke/AaveV4AaveOracleDeployProcedure.sol | 2 +- .../spoke/AaveV4SpokeConfiguratorDeployProcedure.sol | 2 +- .../deploy/spoke/AaveV4SpokeDeployProcedure.sol | 6 +++--- .../spoke/AaveV4TreasurySpokeDeployProcedure.sol | 4 ++-- tests/Base.t.sol | 10 +++++----- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/deployments/procedures/AaveV4DeployProcedureBase.sol b/src/deployments/procedures/AaveV4DeployProcedureBase.sol index cd8160b00..505109d97 100644 --- a/src/deployments/procedures/AaveV4DeployProcedureBase.sol +++ b/src/deployments/procedures/AaveV4DeployProcedureBase.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; contract AaveV4DeployProcedureBase { error InvalidParam(string errorMessage); - function _validateAddress(address addr, string memory errorMessage) internal pure { + function _validateZeroAddress(address addr, string memory errorMessage) internal pure { require(addr != address(0), InvalidParam(errorMessage)); } } diff --git a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol index 64096aea0..ec84e2a07 100644 --- a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol @@ -7,7 +7,7 @@ import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4Deploy contract AaveV4AccessManagerEnumerableDeployProcedure is AaveV4DeployProcedureBase { function _deployAccessManagerEnumerable(address admin) internal returns (address) { - _validateAddress(admin, 'admin'); + _validateZeroAddress(admin, 'admin'); return address(new AccessManagerEnumerable({initialAdmin_: admin})); } } diff --git a/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol index d7a47412c..1e7720f38 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol @@ -6,7 +6,7 @@ import {HubConfigurator} from 'src/hub/HubConfigurator.sol'; import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4HubConfiguratorDeployProcedure is AaveV4DeployProcedureBase { function _deployHubConfigurator(address owner) internal returns (address) { - _validateAddress(owner, 'owner'); + _validateZeroAddress(owner, 'owner'); return address(new HubConfigurator({owner_: owner})); } } diff --git a/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol index 51cc9f089..25193c0ac 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol @@ -6,7 +6,7 @@ import {Hub} from 'src/hub/Hub.sol'; import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4HubDeployProcedure is AaveV4DeployProcedureBase { function _deployHub(address accessManager) internal returns (address) { - _validateAddress(accessManager, 'access manager'); + _validateZeroAddress(accessManager, 'access manager'); return address(new Hub({authority_: accessManager})); } } diff --git a/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol index 5577ea77c..b62a59db8 100644 --- a/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol @@ -9,8 +9,8 @@ contract AaveV4NativeTokenGatewayDeployProcedure is AaveV4DeployProcedureBase { address nativeWrapper, address owner ) internal returns (address) { - _validateAddress(nativeWrapper, 'native wrapper'); - _validateAddress(owner, 'owner'); + _validateZeroAddress(nativeWrapper, 'native wrapper'); + _validateZeroAddress(owner, 'owner'); return address(new NativeTokenGateway({nativeWrapper_: nativeWrapper, initialOwner_: owner})); } } diff --git a/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol index 63d88c51d..a016257f6 100644 --- a/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol @@ -6,7 +6,7 @@ import {SignatureGateway} from 'src/position-manager/SignatureGateway.sol'; import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4SignatureGatewayDeployProcedure is AaveV4DeployProcedureBase { function _deploySignatureGateway(address owner) internal returns (address) { - _validateAddress(owner, 'owner'); + _validateZeroAddress(owner, 'owner'); return address(new SignatureGateway({initialOwner_: owner})); } } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol index 3e8aa10ea..dd16ff9ba 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol @@ -10,7 +10,7 @@ contract AaveV4AaveOracleDeployProcedure is AaveV4DeployProcedureBase { uint8 decimals_, string memory description_ ) internal returns (address) { - _validateAddress(spoke_, 'spoke'); + _validateZeroAddress(spoke_, 'spoke'); require(decimals_ > 0, InvalidParam('oracle decimals')); require(bytes(description_).length > 0, InvalidParam('oracle description')); return diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol index 45c96642b..9a57edcad 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol @@ -7,7 +7,7 @@ import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4Deploy contract AaveV4SpokeConfiguratorDeployProcedure is AaveV4DeployProcedureBase { function _deploySpokeConfigurator(address owner) internal returns (address) { - _validateAddress(owner, 'owner'); + _validateZeroAddress(owner, 'owner'); return address(new SpokeConfigurator({owner_: owner})); } } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol index fbd7670e2..9fd51df77 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol @@ -12,9 +12,9 @@ contract AaveV4SpokeDeployProcedure is AaveV4DeployProcedureBase { address accessManager, address oracle ) internal returns (address spokeProxy, address spokeImplementation) { - _validateAddress(spokeProxyAdminOwner, 'spoke proxy admin owner'); - _validateAddress(accessManager, 'access manager'); - _validateAddress(oracle, 'oracle'); + _validateZeroAddress(spokeProxyAdminOwner, 'spoke proxy admin owner'); + _validateZeroAddress(accessManager, 'access manager'); + _validateZeroAddress(oracle, 'oracle'); spokeImplementation = address(new SpokeInstance({oracle_: oracle})); spokeProxy = Utils.proxify( spokeImplementation, diff --git a/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol index 177fc731a..62ead18aa 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol @@ -7,8 +7,8 @@ import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4Deploy contract AaveV4TreasurySpokeDeployProcedure is AaveV4DeployProcedureBase { function _deployTreasurySpoke(address owner, address hub) internal returns (address) { - _validateAddress(owner, 'owner'); - _validateAddress(hub, 'hub'); + _validateZeroAddress(owner, 'owner'); + _validateZeroAddress(hub, 'hub'); return address(new TreasurySpoke({owner_: owner, hub_: hub})); } } diff --git a/tests/Base.t.sol b/tests/Base.t.sol index f69902030..9f52cd463 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -288,6 +288,11 @@ abstract contract Base is BatchTestProcedures { _setupFixtures(); } + function _initEnvironment() internal { + _mintAndApproveTokenList(); + _configureHubsAndSpokes(); + } + function _setupFixtures() internal virtual { TestTypes.TestEnvReport memory report = _deployFixtures({numHubs: 1, numSpokes: 3}); _setupFixturesRoles(report); @@ -361,11 +366,6 @@ abstract contract Base is BatchTestProcedures { IAccessManager(report.accessManager).renounceRole(Roles.DEFAULT_ADMIN_ROLE, address(this)); } - function _initEnvironment() internal { - _mintAndApproveTokenList(); - _configureHubsAndSpokes(); - } - function _initTokenList() internal { TestTypes.TestTokenInput[] memory tokenInputs = new TestTypes.TestTokenInput[](5); tokenInputs[0] = TestTypes.TestTokenInput({ From b3cf5e517c116ef4f042b69ea74feef79ea89995 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Tue, 16 Dec 2025 21:53:27 -0600 Subject: [PATCH 55/62] fix: func names --- tests/Base.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Base.t.sol b/tests/Base.t.sol index 9f52cd463..d16e5e57e 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -490,7 +490,7 @@ abstract contract Base is BatchTestProcedures { ConfigData.UpdateLiquidationConfigParams[] memory liquidationParams, ConfigData.AddReserveParams[] memory reserveParams ) = _getSpokeReserveParams(); - AaveV4TestOrchestration.configureHubsAssets(_getTestAssetParams()); + AaveV4TestOrchestration.configureHubsAssets(_getAddAssetParams()); AaveV4TestOrchestration.configureHubsSpokes(_getAddSpokeParams()); TestTypes.SpokeReserveId[] memory spokeReserveIds = AaveV4TestOrchestration.configureSpokes( liquidationParams, @@ -864,7 +864,7 @@ abstract contract Base is BatchTestProcedures { return (liquidationParams, reserveParams); } - function _getTestAssetParams() internal view returns (ConfigData.AddAssetParams[] memory) { + function _getAddAssetParams() internal view returns (ConfigData.AddAssetParams[] memory) { bytes memory encodedIrData = abi.encode(_defaultIrData); ConfigData.AddAssetParams[] memory assetParams = new ConfigData.AddAssetParams[](6); From 92eab04eaa88652c2adeaf2e7cc7bf39a79d7b27 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Tue, 16 Dec 2025 22:26:41 -0600 Subject: [PATCH 56/62] test: AaveV4DeployBatchBaseScriptTest --- scripts/deploy/AaveV4DeployBatchBase.s.sol | 7 + src/deployments/utils/MetadataLogger.sol | 2 +- tests/deployments/AaveV4BatchDeployment.t.sol | 4 +- .../scripts/AaveV4DeployBatchBaseScript.t.sol | 405 ++++++++++-------- 4 files changed, 228 insertions(+), 190 deletions(-) diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index d69916600..d75e7f086 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -99,6 +99,13 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { ); sanitizedInputs.spokeAdmin = deployer; } + if (inputs.hubAdmin == address(0)) { + _logAndAppend( + logger, + 'WARNING: Hub Admin is zero address; hub admin roles will be granted to deployer by default' + ); + sanitizedInputs.hubAdmin = deployer; + } } if (inputs.hubLabels.length == 0) { _logAndAppend(logger, 'WARNING: Hub will not be deployed'); diff --git a/src/deployments/utils/MetadataLogger.sol b/src/deployments/utils/MetadataLogger.sol index 86c33934c..126b743d4 100644 --- a/src/deployments/utils/MetadataLogger.sol +++ b/src/deployments/utils/MetadataLogger.sol @@ -9,7 +9,7 @@ contract MetadataLogger is Logger { constructor(string memory outputPath_) Logger(outputPath_) {} function writeJsonReportMarket(OrchestrationReports.FullDeploymentReport memory report) public { - _write('AccessBatchReport', report.accessBatchReport.accessManager); + _write('AccessManager', report.accessBatchReport.accessManager); _write('HubConfigurator', report.configuratorBatchReport.hubConfigurator); _write('SpokeConfigurator', report.configuratorBatchReport.spokeConfigurator); diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index 55798b5ef..ae113cd69 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -48,7 +48,7 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { checkedV4Deployment(); } - function testAaveV4BatchDeployment_withZeroAccessManagerAdmin_withRoles_revertsWithAssertionError() + function testAaveV4BatchDeployment_withZeroAccessManagerAdmin_withRoles_revertsWithInvalidParam() public { // only reverts if grantRoles is true, as access manager admin replaces deployer as default admin @@ -131,7 +131,7 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { this.checkedV4Deployment(); } - function testAaveV4BatchDeployment_withZeroSpokeConfiguratorOwner_withoutRoles_revertsWithAssertionError() + function testAaveV4BatchDeployment_withZeroSpokeConfiguratorOwner_withoutRoles_revertsWithInvalidParam() public { _inputs.spokeConfiguratorOwner = address(0); diff --git a/tests/scripts/AaveV4DeployBatchBaseScript.t.sol b/tests/scripts/AaveV4DeployBatchBaseScript.t.sol index 01de665f7..3745c5b15 100644 --- a/tests/scripts/AaveV4DeployBatchBaseScript.t.sol +++ b/tests/scripts/AaveV4DeployBatchBaseScript.t.sol @@ -3,191 +3,222 @@ pragma solidity ^0.8.0; import {Test} from 'forge-std/Test.sol'; import {AaveV4DeployBatchBaseScript} from 'scripts/deploy/AaveV4DeployBatchBase.s.sol'; -import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {MetadataLogger} from 'src/deployments/utils/MetadataLogger.sol'; - -// contract AaveV4DeployBatchBaseScriptHarness is AaveV4DeployBatchBaseScript { -// string public recordedWarnings; -// bool public promptCalled; - -// constructor() AaveV4DeployBatchBaseScript('in.json', 'out.json') {} - -// function exposedSanitize( -// InputUtils.FullDeployInputs memory inputs, -// address deployer -// ) external view returns (InputUtils.FullDeployInputs memory) { -// return _sanitizeInputs(inputs, deployer); -// } - -// function exposedLoadWarnings( -// InputUtils.FullDeployInputs memory inputs -// ) external returns (string memory warnings, bool promptWasCalled) { -// MetadataLogger logger = new MetadataLogger('output/'); -// recordedWarnings = ''; -// promptCalled = false; -// _loadWarnings(logger, inputs); -// return (recordedWarnings, promptCalled); -// } - -// function _logAndAppend( -// MetadataLogger, -// string memory warnings, -// string memory warning -// ) internal virtual override returns (string memory) { -// recordedWarnings = string.concat(warnings, warning, '\n'); -// return recordedWarnings; -// } - -// function _executeUserPrompt(string memory warnings) internal virtual override { -// promptCalled = true; -// recordedWarnings = warnings; -// } -// } - -// contract AaveV4DeployBatchBaseScriptTest is Test { -// AaveV4DeployBatchBaseScriptHarness internal harness; - -// function setUp() public { -// harness = new AaveV4DeployBatchBaseScriptHarness(); -// } - -// function _nonEmptyLabels() internal pure returns (string[] memory hubLabels, string[] memory spokeLabels) { -// hubLabels = new string[](1); -// hubLabels[0] = 'hub'; -// spokeLabels = new string[](1); -// spokeLabels[0] = 'spoke'; -// } - -// function test_sanitize_defaultsZeroAddressesToDeployer() public { -// (string[] memory hubLabels, string[] memory spokeLabels) = _nonEmptyLabels(); -// InputUtils.FullDeployInputs memory inputs = InputUtils.FullDeployInputs({ -// accessManagerAdmin: address(0), -// hubAdmin: address(0), -// hubConfiguratorOwner: address(0), -// treasurySpokeOwner: address(0), -// spokeAdmin: address(0), -// spokeProxyAdminOwner: address(0), -// spokeConfiguratorOwner: address(0), -// gatewayOwner: address(0), -// nativeWrapper: address(1), -// grantRoles: true, -// hubLabels: hubLabels, -// spokeLabels: spokeLabels -// }); -// address deployer = address(0xBEEF); - -// InputUtils.FullDeployInputs memory sanitized = harness.exposedSanitize(inputs, deployer); - -// assertEq(sanitized.accessManagerAdmin, deployer); -// assertEq(sanitized.hubConfiguratorOwner, deployer); -// assertEq(sanitized.treasurySpokeOwner, deployer); -// assertEq(sanitized.spokeProxyAdminOwner, deployer); -// assertEq(sanitized.spokeConfiguratorOwner, deployer); -// assertEq(sanitized.gatewayOwner, deployer); -// // untouched fields -// assertEq(sanitized.nativeWrapper, inputs.nativeWrapper); -// assertEq(sanitized.hubAdmin, inputs.hubAdmin); -// assertEq(sanitized.spokeAdmin, inputs.spokeAdmin); -// } - -// function test_sanitize_preservesNonZero() public { -// (string[] memory hubLabels, string[] memory spokeLabels) = _nonEmptyLabels(); -// InputUtils.FullDeployInputs memory inputs = InputUtils.FullDeployInputs({ -// accessManagerAdmin: address(1), -// hubAdmin: address(2), -// hubConfiguratorOwner: address(3), -// treasurySpokeOwner: address(4), -// spokeAdmin: address(5), -// spokeProxyAdminOwner: address(6), -// spokeConfiguratorOwner: address(7), -// gatewayOwner: address(8), -// nativeWrapper: address(9), -// grantRoles: true, -// hubLabels: hubLabels, -// spokeLabels: spokeLabels -// }); - -// InputUtils.FullDeployInputs memory sanitized = harness.exposedSanitize(inputs, address(0xBEEF)); - -// assertEq(sanitized.accessManagerAdmin, inputs.accessManagerAdmin); -// assertEq(sanitized.hubConfiguratorOwner, inputs.hubConfiguratorOwner); -// assertEq(sanitized.treasurySpokeOwner, inputs.treasurySpokeOwner); -// assertEq(sanitized.spokeProxyAdminOwner, inputs.spokeProxyAdminOwner); -// assertEq(sanitized.spokeConfiguratorOwner, inputs.spokeConfiguratorOwner); -// assertEq(sanitized.gatewayOwner, inputs.gatewayOwner); -// assertEq(sanitized.nativeWrapper, inputs.nativeWrapper); -// } - -// function test_loadWarnings_noWarnings_noPrompt() public { -// (string[] memory hubLabels, string[] memory spokeLabels) = _nonEmptyLabels(); -// InputUtils.FullDeployInputs memory inputs = InputUtils.FullDeployInputs({ -// accessManagerAdmin: address(1), -// hubAdmin: address(2), -// hubConfiguratorOwner: address(3), -// treasurySpokeOwner: address(4), -// spokeAdmin: address(5), -// spokeProxyAdminOwner: address(6), -// spokeConfiguratorOwner: address(7), -// gatewayOwner: address(8), -// nativeWrapper: address(9), -// grantRoles: false, -// hubLabels: hubLabels, -// spokeLabels: spokeLabels -// }); - -// (string memory warnings, bool promptCalled) = harness.exposedLoadWarnings(inputs); - -// assertEq(bytes(warnings).length, 0); -// assertFalse(promptCalled); -// } - -// function test_loadWarnings_withWarnings_triggersPrompt() public { -// string[] memory empty; -// InputUtils.FullDeployInputs memory inputs = InputUtils.FullDeployInputs({ -// accessManagerAdmin: address(0), -// hubAdmin: address(0), -// hubConfiguratorOwner: address(0), -// treasurySpokeOwner: address(0), -// spokeAdmin: address(0), -// spokeProxyAdminOwner: address(0), -// spokeConfiguratorOwner: address(0), -// gatewayOwner: address(0), -// nativeWrapper: address(0), -// grantRoles: true, -// hubLabels: empty, -// spokeLabels: empty -// }); - -// (string memory warnings, bool promptCalled) = harness.exposedLoadWarnings(inputs); - -// assertTrue(promptCalled); -// assertTrue(bytes(warnings).length > 0); -// // Should include at least one known warning -// assertTrue(_contains(warnings, 'Roles are being set')); -// assertTrue(_contains(warnings, 'Spoke will not be deployed')); -// } - -// function _contains(string memory haystack, string memory needle) internal pure returns (bool) { -// return bytes(haystack).length >= bytes(needle).length && -// bytes(haystack).length != 0 && -// bytes(needle).length != 0 && -// _indexOf(haystack, needle) != type(uint256).max; -// } - -// function _indexOf(string memory haystack, string memory needle) internal pure returns (uint256) { -// bytes memory h = bytes(haystack); -// bytes memory n = bytes(needle); -// if (n.length == 0 || n.length > h.length) return type(uint256).max; -// for (uint256 i; i <= h.length - n.length; ++i) { -// bool match = true; -// for (uint256 j; j < n.length; ++j) { -// if (h[i + j] != n[j]) { -// match = false; -// break; -// } -// } -// if (match) return i; -// } -// return type(uint256).max; -// } -// } +import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; +import {WETH9} from 'src/dependencies/weth/WETH9.sol'; + +contract AaveV4DeployBatchBaseScriptHarness is AaveV4DeployBatchBaseScript { + constructor() AaveV4DeployBatchBaseScript('in.json', 'out.json') {} + + function loadWarningsAndSanitizeInputs( + MetadataLogger logger, + InputUtils.FullDeployInputs memory inputs, + address deployer + ) public returns (InputUtils.FullDeployInputs memory) { + return _loadWarningsAndSanitizeInputs(logger, inputs, deployer); + } + + function logAndAppend(MetadataLogger logger, string memory warning) public { + _logAndAppend(logger, warning); + } + + function _executeUserPrompt() internal override {} +} + +contract AaveV4DeployBatchBaseScriptTest is Test { + AaveV4DeployBatchBaseScriptHarness internal _harness; + InputUtils.FullDeployInputs internal _inputs; + MetadataLogger internal _logger; + address internal _deployer; + + function setUp() public { + _harness = new AaveV4DeployBatchBaseScriptHarness(); + + _inputs.hubLabels = ['hub1', 'hub2', 'hub3']; + _inputs.spokeLabels = ['spoke1', 'spoke2', 'spoke3']; + _inputs.accessManagerAdmin = makeAddr('accessManagerAdmin'); + _inputs.hubAdmin = makeAddr('hubAdmin'); + _inputs.hubConfiguratorOwner = makeAddr('hubConfiguratorOwner'); + _inputs.treasurySpokeOwner = makeAddr('treasurySpokeOwner'); + _inputs.spokeAdmin = makeAddr('spokeAdmin'); + _inputs.spokeProxyAdminOwner = makeAddr('spokeProxyAdminOwner'); + _inputs.spokeConfiguratorOwner = makeAddr('spokeConfiguratorOwner'); + _inputs.gatewayOwner = makeAddr('gatewayOwner'); + _inputs.nativeWrapper = address(new WETH9()); + _inputs.grantRoles = true; + + _logger = new MetadataLogger('dummy/path'); + _deployer = makeAddr('deployer'); + } + + function test_loadWarningsAndSanitizeInputs() public { + InputUtils.FullDeployInputs memory expected = _inputs; + InputUtils.FullDeployInputs memory sanitized = _harness.loadWarningsAndSanitizeInputs( + _logger, + _inputs, + _deployer + ); + assertEq(sanitized, expected); + } + + function test_loadWarningsAndSanitizeInputs_withZeroAccessManagerAdmin_fuzz( + bool grantRoles + ) public { + _inputs.accessManagerAdmin = address(0); + _inputs.grantRoles = grantRoles; + InputUtils.FullDeployInputs memory sanitized = _harness.loadWarningsAndSanitizeInputs( + _logger, + _inputs, + _deployer + ); + InputUtils.FullDeployInputs memory expected = _inputs; + if (grantRoles) { + expected.accessManagerAdmin = _deployer; + } + assertEq(sanitized, expected); + } + + function test_loadWarningsAndSanitizeInputs_withZeroHubAdmin_fuzz(bool grantRoles) public { + _inputs.hubAdmin = address(0); + _inputs.grantRoles = grantRoles; + InputUtils.FullDeployInputs memory sanitized = _harness.loadWarningsAndSanitizeInputs( + _logger, + _inputs, + _deployer + ); + InputUtils.FullDeployInputs memory expected = _inputs; + if (grantRoles) { + expected.hubAdmin = _deployer; + } + assertEq(sanitized, expected); + } + + function test_loadWarningsAndSanitizeInputs_withZeroSpokeAdmin_fuzz(bool grantRoles) public { + _inputs.spokeAdmin = address(0); + _inputs.grantRoles = grantRoles; + InputUtils.FullDeployInputs memory sanitized = _harness.loadWarningsAndSanitizeInputs( + _logger, + _inputs, + _deployer + ); + InputUtils.FullDeployInputs memory expected = _inputs; + if (grantRoles) { + expected.spokeAdmin = _deployer; + } + assertEq(sanitized, expected); + } + + function test_loadWarningsAndSanitizeInputs_withZeroHubConfiguratorOwner_fuzz( + bool grantRoles + ) public { + _inputs.hubConfiguratorOwner = address(0); + _inputs.grantRoles = grantRoles; + InputUtils.FullDeployInputs memory sanitized = _harness.loadWarningsAndSanitizeInputs( + _logger, + _inputs, + _deployer + ); + InputUtils.FullDeployInputs memory expected = _inputs; + if (grantRoles) { + expected.hubConfiguratorOwner = _deployer; + } + assertEq(sanitized, expected); + } + + function test_loadWarningsAndSanitizeInputs_withZeroSpokeConfiguratorOwner_fuzz( + bool grantRoles + ) public { + _inputs.spokeConfiguratorOwner = address(0); + _inputs.grantRoles = grantRoles; + InputUtils.FullDeployInputs memory sanitized = _harness.loadWarningsAndSanitizeInputs( + _logger, + _inputs, + _deployer + ); + InputUtils.FullDeployInputs memory expected = _inputs; + if (grantRoles) { + expected.spokeConfiguratorOwner = _deployer; + } + assertEq(sanitized, expected); + } + + function test_loadWarningsAndSanitizeInputs_withZeroSpokeProxyAdminOwner_fuzz( + bool grantRoles + ) public { + _inputs.spokeProxyAdminOwner = address(0); + _inputs.grantRoles = grantRoles; + InputUtils.FullDeployInputs memory sanitized = _harness.loadWarningsAndSanitizeInputs( + _logger, + _inputs, + _deployer + ); + + InputUtils.FullDeployInputs memory expected = _inputs; + if (grantRoles) { + expected.spokeProxyAdminOwner = _deployer; + } + assertEq(sanitized, expected); + } + + function test_loadWarningsAndSanitizeInputs_withZeroTreasurySpokeOwner_fuzz( + bool grantRoles + ) public { + _inputs.treasurySpokeOwner = address(0); + _inputs.grantRoles = grantRoles; + InputUtils.FullDeployInputs memory sanitized = _harness.loadWarningsAndSanitizeInputs( + _logger, + _inputs, + _deployer + ); + InputUtils.FullDeployInputs memory expected = _inputs; + if (grantRoles) { + expected.treasurySpokeOwner = _deployer; + } + assertEq(sanitized, expected); + } + + function test_loadWarningsAndSanitizeInputs_withZeroGatewayOwner_fuzz(bool grantRoles) public { + _inputs.gatewayOwner = address(0); + _inputs.grantRoles = grantRoles; + InputUtils.FullDeployInputs memory sanitized = _harness.loadWarningsAndSanitizeInputs( + _logger, + _inputs, + _deployer + ); + InputUtils.FullDeployInputs memory expected = _inputs; + expected.gatewayOwner = _deployer; + assertEq(sanitized, expected); + } + + function test_loadWarningsAndSanitizeInputs_withZeroNativeWrapper_fuzz(bool grantRoles) public { + _inputs.nativeWrapper = address(0); + _inputs.grantRoles = grantRoles; + InputUtils.FullDeployInputs memory sanitized = _harness.loadWarningsAndSanitizeInputs( + _logger, + _inputs, + _deployer + ); + InputUtils.FullDeployInputs memory expected = _inputs; + expected.nativeWrapper = address(0); + assertEq(sanitized, expected); + } + + function assertEq( + InputUtils.FullDeployInputs memory a, + InputUtils.FullDeployInputs memory b + ) public { + assertEq(a.accessManagerAdmin, b.accessManagerAdmin, 'access manager admin'); + assertEq(a.hubAdmin, b.hubAdmin, 'hub admin'); + assertEq(a.hubConfiguratorOwner, b.hubConfiguratorOwner, 'hub configurator owner'); + assertEq(a.treasurySpokeOwner, b.treasurySpokeOwner, 'treasury spoke owner'); + assertEq(a.spokeProxyAdminOwner, b.spokeProxyAdminOwner, 'spoke proxy admin owner'); + assertEq(a.spokeConfiguratorOwner, b.spokeConfiguratorOwner, 'spoke configurator owner'); + assertEq(a.spokeAdmin, b.spokeAdmin, 'spoke admin'); + assertEq(a.gatewayOwner, b.gatewayOwner, 'gateway owner'); + assertEq(a.nativeWrapper, b.nativeWrapper, 'native wrapper'); + assertEq(a.grantRoles, b.grantRoles, 'grant roles'); + assertEq(a.hubLabels, b.hubLabels, 'hub labels'); + assertEq(a.spokeLabels, b.spokeLabels, 'spoke labels'); + assertEq(abi.encode(a), abi.encode(b)); + } +} From d851888aa0aea66a00e648c1fef59d25d4be5e12 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:30:14 -0600 Subject: [PATCH 57/62] fix: create2 factory; expand and clean up tests --- scripts/deploy/AaveV4DeployBatchBase.s.sol | 58 +++----- snapshots/Hub.Operations.json | 2 +- snapshots/SignatureGateway.Operations.json | 4 +- .../Spoke.Operations.ZeroRiskPremium.json | 2 +- snapshots/Spoke.Operations.json | 2 +- .../batches/AaveV4SpokeInstanceBatch.sol | 18 ++- .../procedures/AaveV4DeployProcedureBase.sol | 3 + .../AaveV4HubConfiguratorDeployProcedure.sol | 11 +- .../deploy/hub/AaveV4HubDeployProcedure.sol | 11 +- ...eV4InterestRateStrategyDeployProcedure.sol | 11 +- ...aveV4NativeTokenGatewayDeployProcedure.sol | 11 +- .../AaveV4SignatureGatewayDeployProcedure.sol | 11 +- .../spoke/AaveV4AaveOracleDeployProcedure.sol | 1 + ...AaveV4SpokeConfiguratorDeployProcedure.sol | 11 +- .../spoke/AaveV4SpokeDeployProcedure.sol | 39 ++++- src/deployments/utils/InputUtils.sol | 7 + src/deployments/utils/Logger.sol | 5 +- .../utils/libraries/Create2Utils.sol | 83 +++++++++++ src/deployments/utils/libraries/Utils.sol | 29 ---- tests/Base.t.sol | 1 + .../procedures/ProceduresBase.t.sol | 5 +- .../utils/libraries/Create2Utils.t.sol | 133 ++++++++++++++++++ tests/deployments/utils/libraries/Utils.t.sol | 15 -- .../libraries/Create2UtilsWrapper.sol | 50 +++++++ .../scripts/AaveV4DeployBatchBaseScript.t.sol | 2 +- tests/utils/BatchTestProcedures.sol | 2 + 26 files changed, 417 insertions(+), 110 deletions(-) create mode 100644 src/deployments/utils/libraries/Create2Utils.sol delete mode 100644 src/deployments/utils/libraries/Utils.sol create mode 100644 tests/deployments/utils/libraries/Create2Utils.t.sol delete mode 100644 tests/deployments/utils/libraries/Utils.t.sol create mode 100644 tests/mocks/deployments/libraries/Create2UtilsWrapper.sol diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index d75e7f086..92755bdae 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -36,6 +36,7 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { (, address deployer, ) = vm.readCallers(); inputs = _loadWarningsAndSanitizeInputs(logger, inputs, deployer); + logger.log('CHAIN ID = ', block.chainid); logger.log('...Starting Aave V4 Batch Deployment...'); vm.startBroadcast(deployer); OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration @@ -52,84 +53,69 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { FullDeployInputs memory inputs, address deployer ) internal virtual returns (FullDeployInputs memory) { + string memory header = 'WARNING: '; + string memory message = ' is zero address'; + string memory outcome = '; defaulting to deployer'; + FullDeployInputs memory sanitizedInputs = inputs; bool hadWarnings = false; if (inputs.grantRoles) { - _logAndAppend(logger, 'WARNING: Roles are being set'); + _logAndAppend(logger, string.concat(header, 'Roles are being set')); hadWarnings = true; if (inputs.accessManagerAdmin == address(0)) { - _logAndAppend( - logger, - 'WARNING: Access Manager Admin is zero address; role will be granted to deployer by default' - ); + _logAndAppend(logger, string.concat(header, 'Access Manager Admin', message, outcome)); sanitizedInputs.accessManagerAdmin = deployer; } if (inputs.hubConfiguratorOwner == address(0)) { - _logAndAppend( - logger, - 'WARNING: Hub Configurator Owner is zero address; role will be granted to deployer by default' - ); + _logAndAppend(logger, string.concat(header, 'Hub Configurator Owner', message, outcome)); sanitizedInputs.hubConfiguratorOwner = deployer; } if (inputs.spokeConfiguratorOwner == address(0)) { - _logAndAppend( - logger, - 'WARNING: Spoke Configurator Owner is zero address; role will be granted to deployer by default' - ); + _logAndAppend(logger, string.concat(header, 'Spoke Configurator Owner', message, outcome)); sanitizedInputs.spokeConfiguratorOwner = deployer; } if (inputs.spokeProxyAdminOwner == address(0)) { - _logAndAppend( - logger, - 'WARNING: Spoke Proxy Admin Owner is zero address; role will be granted to deployer by default' - ); + _logAndAppend(logger, string.concat(header, 'Spoke Proxy Admin Owner', message, outcome)); sanitizedInputs.spokeProxyAdminOwner = deployer; } if (inputs.treasurySpokeOwner == address(0)) { - _logAndAppend( - logger, - 'WARNING: Treasury Spoke Owner is zero address; role will be granted to deployer by default' - ); + _logAndAppend(logger, string.concat(header, 'Treasury Spoke Owner', message, outcome)); sanitizedInputs.treasurySpokeOwner = deployer; } if (inputs.spokeAdmin == address(0)) { - _logAndAppend( - logger, - 'WARNING: Spoke Admin is zero address; spoke admin roles will be granted to deployer by default' - ); + _logAndAppend(logger, string.concat(header, 'Spoke Admin', message, outcome)); sanitizedInputs.spokeAdmin = deployer; } if (inputs.hubAdmin == address(0)) { - _logAndAppend( - logger, - 'WARNING: Hub Admin is zero address; hub admin roles will be granted to deployer by default' - ); + _logAndAppend(logger, string.concat(header, 'Hub Admin', message, outcome)); sanitizedInputs.hubAdmin = deployer; } } if (inputs.hubLabels.length == 0) { - _logAndAppend(logger, 'WARNING: Hub will not be deployed'); + _logAndAppend(logger, string.concat(header, 'Hub will not be deployed')); hadWarnings = true; sanitizedInputs.hubLabels = new string[](0); } if (inputs.spokeLabels.length == 0) { - _logAndAppend(logger, 'WARNING: Spoke will not be deployed'); + _logAndAppend(logger, string.concat(header, 'Spoke will not be deployed')); hadWarnings = true; sanitizedInputs.spokeLabels = new string[](0); } if (inputs.nativeWrapper == address(0)) { _logAndAppend( logger, - 'WARNING: Native wrapper zero address; NativeTokenGateway & SignatureGateway will not be deployed' + string.concat( + header, + 'Native wrapper', + message, + "; NativeTokenGateway & SignatureGateway will not be deployed'" + ) ); hadWarnings = true; sanitizedInputs.nativeWrapper = address(0); } if (inputs.gatewayOwner == address(0)) { - _logAndAppend( - logger, - 'WARNING: Gateway owner zero address; role will be granted to deployer by default' - ); + _logAndAppend(logger, string.concat(header, 'Gateway owner', message, outcome)); hadWarnings = true; sanitizedInputs.gatewayOwner = deployer; } diff --git a/snapshots/Hub.Operations.json b/snapshots/Hub.Operations.json index 255fcfc37..6ecc85318 100644 --- a/snapshots/Hub.Operations.json +++ b/snapshots/Hub.Operations.json @@ -14,5 +14,5 @@ "restore: full - with transfer": "173415", "restore: partial": "89137", "restore: partial - with transfer": "147439", - "transferShares": "71180" + "transferShares": "71192" } \ No newline at end of file diff --git a/snapshots/SignatureGateway.Operations.json b/snapshots/SignatureGateway.Operations.json index 96eb0ef3e..50851bd0d 100644 --- a/snapshots/SignatureGateway.Operations.json +++ b/snapshots/SignatureGateway.Operations.json @@ -2,9 +2,9 @@ "borrowWithSig": "215605", "repayWithSig": "188872", "setSelfAsUserPositionManagerWithSig": "75402", - "setUsingAsCollateralWithSig": "85053", + "setUsingAsCollateralWithSig": "85065", "supplyWithSig": "153205", "updateUserDynamicConfigWithSig": "62769", "updateUserRiskPremiumWithSig": "61579", - "withdrawWithSig": "131696" + "withdrawWithSig": "131686" } \ No newline at end of file diff --git a/snapshots/Spoke.Operations.ZeroRiskPremium.json b/snapshots/Spoke.Operations.ZeroRiskPremium.json index 352760025..ed2faa23d 100644 --- a/snapshots/Spoke.Operations.ZeroRiskPremium.json +++ b/snapshots/Spoke.Operations.ZeroRiskPremium.json @@ -6,7 +6,7 @@ "liquidationCall: full": "310468", "liquidationCall: partial": "310186", "permitReserve + repay (multicall)": "166029", - "permitReserve + supply (multicall)": "146850", + "permitReserve + supply (multicall)": "146862", "permitReserve + supply + enable collateral (multicall)": "160573", "repay: full": "126094", "repay: partial": "130983", diff --git a/snapshots/Spoke.Operations.json b/snapshots/Spoke.Operations.json index 2ce1b424f..deed9c95d 100644 --- a/snapshots/Spoke.Operations.json +++ b/snapshots/Spoke.Operations.json @@ -6,7 +6,7 @@ "liquidationCall: full": "344031", "liquidationCall: partial": "343749", "permitReserve + repay (multicall)": "163273", - "permitReserve + supply (multicall)": "146850", + "permitReserve + supply (multicall)": "146862", "permitReserve + supply + enable collateral (multicall)": "160573", "repay: full": "120256", "repay: partial": "139545", diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 904f913d3..e8ded90f7 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -3,13 +3,13 @@ pragma solidity ^0.8.0; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; -import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; import { AaveV4AaveOracleDeployProcedure } from 'src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol'; import { AaveV4SpokeDeployProcedure } from 'src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; import {IAaveOracle} from 'src/spoke/interfaces/IAaveOracle.sol'; @@ -23,11 +23,16 @@ contract AaveV4SpokeInstanceBatch is AaveV4SpokeDeployProcedure, AaveV4AaveOracl uint8 oracleDecimals_, string memory oracleDescription_ ) { - // additional 2 nonces for AaveOracle, SpokeInstance, starting from contract nonce of 1 - address predictedSpokeInstance = Utils.computeCreateAddress(address(this), 3); - + // starting from contract nonce of 1 + address predictedOracle = Create2Utils.computeCreateAddress(address(this), 1); + address predictedSpokeProxy = _computeSpokeInstanceAddress( + SALT, + predictedOracle, + spokeProxyAdminOwner_, + accessManager_ + ); address aaveOracle = _deployAaveOracle( - predictedSpokeInstance, + predictedSpokeProxy, oracleDecimals_, oracleDescription_ ); @@ -37,7 +42,8 @@ contract AaveV4SpokeInstanceBatch is AaveV4SpokeDeployProcedure, AaveV4AaveOracl oracle: aaveOracle }); - require(spokeProxy == predictedSpokeInstance, InvalidParam('predicted spoke instance')); + require(aaveOracle == predictedOracle, InvalidParam('predicted oracle')); + require(spokeProxy == predictedSpokeProxy, InvalidParam('predicted spoke instance')); require(ISpoke(spokeProxy).ORACLE() == aaveOracle, InvalidParam('spoke oracle')); require(IAaveOracle(aaveOracle).SPOKE() == spokeProxy, InvalidParam('aave oracle spoke')); diff --git a/src/deployments/procedures/AaveV4DeployProcedureBase.sol b/src/deployments/procedures/AaveV4DeployProcedureBase.sol index 505109d97..a2f89d916 100644 --- a/src/deployments/procedures/AaveV4DeployProcedureBase.sol +++ b/src/deployments/procedures/AaveV4DeployProcedureBase.sol @@ -2,8 +2,11 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; contract AaveV4DeployProcedureBase { error InvalidParam(string errorMessage); + + bytes32 public constant SALT = bytes32('v1'); function _validateZeroAddress(address addr, string memory errorMessage) internal pure { require(addr != address(0), InvalidParam(errorMessage)); } diff --git a/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol index 1e7720f38..30e2793b4 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol @@ -3,10 +3,17 @@ pragma solidity ^0.8.0; import {HubConfigurator} from 'src/hub/HubConfigurator.sol'; -import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import { + Create2Utils, + AaveV4DeployProcedureBase +} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4HubConfiguratorDeployProcedure is AaveV4DeployProcedureBase { function _deployHubConfigurator(address owner) internal returns (address) { _validateZeroAddress(owner, 'owner'); - return address(new HubConfigurator({owner_: owner})); + return + Create2Utils.create2Deploy( + SALT, + abi.encodePacked(type(HubConfigurator).creationCode, abi.encode(owner)) + ); } } diff --git a/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol index 25193c0ac..4e08f928a 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol @@ -3,10 +3,17 @@ pragma solidity ^0.8.0; import {Hub} from 'src/hub/Hub.sol'; -import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import { + Create2Utils, + AaveV4DeployProcedureBase +} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4HubDeployProcedure is AaveV4DeployProcedureBase { function _deployHub(address accessManager) internal returns (address) { _validateZeroAddress(accessManager, 'access manager'); - return address(new Hub({authority_: accessManager})); + return + Create2Utils.create2Deploy( + SALT, + abi.encodePacked(type(Hub).creationCode, abi.encode(accessManager)) + ); } } diff --git a/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol index 7d9caece9..d22a919f8 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol @@ -3,10 +3,17 @@ pragma solidity ^0.8.0; import {AssetInterestRateStrategy} from 'src/hub/AssetInterestRateStrategy.sol'; -import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import { + Create2Utils, + AaveV4DeployProcedureBase +} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4InterestRateStrategyDeployProcedure is AaveV4DeployProcedureBase { function _deployInterestRateStrategy(address hub) internal returns (address) { require(hub != address(0), InvalidParam('hub')); - return address(new AssetInterestRateStrategy({hub_: hub})); + return + Create2Utils.create2Deploy( + SALT, + abi.encodePacked(type(AssetInterestRateStrategy).creationCode, abi.encode(hub)) + ); } } diff --git a/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol index b62a59db8..6c1822540 100644 --- a/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol @@ -3,7 +3,10 @@ pragma solidity ^0.8.0; import {NativeTokenGateway} from 'src/position-manager/NativeTokenGateway.sol'; -import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import { + Create2Utils, + AaveV4DeployProcedureBase +} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4NativeTokenGatewayDeployProcedure is AaveV4DeployProcedureBase { function _deployNativeTokenGateway( address nativeWrapper, @@ -11,6 +14,10 @@ contract AaveV4NativeTokenGatewayDeployProcedure is AaveV4DeployProcedureBase { ) internal returns (address) { _validateZeroAddress(nativeWrapper, 'native wrapper'); _validateZeroAddress(owner, 'owner'); - return address(new NativeTokenGateway({nativeWrapper_: nativeWrapper, initialOwner_: owner})); + return + Create2Utils.create2Deploy( + SALT, + abi.encodePacked(type(NativeTokenGateway).creationCode, abi.encode(nativeWrapper, owner)) + ); } } diff --git a/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol index a016257f6..e500435e1 100644 --- a/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol @@ -3,10 +3,17 @@ pragma solidity ^0.8.0; import {SignatureGateway} from 'src/position-manager/SignatureGateway.sol'; -import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import { + Create2Utils, + AaveV4DeployProcedureBase +} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4SignatureGatewayDeployProcedure is AaveV4DeployProcedureBase { function _deploySignatureGateway(address owner) internal returns (address) { _validateZeroAddress(owner, 'owner'); - return address(new SignatureGateway({initialOwner_: owner})); + return + Create2Utils.create2Deploy( + SALT, + abi.encodePacked(type(SignatureGateway).creationCode, abi.encode(owner)) + ); } } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol index dd16ff9ba..0f82bc5f0 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol @@ -13,6 +13,7 @@ contract AaveV4AaveOracleDeployProcedure is AaveV4DeployProcedureBase { _validateZeroAddress(spoke_, 'spoke'); require(decimals_ > 0, InvalidParam('oracle decimals')); require(bytes(description_).length > 0, InvalidParam('oracle description')); + // AaveOracle must be deployed via create to compute the predicted address via without inputs return address(new AaveOracle({spoke_: spoke_, decimals_: decimals_, description_: description_})); } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol index 9a57edcad..2110fa80b 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol @@ -3,11 +3,18 @@ pragma solidity ^0.8.0; import {SpokeConfigurator} from 'src/spoke/SpokeConfigurator.sol'; -import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import { + Create2Utils, + AaveV4DeployProcedureBase +} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4SpokeConfiguratorDeployProcedure is AaveV4DeployProcedureBase { function _deploySpokeConfigurator(address owner) internal returns (address) { _validateZeroAddress(owner, 'owner'); - return address(new SpokeConfigurator({owner_: owner})); + return + Create2Utils.create2Deploy( + SALT, + abi.encodePacked(type(SpokeConfigurator).creationCode, abi.encode(owner)) + ); } } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol index 9fd51df77..eda4f9e7e 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol @@ -2,9 +2,15 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; +// import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; import {SpokeInstance} from 'src/spoke/instances/SpokeInstance.sol'; -import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import { + Create2Utils, + AaveV4DeployProcedureBase +} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import { + TransparentUpgradeableProxy +} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; contract AaveV4SpokeDeployProcedure is AaveV4DeployProcedureBase { function _deployUpgradableSpokeInstance( @@ -15,12 +21,37 @@ contract AaveV4SpokeDeployProcedure is AaveV4DeployProcedureBase { _validateZeroAddress(spokeProxyAdminOwner, 'spoke proxy admin owner'); _validateZeroAddress(accessManager, 'access manager'); _validateZeroAddress(oracle, 'oracle'); - spokeImplementation = address(new SpokeInstance({oracle_: oracle})); - spokeProxy = Utils.proxify( + spokeImplementation = Create2Utils.create2Deploy( + SALT, + abi.encodePacked(type(SpokeInstance).creationCode, abi.encode(oracle)) + ); + spokeProxy = Create2Utils.proxify( + SALT, spokeImplementation, spokeProxyAdminOwner, abi.encodeCall(SpokeInstance.initialize, (accessManager)) ); return (spokeProxy, spokeImplementation); } + + function _computeSpokeInstanceAddress( + bytes32 salt, + address oracle, + address spokeProxyAdminOwner, + address accessManager + ) internal pure returns (address) { + address spokeImplementation = Create2Utils.computeCreate2Address( + salt, + abi.encodePacked(type(SpokeInstance).creationCode, abi.encode(oracle)) + ); + bytes memory initCode = abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode( + spokeImplementation, + spokeProxyAdminOwner, + abi.encodeCall(SpokeInstance.initialize, (accessManager)) + ) + ); + return Create2Utils.computeCreate2Address(salt, keccak256(initCode)); + } } diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index e66662b68..a4519af18 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -84,4 +84,11 @@ contract InputUtils { HubDeployInputs memory inputs = abi.decode(data, (HubDeployInputs)); return inputs; } + + function _etchCreate2Factory() internal virtual { + vm.etch( + 0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7, + hex'7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3' + ); + } } diff --git a/src/deployments/utils/Logger.sol b/src/deployments/utils/Logger.sol index 898e7db4d..4ba1ba64f 100644 --- a/src/deployments/utils/Logger.sol +++ b/src/deployments/utils/Logger.sol @@ -54,7 +54,10 @@ contract Logger { console.log(); console.log('Saving log to %s', _outputPath); string memory appendedMetadata = withTimestamp ? string.concat(_getTimestamp(), '-') : ''; - vm.writeJson(_json, string.concat(_outputPath, appendedMetadata, fileName)); + vm.writeJson( + _json, + string.concat(_outputPath, appendedMetadata, vm.toString(block.chainid), '-', fileName) + ); } function log(string memory label, address value) public pure { diff --git a/src/deployments/utils/libraries/Create2Utils.sol b/src/deployments/utils/libraries/Create2Utils.sol new file mode 100644 index 000000000..fdfd2caf9 --- /dev/null +++ b/src/deployments/utils/libraries/Create2Utils.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.20; + +import { + TransparentUpgradeableProxy +} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; +import {SpokeInstance} from 'src/spoke/instances/SpokeInstance.sol'; + +library Create2Utils { + // https://github.com/safe-global/safe-singleton-factory + address public constant CREATE2_FACTORY = 0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7; + + error missingCreate2Factory(); + error create2AddressDerivationFailure(); + error nonceNotSupported(); + error failedCreate2FactoryCall(); + + function create2Deploy(bytes32 salt, bytes memory bytecode) internal returns (address) { + require(isContractDeployed(CREATE2_FACTORY), missingCreate2Factory()); + address computed = computeCreate2Address(salt, bytecode); + if (isContractDeployed(computed)) { + return computed; + } else { + bytes memory creationBytecode = abi.encodePacked(salt, bytecode); + (bool success, bytes memory returnData) = CREATE2_FACTORY.call(creationBytecode); + require(success, failedCreate2FactoryCall()); + address deployedAt = address(uint160(bytes20(returnData))); + require(deployedAt == computed, create2AddressDerivationFailure()); + return deployedAt; + } + } + + function proxify( + bytes32 salt, + address logic, + address initialOwner, + bytes memory data + ) internal returns (address) { + return + create2Deploy( + salt, + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(logic, initialOwner, data) + ) + ); + } + + function isContractDeployed(address _addr) internal view returns (bool isContract) { + return (_addr.code.length > 0); + } + + function computeCreateAddress(address deployer, uint8 nonce) internal pure returns (address) { + // RLP([deployer, nonce]) for 0 <= nonce <= 0x7f + // nonce == 0 is encoded as the empty string (0x80) in RLP + require(nonce < 0x80, nonceNotSupported()); + bytes1 nonceRlp = nonce == 0 ? bytes1(0x80) : bytes1(nonce); + bytes memory rlp = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, nonceRlp); + return address(uint160(uint256(keccak256(rlp)))); + } + + function computeCreate2Address( + bytes32 salt, + bytes32 initcodeHash + ) internal pure returns (address) { + return + addressFromLast20Bytes( + keccak256(abi.encodePacked(bytes1(0xff), CREATE2_FACTORY, salt, initcodeHash)) + ); + } + + function computeCreate2Address( + bytes32 salt, + bytes memory bytecode + ) internal pure returns (address) { + return computeCreate2Address(salt, keccak256(abi.encodePacked(bytecode))); + } + + function addressFromLast20Bytes(bytes32 bytesValue) internal pure returns (address) { + return address(uint160(uint256(bytesValue))); + } +} diff --git a/src/deployments/utils/libraries/Utils.sol b/src/deployments/utils/libraries/Utils.sol deleted file mode 100644 index 76f97a4f2..000000000 --- a/src/deployments/utils/libraries/Utils.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.0; - -import { - TransparentUpgradeableProxy -} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; - -library Utils { - function computeCreateAddress(address deployer, uint8 nonce) internal pure returns (address) { - // RLP([deployer, nonce]) for 0 <= nonce <= 0x7f - // nonce == 0 is encoded as the empty string (0x80) in RLP - require(nonce < 0x80, 'Utils: nonce >= 0x80 not supported'); - bytes1 nonceRlp = nonce == 0 ? bytes1(0x80) : bytes1(nonce); - bytes memory rlp = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, nonceRlp); - return address(uint160(uint256(keccak256(rlp)))); - } - - function proxify( - address logic_, - address initialOwner_, - bytes memory data_ - ) internal returns (address) { - return - address( - new TransparentUpgradeableProxy({_logic: logic_, initialOwner: initialOwner_, _data: data_}) - ); - } -} diff --git a/tests/Base.t.sol b/tests/Base.t.sol index d16e5e57e..fe9128f72 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -284,6 +284,7 @@ abstract contract Base is BatchTestProcedures { }); function setUp() public virtual override { + _etchCreate2Factory(); _initTokenList(); _setupFixtures(); } diff --git a/tests/deployments/procedures/ProceduresBase.t.sol b/tests/deployments/procedures/ProceduresBase.t.sol index d5fdc0798..9da3771c3 100644 --- a/tests/deployments/procedures/ProceduresBase.t.sol +++ b/tests/deployments/procedures/ProceduresBase.t.sol @@ -59,8 +59,9 @@ import {ITreasurySpoke} from 'src/spoke/interfaces/ITreasurySpoke.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; import {IAccessManager} from 'src/dependencies/openzeppelin/IAccessManager.sol'; +import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; -contract ProceduresBase is Test { +contract ProceduresBase is Test, InputUtils { address public owner = makeAddr('owner'); address public accessManager; address public hub = makeAddr('hub'); @@ -74,6 +75,8 @@ contract ProceduresBase is Test { address public admin = makeAddr('admin'); function setUp() public virtual { + _etchCreate2Factory(); + accessManager = address(new AccessManagerEnumerable(accessManagerAdmin)); aaveOracle = address(new AaveOracle(spoke, oracleDecimals, oracleDescription)); } diff --git a/tests/deployments/utils/libraries/Create2Utils.t.sol b/tests/deployments/utils/libraries/Create2Utils.t.sol new file mode 100644 index 000000000..debcaa2df --- /dev/null +++ b/tests/deployments/utils/libraries/Create2Utils.t.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Test} from 'forge-std/Test.sol'; +import { + Create2Utils, + Create2UtilsWrapper +} from 'tests/mocks/deployments/libraries/Create2UtilsWrapper.sol'; +import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; +import { + TransparentUpgradeableProxy +} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; + +contract Dummy { + constructor() {} +} + +contract Create2UtilsTest is Test, InputUtils { + Create2UtilsWrapper internal _harness; + function setUp() public { + _harness = new Create2UtilsWrapper(); + } + function testCreate2Deploy_revertsWith_missingCreate2Factory() public { + vm.expectRevert(Create2Utils.missingCreate2Factory.selector); + _harness.create2Deploy(bytes32(0), type(Dummy).creationCode); + } + + function testCreate2Deploy_revertsWith_create2AddressDerivationFailure(bytes32 salt) public { + vm.assume(salt != bytes32(0)); + vm.etch( + Create2Utils.CREATE2_FACTORY, + hex'600060005260206000f3' // runtime: mstore(0,0); return(0,32) + ); + bytes memory bytecode = type(Dummy).creationCode; + vm.expectRevert(Create2Utils.create2AddressDerivationFailure.selector); + _harness.create2Deploy(salt, bytecode); + } + + function testCreate2Deploy_revertsWith_failedCreate2FactoryCall(bytes32 salt) public { + vm.assume(salt != bytes32(0)); + _etchCreate2Factory(); + bytes memory bytecode = hex'fd'; + vm.expectRevert(Create2Utils.failedCreate2FactoryCall.selector); + _harness.create2Deploy(salt, bytecode); + } + + function testCreate2Deploy_returnsDeployedAddress(bytes32 salt) public { + vm.assume(salt != bytes32(0)); + _etchCreate2Factory(); + bytes memory bytecode = type(Dummy).creationCode; + address deployed = _harness.create2Deploy(salt, bytecode); + assertEq(_harness.create2Deploy(salt, bytecode), deployed); + } + + function testCreate2Deploy_fuzz(bytes32 salt) public { + vm.assume(salt != bytes32(0)); + _etchCreate2Factory(); + bytes memory bytecode = type(Dummy).creationCode; + + assertEq( + _harness.create2Deploy(salt, bytecode), + _harness.computeCreate2Address(salt, keccak256(bytecode)) + ); + } + + function testProxify_fuzz(bytes32 salt, address initialOwner) public { + vm.assume(salt != bytes32(0)); + vm.assume(initialOwner != address(0)); + _etchCreate2Factory(); + address logic = address(new Dummy()); + bytes memory initData = bytes(''); + assertEq( + _harness.proxify(salt, logic, initialOwner, initData), + _harness.computeCreate2Address( + salt, + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(logic, initialOwner, initData) + ) + ) + ) + ); + } + + function testIsContractDeployed_fuzz(address addr) public { + vm.assume(addr != address(0)); + assumeUnusedAddress(addr); + assertFalse(_harness.isContractDeployed(addr)); + } + + function testIsContractDeployed() public { + address deployed = address(new Dummy()); + assertTrue(_harness.isContractDeployed(deployed)); + } + + function testComputeCreateAddress_revertsWith_nonceNotSupported( + address deployer, + uint8 nonce + ) public { + vm.assume(deployer != address(0)); + vm.assume(nonce >= 0x80); + vm.expectRevert(Create2Utils.nonceNotSupported.selector); + _harness.computeCreateAddress(deployer, nonce); + } + + function testComputeCreateAddress_fuzz(address deployer, uint8 nonce) public view { + vm.assume(deployer != address(0)); + vm.assume(nonce < 0x80); + address expected = vm.computeCreateAddress(deployer, nonce); + assertEq(_harness.computeCreateAddress(deployer, nonce), expected); + } + + function testComputeCreate2Address_fuzz(bytes32 salt, bytes32 initcode) public { + vm.assume(salt != bytes32(0)); + vm.assume(initcode != bytes32(0)); + address expected = _harness.computeCreate2Address(salt, initcode); + assertEq(_harness.computeCreate2Address(salt, initcode), expected); + } + + function testComputeCreate2Address_fuzz(bytes32 salt, bytes memory bytecode) public { + vm.assume(salt != bytes32(0)); + vm.assume(bytecode.length > 0); + address expected = _harness.computeCreate2Address(salt, keccak256(abi.encodePacked(bytecode))); + assertEq(_harness.computeCreate2Address(salt, bytecode), expected); + } + + function testAddressFromLast20Bytes_fuzz(bytes32 bytesValue) public view { + vm.assume(bytesValue != bytes32(0)); + assertEq(_harness.addressFromLast20Bytes(bytesValue), address(uint160(uint256(bytesValue)))); + } +} diff --git a/tests/deployments/utils/libraries/Utils.t.sol b/tests/deployments/utils/libraries/Utils.t.sol deleted file mode 100644 index e79014d09..000000000 --- a/tests/deployments/utils/libraries/Utils.t.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.0; - -import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; -import {Test} from 'forge-std/Test.sol'; - -contract UtilsTest is Test { - function testComputeCreateAddress_fuzz(address deployer, uint8 nonce) public pure { - vm.assume(deployer != address(0)); - vm.assume(nonce < 0x80); - address expected = vm.computeCreateAddress(deployer, nonce); - assertEq(Utils.computeCreateAddress(deployer, nonce), expected); - } -} diff --git a/tests/mocks/deployments/libraries/Create2UtilsWrapper.sol b/tests/mocks/deployments/libraries/Create2UtilsWrapper.sol new file mode 100644 index 000000000..3349407be --- /dev/null +++ b/tests/mocks/deployments/libraries/Create2UtilsWrapper.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.20; + +import { + TransparentUpgradeableProxy +} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; +import {SpokeInstance} from 'src/spoke/instances/SpokeInstance.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; + +contract Create2UtilsWrapper { + function isContractDeployed(address addr) external view returns (bool) { + return Create2Utils.isContractDeployed(addr); + } + + function create2Deploy(bytes32 salt, bytes memory bytecode) external returns (address) { + return Create2Utils.create2Deploy(salt, bytecode); + } + + function proxify( + bytes32 salt, + address logic, + address initialOwner, + bytes memory data + ) external returns (address) { + return Create2Utils.proxify(salt, logic, initialOwner, data); + } + + function computeCreateAddress(address deployer, uint8 nonce) external pure returns (address) { + return Create2Utils.computeCreateAddress(deployer, nonce); + } + + function computeCreate2Address( + bytes32 salt, + bytes32 initcodeHash + ) external pure returns (address) { + return Create2Utils.computeCreate2Address(salt, initcodeHash); + } + + function computeCreate2Address( + bytes32 salt, + bytes memory bytecode + ) external pure returns (address) { + return Create2Utils.computeCreate2Address(salt, bytecode); + } + + function addressFromLast20Bytes(bytes32 bytesValue) external pure returns (address) { + return Create2Utils.addressFromLast20Bytes(bytesValue); + } +} diff --git a/tests/scripts/AaveV4DeployBatchBaseScript.t.sol b/tests/scripts/AaveV4DeployBatchBaseScript.t.sol index 3745c5b15..63e14bf5a 100644 --- a/tests/scripts/AaveV4DeployBatchBaseScript.t.sol +++ b/tests/scripts/AaveV4DeployBatchBaseScript.t.sol @@ -206,7 +206,7 @@ contract AaveV4DeployBatchBaseScriptTest is Test { function assertEq( InputUtils.FullDeployInputs memory a, InputUtils.FullDeployInputs memory b - ) public { + ) public pure { assertEq(a.accessManagerAdmin, b.accessManagerAdmin, 'access manager admin'); assertEq(a.hubAdmin, b.hubAdmin, 'hub admin'); assertEq(a.hubConfiguratorOwner, b.hubConfiguratorOwner, 'hub configurator owner'); diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 6eb77204f..01d23d2e9 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -65,6 +65,8 @@ contract BatchTestProcedures is Test, InputUtils, WETHDeployProcedure { _logger = new Logger('dummy/path'); _hubLabels = ['hub1', 'hub2', 'hub3']; _spokeLabels = ['spoke1', 'spoke2', 'spoke3']; + + _etchCreate2Factory(); } function checkedV4Deployment() public { From 549265366f70efed3b573b6a6b28f9c06a50857a Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:35:40 -0600 Subject: [PATCH 58/62] chore: clean up logging --- scripts/deploy/AaveV4DeployBatchBase.s.sol | 27 +++++++++++----------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/scripts/deploy/AaveV4DeployBatchBase.s.sol b/scripts/deploy/AaveV4DeployBatchBase.s.sol index 92755bdae..f9ae25d83 100644 --- a/scripts/deploy/AaveV4DeployBatchBase.s.sol +++ b/scripts/deploy/AaveV4DeployBatchBase.s.sol @@ -36,7 +36,7 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { (, address deployer, ) = vm.readCallers(); inputs = _loadWarningsAndSanitizeInputs(logger, inputs, deployer); - logger.log('CHAIN ID = ', block.chainid); + logger.log('CHAIN ID', block.chainid); logger.log('...Starting Aave V4 Batch Deployment...'); vm.startBroadcast(deployer); OrchestrationReports.FullDeploymentReport memory report = AaveV4DeployOrchestration @@ -53,51 +53,50 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { FullDeployInputs memory inputs, address deployer ) internal virtual returns (FullDeployInputs memory) { - string memory header = 'WARNING: '; string memory message = ' is zero address'; string memory outcome = '; defaulting to deployer'; FullDeployInputs memory sanitizedInputs = inputs; bool hadWarnings = false; if (inputs.grantRoles) { - _logAndAppend(logger, string.concat(header, 'Roles are being set')); + _logAndAppend(logger, string.concat('Roles are being set')); hadWarnings = true; if (inputs.accessManagerAdmin == address(0)) { - _logAndAppend(logger, string.concat(header, 'Access Manager Admin', message, outcome)); + _logAndAppend(logger, string.concat('Access Manager Admin', message, outcome)); sanitizedInputs.accessManagerAdmin = deployer; } if (inputs.hubConfiguratorOwner == address(0)) { - _logAndAppend(logger, string.concat(header, 'Hub Configurator Owner', message, outcome)); + _logAndAppend(logger, string.concat('Hub Configurator Owner', message, outcome)); sanitizedInputs.hubConfiguratorOwner = deployer; } if (inputs.spokeConfiguratorOwner == address(0)) { - _logAndAppend(logger, string.concat(header, 'Spoke Configurator Owner', message, outcome)); + _logAndAppend(logger, string.concat('Spoke Configurator Owner', message, outcome)); sanitizedInputs.spokeConfiguratorOwner = deployer; } if (inputs.spokeProxyAdminOwner == address(0)) { - _logAndAppend(logger, string.concat(header, 'Spoke Proxy Admin Owner', message, outcome)); + _logAndAppend(logger, string.concat('Spoke Proxy Admin Owner', message, outcome)); sanitizedInputs.spokeProxyAdminOwner = deployer; } if (inputs.treasurySpokeOwner == address(0)) { - _logAndAppend(logger, string.concat(header, 'Treasury Spoke Owner', message, outcome)); + _logAndAppend(logger, string.concat('Treasury Spoke Owner', message, outcome)); sanitizedInputs.treasurySpokeOwner = deployer; } if (inputs.spokeAdmin == address(0)) { - _logAndAppend(logger, string.concat(header, 'Spoke Admin', message, outcome)); + _logAndAppend(logger, string.concat('Spoke Admin', message, outcome)); sanitizedInputs.spokeAdmin = deployer; } if (inputs.hubAdmin == address(0)) { - _logAndAppend(logger, string.concat(header, 'Hub Admin', message, outcome)); + _logAndAppend(logger, string.concat('Hub Admin', message, outcome)); sanitizedInputs.hubAdmin = deployer; } } if (inputs.hubLabels.length == 0) { - _logAndAppend(logger, string.concat(header, 'Hub will not be deployed')); + _logAndAppend(logger, string.concat('Hub will not be deployed')); hadWarnings = true; sanitizedInputs.hubLabels = new string[](0); } if (inputs.spokeLabels.length == 0) { - _logAndAppend(logger, string.concat(header, 'Spoke will not be deployed')); + _logAndAppend(logger, string.concat('Spoke will not be deployed')); hadWarnings = true; sanitizedInputs.spokeLabels = new string[](0); } @@ -105,7 +104,6 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { _logAndAppend( logger, string.concat( - header, 'Native wrapper', message, "; NativeTokenGateway & SignatureGateway will not be deployed'" @@ -115,7 +113,7 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { sanitizedInputs.nativeWrapper = address(0); } if (inputs.gatewayOwner == address(0)) { - _logAndAppend(logger, string.concat(header, 'Gateway owner', message, outcome)); + _logAndAppend(logger, string.concat('Gateway owner', message, outcome)); hadWarnings = true; sanitizedInputs.gatewayOwner = deployer; } @@ -135,6 +133,7 @@ abstract contract AaveV4DeployBatchBaseScript is Script, InputUtils { } function _logAndAppend(MetadataLogger logger, string memory warning) internal virtual { + warning = string.concat('WARNING: ', warning); logger.log(warning); _warnings.s.push(warning); } From 90f133f01d383fcd7cd18618a08fa66562b70539 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Thu, 18 Dec 2025 22:11:47 -0600 Subject: [PATCH 59/62] fix: pragma consistency; errors --- .../batches/AaveV4SpokeInstanceBatch.sol | 8 +- .../procedures/AaveV4DeployProcedureBase.sol | 5 - ...AccessManagerEnumerableDeployProcedure.sol | 2 +- .../AaveV4HubConfiguratorDeployProcedure.sol | 2 +- .../deploy/hub/AaveV4HubDeployProcedure.sol | 2 +- ...eV4InterestRateStrategyDeployProcedure.sol | 2 +- ...aveV4NativeTokenGatewayDeployProcedure.sol | 4 +- .../AaveV4SignatureGatewayDeployProcedure.sol | 2 +- .../spoke/AaveV4AaveOracleDeployProcedure.sol | 6 +- ...AaveV4SpokeConfiguratorDeployProcedure.sol | 2 +- .../spoke/AaveV4SpokeDeployProcedure.sol | 6 +- .../AaveV4TreasurySpokeDeployProcedure.sol | 4 +- .../AaveV4AccessManagerRolesProcedure.sol | 6 +- .../roles/AaveV4HubRolesProcedure.sol | 8 +- .../roles/AaveV4SpokeRolesProcedure.sol | 8 +- src/deployments/utils/InputUtils.sol | 3 +- src/deployments/utils/libraries/Roles.sol | 2 +- tests/deployments/AaveV4BatchDeployment.t.sol | 91 ++++++------------- ...cessManagerEnumerableDeployProcedure.t.sol | 4 +- ...AaveV4HubConfiguratorDeployProcedure.t.sol | 6 +- .../deploy/hub/AaveV4HubDeployProcedure.t.sol | 6 +- ...4InterestRateStrategyDeployProcedure.t.sol | 4 +- ...eV4NativeTokenGatewayDeployProcedure.t.sol | 10 +- ...aveV4SignatureGatewayDeployProcedure.t.sol | 6 +- .../AaveV4AccessManagerRolesProcedure.t.sol | 14 +-- .../roles/AaveV4HubRolesProcedure.t.sol | 54 ++++------- .../roles/AaveV4SpokeRolesProcedure.t.sol | 60 ++++-------- .../AaveV4AaveOracleDeployProcedure.t.sol | 14 +-- ...veV4SpokeConfiguratorDeployProcedure.t.sol | 6 +- .../spoke/AaveV4SpokeDeployProcedure.t.sol | 17 +--- .../AaveV4TreasurySpokeDeployProcedure.t.sol | 8 +- .../utils/libraries/Create2Utils.t.sol | 6 +- 32 files changed, 128 insertions(+), 250 deletions(-) diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index e8ded90f7..1eff60724 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -42,10 +42,10 @@ contract AaveV4SpokeInstanceBatch is AaveV4SpokeDeployProcedure, AaveV4AaveOracl oracle: aaveOracle }); - require(aaveOracle == predictedOracle, InvalidParam('predicted oracle')); - require(spokeProxy == predictedSpokeProxy, InvalidParam('predicted spoke instance')); - require(ISpoke(spokeProxy).ORACLE() == aaveOracle, InvalidParam('spoke oracle')); - require(IAaveOracle(aaveOracle).SPOKE() == spokeProxy, InvalidParam('aave oracle spoke')); + assert(aaveOracle == predictedOracle); + assert(spokeProxy == predictedSpokeProxy); + assert(ISpoke(spokeProxy).ORACLE() == aaveOracle); + assert(IAaveOracle(aaveOracle).SPOKE() == spokeProxy); _report = BatchReports.SpokeInstanceBatchReport({ aaveOracle: aaveOracle, diff --git a/src/deployments/procedures/AaveV4DeployProcedureBase.sol b/src/deployments/procedures/AaveV4DeployProcedureBase.sol index a2f89d916..2c34ba743 100644 --- a/src/deployments/procedures/AaveV4DeployProcedureBase.sol +++ b/src/deployments/procedures/AaveV4DeployProcedureBase.sol @@ -4,10 +4,5 @@ pragma solidity ^0.8.0; import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; contract AaveV4DeployProcedureBase { - error InvalidParam(string errorMessage); - bytes32 public constant SALT = bytes32('v1'); - function _validateZeroAddress(address addr, string memory errorMessage) internal pure { - require(addr != address(0), InvalidParam(errorMessage)); - } } diff --git a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol index ec84e2a07..dd2d6c372 100644 --- a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol @@ -7,7 +7,7 @@ import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4Deploy contract AaveV4AccessManagerEnumerableDeployProcedure is AaveV4DeployProcedureBase { function _deployAccessManagerEnumerable(address admin) internal returns (address) { - _validateZeroAddress(admin, 'admin'); + require(admin != address(0), 'invalid admin'); return address(new AccessManagerEnumerable({initialAdmin_: admin})); } } diff --git a/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol index 30e2793b4..169c5c2a3 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol @@ -9,7 +9,7 @@ import { } from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4HubConfiguratorDeployProcedure is AaveV4DeployProcedureBase { function _deployHubConfigurator(address owner) internal returns (address) { - _validateZeroAddress(owner, 'owner'); + require(owner != address(0), 'invalid owner'); return Create2Utils.create2Deploy( SALT, diff --git a/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol index 4e08f928a..961579e2b 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol @@ -9,7 +9,7 @@ import { } from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4HubDeployProcedure is AaveV4DeployProcedureBase { function _deployHub(address accessManager) internal returns (address) { - _validateZeroAddress(accessManager, 'access manager'); + require(accessManager != address(0), 'invalid access manager'); return Create2Utils.create2Deploy( SALT, diff --git a/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol index d22a919f8..0f90d5b19 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol @@ -9,7 +9,7 @@ import { } from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4InterestRateStrategyDeployProcedure is AaveV4DeployProcedureBase { function _deployInterestRateStrategy(address hub) internal returns (address) { - require(hub != address(0), InvalidParam('hub')); + require(hub != address(0), 'invalid hub'); return Create2Utils.create2Deploy( SALT, diff --git a/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol index 6c1822540..ac04bfa53 100644 --- a/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol @@ -12,8 +12,8 @@ contract AaveV4NativeTokenGatewayDeployProcedure is AaveV4DeployProcedureBase { address nativeWrapper, address owner ) internal returns (address) { - _validateZeroAddress(nativeWrapper, 'native wrapper'); - _validateZeroAddress(owner, 'owner'); + require(nativeWrapper != address(0), 'invalid native wrapper'); + require(owner != address(0), 'invalid owner'); return Create2Utils.create2Deploy( SALT, diff --git a/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol index e500435e1..beec26909 100644 --- a/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol @@ -9,7 +9,7 @@ import { } from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4SignatureGatewayDeployProcedure is AaveV4DeployProcedureBase { function _deploySignatureGateway(address owner) internal returns (address) { - _validateZeroAddress(owner, 'owner'); + require(owner != address(0), 'invalid owner'); return Create2Utils.create2Deploy( SALT, diff --git a/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol index 0f82bc5f0..eedaed73b 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol @@ -10,9 +10,9 @@ contract AaveV4AaveOracleDeployProcedure is AaveV4DeployProcedureBase { uint8 decimals_, string memory description_ ) internal returns (address) { - _validateZeroAddress(spoke_, 'spoke'); - require(decimals_ > 0, InvalidParam('oracle decimals')); - require(bytes(description_).length > 0, InvalidParam('oracle description')); + require(spoke_ != address(0), 'invalid spoke'); + require(decimals_ > 0, 'invalid oracle decimals'); + require(bytes(description_).length > 0, 'invalid oracle description'); // AaveOracle must be deployed via create to compute the predicted address via without inputs return address(new AaveOracle({spoke_: spoke_, decimals_: decimals_, description_: description_})); diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol index 2110fa80b..d5690ee8e 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol @@ -10,7 +10,7 @@ import { contract AaveV4SpokeConfiguratorDeployProcedure is AaveV4DeployProcedureBase { function _deploySpokeConfigurator(address owner) internal returns (address) { - _validateZeroAddress(owner, 'owner'); + require(owner != address(0), 'invalid owner'); return Create2Utils.create2Deploy( SALT, diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol index eda4f9e7e..f842eb9ad 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol @@ -18,9 +18,9 @@ contract AaveV4SpokeDeployProcedure is AaveV4DeployProcedureBase { address accessManager, address oracle ) internal returns (address spokeProxy, address spokeImplementation) { - _validateZeroAddress(spokeProxyAdminOwner, 'spoke proxy admin owner'); - _validateZeroAddress(accessManager, 'access manager'); - _validateZeroAddress(oracle, 'oracle'); + require(spokeProxyAdminOwner != address(0), 'invalid spoke proxy admin owner'); + require(accessManager != address(0), 'invalid access manager'); + require(oracle != address(0), 'invalid oracle'); spokeImplementation = Create2Utils.create2Deploy( SALT, abi.encodePacked(type(SpokeInstance).creationCode, abi.encode(oracle)) diff --git a/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol index 62ead18aa..b8808febd 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol @@ -7,8 +7,8 @@ import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4Deploy contract AaveV4TreasurySpokeDeployProcedure is AaveV4DeployProcedureBase { function _deployTreasurySpoke(address owner, address hub) internal returns (address) { - _validateZeroAddress(owner, 'owner'); - _validateZeroAddress(hub, 'hub'); + require(owner != address(0), 'invalid owner'); + require(hub != address(0), 'invalid hub'); return address(new TreasurySpoke({owner_: owner, hub_: hub})); } } diff --git a/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol index f1db0eccb..8537647fd 100644 --- a/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4AccessManagerRolesProcedure.sol @@ -12,9 +12,9 @@ library AaveV4AccessManagerRolesProcedure { address adminToAdd, address adminToRemove ) internal { - require(accessManager != address(0), AaveV4DeployProcedureBase.InvalidParam('access manager')); - require(adminToAdd != address(0), AaveV4DeployProcedureBase.InvalidParam('admin to add')); - require(adminToRemove != address(0), AaveV4DeployProcedureBase.InvalidParam('admin to remove')); + require(accessManager != address(0), 'invalid access manager'); + require(adminToAdd != address(0), 'invalid admin to add'); + require(adminToRemove != address(0), 'invalid admin to remove'); IAccessManager(accessManager).grantRole({ roleId: Roles.DEFAULT_ADMIN_ROLE, account: adminToAdd, diff --git a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol index 3512f21c7..496726537 100644 --- a/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4HubRolesProcedure.sol @@ -69,12 +69,12 @@ library AaveV4HubRolesProcedure { } function _validateAccessManagerAndHub(address accessManager, address hub) private pure { - require(accessManager != address(0), AaveV4DeployProcedureBase.InvalidParam('access manager')); - require(hub != address(0), AaveV4DeployProcedureBase.InvalidParam('hub')); + require(accessManager != address(0), 'invalid access manager'); + require(hub != address(0), 'invalid hub'); } function _validateAccessManagerAndAdmin(address accessManager, address admin) private pure { - require(accessManager != address(0), AaveV4DeployProcedureBase.InvalidParam('access manager')); - require(admin != address(0), AaveV4DeployProcedureBase.InvalidParam('admin')); + require(accessManager != address(0), 'invalid access manager'); + require(admin != address(0), 'invalid admin'); } } diff --git a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol index 8f122afed..04f38ff0e 100644 --- a/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol +++ b/src/deployments/procedures/roles/AaveV4SpokeRolesProcedure.sol @@ -76,12 +76,12 @@ library AaveV4SpokeRolesProcedure { } function _validateAccessManagerAndSpoke(address accessManager, address spoke) private pure { - require(accessManager != address(0), AaveV4DeployProcedureBase.InvalidParam('access manager')); - require(spoke != address(0), AaveV4DeployProcedureBase.InvalidParam('spoke')); + require(accessManager != address(0), 'invalid access manager'); + require(spoke != address(0), 'invalid spoke'); } function _validateAccessManagerAndAdmin(address accessManager, address admin) private pure { - require(accessManager != address(0), AaveV4DeployProcedureBase.InvalidParam('access manager')); - require(admin != address(0), AaveV4DeployProcedureBase.InvalidParam('admin')); + require(accessManager != address(0), 'invalid access manager'); + require(admin != address(0), 'invalid admin'); } } diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index a4519af18..c808a07d8 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import 'forge-std/StdJson.sol'; import 'forge-std/Vm.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; contract InputUtils { using stdJson for string; @@ -87,7 +88,7 @@ contract InputUtils { function _etchCreate2Factory() internal virtual { vm.etch( - 0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7, + Create2Utils.CREATE2_FACTORY, hex'7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3' ); } diff --git a/src/deployments/utils/libraries/Roles.sol b/src/deployments/utils/libraries/Roles.sol index fec1b9eb8..51c9727a8 100644 --- a/src/deployments/utils/libraries/Roles.sol +++ b/src/deployments/utils/libraries/Roles.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (c) 2025 Aave Labs -pragma solidity ^0.8.20; +pragma solidity ^0.8.0; /// @title Roles library /// @author Aave Labs diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index ae113cd69..368352a16 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -48,16 +48,12 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { checkedV4Deployment(); } - function testAaveV4BatchDeployment_withZeroAccessManagerAdmin_withRoles_revertsWithInvalidParam() - public - { + function testAaveV4BatchDeployment_withZeroAccessManagerAdmin_withRoles_reverts() public { // only reverts if grantRoles is true, as access manager admin replaces deployer as default admin _inputs.accessManagerAdmin = address(0); _inputs.grantRoles = true; - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin to add') - ); + vm.expectRevert('invalid admin to add'); this.checkedV4Deployment(); } @@ -70,13 +66,11 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { /// @dev Reverts as hubConfigurator is always deployed /// and owners are needed on initial deployment - function testAaveV4BatchDeployment_withZeroHubConfiguratorOwner() public { + function testAaveV4BatchDeployment_withZeroHubConfiguratorOwner_reverts() public { _inputs.hubConfiguratorOwner = address(0); _inputs.grantRoles = vm.randomBool(); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + vm.expectRevert('invalid owner'); this.checkedV4Deployment(); } @@ -93,9 +87,9 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { _inputs.hubLabels = new string[](0); } - (bool isExpectedError, bytes memory errorSelector) = _getExpectedError(); + (bool isExpectedError, bytes memory errorMessage) = _getExpectedError(); if (isExpectedError) { - vm.expectRevert(errorSelector); + vm.expectRevert(errorMessage); this.checkedV4Deployment(); } else { checkedV4Deployment(); @@ -112,34 +106,28 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { _inputs.spokeLabels = new string[](0); } - (bool isExpectedError, bytes memory errorSelector) = _getExpectedError(); + (bool isExpectedError, bytes memory errorMessage) = _getExpectedError(); if (isExpectedError) { - vm.expectRevert(errorSelector); + vm.expectRevert(errorMessage); this.checkedV4Deployment(); } else { checkedV4Deployment(); } } - function testAaveV4BatchDeployment_withZeroSpokeConfiguratorOwner() public { + function testAaveV4BatchDeployment_withZeroSpokeConfiguratorOwner_reverts() public { _inputs.spokeConfiguratorOwner = address(0); _inputs.grantRoles = vm.randomBool(); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + vm.expectRevert('invalid owner'); this.checkedV4Deployment(); } - function testAaveV4BatchDeployment_withZeroSpokeConfiguratorOwner_withoutRoles_revertsWithInvalidParam() - public - { + function testAaveV4BatchDeployment_withZeroSpokeConfiguratorOwner_withoutRoles_reverts() public { _inputs.spokeConfiguratorOwner = address(0); _inputs.grantRoles = false; - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + vm.expectRevert('invalid owner'); this.checkedV4Deployment(); } @@ -169,9 +157,9 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { _deployer = deployer; _inputs = deployInputs; - (bool isExpectedError, bytes memory errorSelector) = _getExpectedError(); + (bool isExpectedError, bytes memory errorMessage) = _getExpectedError(); if (isExpectedError) { - vm.expectRevert(errorSelector); + vm.expectRevert(errorMessage); this.checkedV4Deployment(); } else { checkedV4Deployment(); @@ -205,9 +193,9 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { _deployer = deployer; _inputs = deployInputs; - (bool isExpectedError, bytes memory errorSelector) = _getExpectedError(); + (bool isExpectedError, bytes memory errorMessage) = _getExpectedError(); if (isExpectedError) { - vm.expectRevert(errorSelector); + vm.expectRevert(errorMessage); this.checkedV4Deployment(); } else { checkedV4Deployment(); @@ -236,70 +224,43 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { function _getExpectedError() internal view - returns (bool isExpectedError, bytes memory errorSelector) + returns (bool isExpectedError, bytes memory errorMessage) { // deployer is initial admin for access manager - if (_deployer == address(0)) return (true, abi.encodePacked('')); + if (_deployer == address(0)) return (true, bytes('invalid deployer')); // configurators always deployed if (_inputs.spokeConfiguratorOwner == address(0)) { - return ( - true, - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + return (true, bytes('invalid owner')); } if (_inputs.hubConfiguratorOwner == address(0)) { - return ( - true, - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + return (true, bytes('invalid owner')); } // gateways only when native wrapper is set if (_inputs.nativeWrapper != address(0) && _inputs.gatewayOwner == address(0)) { - return ( - true, - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + return (true, bytes('invalid owner')); } // hubs require treasury owner when deployed if (_inputs.hubLabels.length > 0 && _inputs.treasurySpokeOwner == address(0)) { - return ( - true, - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + return (true, bytes('invalid owner')); } // spokes require proxy admin owner when deployed if (_inputs.spokeLabels.length > 0 && _inputs.spokeProxyAdminOwner == address(0)) { - return ( - true, - abi.encodeWithSelector( - AaveV4DeployProcedureBase.InvalidParam.selector, - 'spoke proxy admin owner' - ) - ); + return (true, bytes('invalid spoke proxy admin owner')); } if (_inputs.grantRoles) { if (_inputs.accessManagerAdmin == address(0)) { - return ( - true, - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') - ); + return (true, bytes('invalid admin')); } if (_inputs.hubLabels.length > 0 && _inputs.hubAdmin == address(0)) { - return ( - true, - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') - ); + return (true, bytes('invalid admin')); } if (_inputs.spokeLabels.length > 0 && _inputs.spokeAdmin == address(0)) { - return ( - true, - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') - ); + return (true, bytes('invalid admin')); } } } diff --git a/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol b/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol index 2d2928327..5738898e0 100644 --- a/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol @@ -26,9 +26,7 @@ contract AaveV4AccessManagerEnumerableDeployProcedureTest is ProceduresBase { } function test_deployAccessManagerEnumerable_reverts() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') - ); + vm.expectRevert('invalid admin'); aaveV4AccessManagerEnumerableDeployProcedureWrapper.deployAccessManagerEnumerable(address(0)); } } diff --git a/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol index f12eef96e..41e0c3b10 100644 --- a/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol @@ -19,10 +19,8 @@ contract AaveV4HubConfiguratorDeployProcedureTest is ProceduresBase { assertEq(Ownable(hubConfigurator).owner(), owner); } - function test_deployHubConfigurator_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + function test_deployHubConfigurator_reverts() public { + vm.expectRevert('invalid owner'); aaveV4HubConfiguratorDeployProcedureWrapper.deployHubConfigurator(address(0)); } } diff --git a/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol index 936bf86ce..1b25ba9df 100644 --- a/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol @@ -17,10 +17,8 @@ contract AaveV4HubDeployProcedureTest is ProceduresBase { assertEq(IHub(hub).authority(), accessManager); } - function test_deployHub_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_deployHub_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4HubDeployProcedureWrapper.deployHub(address(0)); } } diff --git a/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol index 4e0bbbcc4..7cb9b18db 100644 --- a/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol @@ -19,8 +19,8 @@ contract AaveV4InterestRateStrategyDeployProcedureTest is ProceduresBase { assertEq(IAssetInterestRateStrategy(interestRateStrategy).HUB(), hub); } - function test_deployInterestRateStrategy_revertsWithInvalidParam() public { - vm.expectRevert(abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'hub')); + function test_deployInterestRateStrategy_reverts() public { + vm.expectRevert('invalid hub'); aaveV4InterestRateStrategyDeployProcedureWrapper.deployInterestRateStrategy(address(0)); } } diff --git a/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol b/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol index 6f76affa1..0141222cf 100644 --- a/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol @@ -19,15 +19,11 @@ contract AaveV4NativeTokenGatewayDeployProcedureTest is ProceduresBase { assertEq(Ownable(nativeTokenGateway).owner(), owner); } - function test_deployNativeTokenGateway_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'native wrapper') - ); + function test_deployNativeTokenGateway_reverts() public { + vm.expectRevert('invalid native wrapper'); aaveV4NativeTokenGatewayDeployProcedureWrapper.deployNativeTokenGateway(address(0), owner); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + vm.expectRevert('invalid owner'); aaveV4NativeTokenGatewayDeployProcedureWrapper.deployNativeTokenGateway( nativeWrapper, address(0) diff --git a/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol b/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol index 05963faeb..411a0e697 100644 --- a/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol @@ -20,10 +20,8 @@ contract AaveV4SignatureGatewayDeployProcedureTest is ProceduresBase { assertEq(Ownable(signatureGateway).owner(), owner); } - function test_deploySignatureGateway_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + function test_deploySignatureGateway_reverts() public { + vm.expectRevert('invalid owner'); aaveV4SignatureGatewayDeployProcedureWrapper.deploySignatureGateway(address(0)); } } diff --git a/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol b/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol index 38f87c192..722190a18 100644 --- a/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol +++ b/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol @@ -23,29 +23,23 @@ contract AaveV4AccessManagerRolesProcedureTest is ProceduresBase { assertEq(executionDelay, 0); } - function test_grantRootAdminRole_revertsWithInvalidParam() public { + function test_grantRootAdminRole_reverts() public { address newAdmin = makeAddr('newAdmin'); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + vm.expectRevert('invalid access manager'); aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole({ accessManager: address(0), adminToAdd: newAdmin, adminToRemove: address(0) }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin to add') - ); + vm.expectRevert('invalid admin to add'); aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole({ accessManager: accessManager, adminToAdd: address(0), adminToRemove: newAdmin }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin to remove') - ); + vm.expectRevert('invalid admin to remove'); aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole({ accessManager: accessManager, adminToAdd: newAdmin, diff --git a/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol b/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol index 9dafc985b..7f0b391d2 100644 --- a/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol +++ b/tests/deployments/procedures/deploy/roles/AaveV4HubRolesProcedure.t.sol @@ -11,84 +11,66 @@ contract AaveV4HubRolesProcedureTest is ProceduresBase { aaveV4HubRolesProcedureWrapper = new AaveV4HubRolesProcedureWrapper(); } - function test_grantHubAdminRole_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_grantHubAdminRole_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4HubRolesProcedureWrapper.grantHubAdminRole({accessManager: address(0), admin: admin}); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') - ); + vm.expectRevert('invalid admin'); aaveV4HubRolesProcedureWrapper.grantHubAdminRole({ accessManager: accessManager, admin: address(0) }); } - function test_grantHubFeeMinterRole_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_grantHubFeeMinterRole_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4HubRolesProcedureWrapper.grantHubFeeMinterRole({accessManager: address(0), admin: admin}); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') - ); + vm.expectRevert('invalid admin'); aaveV4HubRolesProcedureWrapper.grantHubFeeMinterRole({ accessManager: accessManager, admin: address(0) }); } - function test_grantHubConfiguratorRole_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_grantHubConfiguratorRole_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4HubRolesProcedureWrapper.grantHubConfiguratorRole({ accessManager: address(0), admin: admin }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') - ); + vm.expectRevert('invalid admin'); aaveV4HubRolesProcedureWrapper.grantHubConfiguratorRole({ accessManager: accessManager, admin: address(0) }); } - function test_setupHubRoles_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_setupHubRoles_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4HubRolesProcedureWrapper.setupHubRoles({accessManager: address(0), hub: hub}); - vm.expectRevert(abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'hub')); + vm.expectRevert('invalid hub'); aaveV4HubRolesProcedureWrapper.setupHubRoles({accessManager: accessManager, hub: address(0)}); } - function test_setupHubFeeMinterRole_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_setupHubFeeMinterRole_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4HubRolesProcedureWrapper.setupHubFeeMinterRole({accessManager: address(0), hub: hub}); - vm.expectRevert(abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'hub')); + vm.expectRevert('invalid hub'); aaveV4HubRolesProcedureWrapper.setupHubFeeMinterRole({ accessManager: accessManager, hub: address(0) }); } - function test_setupHubConfiguratorRole_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_setupHubConfiguratorRole_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4HubRolesProcedureWrapper.setupHubConfiguratorRole({accessManager: address(0), hub: hub}); - vm.expectRevert(abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'hub')); + vm.expectRevert('invalid hub'); aaveV4HubRolesProcedureWrapper.setupHubConfiguratorRole({ accessManager: accessManager, hub: address(0) diff --git a/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol b/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol index 6c4d6612a..680e5543a 100644 --- a/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol +++ b/tests/deployments/procedures/deploy/roles/AaveV4SpokeRolesProcedure.t.sol @@ -11,102 +11,78 @@ contract AaveV4SpokeRolesProcedureTest is ProceduresBase { aaveV4SpokeRolesProcedureWrapper = new AaveV4SpokeRolesProcedureWrapper(); } - function test_grantSpokeAdminRole_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_grantSpokeAdminRole_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4SpokeRolesProcedureWrapper.grantSpokeAdminRole({accessManager: address(0), admin: admin}); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') - ); + vm.expectRevert('invalid admin'); aaveV4SpokeRolesProcedureWrapper.grantSpokeAdminRole({ accessManager: accessManager, admin: address(0) }); } - function test_grantSpokePositionUpdaterRole_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_grantSpokePositionUpdaterRole_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4SpokeRolesProcedureWrapper.grantSpokePositionUpdaterRole({ accessManager: address(0), admin: admin }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') - ); + vm.expectRevert('invalid admin'); aaveV4SpokeRolesProcedureWrapper.grantSpokePositionUpdaterRole({ accessManager: accessManager, admin: address(0) }); } - function test_grantSpokeConfiguratorRole_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_grantSpokeConfiguratorRole_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4SpokeRolesProcedureWrapper.grantSpokeConfiguratorRole({ accessManager: address(0), admin: admin }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'admin') - ); + vm.expectRevert('invalid admin'); aaveV4SpokeRolesProcedureWrapper.grantSpokeConfiguratorRole({ accessManager: accessManager, admin: address(0) }); } - function test_setupSpokeRoles_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_setupSpokeRoles_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4SpokeRolesProcedureWrapper.setupSpokeRoles({accessManager: address(0), spoke: spoke}); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'spoke') - ); + vm.expectRevert('invalid spoke'); aaveV4SpokeRolesProcedureWrapper.setupSpokeRoles({ accessManager: accessManager, spoke: address(0) }); } - function test_setupSpokePositionUpdaterRole_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_setupSpokePositionUpdaterRole_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4SpokeRolesProcedureWrapper.setupSpokePositionUpdaterRole({ accessManager: address(0), spoke: spoke }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'spoke') - ); + vm.expectRevert('invalid spoke'); aaveV4SpokeRolesProcedureWrapper.setupSpokePositionUpdaterRole({ accessManager: accessManager, spoke: address(0) }); } - function test_setupSpokeConfiguratorRole_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + function test_setupSpokeConfiguratorRole_reverts() public { + vm.expectRevert('invalid access manager'); aaveV4SpokeRolesProcedureWrapper.setupSpokeConfiguratorRole({ accessManager: address(0), spoke: spoke }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'spoke') - ); + vm.expectRevert('invalid spoke'); aaveV4SpokeRolesProcedureWrapper.setupSpokeConfiguratorRole({ accessManager: accessManager, spoke: address(0) diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol index 3db5f6f11..8090b647c 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol @@ -22,28 +22,22 @@ contract AaveV4AaveOracleDeployProcedureTest is ProceduresBase { assertEq(IAaveOracle(aaveOracle).DESCRIPTION(), oracleDescription); } - function test_deployAaveOracle_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'spoke') - ); + function test_deployAaveOracle_reverts() public { + vm.expectRevert('invalid spoke'); aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle({ spoke: address(0), decimals: oracleDecimals, description: oracleDescription }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'oracle decimals') - ); + vm.expectRevert('invalid oracle decimals'); aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle({ spoke: spoke, decimals: 0, description: oracleDescription }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'oracle description') - ); + vm.expectRevert('invalid oracle description'); aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle({ spoke: spoke, decimals: oracleDecimals, diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol index 3f65a8935..e10486c5c 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol @@ -19,10 +19,8 @@ contract AaveV4SpokeConfiguratorDeployProcedureTest is ProceduresBase { assertEq(Ownable(spokeConfigurator).owner(), owner); } - function test_deploySpokeConfigurator_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + function test_deploySpokeConfigurator_reverts() public { + vm.expectRevert('invalid owner'); aaveV4SpokeConfiguratorDeployProcedureWrapper.deploySpokeConfigurator(address(0)); } } diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol index 619a9e402..1b973e014 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol @@ -21,31 +21,22 @@ contract AaveV4SpokeDeployProcedureTest is ProceduresBase { assertEq(ISpoke(spokeProxy).ORACLE(), aaveOracle); } - function test_deployUpgradableSpokeInstance_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector( - AaveV4DeployProcedureBase.InvalidParam.selector, - 'spoke proxy admin owner' - ) - ); + function test_deployUpgradableSpokeInstance_reverts() public { + vm.expectRevert('invalid spoke proxy admin owner'); aaveV4SpokeDeployProcedureWrapper.deployUpgradableSpokeInstance({ spokeProxyAdminOwner: address(0), accessManager: accessManager, oracle: aaveOracle }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'access manager') - ); + vm.expectRevert('invalid access manager'); aaveV4SpokeDeployProcedureWrapper.deployUpgradableSpokeInstance({ spokeProxyAdminOwner: owner, accessManager: address(0), oracle: aaveOracle }); - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'oracle') - ); + vm.expectRevert('invalid oracle'); aaveV4SpokeDeployProcedureWrapper.deployUpgradableSpokeInstance({ spokeProxyAdminOwner: owner, accessManager: accessManager, diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol index 30ed9275d..dc9a51526 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol @@ -21,13 +21,11 @@ contract AaveV4TreasurySpokeDeployProcedureTest is ProceduresBase { assertEq(address(ITreasurySpoke(treasurySpoke).HUB()), hub); } - function test_deployTreasurySpoke_revertsWithInvalidParam() public { - vm.expectRevert( - abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'owner') - ); + function test_deployTreasurySpoke_reverts() public { + vm.expectRevert('invalid owner'); aaveV4TreasurySpokeDeployProcedureWrapper.deployTreasurySpoke({owner: address(0), hub: hub}); - vm.expectRevert(abi.encodeWithSelector(AaveV4DeployProcedureBase.InvalidParam.selector, 'hub')); + vm.expectRevert('invalid hub'); aaveV4TreasurySpokeDeployProcedureWrapper.deployTreasurySpoke({owner: owner, hub: address(0)}); } } diff --git a/tests/deployments/utils/libraries/Create2Utils.t.sol b/tests/deployments/utils/libraries/Create2Utils.t.sol index debcaa2df..491ec43b0 100644 --- a/tests/deployments/utils/libraries/Create2Utils.t.sol +++ b/tests/deployments/utils/libraries/Create2Utils.t.sol @@ -84,7 +84,7 @@ contract Create2UtilsTest is Test, InputUtils { ); } - function testIsContractDeployed_fuzz(address addr) public { + function testIsContractDeployed_fuzz(address addr) public view { vm.assume(addr != address(0)); assumeUnusedAddress(addr); assertFalse(_harness.isContractDeployed(addr)); @@ -112,14 +112,14 @@ contract Create2UtilsTest is Test, InputUtils { assertEq(_harness.computeCreateAddress(deployer, nonce), expected); } - function testComputeCreate2Address_fuzz(bytes32 salt, bytes32 initcode) public { + function testComputeCreate2Address_fuzz(bytes32 salt, bytes32 initcode) public view { vm.assume(salt != bytes32(0)); vm.assume(initcode != bytes32(0)); address expected = _harness.computeCreate2Address(salt, initcode); assertEq(_harness.computeCreate2Address(salt, initcode), expected); } - function testComputeCreate2Address_fuzz(bytes32 salt, bytes memory bytecode) public { + function testComputeCreate2Address_fuzz(bytes32 salt, bytes memory bytecode) public view { vm.assume(salt != bytes32(0)); vm.assume(bytecode.length > 0); address expected = _harness.computeCreate2Address(salt, keccak256(abi.encodePacked(bytecode))); From b8acf9c86e37812c78a81950326d95686012bfd0 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 19 Dec 2025 18:34:52 -0600 Subject: [PATCH 60/62] fix: pr comments --- config/AaveV4DeployInput.json | 3 +- snapshots/Hub.Operations.json | 2 +- snapshots/SignatureGateway.Operations.json | 8 +- .../Spoke.Operations.ZeroRiskPremium.json | 2 +- snapshots/Spoke.Operations.json | 2 +- src/deployments/batches/AaveV4AccessBatch.sol | 7 +- .../batches/AaveV4ConfiguratorBatch.sol | 12 ++- .../batches/AaveV4GatewayBatch.sol | 10 ++- src/deployments/batches/AaveV4HubBatch.sol | 15 +++- .../batches/AaveV4SpokeInstanceBatch.sol | 22 +++-- .../orchestration/AaveV4DeployBase.sol | 28 +++--- .../AaveV4DeployOrchestration.sol | 90 +++++++++++++------ .../procedures/AaveV4DeployProcedureBase.sol | 3 +- ...AccessManagerEnumerableDeployProcedure.sol | 11 ++- .../AaveV4HubConfiguratorDeployProcedure.sol | 11 ++- .../deploy/hub/AaveV4HubDeployProcedure.sol | 11 ++- ...eV4InterestRateStrategyDeployProcedure.sol | 11 ++- ...aveV4NativeTokenGatewayDeployProcedure.sol | 12 +-- .../AaveV4SignatureGatewayDeployProcedure.sol | 11 ++- .../spoke/AaveV4AaveOracleDeployProcedure.sol | 3 +- ...AaveV4SpokeConfiguratorDeployProcedure.sol | 11 +-- .../spoke/AaveV4SpokeDeployProcedure.sol | 14 ++- .../AaveV4TreasurySpokeDeployProcedure.sol | 15 +++- src/deployments/utils/InputUtils.sol | 2 + .../utils/libraries/Create2Utils.sol | 18 ++-- tests/Base.t.sol | 7 +- tests/deployments/AaveV4BatchDeployment.t.sol | 3 +- .../batches/AaveV4AccessBatch.t.sol | 2 +- tests/deployments/batches/BatchBase.t.sol | 11 ++- .../orchestration/AaveV4TestOrchestration.sol | 35 ++++---- .../procedures/ProceduresBase.t.sol | 3 +- ...cessManagerEnumerableDeployProcedure.t.sol | 7 +- ...AaveV4HubConfiguratorDeployProcedure.t.sol | 8 +- .../deploy/hub/AaveV4HubDeployProcedure.t.sol | 4 +- ...4InterestRateStrategyDeployProcedure.t.sol | 7 +- ...eV4NativeTokenGatewayDeployProcedure.t.sol | 17 ++-- ...aveV4SignatureGatewayDeployProcedure.t.sol | 5 +- .../AaveV4AccessManagerRolesProcedure.t.sol | 10 +-- .../AaveV4AaveOracleDeployProcedure.t.sol | 12 ++- ...veV4SpokeConfiguratorDeployProcedure.t.sol | 4 +- .../spoke/AaveV4SpokeDeployProcedure.t.sol | 11 ++- .../AaveV4TreasurySpokeDeployProcedure.t.sol | 15 +++- .../utils/libraries/Create2Utils.t.sol | 9 +- ...AaveV4AaveOracleDeployProcedureWrapper.sol | 5 +- ...anagerEnumerableDeployProcedureWrapper.sol | 4 +- ...4HubConfiguratorDeployProcedureWrapper.sol | 4 +- .../AaveV4HubDeployProcedureWrapper.sol | 4 +- ...restRateStrategyDeployProcedureWrapper.sol | 4 +- ...tiveTokenGatewayDeployProcedureWrapper.sol | 5 +- ...SignatureGatewayDeployProcedureWrapper.sol | 4 +- ...pokeConfiguratorDeployProcedureWrapper.sol | 4 +- .../AaveV4SpokeDeployProcedureWrapper.sol | 5 +- ...eV4TreasurySpokeDeployProcedureWrapper.sol | 8 +- tests/unit/Spoke/Spoke.DynamicConfig.t.sol | 4 +- 54 files changed, 342 insertions(+), 213 deletions(-) diff --git a/config/AaveV4DeployInput.json b/config/AaveV4DeployInput.json index 6dbfb8b7b..1271033b3 100644 --- a/config/AaveV4DeployInput.json +++ b/config/AaveV4DeployInput.json @@ -10,5 +10,6 @@ "nativeWrapper": "0x0000000000000000000000000000000000000006", "grantRoles": true, "hubLabels": ["Hub 1", "Hub 2", "Hub 3"], - "spokeLabels": ["Spoke 1", "Spoke 2", "Spoke 3"] + "spokeLabels": ["Spoke 1", "Spoke 2", "Spoke 3"], + "salt": "salt" } diff --git a/snapshots/Hub.Operations.json b/snapshots/Hub.Operations.json index 6ecc85318..57cc062f4 100644 --- a/snapshots/Hub.Operations.json +++ b/snapshots/Hub.Operations.json @@ -11,7 +11,7 @@ "remove: partial": "81640", "reportDeficit": "115225", "restore: full": "80471", - "restore: full - with transfer": "173415", + "restore: full - with transfer": "173421", "restore: partial": "89137", "restore: partial - with transfer": "147439", "transferShares": "71192" diff --git a/snapshots/SignatureGateway.Operations.json b/snapshots/SignatureGateway.Operations.json index 50851bd0d..e87d6eaea 100644 --- a/snapshots/SignatureGateway.Operations.json +++ b/snapshots/SignatureGateway.Operations.json @@ -1,10 +1,10 @@ { "borrowWithSig": "215605", - "repayWithSig": "188872", - "setSelfAsUserPositionManagerWithSig": "75402", - "setUsingAsCollateralWithSig": "85065", + "repayWithSig": "188860", + "setSelfAsUserPositionManagerWithSig": "75390", + "setUsingAsCollateralWithSig": "85053", "supplyWithSig": "153205", "updateUserDynamicConfigWithSig": "62769", "updateUserRiskPremiumWithSig": "61579", - "withdrawWithSig": "131686" + "withdrawWithSig": "131696" } \ No newline at end of file diff --git a/snapshots/Spoke.Operations.ZeroRiskPremium.json b/snapshots/Spoke.Operations.ZeroRiskPremium.json index ed2faa23d..9b4f9ec68 100644 --- a/snapshots/Spoke.Operations.ZeroRiskPremium.json +++ b/snapshots/Spoke.Operations.ZeroRiskPremium.json @@ -10,7 +10,7 @@ "permitReserve + supply + enable collateral (multicall)": "160573", "repay: full": "126094", "repay: partial": "130983", - "setUserPositionManagerWithSig: disable": "44846", + "setUserPositionManagerWithSig: disable": "44822", "setUserPositionManagerWithSig: enable": "68875", "supply + enable collateral (multicall)": "140624", "supply: 0 borrows, collateral disabled": "123679", diff --git a/snapshots/Spoke.Operations.json b/snapshots/Spoke.Operations.json index deed9c95d..316fe74ec 100644 --- a/snapshots/Spoke.Operations.json +++ b/snapshots/Spoke.Operations.json @@ -10,7 +10,7 @@ "permitReserve + supply + enable collateral (multicall)": "160573", "repay: full": "120256", "repay: partial": "139545", - "setUserPositionManagerWithSig: disable": "44846", + "setUserPositionManagerWithSig: disable": "44822", "setUserPositionManagerWithSig: enable": "68875", "supply + enable collateral (multicall)": "140624", "supply: 0 borrows, collateral disabled": "123679", diff --git a/src/deployments/batches/AaveV4AccessBatch.sol b/src/deployments/batches/AaveV4AccessBatch.sol index ba49a42c0..438868e6b 100644 --- a/src/deployments/batches/AaveV4AccessBatch.sol +++ b/src/deployments/batches/AaveV4AccessBatch.sol @@ -10,8 +10,11 @@ import { contract AaveV4AccessBatch is AaveV4AccessManagerEnumerableDeployProcedure { BatchReports.AccessBatchReport internal _report; - constructor(address admin_) { - address accessManager = _deployAccessManagerEnumerable(admin_); + constructor(address admin_, bytes32 salt_) { + address accessManager = _deployAccessManagerEnumerable( + admin_, + keccak256(abi.encodePacked(SALT, salt_, 'accessManager')) + ); _report = BatchReports.AccessBatchReport({accessManager: accessManager}); } diff --git a/src/deployments/batches/AaveV4ConfiguratorBatch.sol b/src/deployments/batches/AaveV4ConfiguratorBatch.sol index 11737720a..c83e7bf8d 100644 --- a/src/deployments/batches/AaveV4ConfiguratorBatch.sol +++ b/src/deployments/batches/AaveV4ConfiguratorBatch.sol @@ -16,9 +16,15 @@ contract AaveV4ConfiguratorBatch is { BatchReports.ConfiguratorBatchReport internal _report; - constructor(address hubConfiguratorOwner_, address spokeConfiguratorOwner_) { - address hubConfigurator = _deployHubConfigurator(hubConfiguratorOwner_); - address spokeConfigurator = _deploySpokeConfigurator(spokeConfiguratorOwner_); + constructor(address hubConfiguratorOwner_, address spokeConfiguratorOwner_, bytes32 salt_) { + address hubConfigurator = _deployHubConfigurator( + hubConfiguratorOwner_, + keccak256(abi.encodePacked(SALT, salt_, 'hubConfigurator')) + ); + address spokeConfigurator = _deploySpokeConfigurator( + spokeConfiguratorOwner_, + keccak256(abi.encodePacked(SALT, salt_, 'spokeConfigurator')) + ); _report = BatchReports.ConfiguratorBatchReport({ hubConfigurator: hubConfigurator, diff --git a/src/deployments/batches/AaveV4GatewayBatch.sol b/src/deployments/batches/AaveV4GatewayBatch.sol index 328c662ba..9e69db2bd 100644 --- a/src/deployments/batches/AaveV4GatewayBatch.sol +++ b/src/deployments/batches/AaveV4GatewayBatch.sol @@ -16,12 +16,16 @@ contract AaveV4GatewayBatch is { BatchReports.GatewaysBatchReport internal _report; - constructor(address owner_, address nativeWrapper_) { + constructor(address owner_, address nativeWrapper_, bytes32 salt_) { address nativeGateway = _deployNativeTokenGateway({ nativeWrapper: nativeWrapper_, - owner: owner_ + owner: owner_, + salt: keccak256(abi.encodePacked(SALT, salt_, 'nativeGateway')) }); - address signatureGateway = _deploySignatureGateway(owner_); + address signatureGateway = _deploySignatureGateway( + owner_, + keccak256(abi.encodePacked(SALT, salt_, 'signatureGateway')) + ); _report = BatchReports.GatewaysBatchReport({ nativeGateway: nativeGateway, diff --git a/src/deployments/batches/AaveV4HubBatch.sol b/src/deployments/batches/AaveV4HubBatch.sol index d879c1184..3fe889d32 100644 --- a/src/deployments/batches/AaveV4HubBatch.sol +++ b/src/deployments/batches/AaveV4HubBatch.sol @@ -20,10 +20,17 @@ contract AaveV4HubBatch is { BatchReports.HubBatchReport internal _report; - constructor(address treasurySpokeOwner_, address accessManager_) { - address hub = _deployHub(accessManager_); - address irStrategy = _deployInterestRateStrategy(hub); - address treasurySpoke = _deployTreasurySpoke(treasurySpokeOwner_, hub); + constructor(address treasurySpokeOwner_, address accessManager_, bytes32 salt_) { + address hub = _deployHub(accessManager_, keccak256(abi.encodePacked(SALT, salt_, 'hub'))); + address irStrategy = _deployInterestRateStrategy( + hub, + keccak256(abi.encodePacked(SALT, salt_, 'irStrategy')) + ); + address treasurySpoke = _deployTreasurySpoke( + treasurySpokeOwner_, + hub, + keccak256(abi.encodePacked(SALT, salt_, 'treasurySpoke')) + ); _report = BatchReports.HubBatchReport({ hub: hub, diff --git a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol index 1eff60724..a521876ea 100644 --- a/src/deployments/batches/AaveV4SpokeInstanceBatch.sol +++ b/src/deployments/batches/AaveV4SpokeInstanceBatch.sol @@ -21,25 +21,29 @@ contract AaveV4SpokeInstanceBatch is AaveV4SpokeDeployProcedure, AaveV4AaveOracl address spokeProxyAdminOwner_, address accessManager_, uint8 oracleDecimals_, - string memory oracleDescription_ + string memory oracleDescription_, + bytes32 salt_ ) { + bytes32 spokeInstanceSalt = keccak256(abi.encodePacked(SALT, salt_, 'spokeInstance')); // starting from contract nonce of 1 address predictedOracle = Create2Utils.computeCreateAddress(address(this), 1); - address predictedSpokeProxy = _computeSpokeInstanceAddress( - SALT, - predictedOracle, - spokeProxyAdminOwner_, - accessManager_ - ); + address predictedSpokeProxy = _computeSpokeInstanceAddress({ + spokeProxyAdminOwner: spokeProxyAdminOwner_, + accessManager: accessManager_, + oracle: predictedOracle, + salt: spokeInstanceSalt + }); address aaveOracle = _deployAaveOracle( predictedSpokeProxy, oracleDecimals_, - oracleDescription_ + oracleDescription_, + keccak256(abi.encodePacked(SALT, salt_, 'aaveOracle')) ); (address spokeProxy, address spokeImplementation) = _deployUpgradableSpokeInstance({ spokeProxyAdminOwner: spokeProxyAdminOwner_, accessManager: accessManager_, - oracle: aaveOracle + oracle: aaveOracle, + salt: spokeInstanceSalt }); assert(aaveOracle == predictedOracle); diff --git a/src/deployments/orchestration/AaveV4DeployBase.sol b/src/deployments/orchestration/AaveV4DeployBase.sol index 1084f22ad..2507fdf95 100644 --- a/src/deployments/orchestration/AaveV4DeployBase.sol +++ b/src/deployments/orchestration/AaveV4DeployBase.sol @@ -13,28 +13,32 @@ import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInsta library AaveV4DeployBase { function deployAccessBatch( - address admin + address admin, + bytes32 salt ) internal returns (BatchReports.AccessBatchReport memory) { - AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin); + AaveV4AccessBatch accessBatch = new AaveV4AccessBatch(admin, salt); return accessBatch.getReport(); } function deployConfiguratorBatch( address hubConfiguratorOwner, - address spokeConfiguratorOwner + address spokeConfiguratorOwner, + bytes32 salt ) internal returns (BatchReports.ConfiguratorBatchReport memory) { AaveV4ConfiguratorBatch configuratorBatch = new AaveV4ConfiguratorBatch( hubConfiguratorOwner, - spokeConfiguratorOwner + spokeConfiguratorOwner, + salt ); return configuratorBatch.getReport(); } function deployHubBatch( address treasurySpokeOwner, - address accessManager + address accessManager, + bytes32 salt ) internal returns (BatchReports.HubBatchReport memory) { - AaveV4HubBatch hubBatch = new AaveV4HubBatch(treasurySpokeOwner, accessManager); + AaveV4HubBatch hubBatch = new AaveV4HubBatch(treasurySpokeOwner, accessManager, salt); return hubBatch.getReport(); } @@ -43,24 +47,28 @@ library AaveV4DeployBase { address accessManager, uint8 oracleDecimals, string memory oracleSuffix, - string memory label + string memory label, + bytes32 salt ) internal returns (BatchReports.SpokeInstanceBatchReport memory) { AaveV4SpokeInstanceBatch spokeInstanceBatch = new AaveV4SpokeInstanceBatch({ spokeProxyAdminOwner_: spokeProxyAdminOwner, accessManager_: accessManager, oracleDecimals_: oracleDecimals, - oracleDescription_: string.concat(label, oracleSuffix) + oracleDescription_: string.concat(label, oracleSuffix), + salt_: salt }); return spokeInstanceBatch.getReport(); } function deployGatewaysBatch( address owner, - address nativeWrapper + address nativeWrapper, + bytes32 salt ) internal returns (BatchReports.GatewaysBatchReport memory) { AaveV4GatewayBatch gatewayBatch = new AaveV4GatewayBatch({ owner_: owner, - nativeWrapper_: nativeWrapper + nativeWrapper_: nativeWrapper, + salt_: salt }); return gatewayBatch.getReport(); } diff --git a/src/deployments/orchestration/AaveV4DeployOrchestration.sol b/src/deployments/orchestration/AaveV4DeployOrchestration.sol index 9fe0351b9..df9a07d73 100644 --- a/src/deployments/orchestration/AaveV4DeployOrchestration.sol +++ b/src/deployments/orchestration/AaveV4DeployOrchestration.sol @@ -36,19 +36,23 @@ library AaveV4DeployOrchestration { address deployer, InputUtils.FullDeployInputs memory deployInputs ) internal returns (OrchestrationReports.FullDeploymentReport memory report) { + bytes32 rootSalt = keccak256(abi.encode(deployInputs.salt)); + // Deploy Access Batch // initialize with deployer as access manager admin address initialAdmin = deployer; report.accessBatchReport = _deployAccessBatch({ logger: logger, - accessManagerAdmin: initialAdmin + accessManagerAdmin: initialAdmin, + salt: rootSalt }); // Deploy Configurator Batch report.configuratorBatchReport = _deployConfiguratorBatch({ logger: logger, hubConfiguratorOwner: deployInputs.hubConfiguratorOwner, - spokeConfiguratorOwner: deployInputs.spokeConfiguratorOwner + spokeConfiguratorOwner: deployInputs.spokeConfiguratorOwner, + salt: keccak256(abi.encode(rootSalt, 'config')) }); // Deploy Hub Batches @@ -56,7 +60,8 @@ library AaveV4DeployOrchestration { logger: logger, treasurySpokeOwner: deployInputs.treasurySpokeOwner, accessManager: report.accessBatchReport.accessManager, - hubLabels: deployInputs.hubLabels + hubLabels: deployInputs.hubLabels, + rootSalt: rootSalt }); // Deploy Spoke Instance Batches @@ -64,7 +69,8 @@ library AaveV4DeployOrchestration { logger: logger, spokeProxyAdminOwner: deployInputs.spokeProxyAdminOwner, accessManager: report.accessBatchReport.accessManager, - spokeLabels: deployInputs.spokeLabels + spokeLabels: deployInputs.spokeLabels, + rootSalt: rootSalt }); // Deploy Gateways Batch if native wrapper is not zero address @@ -72,7 +78,8 @@ library AaveV4DeployOrchestration { report.gatewaysBatchReport = _deployGatewayBatch({ logger: logger, gatewayOwner: deployInputs.gatewayOwner, - nativeWrapper: deployInputs.nativeWrapper + nativeWrapper: deployInputs.nativeWrapper, + salt: keccak256(abi.encode(rootSalt, 'gateways')) }); } @@ -143,11 +150,12 @@ library AaveV4DeployOrchestration { function _deployAccessBatch( Logger logger, - address accessManagerAdmin + address accessManagerAdmin, + bytes32 salt ) internal returns (BatchReports.AccessBatchReport memory report) { logger.log('...Deploying AccessBatch...'); - report = AaveV4DeployBase.deployAccessBatch({admin: accessManagerAdmin}); + report = AaveV4DeployBase.deployAccessBatch({admin: accessManagerAdmin, salt: salt}); logger.log('AccessManager', report.accessManager); logger.log(''); @@ -157,13 +165,15 @@ library AaveV4DeployOrchestration { function _deployConfiguratorBatch( Logger logger, address hubConfiguratorOwner, - address spokeConfiguratorOwner + address spokeConfiguratorOwner, + bytes32 salt ) internal returns (BatchReports.ConfiguratorBatchReport memory report) { logger.log('...Deploying ConfiguratorBatch...'); report = AaveV4DeployBase.deployConfiguratorBatch({ hubConfiguratorOwner: hubConfiguratorOwner, - spokeConfiguratorOwner: spokeConfiguratorOwner + spokeConfiguratorOwner: spokeConfiguratorOwner, + salt: salt }); logger.log('HubConfigurator', report.hubConfigurator); @@ -176,12 +186,19 @@ library AaveV4DeployOrchestration { Logger logger, address treasurySpokeOwner, address accessManager, - string[] memory hubLabels + string[] memory hubLabels, + bytes32 rootSalt ) internal returns (OrchestrationReports.HubDeploymentReport[] memory hubBatchReports) { uint256 hubCount = hubLabels.length; hubBatchReports = new OrchestrationReports.HubDeploymentReport[](hubCount); for (uint256 i; i < hubCount; ++i) { - hubBatchReports[i] = _deployHub(logger, treasurySpokeOwner, accessManager, hubLabels[i]); + hubBatchReports[i] = _deployHub({ + logger: logger, + treasurySpokeOwner: treasurySpokeOwner, + accessManager: accessManager, + label: hubLabels[i], + salt: keccak256(abi.encode(rootSalt, 'hub', hubLabels[i])) + }); } logger.log(''); return hubBatchReports; @@ -191,14 +208,16 @@ library AaveV4DeployOrchestration { Logger logger, address treasurySpokeOwner, address accessManager, - string memory label + string memory label, + bytes32 salt ) internal returns (OrchestrationReports.HubDeploymentReport memory) { OrchestrationReports.HubDeploymentReport memory hubReport; hubReport.label = label; hubReport.report = _deployHubBatch({ logger: logger, treasurySpokeOwner: treasurySpokeOwner, - accessManager: accessManager + accessManager: accessManager, + salt: salt }); logger.log(label); @@ -216,7 +235,8 @@ library AaveV4DeployOrchestration { Logger logger, address spokeProxyAdminOwner, address accessManager, - string[] memory spokeLabels + string[] memory spokeLabels, + bytes32 rootSalt ) internal returns (OrchestrationReports.SpokeDeploymentReport[] memory spokeBatchReports) { uint256 spokeCount = spokeLabels.length; spokeBatchReports = new OrchestrationReports.SpokeDeploymentReport[](spokeCount); @@ -225,7 +245,8 @@ library AaveV4DeployOrchestration { logger: logger, spokeProxyAdminOwner: spokeProxyAdminOwner, accessManager: accessManager, - label: spokeLabels[i] + label: spokeLabels[i], + salt: keccak256(abi.encode(rootSalt, 'spoke', spokeLabels[i])) }); } logger.log(''); @@ -236,7 +257,8 @@ library AaveV4DeployOrchestration { Logger logger, address spokeProxyAdminOwner, address accessManager, - string memory label + string memory label, + bytes32 salt ) internal returns (OrchestrationReports.SpokeDeploymentReport memory) { OrchestrationReports.SpokeDeploymentReport memory spokeReport; @@ -245,7 +267,8 @@ library AaveV4DeployOrchestration { logger: logger, spokeProxyAdminOwner: spokeProxyAdminOwner, accessManager: accessManager, - label: label + label: label, + salt: salt }); logger.log(label); @@ -266,38 +289,47 @@ library AaveV4DeployOrchestration { Logger logger, address spokeProxyAdminOwner, address accessManager, - string memory label + string memory label, + bytes32 salt ) internal returns (BatchReports.SpokeInstanceBatchReport memory report) { logger.log('...Deploying AaveV4SpokeInstanceBatch...'); - report = AaveV4DeployBase.deploySpokeInstanceBatch( - spokeProxyAdminOwner, - accessManager, - ORACLE_DECIMALS, - ORACLE_SUFFIX, - label - ); + report = AaveV4DeployBase.deploySpokeInstanceBatch({ + spokeProxyAdminOwner: spokeProxyAdminOwner, + accessManager: accessManager, + oracleDecimals: ORACLE_DECIMALS, + oracleSuffix: ORACLE_SUFFIX, + label: label, + salt: salt + }); return report; } function _deployHubBatch( Logger logger, address treasurySpokeOwner, - address accessManager + address accessManager, + bytes32 salt ) internal returns (BatchReports.HubBatchReport memory report) { logger.log('...Deploying HubBatch...'); - report = AaveV4DeployBase.deployHubBatch(treasurySpokeOwner, accessManager); + report = AaveV4DeployBase.deployHubBatch({ + treasurySpokeOwner: treasurySpokeOwner, + accessManager: accessManager, + salt: salt + }); return report; } function _deployGatewayBatch( Logger logger, address gatewayOwner, - address nativeWrapper + address nativeWrapper, + bytes32 salt ) internal returns (BatchReports.GatewaysBatchReport memory report) { logger.log('...Deploying GatewayBatch...'); report = AaveV4DeployBase.deployGatewaysBatch({ owner: gatewayOwner, - nativeWrapper: nativeWrapper + nativeWrapper: nativeWrapper, + salt: salt }); logger.log('NativeTokenGateway', report.nativeGateway); logger.log('SignatureGateway', report.signatureGateway); diff --git a/src/deployments/procedures/AaveV4DeployProcedureBase.sol b/src/deployments/procedures/AaveV4DeployProcedureBase.sol index 2c34ba743..80fb799ef 100644 --- a/src/deployments/procedures/AaveV4DeployProcedureBase.sol +++ b/src/deployments/procedures/AaveV4DeployProcedureBase.sol @@ -2,7 +2,6 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; contract AaveV4DeployProcedureBase { - bytes32 public constant SALT = bytes32('v1'); + bytes32 public constant SALT = keccak256('AAVE_V4_v1'); } diff --git a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol index dd2d6c372..b48039c40 100644 --- a/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol +++ b/src/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.sol @@ -2,12 +2,17 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {AccessManagerEnumerable} from 'src/access/AccessManagerEnumerable.sol'; import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import {AccessManagerEnumerable} from 'src/access/AccessManagerEnumerable.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; contract AaveV4AccessManagerEnumerableDeployProcedure is AaveV4DeployProcedureBase { - function _deployAccessManagerEnumerable(address admin) internal returns (address) { + function _deployAccessManagerEnumerable(address admin, bytes32 salt) internal returns (address) { require(admin != address(0), 'invalid admin'); - return address(new AccessManagerEnumerable({initialAdmin_: admin})); + return + Create2Utils.create2Deploy( + salt, + abi.encodePacked(type(AccessManagerEnumerable).creationCode, abi.encode(admin)) + ); } } diff --git a/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol index 169c5c2a3..427f31a71 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.sol @@ -2,17 +2,16 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; import {HubConfigurator} from 'src/hub/HubConfigurator.sol'; -import { - Create2Utils, - AaveV4DeployProcedureBase -} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; + contract AaveV4HubConfiguratorDeployProcedure is AaveV4DeployProcedureBase { - function _deployHubConfigurator(address owner) internal returns (address) { + function _deployHubConfigurator(address owner, bytes32 salt) internal returns (address) { require(owner != address(0), 'invalid owner'); return Create2Utils.create2Deploy( - SALT, + salt, abi.encodePacked(type(HubConfigurator).creationCode, abi.encode(owner)) ); } diff --git a/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol index 961579e2b..1bc799bd2 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.sol @@ -2,17 +2,16 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; import {Hub} from 'src/hub/Hub.sol'; -import { - Create2Utils, - AaveV4DeployProcedureBase -} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; + contract AaveV4HubDeployProcedure is AaveV4DeployProcedureBase { - function _deployHub(address accessManager) internal returns (address) { + function _deployHub(address accessManager, bytes32 salt) internal returns (address) { require(accessManager != address(0), 'invalid access manager'); return Create2Utils.create2Deploy( - SALT, + salt, abi.encodePacked(type(Hub).creationCode, abi.encode(accessManager)) ); } diff --git a/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol b/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol index 0f90d5b19..4db31c912 100644 --- a/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol +++ b/src/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.sol @@ -2,17 +2,16 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; import {AssetInterestRateStrategy} from 'src/hub/AssetInterestRateStrategy.sol'; -import { - Create2Utils, - AaveV4DeployProcedureBase -} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; + contract AaveV4InterestRateStrategyDeployProcedure is AaveV4DeployProcedureBase { - function _deployInterestRateStrategy(address hub) internal returns (address) { + function _deployInterestRateStrategy(address hub, bytes32 salt) internal returns (address) { require(hub != address(0), 'invalid hub'); return Create2Utils.create2Deploy( - SALT, + salt, abi.encodePacked(type(AssetInterestRateStrategy).creationCode, abi.encode(hub)) ); } diff --git a/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol index ac04bfa53..9c15cc516 100644 --- a/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.sol @@ -2,21 +2,21 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; import {NativeTokenGateway} from 'src/position-manager/NativeTokenGateway.sol'; -import { - Create2Utils, - AaveV4DeployProcedureBase -} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; + contract AaveV4NativeTokenGatewayDeployProcedure is AaveV4DeployProcedureBase { function _deployNativeTokenGateway( address nativeWrapper, - address owner + address owner, + bytes32 salt ) internal returns (address) { require(nativeWrapper != address(0), 'invalid native wrapper'); require(owner != address(0), 'invalid owner'); return Create2Utils.create2Deploy( - SALT, + salt, abi.encodePacked(type(NativeTokenGateway).creationCode, abi.encode(nativeWrapper, owner)) ); } diff --git a/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol index beec26909..0f72d1d92 100644 --- a/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol +++ b/src/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.sol @@ -2,17 +2,16 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; import {SignatureGateway} from 'src/position-manager/SignatureGateway.sol'; -import { - Create2Utils, - AaveV4DeployProcedureBase -} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; + contract AaveV4SignatureGatewayDeployProcedure is AaveV4DeployProcedureBase { - function _deploySignatureGateway(address owner) internal returns (address) { + function _deploySignatureGateway(address owner, bytes32 salt) internal returns (address) { require(owner != address(0), 'invalid owner'); return Create2Utils.create2Deploy( - SALT, + salt, abi.encodePacked(type(SignatureGateway).creationCode, abi.encode(owner)) ); } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol index eedaed73b..323735788 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.sol @@ -8,7 +8,8 @@ contract AaveV4AaveOracleDeployProcedure is AaveV4DeployProcedureBase { function _deployAaveOracle( address spoke_, uint8 decimals_, - string memory description_ + string memory description_, + bytes32 salt_ ) internal returns (address) { require(spoke_ != address(0), 'invalid spoke'); require(decimals_ > 0, 'invalid oracle decimals'); diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol index d5690ee8e..68f0034d0 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.sol @@ -1,19 +1,16 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; - +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; import {SpokeConfigurator} from 'src/spoke/SpokeConfigurator.sol'; -import { - Create2Utils, - AaveV4DeployProcedureBase -} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; contract AaveV4SpokeConfiguratorDeployProcedure is AaveV4DeployProcedureBase { - function _deploySpokeConfigurator(address owner) internal returns (address) { + function _deploySpokeConfigurator(address owner, bytes32 salt) internal returns (address) { require(owner != address(0), 'invalid owner'); return Create2Utils.create2Deploy( - SALT, + salt, abi.encodePacked(type(SpokeConfigurator).creationCode, abi.encode(owner)) ); } diff --git a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol index f842eb9ad..ef95c9197 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.sol @@ -2,12 +2,9 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -// import {Utils} from 'src/deployments/utils/libraries/Utils.sol'; +import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; import {SpokeInstance} from 'src/spoke/instances/SpokeInstance.sol'; -import { - Create2Utils, - AaveV4DeployProcedureBase -} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; import { TransparentUpgradeableProxy } from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; @@ -16,17 +13,18 @@ contract AaveV4SpokeDeployProcedure is AaveV4DeployProcedureBase { function _deployUpgradableSpokeInstance( address spokeProxyAdminOwner, address accessManager, - address oracle + address oracle, + bytes32 salt ) internal returns (address spokeProxy, address spokeImplementation) { require(spokeProxyAdminOwner != address(0), 'invalid spoke proxy admin owner'); require(accessManager != address(0), 'invalid access manager'); require(oracle != address(0), 'invalid oracle'); spokeImplementation = Create2Utils.create2Deploy( - SALT, + salt, abi.encodePacked(type(SpokeInstance).creationCode, abi.encode(oracle)) ); spokeProxy = Create2Utils.proxify( - SALT, + salt, spokeImplementation, spokeProxyAdminOwner, abi.encodeCall(SpokeInstance.initialize, (accessManager)) diff --git a/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol b/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol index b8808febd..c2b7eccaf 100644 --- a/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol +++ b/src/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.sol @@ -2,13 +2,22 @@ // Copyright (c) 2025 Aave Labs pragma solidity ^0.8.0; -import {TreasurySpoke} from 'src/spoke/TreasurySpoke.sol'; import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol'; +import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol'; +import {TreasurySpoke} from 'src/spoke/TreasurySpoke.sol'; contract AaveV4TreasurySpokeDeployProcedure is AaveV4DeployProcedureBase { - function _deployTreasurySpoke(address owner, address hub) internal returns (address) { + function _deployTreasurySpoke( + address owner, + address hub, + bytes32 salt + ) internal returns (address) { require(owner != address(0), 'invalid owner'); require(hub != address(0), 'invalid hub'); - return address(new TreasurySpoke({owner_: owner, hub_: hub})); + return + Create2Utils.create2Deploy( + salt, + abi.encodePacked(type(TreasurySpoke).creationCode, abi.encode(owner, hub)) + ); } } diff --git a/src/deployments/utils/InputUtils.sol b/src/deployments/utils/InputUtils.sol index c808a07d8..0f4d80c16 100644 --- a/src/deployments/utils/InputUtils.sol +++ b/src/deployments/utils/InputUtils.sol @@ -23,6 +23,7 @@ contract InputUtils { /// @dev grantRoles A boolean indicating if roles should be granted. /// @dev hubLabels An array of hub labels; the number of hub labels defines the number of hubs to deploy. /// @dev spokeLabels An array of spoke labels; the number of spoke labels defines the number of spokes to deploy. + /// @dev salt The root salt to use for the deployment. struct FullDeployInputs { address accessManagerAdmin; address hubAdmin; @@ -36,6 +37,7 @@ contract InputUtils { bool grantRoles; string[] hubLabels; string[] spokeLabels; + bytes32 salt; } struct SpokeDeployInputs { diff --git a/src/deployments/utils/libraries/Create2Utils.sol b/src/deployments/utils/libraries/Create2Utils.sol index fdfd2caf9..fb979c8cd 100644 --- a/src/deployments/utils/libraries/Create2Utils.sol +++ b/src/deployments/utils/libraries/Create2Utils.sol @@ -15,20 +15,18 @@ library Create2Utils { error create2AddressDerivationFailure(); error nonceNotSupported(); error failedCreate2FactoryCall(); + error contractAlreadyDeployed(); function create2Deploy(bytes32 salt, bytes memory bytecode) internal returns (address) { require(isContractDeployed(CREATE2_FACTORY), missingCreate2Factory()); address computed = computeCreate2Address(salt, bytecode); - if (isContractDeployed(computed)) { - return computed; - } else { - bytes memory creationBytecode = abi.encodePacked(salt, bytecode); - (bool success, bytes memory returnData) = CREATE2_FACTORY.call(creationBytecode); - require(success, failedCreate2FactoryCall()); - address deployedAt = address(uint160(bytes20(returnData))); - require(deployedAt == computed, create2AddressDerivationFailure()); - return deployedAt; - } + require(!isContractDeployed(computed), contractAlreadyDeployed()); + bytes memory creationBytecode = abi.encodePacked(salt, bytecode); + (bool success, bytes memory returnData) = CREATE2_FACTORY.call(creationBytecode); + require(success, failedCreate2FactoryCall()); + address deployedAt = address(uint160(bytes20(returnData))); + require(deployedAt == computed, create2AddressDerivationFailure()); + return deployedAt; } function proxify( diff --git a/tests/Base.t.sol b/tests/Base.t.sol index fe9128f72..b1d2dee9a 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -324,7 +324,8 @@ abstract contract Base is BatchTestProcedures { spokeConfiguratorAdmin: SPOKE_CONFIGURATOR_ADMIN, hubCount: numHubs, spokeCount: numSpokes, - nativeWrapper: address(tokenList.weth) + nativeWrapper: address(tokenList.weth), + salt: keccak256(abi.encodePacked(vm.randomBytes(32))) }); for (uint256 i; i < numHubs; ++i) { _hubs.push(IHub(report.hubReports[i].hub)); @@ -2336,6 +2337,10 @@ abstract contract Base is BatchTestProcedures { return vm.randomUint(0, PercentageMath.PERCENTAGE_FACTOR).toUint16(); } + function _randomBps(uint256 maxBps) internal returns (uint16) { + return vm.randomUint(0, maxBps).toUint16(); + } + function _hub(ISpoke spoke, uint256 reserveId) internal view returns (IHub) { return IHub(address(spoke.getReserve(reserveId).hub)); } diff --git a/tests/deployments/AaveV4BatchDeployment.t.sol b/tests/deployments/AaveV4BatchDeployment.t.sol index 368352a16..4fdd41a5a 100644 --- a/tests/deployments/AaveV4BatchDeployment.t.sol +++ b/tests/deployments/AaveV4BatchDeployment.t.sol @@ -20,7 +20,8 @@ contract AaveV4BatchDeploymentTest is BatchTestProcedures { nativeWrapper: _weth9, grantRoles: true, hubLabels: _hubLabels, - spokeLabels: _spokeLabels + spokeLabels: _spokeLabels, + salt: bytes32(0) }); } diff --git a/tests/deployments/batches/AaveV4AccessBatch.t.sol b/tests/deployments/batches/AaveV4AccessBatch.t.sol index 69adf37b3..46d082f98 100644 --- a/tests/deployments/batches/AaveV4AccessBatch.t.sol +++ b/tests/deployments/batches/AaveV4AccessBatch.t.sol @@ -8,7 +8,7 @@ contract AaveV4AccessBatchTest is BatchBaseTest { AaveV4AccessBatch public aaveV4AccessBatch; function setUp() public override { super.setUp(); - aaveV4AccessBatch = new AaveV4AccessBatch(admin); + aaveV4AccessBatch = new AaveV4AccessBatch(admin, salt); } function test_getReport() public view { diff --git a/tests/deployments/batches/BatchBase.t.sol b/tests/deployments/batches/BatchBase.t.sol index 0aac98a43..75a62b750 100644 --- a/tests/deployments/batches/BatchBase.t.sol +++ b/tests/deployments/batches/BatchBase.t.sol @@ -4,14 +4,17 @@ pragma solidity ^0.8.0; import {Test} from 'forge-std/Test.sol'; +import {InputUtils} from 'src/deployments/utils/InputUtils.sol'; import {Roles} from 'src/deployments/utils/libraries/Roles.sol'; import {BatchReports} from 'src/deployments/libraries/BatchReports.sol'; import {AaveV4AccessBatch} from 'src/deployments/batches/AaveV4AccessBatch.sol'; - import {IAccessManagerEnumerable} from 'src/access/interfaces/IAccessManagerEnumerable.sol'; -contract BatchBaseTest is Test { +contract BatchBaseTest is Test, InputUtils { address public admin = makeAddr('admin'); - - function setUp() public virtual {} + bytes32 public salt; + function setUp() public virtual { + salt = keccak256('testSalt'); + _etchCreate2Factory(); + } } diff --git a/tests/deployments/orchestration/AaveV4TestOrchestration.sol b/tests/deployments/orchestration/AaveV4TestOrchestration.sol index e7044f20e..5c7a3ca55 100644 --- a/tests/deployments/orchestration/AaveV4TestOrchestration.sol +++ b/tests/deployments/orchestration/AaveV4TestOrchestration.sol @@ -66,7 +66,8 @@ library AaveV4TestOrchestration { address spokeConfiguratorAdmin, uint256 hubCount, uint256 spokeCount, - address nativeWrapper + address nativeWrapper, + bytes32 salt ) external returns (TestTypes.TestEnvReport memory) { TestTypes.TestEnvReport memory report; @@ -74,14 +75,15 @@ library AaveV4TestOrchestration { report.spokeReports = new TestTypes.TestSpokeReport[](spokeCount); // Deploy Access Batch - report.accessManager = AaveV4DeployBase.deployAccessBatch(admin).accessManager; + report.accessManager = AaveV4DeployBase.deployAccessBatch(admin, salt).accessManager; // Deploy Hub Batches for (uint256 i; i < hubCount; ++i) { - BatchReports.HubBatchReport memory hubReport = AaveV4DeployBase.deployHubBatch( - treasuryAdmin, - report.accessManager - ); + BatchReports.HubBatchReport memory hubReport = AaveV4DeployBase.deployHubBatch({ + treasurySpokeOwner: treasuryAdmin, + accessManager: report.accessManager, + salt: keccak256(abi.encodePacked(salt, 'hub-', string(abi.encode(i)))) + }); report.hubReports[i].hub = hubReport.hub; report.hubReports[i].irStrategy = hubReport.irStrategy; report.hubReports[i].treasurySpoke = hubReport.treasurySpoke; @@ -90,13 +92,14 @@ library AaveV4TestOrchestration { // Deploy Spoke Instance Batches for (uint256 i; i < spokeCount; ++i) { BatchReports.SpokeInstanceBatchReport memory spokeReport = AaveV4DeployBase - .deploySpokeInstanceBatch( - admin, - report.accessManager, - Constants.ORACLE_DECIMALS, - Constants.ORACLE_SUFFIX, - string.concat('Spoke ', string(abi.encode(i)), Constants.ORACLE_SUFFIX) - ); + .deploySpokeInstanceBatch({ + spokeProxyAdminOwner: admin, + accessManager: report.accessManager, + oracleDecimals: Constants.ORACLE_DECIMALS, + oracleSuffix: Constants.ORACLE_SUFFIX, + label: string.concat('Spoke ', string(abi.encode(i)), Constants.ORACLE_SUFFIX), + salt: keccak256(abi.encodePacked(salt, 'spoke-', string(abi.encode(i)))) + }); report.spokeReports[i].spoke = spokeReport.spokeProxy; report.spokeReports[i].aaveOracle = spokeReport.aaveOracle; } @@ -105,7 +108,8 @@ library AaveV4TestOrchestration { BatchReports.ConfiguratorBatchReport memory configuratorReport = AaveV4DeployBase .deployConfiguratorBatch({ hubConfiguratorOwner: hubConfiguratorAdmin, - spokeConfiguratorOwner: spokeConfiguratorAdmin + spokeConfiguratorOwner: spokeConfiguratorAdmin, + salt: keccak256(abi.encodePacked(salt, 'configurator')) }); report.configuratorReport.hubConfigurator = configuratorReport.hubConfigurator; report.configuratorReport.spokeConfigurator = configuratorReport.spokeConfigurator; @@ -113,7 +117,8 @@ library AaveV4TestOrchestration { // Deploy Gateways Batch BatchReports.GatewaysBatchReport memory gatewaysReport = AaveV4DeployBase.deployGatewaysBatch({ owner: admin, - nativeWrapper: nativeWrapper + nativeWrapper: nativeWrapper, + salt: keccak256(abi.encodePacked(salt, 'gateways')) }); report.gatewaysReport.signatureGateway = gatewaysReport.signatureGateway; report.gatewaysReport.nativeGateway = gatewaysReport.nativeGateway; diff --git a/tests/deployments/procedures/ProceduresBase.t.sol b/tests/deployments/procedures/ProceduresBase.t.sol index 9da3771c3..982be2a44 100644 --- a/tests/deployments/procedures/ProceduresBase.t.sol +++ b/tests/deployments/procedures/ProceduresBase.t.sol @@ -73,11 +73,12 @@ contract ProceduresBase is Test, InputUtils { address public aaveOracle; address public treasurySpoke = makeAddr('treasurySpoke'); address public admin = makeAddr('admin'); - + bytes32 public salt; function setUp() public virtual { _etchCreate2Factory(); accessManager = address(new AccessManagerEnumerable(accessManagerAdmin)); aaveOracle = address(new AaveOracle(spoke, oracleDecimals, oracleDescription)); + salt = keccak256('testSalt'); } } diff --git a/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol b/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol index 5738898e0..b9a086014 100644 --- a/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/AaveV4AccessManagerEnumerableDeployProcedure.t.sol @@ -14,7 +14,7 @@ contract AaveV4AccessManagerEnumerableDeployProcedureTest is ProceduresBase { function test_deployAccessManagerEnumerable() public { address accessManagerEnumerable = aaveV4AccessManagerEnumerableDeployProcedureWrapper - .deployAccessManagerEnumerable(accessManagerAdmin); + .deployAccessManagerEnumerable(accessManagerAdmin, salt); assertNotEq(accessManagerEnumerable, address(0)); (bool hasRole, uint32 executionDelay) = IAccessManagerEnumerable(accessManagerEnumerable) .hasRole( @@ -27,6 +27,9 @@ contract AaveV4AccessManagerEnumerableDeployProcedureTest is ProceduresBase { function test_deployAccessManagerEnumerable_reverts() public { vm.expectRevert('invalid admin'); - aaveV4AccessManagerEnumerableDeployProcedureWrapper.deployAccessManagerEnumerable(address(0)); + aaveV4AccessManagerEnumerableDeployProcedureWrapper.deployAccessManagerEnumerable( + address(0), + salt + ); } } diff --git a/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol index 41e0c3b10..e3e2575d9 100644 --- a/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/hub/AaveV4HubConfiguratorDeployProcedure.t.sol @@ -13,7 +13,8 @@ contract AaveV4HubConfiguratorDeployProcedureTest is ProceduresBase { function test_deployHubConfigurator() public { address hubConfigurator = aaveV4HubConfiguratorDeployProcedureWrapper.deployHubConfigurator( - owner + owner, + salt ); assertNotEq(hubConfigurator, address(0)); assertEq(Ownable(hubConfigurator).owner(), owner); @@ -21,6 +22,9 @@ contract AaveV4HubConfiguratorDeployProcedureTest is ProceduresBase { function test_deployHubConfigurator_reverts() public { vm.expectRevert('invalid owner'); - aaveV4HubConfiguratorDeployProcedureWrapper.deployHubConfigurator(address(0)); + aaveV4HubConfiguratorDeployProcedureWrapper.deployHubConfigurator({ + owner: address(0), + salt: salt + }); } } diff --git a/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol index 1b25ba9df..4e461d4ad 100644 --- a/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/hub/AaveV4HubDeployProcedure.t.sol @@ -12,13 +12,13 @@ contract AaveV4HubDeployProcedureTest is ProceduresBase { } function test_deployHub() public { - address hub = aaveV4HubDeployProcedureWrapper.deployHub(accessManager); + address hub = aaveV4HubDeployProcedureWrapper.deployHub(accessManager, salt); assertNotEq(hub, address(0)); assertEq(IHub(hub).authority(), accessManager); } function test_deployHub_reverts() public { vm.expectRevert('invalid access manager'); - aaveV4HubDeployProcedureWrapper.deployHub(address(0)); + aaveV4HubDeployProcedureWrapper.deployHub({accessManager: address(0), salt: salt}); } } diff --git a/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol b/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol index 7cb9b18db..1bb54726f 100644 --- a/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/hub/AaveV4InterestRateStrategyDeployProcedure.t.sol @@ -14,13 +14,16 @@ contract AaveV4InterestRateStrategyDeployProcedureTest is ProceduresBase { function test_deployInterestRateStrategy() public { address interestRateStrategy = aaveV4InterestRateStrategyDeployProcedureWrapper - .deployInterestRateStrategy(hub); + .deployInterestRateStrategy(hub, salt); assertNotEq(interestRateStrategy, address(0)); assertEq(IAssetInterestRateStrategy(interestRateStrategy).HUB(), hub); } function test_deployInterestRateStrategy_reverts() public { vm.expectRevert('invalid hub'); - aaveV4InterestRateStrategyDeployProcedureWrapper.deployInterestRateStrategy(address(0)); + aaveV4InterestRateStrategyDeployProcedureWrapper.deployInterestRateStrategy({ + hub: address(0), + salt: salt + }); } } diff --git a/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol b/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol index 0141222cf..53c58bc91 100644 --- a/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/position-manager/AaveV4NativeTokenGatewayDeployProcedure.t.sol @@ -14,19 +14,24 @@ contract AaveV4NativeTokenGatewayDeployProcedureTest is ProceduresBase { function test_deployHubConfigurator() public { address nativeTokenGateway = aaveV4NativeTokenGatewayDeployProcedureWrapper - .deployNativeTokenGateway(nativeWrapper, owner); + .deployNativeTokenGateway(nativeWrapper, owner, salt); assertNotEq(nativeTokenGateway, address(0)); assertEq(Ownable(nativeTokenGateway).owner(), owner); } function test_deployNativeTokenGateway_reverts() public { vm.expectRevert('invalid native wrapper'); - aaveV4NativeTokenGatewayDeployProcedureWrapper.deployNativeTokenGateway(address(0), owner); + aaveV4NativeTokenGatewayDeployProcedureWrapper.deployNativeTokenGateway({ + nativeWrapper: address(0), + owner: owner, + salt: salt + }); vm.expectRevert('invalid owner'); - aaveV4NativeTokenGatewayDeployProcedureWrapper.deployNativeTokenGateway( - nativeWrapper, - address(0) - ); + aaveV4NativeTokenGatewayDeployProcedureWrapper.deployNativeTokenGateway({ + nativeWrapper: nativeWrapper, + owner: address(0), + salt: salt + }); } } diff --git a/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol b/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol index 411a0e697..cf57b2e57 100644 --- a/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/position-manager/AaveV4SignatureGatewayDeployProcedure.t.sol @@ -14,7 +14,8 @@ contract AaveV4SignatureGatewayDeployProcedureTest is ProceduresBase { function test_deploySignatureGateway() public { address signatureGateway = aaveV4SignatureGatewayDeployProcedureWrapper.deploySignatureGateway( - owner + owner, + salt ); assertNotEq(signatureGateway, address(0)); assertEq(Ownable(signatureGateway).owner(), owner); @@ -22,6 +23,6 @@ contract AaveV4SignatureGatewayDeployProcedureTest is ProceduresBase { function test_deploySignatureGateway_reverts() public { vm.expectRevert('invalid owner'); - aaveV4SignatureGatewayDeployProcedureWrapper.deploySignatureGateway(address(0)); + aaveV4SignatureGatewayDeployProcedureWrapper.deploySignatureGateway(address(0), salt); } } diff --git a/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol b/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol index 722190a18..dc5c3b9bb 100644 --- a/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol +++ b/tests/deployments/procedures/deploy/roles/AaveV4AccessManagerRolesProcedure.t.sol @@ -55,11 +55,11 @@ contract AaveV4AccessManagerRolesProcedureTest is ProceduresBase { address(aaveV4AccessManagerRolesProcedureWrapper), 0 ); - aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole( - accessManager, - newAdmin, - address(aaveV4AccessManagerRolesProcedureWrapper) - ); + aaveV4AccessManagerRolesProcedureWrapper.grantRootAdminRole({ + accessManager: accessManager, + adminToAdd: newAdmin, + adminToRemove: address(aaveV4AccessManagerRolesProcedureWrapper) + }); vm.stopPrank(); } } diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol index 8090b647c..5e9c9e54d 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4AaveOracleDeployProcedure.t.sol @@ -15,7 +15,8 @@ contract AaveV4AaveOracleDeployProcedureTest is ProceduresBase { address aaveOracle = aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle( spoke, oracleDecimals, - oracleDescription + oracleDescription, + salt ); assertNotEq(aaveOracle, address(0)); assertEq(IAaveOracle(aaveOracle).DECIMALS(), oracleDecimals); @@ -27,21 +28,24 @@ contract AaveV4AaveOracleDeployProcedureTest is ProceduresBase { aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle({ spoke: address(0), decimals: oracleDecimals, - description: oracleDescription + description: oracleDescription, + salt: salt }); vm.expectRevert('invalid oracle decimals'); aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle({ spoke: spoke, decimals: 0, - description: oracleDescription + description: oracleDescription, + salt: salt }); vm.expectRevert('invalid oracle description'); aaveV4AaveOracleDeployProcedureWrapper.deployAaveOracle({ spoke: spoke, decimals: oracleDecimals, - description: '' + description: '', + salt: salt }); } } diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol index e10486c5c..11aa24623 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeConfiguratorDeployProcedure.t.sol @@ -14,13 +14,13 @@ contract AaveV4SpokeConfiguratorDeployProcedureTest is ProceduresBase { function test_deploySpokeConfigurator() public { address spokeConfigurator = aaveV4SpokeConfiguratorDeployProcedureWrapper - .deploySpokeConfigurator(owner); + .deploySpokeConfigurator(owner, salt); assertNotEq(spokeConfigurator, address(0)); assertEq(Ownable(spokeConfigurator).owner(), owner); } function test_deploySpokeConfigurator_reverts() public { vm.expectRevert('invalid owner'); - aaveV4SpokeConfiguratorDeployProcedureWrapper.deploySpokeConfigurator(address(0)); + aaveV4SpokeConfiguratorDeployProcedureWrapper.deploySpokeConfigurator(address(0), salt); } } diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol index 1b973e014..4e8c8818d 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4SpokeDeployProcedure.t.sol @@ -13,7 +13,7 @@ contract AaveV4SpokeDeployProcedureTest is ProceduresBase { function test_deployUpgradableSpokeInstance() public { (address spokeProxy, address spokeImplementation) = aaveV4SpokeDeployProcedureWrapper - .deployUpgradableSpokeInstance(owner, accessManager, aaveOracle); + .deployUpgradableSpokeInstance(owner, accessManager, aaveOracle, salt); assertNotEq(spokeProxy, address(0)); assertNotEq(spokeImplementation, address(0)); assertEq(Ownable(ProxyHelper.getProxyAdmin(spokeProxy)).owner(), owner); @@ -26,21 +26,24 @@ contract AaveV4SpokeDeployProcedureTest is ProceduresBase { aaveV4SpokeDeployProcedureWrapper.deployUpgradableSpokeInstance({ spokeProxyAdminOwner: address(0), accessManager: accessManager, - oracle: aaveOracle + oracle: aaveOracle, + salt: salt }); vm.expectRevert('invalid access manager'); aaveV4SpokeDeployProcedureWrapper.deployUpgradableSpokeInstance({ spokeProxyAdminOwner: owner, accessManager: address(0), - oracle: aaveOracle + oracle: aaveOracle, + salt: salt }); vm.expectRevert('invalid oracle'); aaveV4SpokeDeployProcedureWrapper.deployUpgradableSpokeInstance({ spokeProxyAdminOwner: owner, accessManager: accessManager, - oracle: address(0) + oracle: address(0), + salt: salt }); } } diff --git a/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol b/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol index dc9a51526..3463c4112 100644 --- a/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol +++ b/tests/deployments/procedures/deploy/spoke/AaveV4TreasurySpokeDeployProcedure.t.sol @@ -14,7 +14,8 @@ contract AaveV4TreasurySpokeDeployProcedureTest is ProceduresBase { function test_deployTreasurySpoke() public { address treasurySpoke = aaveV4TreasurySpokeDeployProcedureWrapper.deployTreasurySpoke( owner, - hub + hub, + salt ); assertNotEq(treasurySpoke, address(0)); assertEq(Ownable(treasurySpoke).owner(), owner); @@ -23,9 +24,17 @@ contract AaveV4TreasurySpokeDeployProcedureTest is ProceduresBase { function test_deployTreasurySpoke_reverts() public { vm.expectRevert('invalid owner'); - aaveV4TreasurySpokeDeployProcedureWrapper.deployTreasurySpoke({owner: address(0), hub: hub}); + aaveV4TreasurySpokeDeployProcedureWrapper.deployTreasurySpoke({ + owner: address(0), + hub: hub, + salt: salt + }); vm.expectRevert('invalid hub'); - aaveV4TreasurySpokeDeployProcedureWrapper.deployTreasurySpoke({owner: owner, hub: address(0)}); + aaveV4TreasurySpokeDeployProcedureWrapper.deployTreasurySpoke({ + owner: owner, + hub: address(0), + salt: salt + }); } } diff --git a/tests/deployments/utils/libraries/Create2Utils.t.sol b/tests/deployments/utils/libraries/Create2Utils.t.sol index 491ec43b0..571174430 100644 --- a/tests/deployments/utils/libraries/Create2Utils.t.sol +++ b/tests/deployments/utils/libraries/Create2Utils.t.sol @@ -45,12 +45,15 @@ contract Create2UtilsTest is Test, InputUtils { _harness.create2Deploy(salt, bytecode); } - function testCreate2Deploy_returnsDeployedAddress(bytes32 salt) public { + function testCreate2Deploy_revertsWith_contractAlreadyDeployed(bytes32 salt) public { vm.assume(salt != bytes32(0)); _etchCreate2Factory(); bytes memory bytecode = type(Dummy).creationCode; - address deployed = _harness.create2Deploy(salt, bytecode); - assertEq(_harness.create2Deploy(salt, bytecode), deployed); + _harness.create2Deploy(salt, bytecode); + + // after already deployed, it should now revert + vm.expectRevert(Create2Utils.contractAlreadyDeployed.selector); + _harness.create2Deploy(salt, bytecode); } function testCreate2Deploy_fuzz(bytes32 salt) public { diff --git a/tests/mocks/deployments/procedures/AaveV4AaveOracleDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4AaveOracleDeployProcedureWrapper.sol index 64b728e5c..a31f0a25b 100644 --- a/tests/mocks/deployments/procedures/AaveV4AaveOracleDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4AaveOracleDeployProcedureWrapper.sol @@ -12,8 +12,9 @@ contract AaveV4AaveOracleDeployProcedureWrapper is AaveV4AaveOracleDeployProcedu function deployAaveOracle( address spoke, uint8 decimals, - string memory description + string memory description, + bytes32 salt ) external returns (address) { - return _deployAaveOracle(spoke, decimals, description); + return _deployAaveOracle(spoke, decimals, description, salt); } } diff --git a/tests/mocks/deployments/procedures/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol index 5a76d95b6..67fe7d353 100644 --- a/tests/mocks/deployments/procedures/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4AccessManagerEnumerableDeployProcedureWrapper.sol @@ -10,7 +10,7 @@ contract AaveV4AccessManagerEnumerableDeployProcedureWrapper is AaveV4AccessManagerEnumerableDeployProcedure { bool public IS_TEST = true; - function deployAccessManagerEnumerable(address admin) external returns (address) { - return _deployAccessManagerEnumerable(admin); + function deployAccessManagerEnumerable(address admin, bytes32 salt) external returns (address) { + return _deployAccessManagerEnumerable(admin, salt); } } diff --git a/tests/mocks/deployments/procedures/AaveV4HubConfiguratorDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4HubConfiguratorDeployProcedureWrapper.sol index f76b0462a..4c908f675 100644 --- a/tests/mocks/deployments/procedures/AaveV4HubConfiguratorDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4HubConfiguratorDeployProcedureWrapper.sol @@ -9,7 +9,7 @@ import { contract AaveV4HubConfiguratorDeployProcedureWrapper is AaveV4HubConfiguratorDeployProcedure { bool public IS_TEST = true; - function deployHubConfigurator(address owner) external returns (address) { - return _deployHubConfigurator(owner); + function deployHubConfigurator(address owner, bytes32 salt) external returns (address) { + return _deployHubConfigurator(owner, salt); } } diff --git a/tests/mocks/deployments/procedures/AaveV4HubDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4HubDeployProcedureWrapper.sol index d907be8ad..1f576abd4 100644 --- a/tests/mocks/deployments/procedures/AaveV4HubDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4HubDeployProcedureWrapper.sol @@ -9,7 +9,7 @@ import { contract AaveV4HubDeployProcedureWrapper is AaveV4HubDeployProcedure { bool public IS_TEST = true; - function deployHub(address accessManager) external returns (address) { - return _deployHub(accessManager); + function deployHub(address accessManager, bytes32 salt) external returns (address) { + return _deployHub(accessManager, salt); } } diff --git a/tests/mocks/deployments/procedures/AaveV4InterestRateStrategyDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4InterestRateStrategyDeployProcedureWrapper.sol index dcbdfcecc..43b21854c 100644 --- a/tests/mocks/deployments/procedures/AaveV4InterestRateStrategyDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4InterestRateStrategyDeployProcedureWrapper.sol @@ -11,7 +11,7 @@ contract AaveV4InterestRateStrategyDeployProcedureWrapper is { bool public IS_TEST = true; - function deployInterestRateStrategy(address hub) external returns (address) { - return _deployInterestRateStrategy(hub); + function deployInterestRateStrategy(address hub, bytes32 salt) external returns (address) { + return _deployInterestRateStrategy(hub, salt); } } diff --git a/tests/mocks/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol index 0925ab00e..27ef5886b 100644 --- a/tests/mocks/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4NativeTokenGatewayDeployProcedureWrapper.sol @@ -11,8 +11,9 @@ contract AaveV4NativeTokenGatewayDeployProcedureWrapper is AaveV4NativeTokenGate function deployNativeTokenGateway( address nativeWrapper, - address owner + address owner, + bytes32 salt ) external returns (address) { - return _deployNativeTokenGateway(nativeWrapper, owner); + return _deployNativeTokenGateway(nativeWrapper, owner, salt); } } diff --git a/tests/mocks/deployments/procedures/AaveV4SignatureGatewayDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4SignatureGatewayDeployProcedureWrapper.sol index 65d4f514c..fadc7cc84 100644 --- a/tests/mocks/deployments/procedures/AaveV4SignatureGatewayDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4SignatureGatewayDeployProcedureWrapper.sol @@ -9,7 +9,7 @@ import { contract AaveV4SignatureGatewayDeployProcedureWrapper is AaveV4SignatureGatewayDeployProcedure { bool public IS_TEST = true; - function deploySignatureGateway(address owner) external returns (address) { - return _deploySignatureGateway(owner); + function deploySignatureGateway(address owner, bytes32 salt) external returns (address) { + return _deploySignatureGateway(owner, salt); } } diff --git a/tests/mocks/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol index 9f6cddd69..20b596fe1 100644 --- a/tests/mocks/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4SpokeConfiguratorDeployProcedureWrapper.sol @@ -9,7 +9,7 @@ import { contract AaveV4SpokeConfiguratorDeployProcedureWrapper is AaveV4SpokeConfiguratorDeployProcedure { bool public IS_TEST = true; - function deploySpokeConfigurator(address owner) external returns (address) { - return _deploySpokeConfigurator(owner); + function deploySpokeConfigurator(address owner, bytes32 salt) external returns (address) { + return _deploySpokeConfigurator(owner, salt); } } diff --git a/tests/mocks/deployments/procedures/AaveV4SpokeDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4SpokeDeployProcedureWrapper.sol index 5773cdf65..03e0640c9 100644 --- a/tests/mocks/deployments/procedures/AaveV4SpokeDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4SpokeDeployProcedureWrapper.sol @@ -12,8 +12,9 @@ contract AaveV4SpokeDeployProcedureWrapper is AaveV4SpokeDeployProcedure { function deployUpgradableSpokeInstance( address spokeProxyAdminOwner, address accessManager, - address oracle + address oracle, + bytes32 salt ) external returns (address spokeProxy, address spokeImplementation) { - return _deployUpgradableSpokeInstance(spokeProxyAdminOwner, accessManager, oracle); + return _deployUpgradableSpokeInstance(spokeProxyAdminOwner, accessManager, oracle, salt); } } diff --git a/tests/mocks/deployments/procedures/AaveV4TreasurySpokeDeployProcedureWrapper.sol b/tests/mocks/deployments/procedures/AaveV4TreasurySpokeDeployProcedureWrapper.sol index 8632629c0..4438ee36c 100644 --- a/tests/mocks/deployments/procedures/AaveV4TreasurySpokeDeployProcedureWrapper.sol +++ b/tests/mocks/deployments/procedures/AaveV4TreasurySpokeDeployProcedureWrapper.sol @@ -9,7 +9,11 @@ import { contract AaveV4TreasurySpokeDeployProcedureWrapper is AaveV4TreasurySpokeDeployProcedure { bool public IS_TEST = true; - function deployTreasurySpoke(address owner, address hub) external returns (address) { - return _deployTreasurySpoke(owner, hub); + function deployTreasurySpoke( + address owner, + address hub, + bytes32 salt + ) external returns (address) { + return _deployTreasurySpoke(owner, hub, salt); } } diff --git a/tests/unit/Spoke/Spoke.DynamicConfig.t.sol b/tests/unit/Spoke/Spoke.DynamicConfig.t.sol index dd05237e4..fadf6a85d 100644 --- a/tests/unit/Spoke/Spoke.DynamicConfig.t.sol +++ b/tests/unit/Spoke/Spoke.DynamicConfig.t.sol @@ -332,7 +332,9 @@ contract SpokeDynamicConfigTest is SpokeBase { spoke1, reserveId ); - dynConf.collateralFactor = _randomBps(); + dynConf.collateralFactor = _randomBps( + PercentageMath.PERCENTAGE_FACTOR.percentDivDown(dynConf.maxLiquidationBonus) + ); vm.expectEmit(address(spoke1)); emit ISpoke.AddDynamicReserveConfig(reserveId, dynamicConfigKey, dynConf); From 7a82a0b9470f808dcc4e56aec3ddff3b7b8a1d9a Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Fri, 19 Dec 2025 22:30:49 -0600 Subject: [PATCH 61/62] fix: tmp fix for CI --- tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Base.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Base.t.sol b/tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Base.t.sol index ff22caaee..20a7ba793 100644 --- a/tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Base.t.sol +++ b/tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Base.t.sol @@ -1355,7 +1355,7 @@ contract SpokeLiquidationCallBaseTest is LiquidationLogicBaseTest { _assertBeforeLiquidation(params, accountsInfoBefore, liquidationMetadata); - _expectEventsAndCalls(params, accountsInfoBefore, liquidationMetadata); + // _expectEventsAndCalls(params, accountsInfoBefore, liquidationMetadata); vm.recordLogs(); vm.prank(params.liquidator); params.spoke.liquidationCall( From dfe4808a13889ec1b5f094ec7d7f827a94b9b501 Mon Sep 17 00:00:00 2001 From: YBM <31329384+yan-man@users.noreply.github.com> Date: Tue, 23 Dec 2025 17:30:44 -0600 Subject: [PATCH 62/62] test: resolve --- tests/Base.t.sol | 2 +- tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Base.t.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Base.t.sol b/tests/Base.t.sol index b1d2dee9a..c2d7f41a0 100644 --- a/tests/Base.t.sol +++ b/tests/Base.t.sol @@ -1733,7 +1733,7 @@ abstract contract Base is BatchTestProcedures { ); uint256 restoredPremiumRay = (premiumAmountToRestore * WadRayMath.RAY).min(premiumDebtRay); - uint256 restoredShares = drawnDebtToRestore.rayDivDown(hub.getAssetDrawnIndex(reserveId)); + uint256 restoredShares = drawnDebtToRestore.rayDivDown(hub.getAssetDrawnIndex(assetId)); uint256 riskPremium = _getUserLastRiskPremium(spoke, user); return diff --git a/tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Base.t.sol b/tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Base.t.sol index 20a7ba793..ff22caaee 100644 --- a/tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Base.t.sol +++ b/tests/unit/Spoke/Liquidations/Spoke.LiquidationCall.Base.t.sol @@ -1355,7 +1355,7 @@ contract SpokeLiquidationCallBaseTest is LiquidationLogicBaseTest { _assertBeforeLiquidation(params, accountsInfoBefore, liquidationMetadata); - // _expectEventsAndCalls(params, accountsInfoBefore, liquidationMetadata); + _expectEventsAndCalls(params, accountsInfoBefore, liquidationMetadata); vm.recordLogs(); vm.prank(params.liquidator); params.spoke.liquidationCall(