Skip to main content
ClaudeWave
Skill55 repo starsupdated 4mo ago

restaking

>

Install in Claude Code
Copy
git clone --depth 1 https://github.com/PurpleAILAB/Vigilo /tmp/restaking && cp -r /tmp/restaking/packages/opencode/skills/restaking ~/.claude/skills/restaking
Then start a new Claude Code session; the skill loads automatically.

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