EigenLayerVerifier
Overview​
EigenLayerVerifier is a custom ICustomVerifier implementation tailored to securely authorize calls to EigenLayer contracts like DelegationManager, StrategyManager, and RewardsCoordinator. It uses strict role-based gating, exact calldata matching, and entity specific validation to ensure that only authorized vaults and bots can interact with EigenLayer staking, delegation, withdrawal, and rewards workflows.
Purpose​
This verifier protects EigenLayer operations by:
- Ensuring only whitelisted entities (vaults, strategies, operators) can execute actions.
- Verifying target contracts and function selectors precisely.
- Enforcing exact calldata encoding to eliminate any ambiguity or abuse.
Role Definitions​
| Role Constant | Description |
|---|---|
CALLER_ROLE | Address allowed to initiate EigenLayer calls (typically curators) |
ASSET_ROLE | Whitelisted ERC20 token allowed in strategy deposits or withdrawals |
STRATEGY_ROLE | Whitelisted EigenLayer strategy contracts |
OPERATOR_ROLE | Approved EigenLayer operator address for delegation |
MELLOW_VAULT_ROLE | Whitelisted vaults acting as stakers or earners (usually Subvault) |
RECEIVER_ROLE | Authorized receivers for claimed rewards |
Constructor​
constructor(address delegationManager_, address strategyManager_, address rewardsCoordinator_, string memory name_, uint256 version_)
Initializes the verifier by:
- Setting immutable references to EigenLayer's
DelegationManager,StrategyManager, andRewardsCoordinator. - Inheriting access control via
OwnedCustomVerifier.
verifyCall​
function verifyCall(
address who,
address where,
uint256 value,
bytes calldata callData,
bytes calldata /* verificationData */
) external view override returns (bool)
General Preconditions​
whomust haveCALLER_ROLE.valuemust be 0 (no ETH allowed).callData.length >= 4(valid selector).
Validated Targets & Selectors​
StrategyManager – depositIntoStrategy​
depositIntoStrategy(IStrategy, address asset, uint256 shares)
- Strategy must have
STRATEGY_ROLE. - Asset must have
ASSET_ROLE. - Shares must be non-zero.
- Calldata must match.
DelegationManager​
delegateTo(address operator, SignatureWithExpiry signature, bytes32 salt)
- Operator must have
OPERATOR_ROLE. - Calldata must match.
queueWithdrawals(QueuedWithdrawalParams[] params)
- Only one
params.length == 1allowed. - Param must include one strategy with
STRATEGY_ROLEand one deposit share > 0. - Calldata must match.
completeQueuedWithdrawal(Withdrawal, address[] tokens, bool receiveAsTokens)
receiveAsTokensmust betrue.- Withdrawal must have only one strategy with
STRATEGY_ROLEandstakerwithMELLOW_VAULT_ROLE. tokens.length == 1and token must haveASSET_ROLE.- Calldata must match.
RewardsCoordinator – processClaim​
Selector: processClaim(RewardsMerkleClaim claimData, address receiver)
claimData.earnerLeaf.earnermust haveMELLOW_VAULT_ROLE.receivermust haveRECEIVER_ROLE.- Calldata must match.
Security Properties​
- Role enforcement: Prevents unauthorized usage of EigenLayer functions.
- Exact calldata match: Avoids incorrect encoding or maliciously crafted data.
- Zero ETH transfers: Disallows unexpected native token usage.
- Single param enforcement (withdrawals): Minimizes complexity and risk surface.