Install in Claude Code
Copygit clone --depth 1 https://github.com/PurpleAILAB/Vigilo /tmp/restaking && cp -r /tmp/restaking/packages/opencode/skills/restaking ~/.claude/skills/restakingThen start a new Claude Code session; the skill loads automatically.
Definition
SKILL.md
# Restaking Protocol Vulnerability Analysis
**2025-2026 Statistics**: Restaking protocols hold $15B+ TVL (EigenLayer alone), with emerging attack vectors around slashing propagation and operator collusion causing significant concern.
---
## Restaking Overview
Restaking allows already-staked ETH (native or LST) to secure additional protocols (AVS - Actively Validated Services) for extra yield, while introducing layered risk.
```
ETH Staker
↓ Stake
Ethereum Beacon Chain (32 ETH validator)
↓ Restake
EigenLayer (extends security to AVS)
↓ Delegate
Operators (run AVS software)
↓ Secure
AVS (bridges, oracles, DA layers, etc.)
```
**Key Risk**: Slashing in AVS propagates back to original ETH stake.
---
## Why Restaking Fails (Root Causes)
### Root Cause 1: Cascading Slashing
Single misbehavior triggers slashing across multiple protocols.
```
Operator misbehaves on AVS-A
↓ Slashed on AVS-A
↓ EigenLayer reduces operator stake
↓ All delegators to this operator lose funds
↓ Multiple AVS security degraded simultaneously
```
**Attacker's view**: "One compromised operator affects thousands of users across multiple protocols."
### Root Cause 2: Unbounded Operator Trust
Stakers delegate to operators without understanding full risk exposure.
```solidity
// VULNERABLE: No limit on AVS registration
function registerForAVS(address avs) external onlyOperator {
registeredAVS[msg.sender].push(avs); // @audit Operator can register for unlimited AVS
// Staker funds now exposed to all AVS risks
}
```
### Root Cause 3: Withdrawal Queue Manipulation
Long withdrawal periods create opportunities for exploitation.
```solidity
// VULNERABLE: Fixed withdrawal delay
uint256 constant WITHDRAWAL_DELAY = 7 days;
function initiateWithdrawal(uint256 shares) external {
withdrawalQueue[msg.sender] = Withdrawal(shares, block.timestamp + WITHDRAWAL_DELAY);
// @audit If slashing occurs during delay, user loses more than expected
}
```
### Root Cause 4: LST/LRT Depeg Risk
Liquid (re)staking tokens can depeg from underlying, causing liquidation cascades.
```
stETH price drops 5% vs ETH
↓ Lending protocols see collateral value drop
↓ Liquidations trigger
↓ More stETH sold
↓ Further depeg
↓ Cascade continues
```
---
## The Restaking Risk Matrix (Core Artifact)
For each restaking integration, document:
| Component | Risk Type | Exposure | Mitigation | Status |
|-----------|-----------|----------|------------|--------|
| Operator A | Slashing | 3 AVS | Max slashing cap | Partial |
| AVS-Bridge | Corruption | $50M TVL | Fraud proofs | Active |
| stETH collateral | Depeg | 10% of protocol | Circuit breaker | Missing |
| Withdrawal queue | DoS | 7-day delay | Partial withdrawal | None |
---
## Detection Patterns
### Pattern 1: Unbounded Slashing Exposure
**Root Cause**: Cascading Slashing
```solidity
// VULNERABLE: No cap on slashable amount
function slash(address operator, uint256 amount) external onlyAVS {
operatorStake[operator] -= amount; // @audit Can slash entire stake
// No protection for delegators
}
// VULNERABLE: No limit on simultaneous slashing
mapping(address => address[]) public operatorAVS;
function executeSlashing(address operator) external {
for (uint i = 0; i < operatorAVS[operator].length; i++) {
IAVs(operatorAVS[operator][i]).slash(operator);
// @audit Multiple AVS can slash simultaneously
}
}
```
**Attack Flow**:
1. Operator registers for many AVS
2. Single misbehavior triggers multi-AVS slashing
3. Operator stake completely drained
4. Delegators lose everything
5. AVS security simultaneously compromised
**Search Queries**:
```
Grep("slash|slashing|penalty", glob="**/*.sol")
Grep("operator.*stake|stake.*operator", glob="**/*.sol")
```
**Mitigation**:
```solidity
// Per-AVS slashing cap
mapping(address => uint256) public maxSlashPerAVS;
function slash(address operator, uint256 amount) external onlyAVS {
uint256 cappedAmount = Math.min(amount, maxSlashPerAVS[msg.sender]);
operatorStake[operator] -= cappedAmount;
}
// Global slashing cap per time period
mapping(address => uint256) public slashingThisPeriod;
uint256 constant MAX_SLASHING_PER_PERIOD = 10e18; // 10 ETH
```
### Pattern 2: Operator Collusion
**Root Cause**: Insufficient Operator Validation
```solidity
// VULNERABLE: No operator quality checks
function registerAsOperator() external payable {
require(msg.value >= MIN_STAKE);
operators[msg.sender] = true;
// @audit Anyone with MIN_STAKE can become operator
// No reputation, no KYC, no history check
}
// VULNERABLE: Operators can collude
function validateBlock(bytes calldata blockData) external onlyOperator {
// @audit Multiple operators from same entity can sign
// Sybil attack possible
}
```
**Search Queries**:
```
Grep("registerOperator|isOperator|onlyOperator", glob="**/*.sol")
Grep("validateBlock|sign|attest", glob="**/*.sol")
```
### Pattern 3: Withdrawal Queue Exploitation
**Root Cause**: Withdrawal Queue Manipulation
```solidity
// VULNERABLE: No slashing protection during withdrawal
function completeWithdrawal(uint256 withdrawalId) external {
Withdrawal storage w = withdrawals[withdrawalId];
require(block.timestamp >= w.unlockTime);
uint256 amount = w.shares * totalAssets() / totalShares();
// @audit If slashing occurred, totalAssets decreased
// User receives less than expected
_transfer(msg.sender, amount);
}
```
**Attack Flow**:
1. User initiates withdrawal
2. During 7-day delay, operator gets slashed
3. totalAssets decreases
4. User's share worth less
5. User receives less than when they initiated
**Search Queries**:
```
Grep("withdrawal.*queue|queue.*withdrawal", glob="**/*.sol")
Grep("initiateWithdrawal|completeWithdrawal|unstake", glob="**/*.sol")
```
**Mitigation**:
```solidity
// Lock in exit value at initiation
function initiateWithdrawal(uint256 shares) external {
uint256 asse