Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
75e9f55
feat: Simple contract to mint fee shares
CheyenneAtapour Feb 17, 2026
9ec1d11
chore: Cleanup
CheyenneAtapour Feb 17, 2026
4dc1448
feat: Make contract usable with all hubs
CheyenneAtapour Feb 17, 2026
0f6dab4
fix: Pr comments
CheyenneAtapour Feb 17, 2026
4f0492e
fix: test comment
CheyenneAtapour Feb 17, 2026
d9bfd8d
fix: Address pr comments
CheyenneAtapour Feb 25, 2026
cf0e864
Merge remote-tracking branch 'origin/main' into feat/fee-minter
CheyenneAtapour Feb 25, 2026
ba91946
fix: address pr comments
CheyenneAtapour Feb 26, 2026
729a05f
feat: Integrate with chainlink automation
CheyenneAtapour Feb 26, 2026
89d75b4
fix: test suite
CheyenneAtapour Feb 27, 2026
521c61c
chore: cleanup
CheyenneAtapour Feb 27, 2026
3a54457
fix: Cleanup natspec
CheyenneAtapour Feb 28, 2026
05bcd6c
fix: typo
CheyenneAtapour Mar 4, 2026
aba7d8c
Merge remote-tracking branch 'origin/main' into feat/fee-minter
CheyenneAtapour Mar 10, 2026
55f3330
Merge remote-tracking branch 'origin/main' into feat/fee-minter
CheyenneAtapour Mar 12, 2026
60d2395
Merge remote-tracking branch 'origin/main' into feat/fee-minter
CheyenneAtapour Mar 25, 2026
01fc11f
merge in main
CheyenneAtapour Mar 28, 2026
d6c0ac0
fix: Address pr comments
CheyenneAtapour Mar 28, 2026
9a0ce16
fix: Address pr comments
CheyenneAtapour Mar 28, 2026
36d151c
fix: Some pr comments
CheyenneAtapour Apr 9, 2026
976361e
Merge remote-tracking branch 'origin/main' into feat/fee-minter
CheyenneAtapour Apr 9, 2026
e0244e0
merge in main
CheyenneAtapour Apr 9, 2026
6e155aa
fix: Remaining pr comments
CheyenneAtapour Apr 9, 2026
39c7c5a
feat: Remove time component from fee minter
CheyenneAtapour Apr 9, 2026
56fbaf0
fix: Remove extraneous functions
CheyenneAtapour Apr 9, 2026
7bb20ec
fix : address pr comments & cleanup
Kogaroshi Apr 15, 2026
55f1f82
fix : renaming
Kogaroshi Apr 15, 2026
c0c322d
feat : add FeeSharesMinter to deploy engine
Kogaroshi Apr 15, 2026
8bb19cc
fix: address fee minter comments (#1299)
yan-man Apr 16, 2026
98c4cc4
fix: address comments
avniculae May 21, 2026
c85cb6f
feat: migrate FeeSharesMinter to CRE
avniculae May 22, 2026
9010c1f
feat: add FeeSharesMinter support in config engine
avniculae May 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions scripts/deploy/AaveV4DeployBatchBase.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ abstract contract AaveV4DeployBatchBaseScript is Script {
_logWarning(string.concat('treasury spoke owner', message, outcome));
sanitizedInputs.treasurySpokeOwner = deployer;
}
if (inputs.feeSharesMinterOwner == address(0)) {
_logWarning(string.concat('fee shares minter owner', message, outcome));
sanitizedInputs.feeSharesMinterOwner = deployer;
}
if (inputs.spokeAdmin == address(0)) {
_logWarning(string.concat('spoke admin', message, outcome));
sanitizedInputs.spokeAdmin = deployer;
Expand All @@ -133,6 +137,9 @@ abstract contract AaveV4DeployBatchBaseScript is Script {
_logWarning(string.concat('treasury spoke owner', message, outcome));
sanitizedInputs.treasurySpokeOwner = deployer;

_logWarning(string.concat('fee shares minter owner', message, outcome));
sanitizedInputs.feeSharesMinterOwner = deployer;

_logWarning(string.concat('proxy admin owner', message, outcome));
sanitizedInputs.proxyAdminOwner = deployer;
}
Expand Down
1 change: 1 addition & 0 deletions scripts/deploy/examples/AaveV4DeployAnvil.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ contract AaveV4DeployAnvil is AaveV4DeployBatchBaseScript {
hubAdmin: address(0),
hubConfiguratorAdmin: address(0),
treasurySpokeOwner: address(0),
feeSharesMinterOwner: address(0),
spokeAdmin: address(0),
spokeConfiguratorAdmin: address(1),
gatewayOwner: address(2),
Expand Down
9 changes: 9 additions & 0 deletions snapshots/FeeSharesMinter.Operations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"onReport": "117135",
"setConfig: cold": "59220",
"setConfig: disable": "37308",
"setConfig: warm": "42120",
"setWorkflowConfig: cold": "72976",
"setWorkflowConfig: deactivate": "35952",
"setWorkflowConfig: warm": "35964"
}
18 changes: 18 additions & 0 deletions src/config-engine/AaveV4ConfigEngine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {HubEngine} from 'src/config-engine/libraries/HubEngine.sol';
import {SpokeEngine} from 'src/config-engine/libraries/SpokeEngine.sol';
import {AccessManagerEngine} from 'src/config-engine/libraries/AccessManagerEngine.sol';
import {PositionManagerEngine} from 'src/config-engine/libraries/PositionManagerEngine.sol';
import {FeeSharesMinterEngine} from 'src/config-engine/libraries/FeeSharesMinterEngine.sol';
import {IAaveV4ConfigEngine} from 'src/config-engine/interfaces/IAaveV4ConfigEngine.sol';

/// @title AaveV4ConfigEngine
Expand Down Expand Up @@ -126,4 +127,21 @@ contract AaveV4ConfigEngine is IAaveV4ConfigEngine {
function executeTargetAdminDelayUpdates(TargetAdminDelayUpdate[] calldata updates) external {
AccessManagerEngine.executeTargetAdminDelayUpdates(updates);
}

/// @inheritdoc IAaveV4ConfigEngine
function executeFeeSharesMinterConfigs(FeeSharesMinterConfig[] calldata configs) external {
FeeSharesMinterEngine.executeFeeSharesMinterConfigs(configs);
}

/// @inheritdoc IAaveV4ConfigEngine
function executeFeeSharesMinterHubConfigs(FeeSharesMinterHubConfig[] calldata configs) external {
FeeSharesMinterEngine.executeFeeSharesMinterHubConfigs(configs);
}

/// @inheritdoc IAaveV4ConfigEngine
function executeFeeSharesMinterWorkflowConfigs(
FeeSharesMinterWorkflowConfig[] calldata configs
) external {
FeeSharesMinterEngine.executeFeeSharesMinterWorkflowConfigs(configs);
}
}
59 changes: 59 additions & 0 deletions src/config-engine/AaveV4Payload.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ abstract contract AaveV4Payload {
_executeHubActions();
_executeSpokeActions();
_executePositionManagerActions();
_executeFeeSharesMinterActions();
_postExecute();
}

Expand Down Expand Up @@ -260,6 +261,39 @@ abstract contract AaveV4Payload {
return new IAaveV4ConfigEngine.PositionManagerRoleRenouncement[](0);
}

/// @notice Returns the per-asset FeeSharesMinter configs to execute. Override to provide configs.
/// @return An array of FeeSharesMinterConfig structs (empty by default).
function feeSharesMinterConfigs()
public
view
virtual
returns (IAaveV4ConfigEngine.FeeSharesMinterConfig[] memory)
{
return new IAaveV4ConfigEngine.FeeSharesMinterConfig[](0);
}

/// @notice Returns the hub-wide FeeSharesMinter configs to execute. Override to provide configs.
/// @return An array of FeeSharesMinterHubConfig structs (empty by default).
function feeSharesMinterHubConfigs()
public
view
virtual
returns (IAaveV4ConfigEngine.FeeSharesMinterHubConfig[] memory)
{
return new IAaveV4ConfigEngine.FeeSharesMinterHubConfig[](0);
}

/// @notice Returns the FeeSharesMinter workflow configs to execute. Override to provide configs.
/// @return An array of FeeSharesMinterWorkflowConfig structs (empty by default).
function feeSharesMinterWorkflowConfigs()
public
view
virtual
returns (IAaveV4ConfigEngine.FeeSharesMinterWorkflowConfig[] memory)
{
return new IAaveV4ConfigEngine.FeeSharesMinterWorkflowConfig[](0);
}

/// @notice Executes all hub-related configuration actions via delegatecall to the engine.
function _executeHubActions() internal {
IAaveV4ConfigEngine.AssetListing[] memory listings = hubAssetListings();
Expand Down Expand Up @@ -421,6 +455,31 @@ abstract contract AaveV4Payload {
}
}

/// @notice Executes all FeeSharesMinter configuration actions via delegatecall to the engine.
function _executeFeeSharesMinterActions() internal {
IAaveV4ConfigEngine.FeeSharesMinterWorkflowConfig[]
memory workflowConfigs = feeSharesMinterWorkflowConfigs();
if (workflowConfigs.length > 0) {
_delegateCallEngine(
abi.encodeCall(IAaveV4ConfigEngine.executeFeeSharesMinterWorkflowConfigs, (workflowConfigs))
);
}

IAaveV4ConfigEngine.FeeSharesMinterConfig[] memory configs = feeSharesMinterConfigs();
if (configs.length > 0) {
_delegateCallEngine(
abi.encodeCall(IAaveV4ConfigEngine.executeFeeSharesMinterConfigs, (configs))
);
}

IAaveV4ConfigEngine.FeeSharesMinterHubConfig[] memory hubConfigs = feeSharesMinterHubConfigs();
if (hubConfigs.length > 0) {
_delegateCallEngine(
abi.encodeCall(IAaveV4ConfigEngine.executeFeeSharesMinterHubConfigs, (hubConfigs))
);
}
}

/// @notice Delegatecalls the config engine with the given calldata.
/// @param data The ABI-encoded function call to forward to CONFIG_ENGINE.
/// @dev Bubbles up any revert reason from the engine call. Assumes the engine functions return no data.
Expand Down
49 changes: 49 additions & 0 deletions src/config-engine/interfaces/IAaveV4ConfigEngine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {ISpokeConfigurator} from 'src/spoke/interfaces/ISpokeConfigurator.sol';
import {IHub} from 'src/hub/interfaces/IHub.sol';
import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol';
import {IAssetInterestRateStrategy} from 'src/hub/interfaces/IAssetInterestRateStrategy.sol';
import {IFeeSharesMinter} from 'src/utils/IFeeSharesMinter.sol';

/// @title IAaveV4ConfigEngine
/// @author Aave Labs
Expand Down Expand Up @@ -336,6 +337,39 @@ interface IAaveV4ConfigEngine {
uint32 newDelay;
}

/// @notice Parameters for setting the FeeSharesMinter per-asset minimum accrued fees percent.
/// @dev feeSharesMinter The FeeSharesMinter address.
/// @dev hub The address of the Hub.
/// @dev assetId The identifier of the asset.
/// @dev minAccruedFeesPercent The minimum ratio of accrued fees to total added assets, in BPS.
struct FeeSharesMinterConfig {
address feeSharesMinter;
address hub;
uint256 assetId;
uint16 minAccruedFeesPercent;
}

/// @notice Parameters for setting the FeeSharesMinter minimum accrued fees percent for every
/// asset currently listed on a Hub.
/// @dev feeSharesMinter The FeeSharesMinter address.
/// @dev hub The address of the Hub.
/// @dev minAccruedFeesPercent The minimum ratio of accrued fees to total added assets, in BPS.
struct FeeSharesMinterHubConfig {
address feeSharesMinter;
address hub;
uint16 minAccruedFeesPercent;
}

/// @notice Parameters for setting a FeeSharesMinter workflow authorization.
/// @dev feeSharesMinter The FeeSharesMinter address.
/// @dev workflowId The CRE workflow identifier.
/// @dev config The workflow configuration.
struct FeeSharesMinterWorkflowConfig {
address feeSharesMinter;
bytes32 workflowId;
IFeeSharesMinter.WorkflowConfig config;
}

/// @notice Lists new assets on Hubs via the HubConfigurator.
/// @param listings The asset listings to execute.
function executeHubAssetListings(AssetListing[] calldata listings) external;
Expand Down Expand Up @@ -429,4 +463,19 @@ interface IAaveV4ConfigEngine {
/// @notice Updates target admin delays via AccessManager.
/// @param updates The target admin delay updates to execute.
function executeTargetAdminDelayUpdates(TargetAdminDelayUpdate[] calldata updates) external;

/// @notice Sets per-asset minimum accrued fees percent on FeeSharesMinters.
/// @param configs The per-asset FeeSharesMinter configs to execute.
function executeFeeSharesMinterConfigs(FeeSharesMinterConfig[] calldata configs) external;

/// @notice Sets the minimum accrued fees percent on FeeSharesMinters for every asset currently
/// listed on each Hub.
/// @param configs The hub-wide FeeSharesMinter configs to execute.
function executeFeeSharesMinterHubConfigs(FeeSharesMinterHubConfig[] calldata configs) external;

/// @notice Registers or updates workflow authorizations on FeeSharesMinters.
/// @param configs The FeeSharesMinter workflow configs to execute.
function executeFeeSharesMinterWorkflowConfigs(
FeeSharesMinterWorkflowConfig[] calldata configs
) external;
}
59 changes: 59 additions & 0 deletions src/config-engine/libraries/FeeSharesMinterEngine.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: LicenseRef-BUSL
pragma solidity ^0.8.0;

import {IHub} from 'src/hub/interfaces/IHub.sol';
import {IFeeSharesMinter} from 'src/utils/IFeeSharesMinter.sol';
import {IAaveV4ConfigEngine} from 'src/config-engine/interfaces/IAaveV4ConfigEngine.sol';

/// @title FeeSharesMinterEngine
/// @author Aave Labs
/// @notice Library containing FeeSharesMinter configuration logic for AaveV4ConfigEngine.
library FeeSharesMinterEngine {
/// @notice Sets per-asset minimum accrued fees percent on FeeSharesMinters.
/// @param configs The per-asset FeeSharesMinter configs to execute.
function executeFeeSharesMinterConfigs(
IAaveV4ConfigEngine.FeeSharesMinterConfig[] calldata configs
) external {
uint256 length = configs.length;
for (uint256 i; i < length; ++i) {
IFeeSharesMinter(configs[i].feeSharesMinter).setConfig(
configs[i].hub,
configs[i].assetId,
configs[i].minAccruedFeesPercent
);
}
}

/// @notice Sets the minimum accrued fees percent on FeeSharesMinters for every asset currently
/// listed on each Hub.
/// @param configs The hub-wide FeeSharesMinter configs to execute.
function executeFeeSharesMinterHubConfigs(
IAaveV4ConfigEngine.FeeSharesMinterHubConfig[] calldata configs
) external {
uint256 length = configs.length;
for (uint256 i; i < length; ++i) {
uint256 assetCount = IHub(configs[i].hub).getAssetCount();
for (uint256 assetId; assetId < assetCount; ++assetId) {
IFeeSharesMinter(configs[i].feeSharesMinter).setConfig(
configs[i].hub,
assetId,
configs[i].minAccruedFeesPercent
);
}
}
}

/// @notice Registers or updates workflow authorizations on FeeSharesMinters.
/// @param configs The FeeSharesMinter workflow configs to execute.
function executeFeeSharesMinterWorkflowConfigs(
IAaveV4ConfigEngine.FeeSharesMinterWorkflowConfig[] calldata configs
) external {
uint256 length = configs.length;
for (uint256 i; i < length; ++i) {
IFeeSharesMinter(configs[i].feeSharesMinter).setWorkflowConfig(
configs[i].workflowId,
configs[i].config
);
}
}
}
16 changes: 16 additions & 0 deletions src/dependencies/chainlink/IReceiver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
// Imported from https://github.com/smartcontractkit/chainlink/blob/v2.22.0/contracts/src/v0.8/keystone/interfaces/IReceiver.sol
pragma solidity ^0.8.0;

import {IERC165} from 'src/dependencies/openzeppelin/IERC165.sol';

/// @title IReceiver - receives keystone reports
/// @notice Implementations must support the IReceiver interface through ERC165.
interface IReceiver is IERC165 {
/// @notice Handles incoming keystone reports.
/// @dev If this function call reverts, it can be retried with a higher gas
/// limit. The receiver is responsible for discarding stale reports.
/// @param metadata Report's metadata.
/// @param report Workflow report.
function onReport(bytes calldata metadata, bytes calldata report) external;
}
11 changes: 9 additions & 2 deletions src/deployments/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ This deploys `LiquidationLogic` via CREATE2 and writes `FOUNDRY_LIBRARIES` to `.
make deploy-contracts
```

This runs `AaveV4DeployOrchestration.deployAaveV4()`, which deploys batches in order: AccessManager → role labeling → Configurators → Configurator role setup → TreasurySpoke → Hubs → Spokes → Gateways → PositionManagers → role grants → DEFAULT_ADMIN transfer.
This runs `AaveV4DeployOrchestration.deployAaveV4()`, which deploys batches in order: AccessManager → role labeling → Configurators → Configurator role setup → TreasurySpoke → FeeSharesMinter → Hubs → Spokes → Gateways → PositionManagers → role grants → DEFAULT_ADMIN transfer.

### TokenizationSpoke

Expand Down Expand Up @@ -66,6 +66,7 @@ src/deployments/
AaveV4AuthorityBatch AccessManagerEnumerable
AaveV4ConfiguratorBatch HubConfigurator, SpokeConfigurator
AaveV4TreasurySpokeBatch TreasurySpoke (single instance, proxy + impl)
AaveV4FeeSharesMinterBatch FeeSharesMinter (single instance for all hubs)
AaveV4HubInstanceBatch HubInstance (proxy + impl), InterestRateStrategy
AaveV4SpokeInstanceBatch SpokeInstance (proxy + impl), AaveOracle
AaveV4GatewayBatch NativeTokenGateway, SignatureGateway
Expand Down Expand Up @@ -130,7 +131,7 @@ See `Roles.sol` NatSpec for the full role strategy and evolution guidelines. All
| --- | --------------------------- | ---------------------------------- | ----------------------------------------------------------------------------- |
| 100 | HUB_DOMAIN_ADMIN_ROLE | hubAdmin | (reserved for future use) |
| 101 | HUB_CONFIGURATOR_ROLE | hubAdmin, HubConfigurator contract | addAsset, updateAssetConfig, addSpoke, updateSpokeConfig, setInterestRateData |
| 102 | HUB_FEE_MINTER_ROLE | hubAdmin | mintFeeShares |
| 102 | HUB_FEE_MINTER_ROLE | hubAdmin, FeeSharesMinter contract | mintFeeShares |
| 103 | HUB_DEFICIT_ELIMINATOR_ROLE | hubAdmin | eliminateDeficit |

#### `HubConfigurator` Roles
Expand Down Expand Up @@ -201,6 +202,11 @@ AaveV4DeployBatchBase.s.sol (Foundry script entry point)
| | new AaveV4TreasurySpokeBatch(owner, salt)
| | Create2Utils.create2Deploy() --> TreasurySpoke
| |
| +-- _deployFeeSharesMinterBatch()
| | AaveV4DeployBase.deployFeeSharesMinterBatch()
| | new AaveV4FeeSharesMinterBatch(owner, salt)
| | Create2Utils.create2Deploy() --> FeeSharesMinter
| |
| +-- InputUtils.validateUniqueLabels() revert on duplicate hub or spoke labels
| |
| +-- _deployHubs(hubLabels) for each hub label:
Expand Down Expand Up @@ -241,6 +247,7 @@ AaveV4DeployBatchBase.s.sol (Foundry script entry point)
| | _grantHubRoles() (if hubLabels.length > 0)
| | AaveV4HubRolesProcedure.grantHubAllRoles() hubAdmin gets roles 101-103
| | AaveV4HubRolesProcedure.grantHubRole() HubConfigurator gets role 101
| | AaveV4HubRolesProcedure.grantHubRole() FeeSharesMinter gets role 102
| | AaveV4HubConfiguratorRolesProcedure.grantHubConfiguratorAllRoles()
| | hubConfiguratorAdmin gets role 200
| | _grantSpokeRoles() (if spokeLabels.length > 0)
Expand Down
25 changes: 25 additions & 0 deletions src/deployments/batches/AaveV4FeeSharesMinterBatch.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: LicenseRef-BUSL
pragma solidity ^0.8.0;

import {BatchReports} from 'src/deployments/libraries/BatchReports.sol';
import {AaveV4FeeSharesMinterDeployProcedure} from 'src/deployments/procedures/deploy/utils/AaveV4FeeSharesMinterDeployProcedure.sol';

/// @title AaveV4FeeSharesMinterBatch
/// @author Aave Labs
/// @notice Deploys the FeeSharesMinter contract, producing a batch report.
contract AaveV4FeeSharesMinterBatch is AaveV4FeeSharesMinterDeployProcedure {
BatchReports.FeeSharesMinterBatchReport internal _report;

/// @dev Constructor.
/// @param owner_ The owner of the FeeSharesMinter.
/// @param salt_ The CREATE2 salt for deterministic deployment.
constructor(address owner_, bytes32 salt_) {
address feeSharesMinter = _deployFeeSharesMinter({owner: owner_, salt: salt_});
_report = BatchReports.FeeSharesMinterBatchReport({feeSharesMinter: feeSharesMinter});
}

/// @notice Returns the batch deployment report.
function getReport() external view returns (BatchReports.FeeSharesMinterBatchReport memory) {
return _report;
}
}
5 changes: 5 additions & 0 deletions src/deployments/libraries/BatchReports.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ library BatchReports {
address treasurySpoke;
}

/// @dev feeSharesMinter The deployed FeeSharesMinter contract address.
struct FeeSharesMinterBatchReport {
address feeSharesMinter;
}

/// @dev signatureGateway The deployed SignatureGateway contract address.
/// @dev nativeGateway The deployed NativeTokenGateway contract address.
struct GatewaysBatchReport {
Expand Down
2 changes: 2 additions & 0 deletions src/deployments/libraries/OrchestrationReports.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ library OrchestrationReports {
/// @dev authorityBatchReport AccessManager deployment report.
/// @dev configuratorBatchReport Configurator deployment report.
/// @dev treasurySpokeBatchReport TreasurySpoke deployment report.
/// @dev feeSharesMinterBatchReport FeeSharesMinter deployment report.
/// @dev spokeInstanceBatchReports Per-spoke deployment reports.
/// @dev hubInstanceBatchReports Per-hub deployment reports.
/// @dev gatewaysBatchReport Gateway deployment report.
Expand All @@ -33,6 +34,7 @@ library OrchestrationReports {
BatchReports.AuthorityBatchReport authorityBatchReport;
BatchReports.ConfiguratorBatchReport configuratorBatchReport;
BatchReports.TreasurySpokeBatchReport treasurySpokeBatchReport;
BatchReports.FeeSharesMinterBatchReport feeSharesMinterBatchReport;
SpokeDeploymentReport[] spokeInstanceBatchReports;
HubDeploymentReport[] hubInstanceBatchReports;
BatchReports.GatewaysBatchReport gatewaysBatchReport;
Expand Down
Loading
Loading