
interface-lint
by Layr-Labs
Contracts of EigenLayer
SKILL.md
name: interface-lint description: Format and lint Solidity interface files following EigenLayer conventions. Use when the user asks to format an interface, add documentation to an interface, or create a new interface. Ensures proper organization with Errors/Events/Types sub-interfaces. allowed-tools: Read, Glob, Grep, Edit, Write, Bash(cast:*)
Interface Lint
Format Solidity interface files following EigenLayer's established conventions for organization, documentation, and error code generation.
Interface Structure
Every interface file should contain four interface contracts in this order:
I{ContractName}Errors- All custom errorsI{ContractName}Types- All structs and enumsI{ContractName}Events- All events (inherits Types for struct access)I{ContractName}- Main interface (inherits Errors and Events)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
// Imports
interface I{ContractName}Errors {
// All errors with error codes
}
interface I{ContractName}Types {
// All structs and enums
}
interface I{ContractName}Events is I{ContractName}Types {
// All events
}
interface I{ContractName} is I{ContractName}Errors, I{ContractName}Events {
// All function declarations
}
Error Documentation
Each error MUST include:
@noticedescribing when the error is thrown@dev Error code: 0x...with the 4-byte selector fromcast sig
Generating Error Codes
Use cast sig to generate the error code:
cast sig "InvalidOperatorSet()"
# Output: 0x7ec5c154
Error Format
interface IContractNameErrors {
/// @notice Thrown when the operator set is not valid
/// @dev Error code: 0x7ec5c154
error InvalidOperatorSet();
/// @notice Thrown when the chainId is invalid
/// @dev Error code: 0x7a47c9a2
error InvalidChainId();
/// @notice Thrown when the key type is not set for the operatorSet
/// @dev Error code: 0xe57cacbd
/// @dev Additional context about why this is required
error KeyTypeNotSet();
}
Types Documentation
Each struct/enum MUST include:
@noticewith a brief description@paramfor each field in structs
interface IContractNameTypes {
/// @notice A per-operatorSet configuration struct
/// @param owner the permissioned owner of the OperatorSet
/// @param maxStalenessPeriod the maximum staleness period in seconds
struct OperatorSetConfig {
address owner;
uint32 maxStalenessPeriod;
}
/// @notice Represents the status of an operator's registration
/// @param registered Whether the operator is currently registered
/// @param slashableUntil Block until which the operator remains slashable
struct RegistrationStatus {
bool registered;
uint32 slashableUntil;
}
}
Event Documentation
Each event MUST include a singular @notice describing when the event is emitted:
interface IContractNameEvents is IContractNameTypes {
/// @notice Emitted when a generation reservation is created
event GenerationReservationCreated(OperatorSet operatorSet);
/// @notice Emitted when an operator set config is set
event OperatorSetConfigSet(OperatorSet operatorSet, OperatorSetConfig config);
/// @notice Emitted when a chainID is added to the whitelist
event ChainIDAddedToWhitelist(uint256 chainID, address operatorTableUpdater);
}
Function Documentation
Each function in the main interface MUST include:
@notice- What the function does@param- Description for each parameter@return- Description for each return value (for view functions)@dev- Additional context (optional, but include caller requirements)@dev Reverts for:- List ALL revert conditions@dev Emits the following events:- List ALL events emitted
Function Documentation Format
interface IContractName is IContractNameErrors, IContractNameEvents {
/// @notice Creates a generation reservation for cross-chain transport
/// @param operatorSet the operatorSet to make a reservation for
/// @param operatorTableCalculator the calculator contract address
/// @param config the config containing owner and staleness period
/// @dev msg.sender must be an authorized caller for operatorSet.avs
/// @dev Reverts for:
/// - CurrentlyPaused: Generation reservations are paused
/// - InvalidPermissions: Caller is not authorized
/// - InvalidOperatorSet: The operatorSet does not exist
/// - GenerationReservationAlreadyExists: Reservation already exists
/// - InvalidStalenessPeriod: The maxStalenessPeriod is invalid
/// @dev Emits the following events:
/// - GenerationReservationCreated: When the reservation is created
/// - OperatorTableCalculatorSet: When the calculator is set
/// - OperatorSetConfigSet: When the config is set
function createGenerationReservation(
OperatorSet calldata operatorSet,
IOperatorTableCalculator operatorTableCalculator,
OperatorSetConfig calldata config
) external;
/// @notice Gets the operator set config
/// @param operatorSet the operatorSet to query
/// @return The OperatorSetConfig for the given operatorSet
/// @dev You should check if an operatorSet has an active reservation first
function getOperatorSetConfig(
OperatorSet memory operatorSet
) external view returns (OperatorSetConfig memory);
}
Revert Conditions Format
List each revert condition with the error name and when it occurs:
/// @dev Reverts for:
/// - CurrentlyPaused: Generation reservations are paused
/// - InvalidPermissions: Caller is not an authorized caller for operatorSet.avs
/// - InvalidOperatorSet: The operatorSet does not exist in the AllocationManager
/// - GenerationReservationAlreadyExists: A generation reservation already exists
For Ownable errors, use the string format:
/// @dev Reverts for:
/// - "Ownable: caller is not the owner": Caller is not the owner
Events Emitted Format
List each event with a brief description of when it's emitted:
/// @dev Emits the following events:
/// - GenerationReservationCreated: When the reservation is successfully created
/// - OperatorTableCalculatorSet: When the calculator is set for the operatorSet
/// - OperatorSetConfigSet: When the config is set for the operatorSet
View Functions
View functions typically don't revert (except for input validation) and don't emit events. Document them simpler:
/// @notice Gets the active generation reservations
/// @return An array of operatorSets with active generationReservations
function getActiveGenerationReservations() external view returns (OperatorSet[] memory);
/// @notice Gets reservations by range for pagination
/// @param startIndex the start index of the range, inclusive
/// @param endIndex the end index of the range, exclusive
/// @return An array of operatorSets in the specified range
/// @dev Reverts for:
/// - InvalidRange: startIndex is greater than endIndex
/// - InvalidEndIndex: endIndex exceeds array length
function getActiveGenerationReservationsByRange(
uint256 startIndex,
uint256 endIndex
) external view returns (OperatorSet[] memory);
Complete Example
Reference: src/contracts/interfaces/ICrossChainRegistry.sol
This file demonstrates the full pattern with:
- Errors interface with
cast sigerror codes - Types interface with documented structs
- Events interface inheriting Types
- Main interface with full function documentation
Checklist for Linting an Interface
- ☐ Split into Errors, Types, Events, and main interface contracts
- ☐ Errors have
@noticeand@dev Error code: 0x...(usecast sig) - ☐ Types have
@noticeand@paramfor each field - ☐ Events have singular
@noticedescribing when emitted - ☐ Events interface inherits Types interface
- ☐ Main interface inherits Errors and Events interfaces
- ☐ Functions have
@notice,@param, and@return(for views) - ☐ Functions list ALL revert conditions under
@dev Reverts for: - ☐ Functions list ALL events under
@dev Emits the following events: - ☐ View functions document reverts only when they can revert
Generating All Error Codes
To generate error codes for an entire interface:
# For each error in the interface, run:
cast sig "ErrorName()"
cast sig "ErrorName(uint256)" # Include params if error has them
# Example output:
# 0x7ec5c154 # InvalidOperatorSet()
# 0x7a47c9a2 # InvalidChainId()
Common Error Patterns
| Error | Typical Code | Usage |
|---|---|---|
InvalidOperatorSet() | 0x7ec5c154 | OperatorSet doesn't exist |
InvalidPermissions() | varies | Caller not authorized |
InvalidCaller() | varies | Wrong msg.sender |
ArrayLengthMismatch() | 0xa24a13a6 | Input arrays have different lengths |
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 500以上
3ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon