Skip to content
Open
Show file tree
Hide file tree
Changes from 28 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
47 changes: 47 additions & 0 deletions src/dependencies/chainlink/AutomationCompatibleInterface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: MIT
// Imported from https://github.com/smartcontractkit/chainlink/blob/v2.22.0/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol
pragma solidity ^0.8.0;

// solhint-disable-next-line interface-starts-with-i
interface AutomationCompatibleInterface {
/**
* @notice method that is simulated by the keepers to see if any work actually
* needs to be performed. This method does does not actually need to be
Comment thread
CheyenneAtapour marked this conversation as resolved.
Outdated
Comment thread
CheyenneAtapour marked this conversation as resolved.
Outdated
* executable, and since it is only ever simulated it can consume lots of gas.
* @dev To ensure that it is never called, you may want to add the
* cannotExecute modifier from KeeperBase to your implementation of this
* method.
* @param checkData specified in the upkeep registration so it is always the
* same for a registered upkeep. This can easily be broken down into specific
* arguments using `abi.decode`, so multiple upkeeps can be registered on the
* same contract and easily differentiated by the contract.
* @return upkeepNeeded boolean to indicate whether the keeper should call
* performUpkeep or not.
* @return performData bytes that the keeper should call performUpkeep with, if
* upkeep is needed. If you would like to encode data to decode later, try
* `abi.encode`.
*/
function checkUpkeep(
bytes calldata checkData
) external returns (bool upkeepNeeded, bytes memory performData);

/**
* @notice method that is actually executed by the keepers, via the registry.
* The data returned by the checkUpkeep simulation will be passed into
* this method to actually be executed.
* @dev The input to this method should not be trusted, and the caller of the
* method should not even be restricted to any single registry. Anyone should
* be able call it, and the input should be validated, there is no guarantee
* that the data passed in is the performData returned from checkUpkeep. This
* could happen due to malicious keepers, racing keepers, or simply a state
* change while the performUpkeep transaction is waiting for confirmation.
* Always validate the data passed in.
* @param performData is the data which was passed back from the checkData
* simulation. If it is encoded, it can easily be decoded into other types by
* calling `abi.decode`. This data should not be trusted, and should be
* validated against the contract's current state.
*/
function performUpkeep(
bytes calldata performData
) external;
}
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
16 changes: 16 additions & 0 deletions src/deployments/orchestration/AaveV4DeployBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {AaveV4PositionManagerBatch} from 'src/deployments/batches/AaveV4Position
import {AaveV4SpokeInstanceBatch} from 'src/deployments/batches/AaveV4SpokeInstanceBatch.sol';
import {AaveV4TokenizationSpokeBatch} from 'src/deployments/batches/AaveV4TokenizationSpokeBatch.sol';
import {AaveV4TreasurySpokeBatch} from 'src/deployments/batches/AaveV4TreasurySpokeBatch.sol';
import {AaveV4FeeSharesMinterBatch} from 'src/deployments/batches/AaveV4FeeSharesMinterBatch.sol';

/// @title AaveV4DeployBase Library
/// @author Aave Labs
Expand Down Expand Up @@ -61,6 +62,21 @@ library AaveV4DeployBase {
return treasurySpokeBatch.getReport();
}

/// @notice Deploys the FeeSharesMinter batch containing the FeeSharesMinter contract.
/// @param owner The owner of the FeeSharesMinter.
/// @param salt The CREATE2 salt for deterministic deployment.
/// @return The FeeSharesMinter batch report.
function deployFeeSharesMinterBatch(
address owner,
bytes32 salt
) internal returns (BatchReports.FeeSharesMinterBatchReport memory) {
AaveV4FeeSharesMinterBatch feeSharesMinterBatch = new AaveV4FeeSharesMinterBatch({
owner_: owner,
salt_: salt
});
return feeSharesMinterBatch.getReport();
}

/// @notice Deploys the Hub instance batch containing the Hub proxy, implementation, and IR strategy.
/// @param proxyAdminOwner The owner of the proxy admin.
/// @param authority The access-control authority for the Hub.
Expand Down
19 changes: 19 additions & 0 deletions src/deployments/orchestration/AaveV4DeployOrchestration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ library AaveV4DeployOrchestration {
salt: salt
});

// Deploy FeeSharesMinter Batch (single instance for all hubs)
report.feeSharesMinterBatchReport = _deployFeeSharesMinterBatch({
logger: logger,
feeSharesMinterOwner: deployInputs.feeSharesMinterOwner,
salt: salt
});

// Validate label uniqueness (duplicate labels produce identical CREATE2 salts)
InputUtils.validateUniqueLabels(deployInputs.hubLabels, 'hub');
InputUtils.validateUniqueLabels(deployInputs.spokeLabels, 'spoke');
Expand Down Expand Up @@ -340,6 +347,18 @@ library AaveV4DeployOrchestration {
return report;
}

function _deployFeeSharesMinterBatch(
Logger logger,
address feeSharesMinterOwner,
bytes32 salt
) internal returns (BatchReports.FeeSharesMinterBatchReport memory report) {
logger.logHeader1('deploying FeeSharesMinterBatch');
report = AaveV4DeployBase.deployFeeSharesMinterBatch({owner: feeSharesMinterOwner, salt: salt});
logger.log('FeeSharesMinter', report.feeSharesMinter);
logger.logNewLine();
return report;
}

function _deployGatewayBatch(
Logger logger,
address gatewayOwner,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: LicenseRef-BUSL
pragma solidity ^0.8.0;

import {AaveV4DeployProcedureBase} from 'src/deployments/procedures/AaveV4DeployProcedureBase.sol';
import {Create2Utils} from 'src/deployments/utils/libraries/Create2Utils.sol';
import {FeeSharesMinter} from 'src/utils/FeeSharesMinter.sol';

/// @title AaveV4FeeSharesMinterDeployProcedure
/// @author Aave Labs
/// @notice Deploys the FeeSharesMinter contract.
contract AaveV4FeeSharesMinterDeployProcedure is AaveV4DeployProcedureBase {
/// @notice Deploys a new FeeSharesMinter instance via CREATE2.
/// @param owner The owner of the FeeSharesMinter.
/// @param salt The CREATE2 salt for deterministic deployment.
/// @return The address of the deployed FeeSharesMinter contract.
function _deployFeeSharesMinter(address owner, bytes32 salt) internal returns (address) {
require(owner != address(0), 'invalid owner');
return
Create2Utils.create2Deploy({
salt: salt,
bytecode: abi.encodePacked(type(FeeSharesMinter).creationCode, abi.encode(owner))
});
}
}
1 change: 1 addition & 0 deletions src/deployments/utils/MetadataLogger.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ contract MetadataLogger is Logger {
_write('hubConfigurator', report.configuratorBatchReport.hubConfigurator);
_write('spokeConfigurator', report.configuratorBatchReport.spokeConfigurator);
_write('treasurySpoke', report.treasurySpokeBatchReport.treasurySpoke);
_write('feeSharesMinter', report.feeSharesMinterBatchReport.feeSharesMinter);

// Group hubs by property type
uint256 hubLen = report.hubInstanceBatchReports.length;
Expand Down
3 changes: 3 additions & 0 deletions src/deployments/utils/libraries/InputUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ library InputUtils {
/// @dev hubConfiguratorAdmin The admin granted all hub configurator roles. Only used when grantRoles is true.
/// @dev treasurySpokeOwner The owner of the TreasurySpoke (Ownable). Required at deploy time (constructor arg).
/// When grantRoles is `false`, defaults to the deployer; ownership can be transferred post-deployment.
/// @dev feeSharesMinterOwner The owner of the FeeSharesMinter (Ownable). Required at deploy time (constructor arg).
/// When grantRoles is `false`, defaults to the deployer; ownership can be transferred post-deployment.
/// @dev spokeAdmin The spoke admin. Only used when grantRoles is true.
/// @dev spokeConfiguratorAdmin The admin granted all spoke configurator roles. Only used when grantRoles is true.
/// @dev gatewayOwner The owner of the native token and signature gateways.
Expand All @@ -34,6 +36,7 @@ library InputUtils {
address hubAdmin;
address hubConfiguratorAdmin;
address treasurySpokeOwner;
address feeSharesMinterOwner;
address spokeAdmin;
address spokeConfiguratorAdmin;
address gatewayOwner;
Expand Down
89 changes: 89 additions & 0 deletions src/utils/FeeSharesMinter.sol
Comment thread
DhairyaSethi marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: LicenseRef-BUSL
pragma solidity 0.8.28;

import {Ownable2Step, Ownable} from 'src/dependencies/openzeppelin/Ownable2Step.sol';
import {PercentageMath} from 'src/libraries/math/PercentageMath.sol';
import {Rescuable} from 'src/utils/Rescuable.sol';
import {IFeeSharesMinter} from 'src/utils/IFeeSharesMinter.sol';
import {IHub} from 'src/hub/interfaces/IHub.sol';

/// @title FeeSharesMinter
/// @author Aave Labs
/// @notice Contract to mint fee shares on the Hub when specific conditions are met.
contract FeeSharesMinter is IFeeSharesMinter, Ownable2Step, Rescuable {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

who will own this contract? if EXECUTOR, then what I don't like is that we have no option to disable fee minting without an AIP

wdyt?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets add OwnableWithGuardian ac and allow disable fee through guardian, or longer way to introduce AccessManager here

mapping(address hub => mapping(uint256 assetId => uint16)) internal _minAccruedFeesPercent;
Comment thread
avniculae marked this conversation as resolved.

/// @dev Constructor.
/// @param owner The owner of the contract.
constructor(address owner) Ownable(owner) {}

/// @inheritdoc IFeeSharesMinter
function setConfig(
address hub,
uint256 assetId,
uint16 minAccruedFeesPercent
) external onlyOwner {
require(minAccruedFeesPercent <= PercentageMath.PERCENTAGE_FACTOR, InvalidConfig());
_minAccruedFeesPercent[hub][assetId] = minAccruedFeesPercent;
Comment thread
avniculae marked this conversation as resolved.
emit ConfigUpdated(hub, assetId, minAccruedFeesPercent);
}

/// @inheritdoc IFeeSharesMinter
function performUpkeep(bytes calldata performData) external override {
(address hub, uint256 assetId) = abi.decode(performData, (address, uint256));
_performUpkeep(hub, assetId);
}

/// @inheritdoc IFeeSharesMinter
function checkUpkeep(
bytes calldata checkData
) external view override returns (bool, bytes memory) {
Comment thread
Kogaroshi marked this conversation as resolved.
Outdated
(address hub, uint256 assetId) = abi.decode(checkData, (address, uint256));
bool upkeepNeeded = _checkUpkeep(hub, assetId);
bytes memory performData = checkData;
Comment thread
avniculae marked this conversation as resolved.
Outdated
return (upkeepNeeded, performData);
}

/// @inheritdoc IFeeSharesMinter
function getConfig(address hub, uint256 assetId) external view returns (uint16) {
return _minAccruedFeesPercent[hub][assetId];
}

/// @dev Internal function to execute fee share minting.
/// @param hub The address of the hub.
/// @param assetId The identifier of the asset.
function _performUpkeep(address hub, uint256 assetId) internal virtual {
require(_checkUpkeep(hub, assetId), ConditionsNotMet());

IHub(hub).mintFeeShares(assetId);
}

/// @dev Internal function to check execution conditions.
/// @param hub The address of the hub.
/// @param assetId The identifier of the asset.
Comment thread
yan-man marked this conversation as resolved.
Outdated
/// @return True if conditions are met, false otherwise.
function _checkUpkeep(address hub, uint256 assetId) internal view virtual returns (bool) {
uint16 minAccruedFeesPercent = _minAccruedFeesPercent[hub][assetId];

IHub hubContract = IHub(hub);
Comment thread
avniculae marked this conversation as resolved.
Outdated
uint256 accruedFees = hubContract.getAssetAccruedFees(assetId);
uint256 totalAddedAssets = hubContract.getAddedAssets(assetId);

if (totalAddedAssets == 0) {
return false;
}
if (PercentageMath.percentDivDown(accruedFees, totalAddedAssets) < minAccruedFeesPercent) {
Comment thread
yan-man marked this conversation as resolved.
Outdated
Comment thread
avniculae marked this conversation as resolved.
Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is bps enough precision here?

return false;
}

// Ensure at least 1 fee share would be minted
uint256 expectedShares = hubContract.previewAddByAssets(assetId, accruedFees);
Comment thread
Kogaroshi marked this conversation as resolved.
Outdated

return expectedShares > 0;
}

/// @inheritdoc Rescuable
function _rescueGuardian() internal view override returns (address) {
return owner();
}
}
46 changes: 46 additions & 0 deletions src/utils/IFeeSharesMinter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: LicenseRef-BUSL
pragma solidity 0.8.28;

import {AutomationCompatibleInterface} from 'src/dependencies/chainlink/AutomationCompatibleInterface.sol';

/// @title IFeeSharesMinter
/// @author Aave Labs
/// @notice Interface for the FeeSharesMinter contract
interface IFeeSharesMinter is AutomationCompatibleInterface {
/// @notice Emitted when the configuration for an asset is updated.
/// @param hub The address of the hub.
Comment thread
Kogaroshi marked this conversation as resolved.
Outdated
/// @param assetId The identifier of the asset.
/// @param minAccruedFeesPercent The new minimum ratio of accrued fees to total added assets, in BPS.
event ConfigUpdated(address indexed hub, uint256 indexed assetId, uint16 minAccruedFeesPercent);

/// @notice Thrown upon minting when the required conditions are not met.
error ConditionsNotMet();

/// @notice Thrown when `setConfig` is called with an invalid value.
error InvalidConfig();
Comment thread
avniculae marked this conversation as resolved.
Outdated

/// @notice Sets the minimum accrued fees percent for a specific asset.
/// @param hub The address of the hub.
Comment thread
Kogaroshi marked this conversation as resolved.
Outdated
/// @param assetId The identifier of the asset.
/// @param minAccruedFeesPercent Minimum ratio of accrued fees to total added assets, in BPS.
function setConfig(address hub, uint256 assetId, uint16 minAccruedFeesPercent) external;

/// @notice Chainlink Automation on-chain execution entry point.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nbd but just need to align on onchain vs on-chain consistency

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we seem to use on-chain in other parts of the repo, so I'd keep as is.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont really mind either way but in JP's tech docs it's using onchain: https://github.com/aave/aave-v4/pull/1297/changes

@CanonicalJP thoughts?

/// @dev performData must be abi.encoded as (address hub, uint256 assetId).
/// @inheritdoc AutomationCompatibleInterface
function performUpkeep(bytes calldata performData) external;
Comment thread
avniculae marked this conversation as resolved.
Outdated

/// @notice Chainlink Automation off-chain simulation check.
/// @dev checkData must be abi.encoded as (address hub, uint256 assetId).
Comment thread
CheyenneAtapour marked this conversation as resolved.
Outdated
/// @dev Returns whether upkeep is needed and the performData in bytes when conditions are met.
/// @inheritdoc AutomationCompatibleInterface
function checkUpkeep(
bytes calldata checkData
) external view returns (bool upkeepNeeded, bytes memory performData);
Comment thread
CheyenneAtapour marked this conversation as resolved.
Outdated

/// @notice Returns the minimum accrued fees percent for a specific asset.
/// @param hub The address of the hub.
Comment thread
Kogaroshi marked this conversation as resolved.
Outdated
/// @param assetId The identifier of the asset.
/// @return The minimum ratio of accrued fees to total added assets, in BPS.
function getConfig(address hub, uint256 assetId) external view returns (uint16);
}
Loading
Loading