interface-lint by Layr-Labs
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.
Content & Writing
713 Stars
472 Forks
Updated Jan 8, 2026, 07:11 PM
Why Use This
This skill provides specialized capabilities for Layr-Labs's codebase.
Use Cases
- Developing new features in the Layr-Labs repository
- Refactoring existing code to follow Layr-Labs standards
- Understanding and working with Layr-Labs's codebase structure
Install Guide
2 steps- 1
Skip this step if Ananke is already installed.
- 2
Skill Snapshot
Auto scan of skill assets. Informational only.
Valid SKILL.md
Checks against SKILL.md specification
Source & Community
Repository eigenlayer-contracts
Skill Version
main
Community
713 472
Updated At Jan 8, 2026, 07:11 PM
Skill Stats
SKILL.md 261 Lines
Total Files 1
Total Size 8.9 KB
License NOASSERTION
---
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:
1. **`I{ContractName}Errors`** - All custom errors
2. **`I{ContractName}Types`** - All structs and enums
3. **`I{ContractName}Events`** - All events (inherits Types for struct access)
4. **`I{ContractName}`** - Main interface (inherits Errors and Events)
```solidity
// 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:
1. `@notice` describing when the error is thrown
2. `@dev Error code: 0x...` with the 4-byte selector from `cast sig`
### Generating Error Codes
Use `cast sig` to generate the error code:
```bash
cast sig "InvalidOperatorSet()"
# Output: 0x7ec5c154
```
### Error Format
```solidity
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:
1. `@notice` with a brief description
2. `@param` for each field in structs
```solidity
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:
```solidity
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:
1. `@notice` - What the function does
2. `@param` - Description for each parameter
3. `@return` - Description for each return value (for view functions)
4. `@dev` - Additional context (optional, but include caller requirements)
5. `@dev Reverts for:` - List ALL revert conditions
6. `@dev Emits the following events:` - List ALL events emitted
### Function Documentation Format
```solidity
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:
```solidity
/// @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:
```solidity
/// @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:
```solidity
/// @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:
```solidity
/// @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 sig` error codes
- Types interface with documented structs
- Events interface inheriting Types
- Main interface with full function documentation
## Checklist for Linting an Interface
1. ☐ Split into Errors, Types, Events, and main interface contracts
2. ☐ Errors have `@notice` and `@dev Error code: 0x...` (use `cast sig`)
3. ☐ Types have `@notice` and `@param` for each field
4. ☐ Events have singular `@notice` describing when emitted
5. ☐ Events interface inherits Types interface
6. ☐ Main interface inherits Errors and Events interfaces
7. ☐ Functions have `@notice`, `@param`, and `@return` (for views)
8. ☐ Functions list ALL revert conditions under `@dev Reverts for:`
9. ☐ Functions list ALL events under `@dev Emits the following events:`
10. ☐ View functions document reverts only when they can revert
## Generating All Error Codes
To generate error codes for an entire interface:
```bash
# 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 | Name Size