---
sidebar_position: 6
title: AVS Contracts
---

The AVS contracts are the contracts that call the [EigenLayer contacts](eigenlayer-contracts/core-contracts.md). An AVS can split onchain components across
multiple contracts to enable a modular design.

:::note
Before the Slashing release introduced [User Access Management (UAM)](https://github.com/eigenfoundation/ELIPs/blob/main/ELIPs/ELIP-003.md), AVS contract calls to EigenLayer were routed through a
single ServiceManager contract. With UAM, a modular approach to AVS contracts is possible. 

The [Hello World](https://github.com/Layr-Labs/hello-world-avs) and [Incredible Squaring](https://github.com/Layr-Labs/incredible-squaring-avs) examples are in the process of being updated to use UAM.
:::


---

---
sidebar_position: 1
title: AVS Overview
---


## What is an Autonomous Verifiable Service (AVS)?

An Autonomous Verifiable Service (AVS) on EigenLayer is a decentralized service built on Ethereum that provides custom verification mechanisms of off-chain operations. Please see the [Intro to EigenLayer](https://docs.eigenlayer.xyz/eigenlayer/overview/) for background context on the broader EigenLayer ecosystem.

An AVS is composed of on-chain contracts for verification and an off-chain network of Operators. Operators execute the service on behalf of the AVS and then post evidence of their execution on-chain to the AVS contracts. Tasks can be initiated via on-chain contracts, off-chain via direct communication with the Operators, or via a task aggregator entity.

The design of the off-chain execution and on-chain verification is entirely flexible based on the needs of the AVS developer. 
- If the Operators perform tasks properly, the AVS can autonomously distribute rewards.
- If the Operators perform tasks maliciously, their delegate stake can be slashed autonomously by the AVS, and the Operator can be removed from the Operator set.

![AVS Architecture](/img/avs/avs-architecture-v2.png)


## Why Build an AVS?

Launching new Web3 projects requires substantial time and effort to bootstrap capital and operators. Builders should focus on their core product differentiators rather than bootstrapping economic security. Building an Autonomous Verifiable Service (AVS) on EigenLayer offers enhanced security, decentralization, and cost efficiency by utilizing Ethereum’s staking mechanism through restaking. This allows developers to focus more on their product’s core value and innovation without the significant overhead of setting up a new consensus mechanism or validator networks from scratch.

The key benefits of building an AVS on EigenLayer include:
- Security via Restaking: leverage Ethereum’s staking mechanism to secure your service.
- Focus on your project's unique value: spend less time and resources accumulating economic security from scratch.
- Bootstrap your Operator network: quickly access a large network of experienced Operators.
- Decentralization and Trust: build on trust-minimized, decentralized infrastructure.
- Composability: seamlessly integrate with the broader Ethereum ecosystem.


## What Can You Build as an AVS?

The scope of AVS design is broad. It includes **any off-chain service** that can be verified on-chain. This flexibility allows AVS developers to design custom verification mechanisms suited to the unique requirements of their service. The only requirement is that some evidence for the off-chain service’s execution is posted on-chain to enable verification of the service.

Examples of these services include rollup services, co-processors, cryptography services, zk Proof services, and more.

![AVS Categories](/img/avs/avs-categories.png)


## Get in Touch

If you would like to discuss your ideas to build an AVS on EigenLayer, submit your contact information via [this form](https://www.eigencloud.xyz/contact) and we'll be in touch shortly.


---

---
sidebar_position: 7
title: AVS Security Models
---

The security model of an AVS defines who or what is trusted in an AVS, and under what conditions that trust holds. AVSs may 
have different levels of decentralization, slashing risks, and trust assumptions.

Security models available to AVSs in order of decentralization include:
* Proof of Authority. An AVS maintains a whitelist of trusted Operators.
* Permissionless Trusted Operation. An AVS trusts the top N Operators by delegated stake to run the service.
  The Permissionless Operator set can be managed by Operator ejection if SLAs are not met.
* Unique Stake allocation. An AVS requires Operators to have a certain amount of Unique Stake (that is, Slashable Stake) allocated.
  Slashing conditions can be: 
  * Objective. Attributable onchain faults. For example, rollup execution validity. 
  * Subjective. Governance based. For example, token holders in a DAO vote to slash, or vote to veto slashing.
  * Intersubjective Slashing Conditions. Broad-based agreement among all reasonable active observers. For example, data
    withholding.

:::note 
The list of security models is not exhaustive. The EigenLayer protocol provides a slashing function that is maximally flexible.
AVSs have flexibility to design their protocols to slash for any reason. AVSs are encouraged to:
* Create robust legibility and process around how their slashing is designed and individual slashing events. 
* Clearly communicate slashing design and individual slashing events to their Operator and Staker communities. 
* Make strong guarantees about how upstream contracts function for Redistributing Operator Sets to their Operator and Staker communities.
:::

---

---
sidebar_position: 1
title: EigenLayer Core Contracts
---

The EigenLayer core contracts are the set of contracts that are implemented and maintained by EigenLabs and upgradeable by
the Protocol Council.

The EigenLayer core contracts are documented in the [eigenlayer-contracts](https://github.com/Layr-Labs/eigenlayer-contracts) repository. The core contracts include contracts for:
* The [EigenLayer protocol](#eigenlayer-protocol-core-contracts) to stake and secure verifiable services, and to enable incentives and consequences for Operator commitments.
* [Permissions](#permissions-core-contracts) including User Access Management (UAM), and managing cryptographic keys for Operators across different Operator Sets.
* The [multichain protocol](#multichain-core-contracts) to enable consumption of EigenLayer Ethereum stake on supported destination chains.

This documentation matches the functionality available in [v1.7.0 of the core contracts](../../../releases.md). For release specific
documentation for other releases, refer to the `/docs` repository on the branch for that release in the [eigenlayer-contracts](https://github.com/Layr-Labs/eigenlayer-contracts) repository.

## EigenLayer Protocol Core Contracts

| Core contract                                                                                                            | Description                                                                                                                                                                                                                                                                                                                                                                     | 
|--------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [StrategyManager](https://github.com/Layr-Labs/eigenlayer-contracts/tree/main/docs#strategymanager)           | Responsible for handling the accounting for Restakers as they deposit and withdraw ERC20 tokens from their corresponding strategies. The StrategyManager tracks the amount of restaked assets each Restaker has within Eigenlayer and handles outflows for burning or redistribution of slashed funds through the `clearBurnOrRedistributableShares` function.                                                                                                                                              |
| [DelegationManager](https://github.com/Layr-Labs/eigenlayer-contracts/tree/main/docs#delegationmanager)       | Responsible for enabling Restakers to delegate assets to Operators, and withdraw assets. The DelegationManager tracks the amount of assets from each Strategy that have been delegated to each Operator, and tracks accounting for slashing.                                                                                                                                    | 
| [EigenPodManager](https://github.com/Layr-Labs/eigenlayer-contracts/tree/main/docs#eigenpodmanager)           | Enables native ETH restaking                                                                                                                                                                                                                                                                                                                                                    | 
| [AllocationManager](https://github.com/Layr-Labs/eigenlayer-contracts/tree/main/docs#allocationmanager)       | Responsible for creating Operator Sets, and Operator registrations to Operator Sets. The Allocation Manager also tracks allocation of stake to a Operator Set, and enables AVSs to slash that stake.                                                                                                                                                                            
| [RewardsCoordinator](https://github.com/Layr-Labs/eigenlayer-contracts/tree/main/docs#allocationmanager)      | Enables AVSs to distribute ERC20 tokens to Operators and Restakers who delegated assets to Operators. The RewardsCoordinator tracks the rewards and enables Operators and Restakers to claim them.
| [AVSDirectory](https://github.com/Layr-Labs/eigenlayer-contracts/tree/main/docs#avsdirectory)                 | Has been replaced by AllocationManager and will be deprecated in a future release. We strongly recommend existing AVSs [migrate to using Operator Sets](../../howto/build/operator-sets/migrate-to-operatorsets.md) on Testnet.                                                                                                                                                 | 

## Permissions Core Contracts

| Core contract                                                                                                            | Description                                                                                                                                                                                                              | 
|--------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [PermissionController](https://github.com/Layr-Labs/eigenlayer-contracts/tree/main/docs#permissioncontroller) | Enables AVSs and Operators to delegate the ability to call certain core contract functions to other addresses. For more information, refer to [User Access Management](../../../concepts/uam/user-access-management.md). |
| [KeyRegistrar](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/permissions/KeyRegistrar.md)    | Manages cryptographic keys for operators across different operator sets. Supports both ECDSA and BN254 key types and ensures global uniqueness of keys across all operator sets.                                         |

## Multichain Core Contracts

| Core contract        | Description                                                                             | 
|----------------------|-----------------------------------------------------------------------------------------|
| [CertificateVerifier](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/multichain/destination/CertificateVerifier.md#certificateverifier)  | Responsible for verifying certificates onchain from an offchain task.                    |
| [OperatorTableUpdater](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/multichain/destination/OperatorTableUpdater.md#operatortableupdater) | Updates Operator table for each Operator Set from the stake root, and validates with storage proofs.       | 
| [CrossChainRegistry](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/multichain/source/CrossChainRegistry.md#crosschainregistry) | Manages the registration and deregistration of Operator Sets to the multichain protocol and helps generate the global stake root.|


---

---
sidebar_position: 5
title: Contract Addresses and Docs
---

## EigenLayer Core Restaking Contracts

The EigenLayer core contracts are located in this repo: [`Layr-Labs/eigenlayer-contracts`](https://github.com/Layr-Labs/eigenlayer-contracts). They enable restaking of liquid staking tokens (LSTs) and beacon chain ETH to secure new services, called AVSs (Autonomous Verifiable Services).

### Deployment Addresses

An up-to-date reference of our current mainnet and testnet contract deployments can be found in the core repository README: [`eigenlayer-contracts/README.md#deployments`](https://github.com/Layr-Labs/eigenlayer-contracts#current-deployment-contracts).

### Technical Documentation

Our most up-to-date contract-level documentation can be found in the core repository's docs folder: [`eigenlayer-contracts/docs`](https://github.com/Layr-Labs/eigenlayer-contracts/tree/main/docs).

---

---
sidebar_position: 1
title: EigenLayer Middleware Contracts
---

The EigenLayer middleware contracts are higher level interfaces to the [EigenLayer core contracts](core-contracts.md).
The middleware contracts can be: 
* Deployed as is. The exception is the ServiceManager contract used to register and deregister an AVS with EigenLayer.
* Modified to implement logic specific to the AVS before deploying 
* Not used. In this case, the interfaces present in the middleware contracts must be implemented in the AVS contracts.

We recommend new AVS developers use the middleware contracts as the higher level interface
to the core contracts. 

The middleware contracts are documented in the [eigenlayer-middleware](https://github.com/Layr-Labs/eigenlayer-middleware) repository.
The ServiceManagerBase contract is the reference implementation for the onchain registration and deregistration that each AVS must have.

---

---
sidebar_position: 4
title: Certificates
---

A certificate is a proof of a task being executed offchain by the Operators of an Operator Set. Typically, a certificate consists of an 
aggregation of Operator signatures that is verified against stake tables. In the case of a single Operator, the Operator can produce
a certificate with only their signature. 

An AVS implementation includes retrieving Operator signatures from Operators running a multichain verification service. For example, 
an AVS run aggregator that produces certificates from Operator signatures. 

The `CertificateVerifier` is responsible for verifying certificates from an offchain task, onchain.

## ECDSA Certificate

For Operator Sets with less than 30 Operators.

```
struct ECDSACertificate {
    uint32 referenceTimestamp;  // When certificate was created
    bytes32 messageHash;        // Hash of the signed message/task result
    bytes sig;                  // Concatenated operator signatures
}
```

## BLS Certificate

More efficient for Operator Sets with more than 30 Operators.

```
struct BN254Certificate {
    uint32 referenceTimestamp;  // When certificate was created
    bytes32 messageHash;        // Hash of the signed message/task result
    BN254.G1Point signature;    // Aggregate signature
    BN254.G2Point apk;         // Aggregate public key
    BN254OperatorInfoWitness[] nonSignerWitnesses; // Proof of non-signers
}
```

---

---
sidebar_position: 2
title: Architecture
---

The Multichain Verification framework uses the core contracts and templates in EigenLayer middleware described in the table. 
These are not pluggable and are intended to interface with offchain, modular components. 

| Contract Name                 | Deployment Target              | Deployer                 | Description                                                                                                                                                                                                      |
|-------------------------------|--------------------------------|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **`CertificateVerifier`**     | One per target chain           | EigenLayer Core Protocol | Enables AVS consumers to verify certificates with aggregated Operator signatures against transported Operator tables. The `CertificateVerifier` is the single integration point between AVSs and their consumers |
| **`KeyRegistrar`**            | Ethereum Singleton             | EigenLayer Core Protocol | Unified module for managing and retrieving BN254 and ECDSA cryptographic keys for Operators with built-in key rotation support, extensible to additional curves like BLS381                                      |
| **`CrossChainRegistry`**      | Ethereum Singleton             | EigenLayer Core Protocol | Coordination contract that manages the registration and deregistration of Operator Sets to the multichain protocol and exposes read-only functions to generate the Operator Table.                               |                            |
| **`OperatorTableCalculator`** | Ethereum, One per Operator Set | AVS Middleware           | Required middleware contract specified by an AVS (one per Operator Set) for calculating operator  weights, or customizable to decorate weights with custom logic such as stake capping                           |
| **`OperatorTableUpdater`**    | One per target chain           | EigenLayer Core Protocol | Parses and verifies the global Stake Table Root and calculates individual Operator tables in the `CertificateVerifier`                                                                                           |


## CertificateVerifier 

The `CertificateVerifier` is the core contract that AVSs need to integrate with, and consumers use to verify operator certificates against transported stake tables. 
It is the gateway to EigenLayer services (that is, where offchain services come onchain), is deployed on every supported target chain, and holds
the weight values from Ethereum for verifying Operator certificates. 

The `CertificateVerifier` has a stable, chain-agnostic integration pattern. You interact with the same 
interface regardless of which chain you're deploying to, or which consumers are using your AVS. This enables a "code once, 
deploy everywhere" workflow that reduces crosschain complexity, eases integration with other AVSs, and simplifies ongoing maintenance.

## KeyRegistrar

The `KeyRegistrar` manages cryptographic keys for Operators across different Operator Sets. It supports both ECDSA and BN254
key types and ensures global uniqueness of keys across all Operator Sets. The `KeyRegistrar` contract provides trusted, 
protocol-controlled code for AVSs to register Operator keys for Operator Sets. 

## CrossChainRegistry

The `CrossChainRegistry` is the core contract that manages the registration and deregistration of Operator Sets to the Multichain protocol. 
The `CrossChainRegistry` contract exposes read-only functions for calculating Operator Tables that are used offchain to generate
the global Stake Table. The `CrossChainRegistry` is the entrypoint for AVSs using the Multichain protocol, and houses configuration
of staleness periods, and specifies the `OperatorTableCalculator` used to define operator weights for each Operator Set.

## OperatorTableCalculator

The `OperatorTableCalculator` is an AVS-deployed contract (one per Operator Set) that can be used for decorating stake weights with custom logic. 
The contract interface allows AVSs to implement complex weighting features such as stake capping, differential asset weighting, 
oracle integrations, and minimum requirements. [Default templates](https://github.com/Layr-Labs/eigenlayer-middleware?tab=readme-ov-file#current-middlewarev2-testnet-deployment) that require no interaction or custom logic are provided for 
AVSs to specify as the `OperatorTableCalculator`.

## OperatorTableUpdater

The `OperatorTableUpdater` interfaces with offchain transport mechanisms. The `OperatorTableUpdater` confirms the data
that it receives from the global stake table and parses it into individual Operator Table updates on the `CertificateVerifier`. 
This enables accurate, timely updates for individual AVS's Operator Tables as Operators are slashed or ejected.

## Contract Interaction

The contracts interact as illustrated.

```mermaid
classDiagram 
direction TD
namespace Middleware-on-Ethereum{
    class OperatorTableCalculator {
        StakeCapping
        StakeWeighting (Multiplier, Oracle)
        ProtocolVotingPowerCalc
    }
    class AVSAdmin {
        metadataURI
        Permissions/multisigs/governance
        verificationDelay
        transportPayments
    }
    class AVSRegistrar {
         registerOperator
         deregisterOperator
    }
    class SlasherEjector {
      submitEvidence
      slashOperator ()
      ejectOperator ()
    }
    class RegistrationHooks{
        RegistrationLogic
        OperatorCaps
        Churn
        Sockets
    }
}
namespace Ethereum-EigenLayer-Core{
    class AllocationManager {
      registerForOperatorSets
      deregisterFromOperatorSets
      allocateStake
      deallocateStake
      slashOperator()
    }
    class KeyRegistrar{
      registerKey
      deregisterKey
      getKey (operator addr)
      isRegistered (operator addr)
    }
    class CrossChainRegistry{
      setOperatorTableCalculator
      getOperatorTableCalculator
      makeGenerationReservation
      addTransportDestination
      calculateOperatorTableBytes()
  }
}
namespace TargetChain{
    class OperatorTableUpdater{
      confirmGlobalTableRoot
      updateOperatorTable()
    }
    class CertificateVerifier{
      n Operator Tables
      updateOperatorTable()
      verifyCert (bool)
    }
    class AVSConsumer{
      requests Operator task 
      receives cert ()
    }
}

namespace Offchain{
 class Operator {
    consumer input
    return certificate()
 }
 class Transport{
    getOperatorTables
    n calculateOperatorTableBytes
    calculateGlobalStakeTable()
  }
}
AllocationManager --> AVSRegistrar
AVSAdmin --> CrossChainRegistry
CrossChainRegistry --> OperatorTableCalculator : Calculates Operator Tables
AVSRegistrar --> RegistrationHooks
RegistrationHooks --> KeyRegistrar
SlasherEjector --> AllocationManager : Slash or eject Operator 
CrossChainRegistry --> Transport : Transports Operator tables
Transport --> OperatorTableUpdater: Update global stake root 
OperatorTableUpdater --> CertificateVerifier: Update Operator Table
Operator --> AVSConsumer : Produces certificate
Operator <-- AVSConsumer : Requests task
AVS Consumer --> CertificateVerifier : Verifies Certificate
```

---

---
sidebar_position: 1
title: Overview
---

:::important
Multichain verification is early-access and in active development. Expect iterative updates before the mainnet release.

Multichain verification implements [ELIP-008 EigenLayer Multichain Verification](https://github.com/eigenfoundation/ELIPs/blob/elip-008v1/ELIPs/ELIP-008.md) and is available on testnet in v1.7.0.
:::

Multichain verification enables developers to build verifiable services that can operate across multiple chains and consumers of 
those services to verify those services on supported chains with the same trust and security of restaked assets on Ethereum.

## Components 

The multichain verification framework uses standardized infrastructure for key management, stake verification, and certificate
validation.

| **Component**                               | **Description**                                                                                                                                                                                                                                                                                                                                                                        | 
|---------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Weight**                                  | Standard process for stake weighting in the core and middleware. The AVS defines an array of numerical values representing an individual Operator's weight for work and reward distribution in the Operator Set. In the simplest form this may represent an Operator’s delegation or allocation of a single asset but is customizable for more complicated work distribution criteria. |
| **Operator table**                          | Data structure representing Operator weights of all Operators in a Operator Set (optionally custom-weighted).                                                                                                                                                                                                                                                                          |
| **Table calculation**                       | To facilitate the generation of Operator weights by the core protocol, AVSs specify a `OperatorTableCalculator` for each Operator Set to decorate stake weighting of different assets and apply the formats required by the AVS.                                                                                                                                                       |
| **Stake table**                             | Data structure (merkle tree) representing the global view of all Operator Sets and their corresponding Operator Tables. One of these lives on each target chain. The root of the stake table is the global table root.                                                                                                                                                                 | 
| **Certificates & certificate verification** | Data structure for signed Operator outputs (certificates) and a core contract (`CertificateVerifier`) for verifying those outputs against the Operator Table and Operator consensus rules (for example, signed weight above nominal or proportional stake thresholds).                                                                                                                 |
| **Stake generation & transport**            | Specification for generating and verifying the global stake table root and transporting it to core contracts on supported target chains. The process is pluggable by AVSs and other third-parties.                                                                                                                                                                                     

## Process

To have a single global root with up-to-date stake representation on target chains where an verifiable service is available: 

1. On Ethereum, the developer of the verifiable service specifies the logic for calculating its single, weighted Operator Table.
2. Offchain, EigenLabs combines the many Operator Set representations to generate a global stake table.
3. Crosschain, the global stake table is transported to target chains, and Operator Tables calculated.
4. On target chains, Operater Tables are used for verifying Operator certificates.
5. Offchain and crosschain, weekly, or as forcible updates are needed (for example, when an Operator is ejected or slashed), the global stake table is regenerated and transported again. 
    This ensures up-to-date weight representations wherever the verifiable service is consumed.

Certificates are an aggregation of signatures from Operators running a multichain verifiable service. To verify operator 
certificates against transported stake tables, consumers use the `CertificateVerifier`.

---

---
sidebar_position: 3
title: Stake Weighting
---

The `OperatorTableCalculator` defines how Operator stakes are weighted and formatted for your specific use case. 
`OperatorTableCalculator` is a mandatory contract that must be deployed, or a calculator address specified that works for their use-case, 
for each Operator Set to participate in multichain verification.

The `OperatorTableCalculator` contract converts raw EigenLayer stake data into weighted Operator Tables reflecting the 
AVS's specific requirements. For example, capping certain operators, weighting different assets differently, or integrating 
external price feeds.

The `OperatorTableCalculator` enables AVSs to control how their stake is weighted while maintaining standardized interfaces
for multichain verification. The stake weights are key to verifying Operator certificates.

## Default Table Calculators

[Default table calculators are provided](https://github.com/Layr-Labs/eigenlayer-middleware?tab=readme-ov-file#current-middlewarev2-testnet-deployment). For AVSs that don't need custom logic, default calculators that return unweighted stake values 
are provided for both `ECDSATableCalculator` and `BLSTableCalculator`.

For larger Operator Sets (30+ operators), BLS provides more efficient verification through aggregate signatures. The BLS 
calculator follows a similar pattern but optimizes for larger scale operations.

## Stake Weights 

By default, Operators are weighted by the number of allocated strategy shares across all strategies in the Operator Set.
This is a sufficient proxy for Operator Sets with single strategies, or if the value of all underlying shares are identical. 

:::note
The number of shares is decimal dependent. Assets with non-standard decimals (for example, USDC, USDT, WBTC) return 
significantly lower numbers of shares. For example, 1 wETH \= 10^18 shares. 1 USDC \= 10^6 shares.
::: 

## Customizing Stake Weights

The weights are captured in OperatorInfo structs for ESDSA and BLS. The weights array is completely flexible and AVSs can 
define any groupings they need. Common patterns include:

* Simple: `[total_stake]`
* Asset-specific: `[eth_stake, steth_stake, eigen_stake]`
* Detailed: `[slashable_stake, delegated_stake, strategy_1_stake, strategy_2_stake]`

Examples of customization options include: 

* Stake Capping: Limit any single operator to maximum 10% of total weight
* Asset Weighting: Weight ETH stakes 2x higher than other assets
* Oracle Integration: Use external price feeds to convert all stakes to USD values
* Minimum Requirements: Filter out operators below certain stake thresholds (that is, set their verification weight to zero)
* Operator Bonding: Operator self-staked assets have double weight

## Implementation Examples

### Simple Equal Weighting

```
// Basic implementation: return raw stake values without modification
function calculateOperatorTable(OperatorSet calldata operatorSet) 
    external view returns (ECDSAOperatorInfo[] memory) {
    return getRawStakeValues(operatorSet);
}
```

### Advanced Custom Weighting

```
// Advanced implementation with asset weighting and stake capping
function calculateOperatorTable(OperatorSet calldata operatorSet) 
    external view returns (ECDSAOperatorInfo[] memory) {
    ECDSAOperatorInfo[] memory operators = getRawStakeValues(operatorSet);
    
    for (uint i = 0; i < operators.length; i++) {
        // Apply asset-specific weighting
        // weights[0] = ETH stake, weights[1] = stablecoin stake
        operators[i].weights[0] *= 2;  // Weight ETH 2x higher
        operators[i].weights[1] *= 1;  // Keep stablecoins at 1x
        
        // Implement stake capping - limit any operator to 10% of total
        uint256 maxWeight = getTotalStake() / 10;
        if (operators[i].weights[0] > maxWeight) {
            operators[i].weights[0] = maxWeight;
        }
        
        // Filter out operators below minimum threshold
        if (operators[i].weights[0] < MINIMUM_STAKE_THRESHOLD) {
            operators[i].weights[0] = 0;  // Zero weight = excluded from verification
        }
    }
    return operators;
}
```

---

---
sidebar_position: 2
title: Key Management for Redistributable Slashing
---

When implementing [redistributable slashing](slashing-concept-developers.md), AVSs face significantly heightened security requirements. Unlike burn-only slashing where compromised keys result in destroyed funds, redistributable slashing allows attackers to steal funds directly.

:::important
When using Redistribution, an attacker that gains access to AVS keys for the slasher and `redistributionRecipient` can drain
the entirety of Operator and Staker allocated stake for a given Operator Set.
:::

For information on AVS key types, refer to [Keys](../../../concepts/keys-and-signatures).

### Critical Key Categories

**Slashing Authority Keys:**
- Keys authorized to call `slashOperator` on the `AllocationManager`
- Should be managed with the highest security standards
- Consider using multi-signature wallets with threshold signatures
- Implement geographic and organizational distribution of signers

**Redistribution Recipient Keys:**
- Keys controlling the `redistributionRecipient` address specified during Operator Set creation
- May receive slashed funds instantly upon calling `clearBurnOrRedistributableShares`
- Should be secured with hardware security modules (HSMs) when possible
- Consider using smart contract wallets rather than EOAs for enhanced security

### Enhanced Key Management Practices

**Multi-Signature Implementation:**
- Use threshold signatures for all critical operations.
- Distribute signing authority across multiple independent parties.
- Implement different threshold requirements for different operation types.
- Maintain offline backup signers in geographically distributed locations.

**Access Control and Separation:**
- Separate slashing authority from other AVS administrative functions
- Use different key sets for operational vs. governance functions
- Implement role-based access controls with principle of least privilege
- Regularly audit and rotate key assignments

**Operational Security:**
- Store keys in dedicated hardware security modules (HSMs)
- Implement comprehensive key rotation schedules
- Maintain secure key backup and recovery procedures
- Use air-gapped systems for key generation and critical operations






---

---
sidebar_position: 1
title: Slashing
---

For information on how slashing works, refer to concept content on [Slashing](../../../concepts/slashing/slashing-concept.md) and
[Operator Sets](../../../concepts/operator-sets/operator-sets-concept).

## Redistribution Recipient

:::important
When using [Redistribution](../../../concepts/slashing/redistribution.md), an attacker that gains access to AVS keys for the slasher and `redistributionRecipient` can drain
the entirety of Operator and Staker allocated stake for a given Operator Set.
:::

When creating a [redistributable Operator Set](../../howto/build/operator-sets/create-operator-sets.md), an immutable `redistributionRecipient` is specified. The `redistributionRecipient`
should be:
* An AVS-controlled role and signing key.
* A smart contract wallet or mulit-sig to ensure enhanced security and programmability.

The `redistributionRecipient` address cannot be changed. While an AVS may use an upstream proxy or pass-through contract, 
the immutability of this address in EigenLayer means an AVS can layer additional guarantees by guarding the upgradability 
of the upstream contract via controls such as governance, and timelocks.

For information on how to implement slashing, refer to: 
* [Implement Slashing](../../howto/build/slashing/implement-slashing)
* [Design Operator Sets](../../howto/build/operator-sets/design-operator-set.md)
* [Migrate to Operator Sets](../../howto/build/operator-sets/migrate-to-operatorsets.md)
* [Veto Committee Design](../../howto/build/slashing/slashing-veto-committee-design.md)

---

---
sidebar_position: 9
title: Tasks
---

Tasks are a common design model used for AVS operations. The task design model is not required by the EigenLayer protocol but
is a common mechanism used by AVSs. Use tasks to organize discrete units of work performed by Operators offchain that
are later validated onchain. A Task can be any unit of work written in any language as needed by the AVS.

Tasks can be submitted either:
1) Onchain by the Consumer (end user) to the AVS contracts.
2) Offchain by the Consumer directly to the Operators.

---

---
sidebar_position: 4
title: User Access Management
---

:::note
There is no support for setting appointees for AVSDirectory functions. The AVSDirectory method will be deprecated in a future upgrade.
[All AVSs will need to migrate to Operator Sets before the upcoming deprecation of AVSDirectory](../howto/build/operator-sets/migrate-to-operatorsets.md).
:::

For concept material on User Access Management (UAM) and roles, refer to:
* [User Access Management](../../concepts/uam/user-access-management.md)
* [Accounts](../../concepts/uam/uam-accounts.md)
* [Admins](../../concepts/uam/uam-admins.md)
* [Appointees](../../concepts/uam/uam-appointees.md)

UAM enables an AVS to split onchain components across multiple contracts to enable a modular design. 
The protocol functions that an AVS can set appointees for are:
* [`AllocationManager.slashOperator`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/AllocationManager.md#slashoperator)
* [`AllocationManager.deregisterFromOperatorSets`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/AllocationManager.md#deregisterfromoperatorsets)
* [`AllocationManager.setAVSRegistrar`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/AllocationManager.md#setavsregistrar)
* [`AllocationManager.updateAVSMetadataURI`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/AllocationManager.md#updateavsmetadatauri)
* [`AllocationManager.createOperatorSets`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/AllocationManager.md#createoperatorsets)
* [`AllocationManager.createRedistributingOperatorSets`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/AllocationManager.md#createredistributingoperatorsets)
* [`AllocationManager.addStrategiesToOperatorSet`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/AllocationManager.md#addstrategiestooperatorset)
* [`AllocationManager.removeStrategiesFromOperatorSet`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/AllocationManager.md#removestrategiesfromoperatorset)
* [`RewardsCoordinator.createOperatorDirectedAVSRewardsSubmission`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/RewardsCoordinator.md#createoperatordirectedavsrewardssubmission)
* [`RewardsCoordinator.createOperatorDirectedOperatorSetRewardsSubmission`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/RewardsCoordinator.md#createoperatordirectedoperatorsetrewardssubmission)
* [`RewardsCoordinator.setClaimerFor`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/RewardsCoordinator.md#setclaimerfor)

For information on how to set admins and appointees for an AVS, refer to:
* [Add and Remove Admins](../howto/build/uam/dev-add-remove-admins.md)
* [Add and Remove Appointees](../howto/build/uam/dev-add-remove-appointees.md)


---

---
sidebar_position: 7
title: Add ERC-20 Tokens as Restakable Asset
---

# Permissionless Token Strategies

Permissionless token support enables any ERC-20 token to be permissionlessly added as a restakable asset, significantly broadening
the scope of assets that can contribute to the security of decentralized networks, and unlocking the cryptoeconomic security of 
ERC-20 tokens on EigenLayer.

With permissionless token support, AVSs can choose to accept any ERC-20 token as a restaked asset to provide cryptoeconomic security for 
their AVS. This allows AVSs to evaluate the supply and utility of all available tokens to create cross-ecosystem partnerships 
while ensuring the safety and security of their services. This increases alignment and connectivity across the ecosystem.

# Adding a New Strategy

To add a new Strategy to the EigenLayer protocol:

* Invoke `StrategyFactory.deployNewStrategy()`.
* Your Strategy is now available to associate with your AVS.

Please see the contract documentation [here](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/StrategyManager.md#strategyfactorydeploynewstrategy) for further detail.

:::note
Custom Strategies are strategies that are not deployed via `StrategyFactory.deployNewStrategy()` and require whitelisting via 
`StrategyFactory.whitelistStrategies` (see [here](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/StrategyManager.md#strategyfactorywhiteliststrategies)). Custom Strategies have custom bytecode and do not implement `StrategyBase`. 

Custom Strategies are not yet supported because the Strategies specification is still evolving alongside the EigenLayer
protocol. AVS developers should build their AVS using the `StrategyBase` interface and functionality, which provides a
stable and supported foundation for integration.
:::

---

---
sidebar_position: 6
title: Manage Registered Operators
---

## AVSRegistrar

The [AVSRegistrar](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/src/contracts/interfaces/IAVSRegistrar.sol) is called when operators register for and deregister from [Operator Sets](../../../concepts/operator-sets/operator-sets-concept.md). By default (if the stored address
is 0), the call is made to the ServiceManager contract for the AVS. If the AVS has set a different contract as the AVSRegistrar, the specified contract is called.

### Setting AVSRegistrar

To set a contract as the AVSRegistrar, call the [`setAVSRegistrar`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/docs/core/AllocationManager.md#setavsregistrar) function. The target contract must also implement 
[`supportsAVS(AVS)`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/src/contracts/interfaces/IAVSRegistrar.sol) returning TRUE or setting the contract as the AVSRegistrar fails.

## Respond to Operator Registrations to Operator Sets

Operators use the [`registerForOperatorSets`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/docs/core/AllocationManager.md#registerforoperatorsets) function to register for AVS's operator sets. AVSs can reject ineligible 
Operators based on their own custom logic specified in the [AVSRegistrar](#avsregistrar).

For an AVS to reject an Operator attempting to join an Operator Set, the call from [AllocationManager](../../concepts/eigenlayer-contracts/core-contracts.md) to the 
[`IAVSRegistrar.registerOperator`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/src/contracts/interfaces/IAVSRegistrar.sol) function must revert. 

## Deregister Operators from, or respond to Operator deregistrations, from Operator Sets

Deregistration from an Operator Set can be triggered by either the Operator, or the AVS for the Operator Set, using the
[`deregisterFromOperatorSets`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/docs/core/AllocationManager.md#deregisterfromoperatorsets) function.

Similar to when an Operator registers for an Operator Set, if the call to [IAVSRegistrar.deregisterOperator](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/src/contracts/interfaces/IAVSRegistrar.sol) reverts, the
deregistration also reverts and does not occur. 


---

---
sidebar_position: 2
title: Configure Multichain AVS
---

:::important
Multichain verification is early-access and in active development. Expect iterative updates before the mainnet release.

Multichain implements [ELIP-008 EigenLayer Multichain Verification](https://github.com/eigenfoundation/ELIPs/blob/main/ELIPs/ELIP-008.md) and is available on testnet and mainnet in v1.7.0.
:::

The diagram illustrates the high level steps to configure multichain verification and create a reservation for a participating
AVS in the multichain verification framework: 

<img src="/img/multichain-registration.png" alt="Multichain Implementation" width="600"/>

Implementers of multichain verification need to:
1. [Configure Operator Set curve type](#1-configure-operator-set-curve-type)
2. [Deploy Operator table calculator](#2-deploy-operator-table-calculator)
3. [(Optional) View the registered cryptographic keys for your Operator Set](#3-optional-view-the-registered-cryptographic-keys-for-your-operator-set)
4. [Opt-in to multichain](#4-opt-in-to-multichain-and-create-a-generation-reservation)
5. [Wait for deployment](#5-wait-for-deployment)

## 1. Configure Operator Set Curve Type

1. Decide on the cryptographic curve type for Operator keys. Choose ECDSA for less than 30 Operators, or BN254 BLS for more than 30 Operators.
2. [Create the Operator Set](../operator-sets/create-operator-sets.md). 
3. [Set the `KeyType` in `KeyRegistrar`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/v1.8.0-rc.0/docs/permissions/KeyRegistrar.md).

## 2. Deploy Operator Table Calculator

[Deploy the `OperatorTableCalculator` contract to define stake weighting logic.](https://github.com/Layr-Labs/eigenlayer-middleware/blob/dev/docs/middlewareV2/OperatorTableCalculator.md)

To use the as-is unweighted stakes, deploy the template `ECDSATableCalculatorBase` or `BN254TableCalculatorBase` contract.
The contract can be upgraded. Alternatively, use the onchain [default unweighted contract provided by EigenLabs](https://github.com/Layr-Labs/eigenlayer-middleware?tab=readme-ov-file#current-middlewarev2-testnet-deployment).

To define custom stake weighting logic, override [`calculateOperatorTable()`](https://github.com/Layr-Labs/eigenlayer-middleware/blob/dev/docs/middlewareV2/OperatorTableCalculator.md#calculateoperatortable) to add:
- Asset weighting (for example, ETH 3500x vs. stablecoins),
- Stake capping per operator,
- Oracle price feed integration,
- Custom filtering logic.

For more information on stake weighting and how to customize, refer to [Stake Weighting](../../../concepts/multichain/stake-weighting.md).

## 3. (Optional) View the registered cryptographic keys for your Operator Set

Operators self-register using [`KeyRegistrar.registerKey(operator, operatorSet, pubkey, sig)`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/v1.7.0-rc.4/docs/permissions/KeyRegistrar.md#key-registration).

## 4. Opt-in to Multichain and create a generation reservation

To enable multichain verification, register with `CrossChainRegistry`. To register, use: 

[`CrossChainRegistry.createGenerationReservation(operatorSet, calculator, config)`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/v1.7.0-rc.4/docs/multichain/source/CrossChainRegistry.md#creategenerationreservation)

Where `config`:
* `staleness` = 14 days (either set t be 0, or exceed 7-day refresh)
* `owner` = Permissioned owner of the Operator Set on target chains

The `staleness` parameter is the length of time that a [certificate](verification-methods.md) remains valid after its reference timestamp. It is set as an integer representing days.

A `staleness` period of `0` completely removes staleness checks, allowing certificates to be validated regardless of their timestamp. The `staleness` must be greater than the update cadence of the Operator tables (communciated offchain 
and currently 7 days). 

The caller must have [UAM permissions](../../../concepts/uam-for-avs.md) for `operatorSet.avs`. 

## 5. Wait for deployment

EigenLabs generates and transports your stake table. To determine when transport is complete, monitor [`OperatorTableUpdater.GlobalRootConfirmed`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/v1.7.0-rc.4/docs/multichain/destination/OperatorTableUpdater.md).


The **operator tables of *all* operatorSets are updated weekly on Monday at 14:00 UTC on mainnet and daily at 14:00 UTC on testnet**. To ensure that an operatorSet can immediately begin verifying certificates and that its stake weights do not become stale between table updates, the multichain protocol updates the table for a *single* operatorSet registered to the protocol when the following events are emitted:

- AllocationManager: `OperatorSlashed`
- AllocationManager: `OperatorAddedToOperatorSet`
- AllocationManager: `OperatorRemovedFromOperatorSet`
- CrossChainRegistry: `GenerationReservationCreated`

## Next 

[Implement how certificate are created, and delivered or exposed.](implement-certificate-verification.md).

---

---
sidebar_position: 4
title: Consume certificates
---

## Obtain, Verify, and Act On Certificates

An AVS consumer is a smart contract, application, or protocol integrating with an AVS. An app builder may be
building both the consuming app and the AVS to make the app verifiable.

The consumer receives, verifies, and acts on certificates returned from the AVS. To do that, consumers:

1. Obtain a Certificate. Depending on the AVS integration model, consumers obtain certificates by:
   * Making a request (for example, API call or onchain function) to the AVS.
   * Reading onchain.
   * Polling from decentralized storage.
   
    :::important
    If retrieving from a cache, consumers need to check the staleness period against the certificate.
    The `staleness` period is set in the [`CrossChainRegistry` by the AVS](configure-multichain).
    :::

2. Use the [`CertificateVerifier`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/v1.8.0-rc.0/docs/multichain/destination/CertificateVerifier.md) contract to [verify the certificate](verification-methods.md). 

3. Once the verification passes, the consumer can act on the AVS output. For example:
   * Use the AVS result (for example, a price, proof, or attestation).
   * Trigger follow-up logic (for example, settlement, payout, update).
   * Log or cache the certificate for transparency or auditability.

## Integration Examples

### Certificate Delivered in Response to Task Request

```
// 1. Consumer requests task from operator
TaskRequest memory task = TaskRequest({data: inputData, deadline: block.timestamp + 1 hours});
bytes memory result = operator.performTask(task);

// 2. Operator responds with certificate
Certificate memory cert = abi.decode(result, (Certificate));

// 3. Consumer verifies immediately
bool isValid = certificateVerifier.verifyCertificateProportion(operatorSet, cert, [6600]);
require(isValid, "Insufficient stake backing");
```

## Certificate Retrieved from Storage Cache

```
// 1. Query cached certificate (from AVS contract, IPFS, etc.)
Certificate memory cachedCert = avs.getLatestResult(taskType);

// 2. Check certificate freshness and validity
require(block.timestamp - cachedCert.referenceTimestamp < MAX_STALENESS, "Certificate too old");
bool isValid = certificateVerifier.verifyCertificateProportion(operatorSet, cachedCert, [5000]);
require(isValid, "Insufficient stake backing");

// 3. Use cached result
processResult(cachedCert.messageHash);
```

:::important
The `staleness` period is set in the [`CrossChainRegistry` by the verification service](configure-multichain).
:::

## Hybrid

The hybrid model queries cached certificates in the first instance, and if the certificate is stale or invalid, obtains a
new certificate using the [AVS integration model](#obtain-verify-and-act-on-certificates).

---

---
sidebar_position: 2
title: Create and Deliver Certificates
---

The AVS developer needs to enable their service to produce stake-backed certificates that are verifiable by 
consumers. This includes: 
1. [Creating and verifying certificates](#create-and-verify-certificates).
2. [Delivering or exposing certificates](#deliver-or-expose-certificates).

:::tip
The [Hourglass template](https://github.com/Layr-Labs/hourglass-avs-template) includes a reference implementation for certificate creation using an AVS aggregator.
:::

## Create and Verify Certificates

To create a certificate for multiple Operators: 
1. Implement the offchain component to collect signed certificates from Operators. 
2. [Create the certificate](https://github.com/eigenfoundation/ELIPs/blob/main/ELIPs/ELIP-008.md#certificates--verification). Ensure the certificate includes the correct `referenceTimestamp` that corresponds to the latest 
(or desired) stake table version transported to the target chain. The `referenceTimestamp` must match the stake table exactly.

Typically, a certificate consists of an aggregation of Operator signatures that is [verified against stake tables using 
the `CertificateVerifier`](verification-methods.md). In the case of a single Operator, the Operator can produce a certificate
with only their signature.

## Deliver or Expose Certificates

Once created, certificates need to be delivered to Consumers, or stored in a location available to Consumers.  Options include:
* Deliver to Consumer in response to requests.
* Push certificate to storage (for example, IPFS or L2 contract). 

The [required threshold (proportional or nominal)](verification-methods.md) for verification also needs to be supplied to the Consumer. 

## Next 

[The AVS Consumer receives, verifies, and acts on certificates returned from the AVS.](consume-certificates.md)

---

---
sidebar_position: 1
title: Overview
---

The following diagram shows:
* The contracts AVS developers interact with, or specify, to build a multichain AVS
* Offchain components AVS developers implement to create and verify certificates. 

In this diagram, the AVS aggregator and the Certificate Storage illustrate one possible approach to implementing 
multichain verification. The architecture of these components is determined and implemented by the AVS and not part of
the multichain verification framework. For a reference implementation of these components, refer to the [Hourglass template](https://github.com/Layr-Labs/hourglass-avs-template).

<img src="/img/implement-multichain.png" alt="Multichain Implementation Overview"/>

The multichain framework is highly flexible and allows AVS developers to: 
* Support single or multiple Operators, with signature aggregation for multiple Operators.
* Choose between different certificate delivery patterns.
* Customize verification logic, based on trust models and service needs.

Onchain components of the multichain framework can also be used by AVS consumers to implement custom logic when verifying
certificates.

:::tip
Using the [Hourglass template](https://github.com/Layr-Labs/hourglass-avs-template) provides a multichain implementation that significantly reduces implementation effort.
:::

To get started implementing multichain verification, refer to [Configure a Multichain AVS](configure-multichain.md).

Refer to the concept material for information on: 
* [Multichain overview](../../../concepts/multichain/multichain-overview.md)
* [Architecture](../../../concepts/multichain/multichain-architecture.md)
* [Stake weighting for the Operator Table Calculator](../../../concepts/multichain/stake-weighting.md)
* [Certificates](../../../concepts/multichain/certificates.md).

---

---
sidebar_position: 5
title: Verify certificates
---

This topic includes:
* [Certificate verification methods](#certificate-verification-methods)
* [Verification examples](#direct-verification-example)
* [Troubleshooting certificate verification](#troubleshooting-certificate-verification)

## Certificate Verification Methods

Choose from the following verification methods depending on your trust requirements:
1. [Direct - Call `CertificateVerifier` functions directly.](#direct-verification-functions)
2. AVS-wrapped - Use verification contract provided by the AVS.
3. [Custom-wrapped - Add your own logic wrapping `CertificateVerifier`.](#custom-verification-logic-example)

## Direct Verification Functions

* Proportional 
    
    `CertificateVerifier.verifyCertificateProportion(operatorSet, cert, [6600]) // ≥ 66 %`
* Nominal
    
    `CertificateVerifier.verifyCertificateNominal(operatorSet, cert, [1000000]) // ≥ 1 M units`

### Direct Verification Example

```
// Same code works on Ethereum, Base, etc.
bool isValid = certificateVerifier.verifyCertificateProportion(
operatorSet,
certificate,
[6600] // Require 66% of stake
);

if (isValid) {
// Process verified result
processOperatorOutput(certificate.messageHash);
}
```

## Custom Verification Function

`(bool valid, uint256[] memory weights) = CertificateVerifier.verifyCertificate(operatorSet, cert)`, then apply custom logic

### Custom Verification Logic Example

```
// Get raw stake weights for custom logic
(bool validSigs, uint256[] memory weights) = certificateVerifier.verifyCertificate(operatorSet, cert);
require(validSigs, "Invalid signatures");

// Apply custom business logic
uint256 totalStake = 0;
uint256 validOperators = 0;
for (uint i = 0; i < weights.length; i++) {
if (weights[i] >= MIN_OPERATOR_STAKE) {
totalStake += weights[i];
validOperators++;
}
}

// Custom requirements: need both 60% stake AND 3+ operators
require(totalStake * 10000 >= getTotalOperatorSetStake() * 6000, "Need 60% stake");
require(validOperators >= 3, "Need 3+ qualified operators");
```
## Troubleshooting Certificate Verification

| Symptom                                              | Likely Cause                             | Fix                                                                                                 |
|------------------------------------------------------|------------------------------------------|-----------------------------------------------------------------------------------------------------|
| `verifyCertificate…` returns false                   | Stake table is stale or wrong curve type | Check `referenceTimestamp`, refresh reservation, and ensure Operators registered the correct curve. |
| Gas cost too high verifying sigs                     | Large OperatorSet using ECDSA            | Switch to BN254 BLS calculator and certificates.                                                    |
| Operator keys missing on target chain                | Key not in `KeyRegistrar`                | Call `isRegistered()`, re-register, and wait for the next table update.                             |
| Certificate verification fails with valid signatures | Operator not in current OperatorSet      | Check operator registration status and OperatorSet membership.                                      |
| Custom verification logic errors                     | Incorrect stake weight interpretation    | Use `verifyCertificate()` to inspect raw weights before applying custom logic.                      |


---

---
sidebar_position: 5
title: Multichain Security Considerations
---

The following table outlines the key security aspects to consider when implementing multichain verification services.

| Risk                    | Mitigation                                       | Implementation                                                                 |
|-------------------------|--------------------------------------------------|---------------------------------------------------------------------------------|
| Stale Stake Data        | Configure appropriate staleness periods          | Set staleness > 7 days in your `OperatorSetConfig`                             |
| Key Compromise          | Monitor for operator ejections and key rotations | Listen for `AllocationManager.OperatorSlashed` and `KeyRegistrar.KeyDeregistered` |
| Insufficient Stake      | Set minimum thresholds in verification           | Use `verifyCertificateNominal()` with minimum stake requirements               |
| Operator Centralization | Implement stake capping in your calculator       | Cap individual operators at 10–20% of total weight                              |
| Certificate Replay      | Check certificate freshness                      | Validate `referenceTimestamp` is recent and within staleness period            |

The following table outlines possible emergency procedures. 

| Procedure                            | Action                                                                      |
|--------------------------------------|-----------------------------------------------------------------------------|
| Operator Ejection                    | Immediately updates across all chains when operators are slashed or ejected |
| Operator Registration/Deregistration | Immediately updates across all chains when operators register or deregister |
| Pause Mechanisms                     | System-wide pause capabilities for critical vulnerabilities                 |
| Key Rotation                         | Operators can rotate compromised keys with configurable delays              |

The **operator tables of *all* operatorSets are updated weekly on Monday at 14:00 UTC on mainnet and daily at 14:00 UTC on testnet**. To ensure that an operatorSet can immediately begin verifying certificates and that its stake weights do not become stale between table updates, the multichain protocol updates the table for a *single* operatorSet registered to the protocol when the following events are emitted:

- AllocationManager: `OperatorSlashed`
- AllocationManager: `OperatorAddedToOperatorSet`
- AllocationManager: `OperatorRemovedFromOperatorSet`
- CrossChainRegistry: `GenerationReservationCreated`

---

---
sidebar_position: 2
title: Create Operator Sets
---

:::tip
If you're new to Operator Sets in EigenLayer, review the [Operator Sets concepts](../../../../concepts/operator-sets/operator-sets-concept.md) before continuing with this topic.
:::

Creating Operator Sets for an AVS is managed by the [AllocationManager core contract](../../../concepts/eigenlayer-contracts/core-contracts.md). Before Operator Sets can be created,
[AVS metadata must be registered](../register-avs-metadata.md).

[Strategies](../../../../concepts/operator-sets/strategies-and-magnitudes) can be added to Operator Sets when the Operator is created, or Strategies can be added to an existing Operator Set.

Operator Sets are either: 
* [Non-redistributing](#create-operator-set). Slashed funds are burnt.
* [Redistributing](#create-redistributing-operator-set). Slashed funds are sent to the [`redistributionRecipient`](../../../concepts/slashing/slashing-concept-developers.md#redistribution-recipient).

The Operator Set type cannot be changed.

## Create Operator Set

To create an Operator Set, call the [`createOperatorSets`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/docs/core/AllocationManager.md#createoperatorsets) function.
To add strategies when creating an Operator Set, specify a `params` array containing the strategies.

On creation, an `id` is assigned to the Operator Set. Together the AVS `address` and `id` are a unique identifier for the Operator Set.
For non-redistributing Operator Sets, the `redistributionRecipient` is the `DEFAULT_BURN_ADDRESS`.

## Create Redistributing Operator Set

To create a [redistributing Operator Set](../../../../concepts/slashing/redistribution.md), call the `createRedistributingOperatorSets` function.

To add strategies when creating an Operator Set, specify a `params` array containing the strategies.
Native ETH cannot be added as a strategy for redistributing Operator Sets because redistribution of native ETH is not supported.

Specify the address to receive slashed funds in `redistributionRecipients`.  The `redistributionRecipient` can only be set 
when creating the Operator Set and cannot be changed. 

On creation, an `id` is assigned to the Operator Set. Together the AVS `address` and `id` are a unique identifier for the Operator Set.

## Complete Operator Set Configuration

Once created:
1. [Update the AVS metadata](update-avs-metadata.md) to provide information on the Operator Set to Stakers and Operators.
2. If required, [add additional Strategies](modify-strategy-composition.md) to the Operator Set.

---

---
sidebar_position: 1
title: Design Operator Sets
---

An [Operator Set](../../../../concepts/operator-sets/operator-sets-concept.md) is a grouping of different types of work within a single AVS. Each AVS has at least one Operator Set. The 
EigenLayer protocol does not enforce criteria for Operator Sets.

## Operator Set Types

Operator Sets are either:
* [Non-redistributing](create-operator-sets.md#create-operator-set). Slashed funds are burnt.
* [Redistributing](create-operator-sets.md#create-redistributing-operator-set). Slashed funds are sent to the [`redistributionRecipient`](../../../concepts/slashing/slashing-concept-developers.md#redistribution-recipient).

The Operator Set type cannot be changed.

## Operator Set Groupings

Best practices for Operator Set design are to logically group AVS tasks (and verification) into separate Operator Sets. 
Organize your Operator Sets according to conditions for which you wish to distribute Rewards. Potential conditions include:
* Unique business logic.
* Unique Stake (cryptoeconomic security) amount and types of token required to be allocated from Operators.
* Slashing conditions.
* Ejection criteria.
* Quantity of Operators and criteria for operators allowed.
* Hardware profiles.
* Liveness guarantees.

For more information on Operator Sets, refer to [Operator Sets](../../../../concepts/operator-sets/operator-sets-concept).

---

---
sidebar_position: 5
title: Migrate to Operator Sets
---

**The AVSDirectory method will be deprecated in a future upgrade. All AVSs will need to migrate to [Operator Sets](../../../../concepts/operator-sets/operator-sets-concept) before the
upcoming deprecation of AVSDirectory.**

Operator Sets are required to [slash](../../../../concepts/slashing/slashing-concept.md). To migrate to, and start using, Operator Sets: 
1. [Upgrade middleware contracts](#upgrade-middleware-contracts) 
2. [Integrate the AllocationManager](#upgrade-middleware-contracts)
3. [Communicate to Operators](#communicate-to-operators)

Migrating now gives time to switch existing quorums over to Operator Sets. After the migration has occurred,
integrations with slashing can go live on Testnet, followed by Mainnet. M2 registration and Operator Set registration can operate in parallel.

## Upgrade middleware contracts

To migrate to Operator Sets:

1. Upgrade middleware contracts to handle the callback from the AllocationManager. The upgrade provides the RegistryCoordinator
the hooks to handle the callback from the AllocationManager. 
2. From the ServiceManager call, add an account to update the AVSRegistrar:
      * With setAppointee where the target is the AllocationManager.
      * The selector is the setAVSRegistrar selector.
3. Call setAVSRegistrar on the AllocationManager from the appointee account and set the RegistryCoordinator as your AVSRegistrar
so that it becomes the destination for registration and deregistration hooks

See example [RegistryCoordinator implementation with the new hooks](https://github.com/Layr-Labs/eigenlayer-middleware/blob/dev/src/SlashingRegistryCoordinator.sol).

## Integrate the AllocationManager

Integrate the AllocationManager by:

1. Creating Operator Sets through the AllocationManager.
2. Adding (or later removing) specific Strategies to that Operator Set to enable Operators to secure the AVS.
3. Specifying an additional AVSRegistrar contract that applies business logic to gate Operator registration to an Operator Set.

## Communicate to Operators

1. Communicate to Operators how to:
   1. Register for Operator Sets using the new registration pathway. 
   2. Allocate slashable stake for slashable Operator Sets.
2. Migrate to distribution of tasks based on the delegated and slashable stake of Operators registered to the AVS’s Operator Sets.

To ensure community and incentive alignment, AVSs need to conduct offchain outreach to communicate
the purpose and task/security makeup of their Operator Sets with their Operators and Stakers before beginning registration.
Include any potential hardware, software, or stake requirements in the communication. The AVS decides task distribution
within an Operator Set.


---

---
sidebar_position: 4
title: Modify Strategy Composition
---

An Operator Set requires at least one [Strategy](../../../../concepts/operator-sets/strategies-and-magnitudes).

To add Strategies to an existing Operator Set, call the [`addStrategiesToOperatorSet`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/docs/core/AllocationManager.md#addstrategiestooperatorset) function.

To remove Strategies from an Operator Set, call the [`removeStrategiesFromOperatorSet`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/docs/core/AllocationManager.md#removestrategiesfromoperatorset) function.

:::note
The Native Eth strategy cannot be added to Redistributing Operator Sets.
:::

---

---
sidebar_position: 3
title: Update AVS Metadata
---

:::tip
The AVS metadata is used to provide information on the [EigenLayer App](https://app.eigenlayer.xyz/) for Stakers and Operators.
:::

Once Operator Sets have been created, the AVS metadata can be updated to include the Operator Sets.

To update metadata, call the [`updateAVSMetadataURI`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/docs/core/AllocationManager.md#avs-metadata) function. Use the following format.

```
{
    "name": "AVS",
    "website": "https.avs.xyz/",
    "description": "Some description about",
    "logo": "http://github.com/logo.png",
    "twitter": "https://twitter.com/avs",
    "operatorSets": [
        {
            "name": "ETH Set",
            "id": "1", 
            "description": "The ETH operatorSet for AVS",
            "software": [
                {
                    "name": "NetworkMonitor",
                    "description": "",
                    "url": "https://link-to-binary-or-github.com"
                },
                {
                    "name": "ValidatorClient",
                    "description": "",
                    "url": "https://link-to-binary-or-github.com"
                }
            ],
            "slashingConditions": ["Condition A", "Condition B"]
        },
        {
            "name": "EIGEN Set",
            "id": "2", 
            "description": "The EIGEN operatorSet for AVS",
            "software": [
                {
                    "name": "NetworkMonitor",
                    "description": "",
                    "url": "https://link-to-binary-or-github.com"
                },
                {
                    "name": "ValidatorClient",
                    "description": "",
                    "url": "https://link-to-binary-or-github.com"
                }
            ],
            "slashingConditions": ["Condition A", "Condition B"]
        }
    ]
}
```

---

---
sidebar_position: 1
title: Register AVS Metadata
---

Metadata must be registered:
* Before an AVS can create [Operator Sets](../../../concepts/operator-sets/operator-sets-concept.md) or register Operators to Operator Sets.
* To [onboard to the AVS Dashboard](../publish/onboard-avs-dashboard.md).

Registering metadata for an AVS is managed by the [AllocationManager core contract](../../concepts/eigenlayer-contracts/core-contracts.md).  

To register metadata, call the [`updateAVSMetadataURI`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/docs/core/AllocationManager.md#avs-metadata) function on the AllocationManager. Invoking [`updateAVSMetadataURI`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/docs/core/AllocationManager.md#avs-metadata)
on the AllocationManager establishes the AVS address in the core EigenLayer protocol. 

## Format

To register metadata, the AVS must provide a URL to the JSON data in the following format. The format is not validated onchain. 

The metadata must be consistently available, and the URL provided to [`updateAVSMetadataURI`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/9a19503e2a4467f0be938f72e80b11768b2e47f9/docs/core/AllocationManager.md#avs-metadata) must not cause redirects.

```
{
    "name": "AVS",
    "website": "https.avs.xyz/",
    "description": "Some description about",
    "logo": "http://github.com/logo.png",
    "twitter": "https://twitter.com/avs",
}
```

## Logo

The logo linked to in the metadata must: 
* Be consistently available.
* Be hosted somewhere retrievable publicly.
* Not cause redirects.
* Be under 1MB.
* Return a png image, and not html with an image embedded or any other format.

If you need a repository for your logo to be hosted publicly, make a PR to the [`eigendata`](https://github.com/Layr-Labs/eigendata)
repository to add your logo.

---

---
sidebar_position: 5
title: Implement Slashing
---

:::important
If you're new to slashing in EigenLayer, make sure you're familiar with [Operator Sets](../../../../concepts/operator-sets/operator-sets-concept.md)
and [Slashing](../../../../concepts/slashing/slashing-concept.md) before implementing slashing.
:::

The [`AllocationManager`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/src/contracts/interfaces/IAllocationManager.sol) provides the interface for the `slashOperator` function.

To implement slashing, AVSs specify:
* Individual Operator
* [Operator Set](../../../../concepts/operator-sets/operator-sets-concept.md)
* [List of Strategies](../../../../concepts/operator-sets/strategies-and-magnitudes)
* [List of proportions (as `wads` or “parts per `1e18`”)](../../../../concepts/operator-sets/strategies-and-magnitudes)
* Description. 

:::warn
EIGEN and Native ETH are not available for redistributing Operator Sets at launch. Setting these Strategies will revert when configuring your Operator Set.
:::
 
## Define Slashing Proportions

In the `wadsToSlash` parameter: 
* 8% slash is represented as `8e16`, or `80000000000000000`. 
* 25% slash is represented as `2.5e17` or `250000000000000000`. 

The indexes in the two arrays must match across `strategies` and `wadsToSlash`. All Strategies supplied must be configured 
as part of the Operator Set.

For more information on how magnitudes are reduced when slashed, refer to [Magnitudes when Slashed](../../../../concepts/slashing/magnitudes-when-slashed.md).

## Define Upstream Redistribution Contracts 

For [redistributable Operator Sets](../../../../concepts/slashing/redistribution.md), implement upstream contracts for [`redistributionRecipient`](../../../concepts/slashing/slashing-concept-developers.md#redistribution-recipient)
to handle redistributed funds once they are transferred directly from the protocol via the `clearBurnOrRedistributableShares` function.

## Returned by `slashOperator`

The `slashOperator` function returns the `slashId` and number of shares slashed for each strategy. The `slashId` is 
incremented for an OperatorSet each time an Operator Set is slashed. Use the `slashID` to programmatically handle slashings.

## Slashing Event Emission

When a slashing occurs, one event is emitted onchain for each slashing. Emitted details identify the Operator
slashed, in what Operator Set, and across which Strategies, with fields for the proportion slashed and meta-data.
```
/// @notice Emitted when an operator is slashed by an operator set for a strategy
/// `wadSlashed` is the proportion of the operator's total delegated stake that was slashed
event OperatorSlashed(
    address operator, OperatorSet operatorSet, IStrategy[] strategies, uint256[] wadSlashed, string description
);
```

---

---
sidebar_position: 2
title: Precision and Rounding Considerations
---

:::warning
Slashing in very small increments, slashing operators with very low magnitudes, or slashing operators with very low share balances may lead to precision loss that results in burned and redistributed amounts being far lower than expected.
:::

AVSs should be aware of potential precision loss during slashing operations. This occurs primarily when:
- Operators have very low allocated magnitudes
- Operators have very few delegated shares
- Very small slashing percentages are used
- Tokens with low decimal precision are involved

### Precision Loss Scenarios

**Magnitude-Related Precision Loss:**
When slashing small magnitudes, the `mulWadRoundUp` operations can result in zero redistributed amounts due to rounding. For example:
- Max magnitude: `1e18`
- Allocated magnitude: `1e4`
- wadsToSlash: `1e14`
- Result: Magnitude slashed rounds to 1 [dust](https://www.techopedia.com/definition/dust-transaction), shares slashed rounds to 0

**Share-Related Precision Loss:**
The `calcSlashedAmount` function depends on sufficient precision in operations to avoid zero results when share counts are very low.

**Token Decimal Considerations:**
Low-decimal tokens require higher minimum deposits to maintain precision:
- USDC/USDT (6 decimals): Requires minimum 1000 tokens to reach 1e9 precision
- WBTC (8 decimals): Requires minimum 10 tokens to reach 1e9 precision
- Standard 18-decimal tokens: Generally safe when following magnitude/share thresholds

## Operator Selection and Slashing Guidelines

To minimize precision loss issues, AVSs should implement the following guidelines:

### Operator Registration Criteria

**Magnitude Thresholds:**
- **Reject operators with allocated magnitude under 1e9**: Operators with very low allocated magnitude are more susceptible to precision loss during slashing
- **Checking**: Query `getAllocatedMagnitude()` for each operator-strategy pair before allowing registration

**Share Thresholds:**
- **Reject operators with fewer than 1e9 delegated shares**: Low share counts increase the likelihood of rounding errors that reduce redistributed amounts
- **Checking**: Query operator's total delegated shares across all strategies before registration
- **Cross-validation**: Ensure both magnitude and share thresholds are met simultaneously, as they are interdependent

### Slashing Amount Considerations

**Percentage Thresholds:**
- **Exercise significant caution when slashing less than 0.01% (1e14 WAD)**: Very small slashing percentages are more prone to precision loss
- **Recommendation**: Consider implementing a minimum slash percentage (e.g., 0.1% or 1e15 WAD) for reliable redistribution

### Implementation Recommendations

**Pre-Registration Validation:**
```solidity
// Example validation checks
require(getAllocatedMagnitude(operator, strategy) >= 1e9, "Insufficient magnitude");
require(getOperatorShares(operator) >= 1e9, "Insufficient shares");
require(tokenDecimals >= 6, "Token decimals too low"); // Adjust based on risk tolerance
```

**Pre-Slash Validation:**
```solidity
// Example pre-slash checks
uint256 expectedSlash = calculateExpectedSlash(operator, strategy, slashPercentage);
require(expectedSlash > 0, "Slash amount would round to zero");
require(slashPercentage >= MINIMUM_SLASH_PERCENTAGE, "Slash percentage too small");
```

**Testing and Validation Tools:**
For practical testing of precision considerations, refer to the [precision analysis demo](https://gist.github.com/wadealexc/1997ae306d1a5a08e5d26db1fac8d533) which provides examples of validations and edge case testing for slashing operations.

**Monitoring and Alerting:**
- **Track precision loss events**: Monitor for slashes that result in zero or unexpectedly small redistributed amounts
- **Alert on edge cases**: Set up alerts for operators approaching magnitude/share thresholds
- **Audit slash outcomes**: Regularly verify that slashed amounts match expected calculations

### Risk Assessment Framework

AVSs should evaluate their specific use case against these parameters:

1. **Expected operator size distribution**: Will most operators easily meet the 1e9 thresholds?
2. **Slashing frequency and amounts**: How often and how much do you expect to slash?
3. **Token ecosystem**: What tokens will operators stake, and do they meet decimal requirements?
4. **Precision tolerance**: Can your protocol tolerate small amounts of precision loss?

### Recovery Procedures

- **Dust accumulation**: Understand that precision loss results in small amounts of dust remaining in the protocol. Precision loss dust cannot be retrieved.
- **Operator remediation**: Develop procedures for operators who fall below thresholds (for example, requiring additional deposits).
- **Slashing adjustments**: Have procedures to adjust slashing parameters if precision loss becomes problematic.


---

---
sidebar_position: 4
title: Risk Assessment for Redistributable Slashing
---

Before implementing redistributable slashing, AVSs should conduct:

* Comprehensive risk assessments covering:
    * **Key Management Risks**: Evaluation of current [key security practices](../../../concepts/slashing/key-management-redistributable-slashing.md)
    * **Operational Risks**: Assessment of internal processes and procedures
    * **Technical Risks**: Analysis of smart contract vulnerabilities and integration points
    * **Economic Risks**: Understanding of changed incentive structures and attack economics

* Threat model analysis covering:
    * **Internal Threats**: Key compromise, insider attacks, governance capture
    * **External Threats**: Economic attacks, MEV extraction, coordinated manipulation
    * **Technical Risks**: Smart contract bugs, integration failures, oracle manipulation
    * **Operational Risks**: Key management failures, process breakdowns, communication failures

* Economic incentive analysis covering:
    * **Slash Incentives**: Understand how redistribution changes slashing motivations
    * **Operator Behavior**: Consider how redistribution affects operator incentives
    * **Staker Risks**: Evaluate the risk-reward profile for stakers
    * **Attack Economics**: Analyze the cost-benefit of potential attacks

## Regulatory and Compliance Considerations

AVSs using redistributable slashing should also consider:
- Potential regulatory implications of controlling redistributed funds
- Compliance requirements for fund management and distribution
- Legal liability for key management failures
- Insurance and risk mitigation strategies

---

---
sidebar_position: 3
title: Security for Redistributable Slashing
---

:::warning
Redistributable slashing increases the attack surface and potential impact of security vulnerabilities. AVSs must implement additional security measures beyond what would be required for burn-only slashing.

AVSs should only implement redistributable slashing if they can meet these enhanced security standards and have thoroughly evaluated the associated risks.
:::

### Monitoring and Incident Response

**Continuous Monitoring and Alerting:**
- Monitor all slashing events for unusual patterns or amounts.
- Track `redistributionRecipient` address activity for unexpected activity.
- Set up alerts for suspicious operator registration patterns.
- Implement automated anomaly detection systems.

**Emergency Procedures:**
- Maintain emergency pause mechanisms for critical vulnerabilities.
- Establish clear incident response procedures.
- Create secure communication channels for emergency coordination.
- Plan for potential key compromise scenarios.

### Smart Contract Integration

**Redistribution Recipient Design:**
When designing the `redistributionRecipient` contract:
- Implement additional access controls and validation logic in the redistribution logic.
- Add time delays for large fund movements.
- Include governance mechanisms for fund distribution.
- Maintain comprehensive audit trails and transparency.
- Consider using a contract rather than an EOA for the `redistributionRecipient`.

**Circuit Breakers and Limits:**
- Implement rate limiting on slashing frequency and amounts.
- Set maximum slash amounts per time period.
- Create automatic shutdown triggers for suspicious activity.
- Maintain manual override capabilities for emergency situations.

**Smart Contract Design:**
- Implement time delays for critical operations.
- Use upgradeable contracts with governance-controlled upgrades.
- Include emergency pause functionality.
- Implement comprehensive access controls and role management.

**Precision loss:** 
- Implement [guidelines to minimize precision loss](precision-rounding-considerations.md).

### Governance and Fraud Prevention

**Veto Mechanisms:**
- Implement governance mechanisms where a committee can review proposed slashings.
- Include meaningful delay periods between slash proposal and execution.
- Allow for community veto of suspicious slashing events.
- Maintain transparent logs of all slashing decisions and rationale.

**Fraud Proofs and Verification:**
- Where possible, implement objective, onchain fraud proofs.
- Create robust legibility around slashing conditions and individual events.
- Enable community verification of slashing claims.
- Implement dispute resolution mechanisms for contested slashes.

### Technical Implementation Guidelines

**Testing and Auditing:**
- Conduct comprehensive security audits focusing on redistributable slashing.
- Implement extensive testing including edge cases and attack scenarios.
- Use formal verification where appropriate for critical components.
- Regular security reviews and penetration testing.

### Catastrophic Bug Mitigation

AVSs should prepare for scenarios where critical bugs could enable unauthorized slashing:

**Circuit Breakers:**
- Implement rate limiting on slashing amounts and frequency.
- Set maximum slash amounts per time period.
- Create automatic shutdown triggers for suspicious activity.
- Maintain manual override capabilities for emergency situations.

**Recovery Mechanisms:**
- Plan for potential fund recovery in case of bugs or exploits.
- Consider insurance or compensation mechanisms.
- Maintain transparency about security measures and incident response.
- Establish clear communication channels with affected parties.

---

---
sidebar_position: 1
title: Design Slashing
---

## Slashing Vetoes

EigenLayer provides a maximally flexible slashing function. AVSs may slash any Operator in any of their Operator Sets for
any reason. Slashing does not have to be objectively attributable (that is, provable on-chain). We encourage AVSs to create
robust legibility and process around individual slashings. Governance, fraud proofs, and decentralization
must be considered in AVS slashing designs. Include delays and veto periods in AVS designs to avoid or cancel slashing
in cases of AVS implementation bugs, improper slashing, or fraud.

**No vetoes are provided by the EigenLayer protocol.**

## Veto Committee Design

One popular AVS design is to utilize a governance mechanism with slashing such that a committee can review a proposed (or queued) 
slashing request. That slashing request can then be either fulfilled or vetoed by a committee of domain experts, governance 
council or multisig address for the AVS. Please see the [vetoable slasher example implementation](https://github.com/Layr-Labs/eigenlayer-middleware/blob/dev/src/slashers/VetoableSlasher.sol) for reference.

Ensure that your slashing process can be resolved within the `DEALLOCATION_DELAY` time window. This is the amount of blocks
between an Operator queuing a deallocation of stake from an Operator Set for a strategy and the deallocation taking effect. 
This will ensure that the slashing event is carried out for the Operator before their stake is deallocated.

## Redistribution

Redistribution may enable AVSs to benefit from a theft related to slashing so additional design care must be taken to consider
the incentives of all parties interacting with the redistribution. Redistribution enables more use-case opportunities 
but the higher risk and slash incentive must be considered for the participants running the AVS code.

---

---
sidebar_position: 5
title: Submit Rewards Submissions
---

:::important
`RewardsCoordinator.createAVSRewardsSubmission` and `RewardsCoordinator.createOperatorDirectedAVSRewardsSubmission` use AVSDirectory. 
The AVSDirectory method will be deprecated in a future upgrade. [All AVSs will need to migrate to Operator Sets before the upcoming deprecation of AVSDirectory](operator-sets/migrate-to-operatorsets.md).

If you are currently using AVSDirectory, `RewardsCoordinator.createAVSRewardsSubmission` and `RewardsCoordinator.createOperatorDirectedAVSRewardsSubmission` can continue to be used while AVSDirectory is being used.
:::

For information on Rewards concepts, refer to [Rewards Overview](../../../concepts/rewards/rewards-concept.md).

Submitting rewards for an AVS is handled by the [RewardsCoorinator core contract](../../concepts/eigenlayer-contracts/core-contracts.md).

To submit rewards submissions, use [`RewardsCoordinator.createOperatorDirectedOperatorSetRewardsSubmission`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/RewardsCoordinator.md#createoperatordirectedoperatorsetrewardssubmission).

An AVS can use onchain or offchain data in rewards logic to determine the reward amount per Operator. The rewards can be calculated 
based on the work performed by Operators during a certain period of time, can be a flat reward rate, or another structure based on 
the AVS’s economic model. An AVS can distribute rewards in any ERC20 token.

For more flexibility, an AVS can submit multiple performance-based Operator rewards denominated in different tokens.

:::note
The reward rate for Stakers is based on the amount of stake delegated to an Operator and does not change based on the 
rewards calculation per Operator by the AVS.
:::

## Implementation Notes 

Each rewards submission specifies:

* Time range for which the rewards submission is valid. Rewards submissions can be retroactive from the [M2 upgrade](https://github.com/Layr-Labs/eigenlayer-contracts/releases/tag/v0.2.3-mainnet-m2)
  and last up to 30 days in the future.
* List of strategies and multipliers that enables the AVS to weigh the relative payout to each strategy within a single rewards submission.
* ERC20 token in which rewards should be denominated.

Additional considerations: 

* Reward roots are posted weekly on Mainnet and daily on Testnet.
* Reward roots are on a 7-day activation delay (that is, when it is claimable against) on Mainnet and 2-hour activation delay on Testnet.
* Reward amounts are calculated based on activity across a 24 hour window. Each window's amounts are cumulative and include day + (day - 1). 
  Reward roots are posted weekly on Mainnet based on that day's snapshot date which correlates to a 24 hour window. Mainnet and Testnet are 
  functionally equivalent in their calculations. The reward roots are only posted weekly for Mainnet.
* Once a rewards submission is made by an AVS, the AVS is unable to retract those rewards. If the AVS does not have any Operators opted 
  into the AVS on a day of an active reward, those tokens are not distributed pro-rata to future days, and are refunded to the AVS. 
  There are two cases where this occurs:
    * An operator is not registered for the entire duration of the submission. The entire operator amount is refunded to the AVS.
    * If an operator is only registered for m days out of n days duration. The operator is only paid amount/m on each of those m days.
* Operators are only distributed rewards on days that they have opted into the AVS for the full day.
* Due to the rounding in the off-chain process, we recommend not making range submission token amounts with more than 15 significant digits of precision. 
  If more than 15 significant digits are provided, the extra precision is truncated.
* Rewards can be made in multiple ERC-20 tokens by submitting rewards submissions for each ERC-20 token to reward in.

## When Rewards are Included
An AVSs reward submission is included in the calculation 2 days after it is submitted. For example, if the AVS submits a 
rewards submission on August 2nd, it is included in the August 4th rewards calculation.

## When Rewards can be Claimed
At most, Restakers and Operators of an AVS will have to wait 16 days to claim a reward (2 day calculation delay + 7 day root 
submission cadence + 7 day activation delay).

At minimum, Restakers and Operators have to wait 9 days to claim a reward.



---

---
sidebar_position: 1
title: Add and Remove Admins
---

:::caution
Security of admin keys is critical. UAM enables appointees with lessened permissions, and use of keys that can be rotated or 
destroyed. For more information on key management best practices, refer to [AVS Developer Security Best Practices](../../../reference/avs-developer-best-practices.md).

After an account has added an admin and the pending admin has accepted, the account address no 
longer has default admin privileges. That is, the original account key of the Operator or AVS cannot be
used for write operations to the protocol, unless previously added as an admin, or is added back as admin in the future.
There is no superadmin role.

The removal of default admin privileges upon adding additional admins enables accounts 
to perform a key rotation to remove permissions from a potentially compromised original key. 

For an account to retain admin 
privileges for its own address, add the account first as an admin. After the account is added as an admin, add other admins as needed.
:::

## Add an Admin Using the Core Contracts

Admins are added via a 2-step handshake. To add an admin:
1. As the account or admin adding the admin, call the [`PermissionController.addPendingAdmin`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/permissions/PermissionController.md#addpendingadmin) function to set the pending admin.
2. As the pending admin, call the [`PermissionController.acceptAdmin`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/permissions/PermissionController.md#acceptadmin) function. Once accepted, the added admin has full admin authority.

## Remove an Admin Using the Core Contracts

The caller must be an admin. Once an account has added an admin, there must always be at least one admin for the account. 

To remove a pending admin before they have called acceptAdmin, call the [`PermissionController.removePendingAdmin`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/permissions/PermissionController.md#removependingadmin) function.

To remove an admin, call the [`PermissionController.removeAdmin`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/permissions/PermissionController.md#removeadmin) function.


---

---
sidebar_position: 2
title: Add and Remove Appointees
---

Only admins (or the account if no admin has been set) can add appointees. Unlike adding an admin, there is no requirement
for an appointee to accept the appointment.

For the list of contracts and functions that can have appointees set, refer to:
* [User Account Management](../../../concepts/uam-for-avs.md) for AVS
* [User Account Management](../../../../operators/concepts/uam-for-operators.md) for Operators

## Add an Admin using Core Contracts 

To add an appointee, call the [PermissionController.setAppointee](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/permissions/PermissionController.md#setappointee) function.

To remove an appointee, call the [PermissionController.removeAppointee](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/permissions/PermissionController.md#removeappointee) function.

---

---
sidebar_position: 6
title: Prepare for and Deploy to Testnet and Mainnet
---


## Preparing and Deploying to Testnet

1. Package the Operator’s long running executable in a way that is easy for Operators to launch  (via binary, docker container, or similar).

2. Author Testnet user and Operator documentation, including:
   - Trust Modeling: clarify any trust assumptions in your architecture to your users. Identify the components that are trusted (centralized) and untrusted (decentralized, trustless).
   - Operator instructions to install, register, deregister.
   - End user (aka “Consumer”) instructions to utilize your AVS service.
   - Communication channels that will be utilized for AVS upgrades.
   - Describe Operator monitoring tooling available, such as GraFana dashboards, log files or similar.

3. Follow the [AVS Developer Security Best Practices](../../reference/avs-developer-best-practices.md) and [Key Manage Considerations for Developers](../../reference/avs-developer-best-practices.md#key-management-recommendation-for-developers).

4.  Follow the [Testnet Dashboard Onboarding instructions](../publish/onboard-avs-dashboard.md).

5. Implement Rewards distributions per the instructions [here](../build/submit-rewards-submissions.md).


## Preparing and Deploying to Mainnet

1. Smart Contract Auditing: have your codebase audited with at least 2-3 reputable audit firms.
2. Finalize User and Operator documentation.
3. Follow the [Mainnet Dashboard Onboarding instructions](../publish/onboard-avs-dashboard.md#mainnet-dashboard-onboarding).

---

---
title: Build and Test Locally
sidebar_position: 2
---

Building with DevKit enables:
* A rapid local iteration loop removing the need for lengthy testnet deployments. 
* Built-in observability and error handling removing the need for protocol-level debugging to understand what's going wrong.

Prerequisites:

[Get Started Building a Task-based AVS](start-building-task-based-avs.md)

To build and test locally:
1. [Set the RPC endpoint URL](#1-set-the-rpc-endpoint-url)
2. [Build your AVS](#2-build-your-avs)
3. [Run AVS tests](#3-run-avs-tests) 
4. [Test AVS with local devnet or by simulating tasks](#4-test-avs)

## 1. Set the RPC Endpoint URL

In the `.env` file, set the `*_FORK_URL` values to Ethereum Sepolia (`L1_FORK_URL`) and Base Sepolia (`L2_FORK_URL`) 
RPC archive node endpoint URLs. Use any reliable RPC provider (for example, QuickNode, Alchemy).

```
cp .env.example .env
# edit `.env` and set your L1_FORK_URL and L2_FORK_URL to point to your RPC endpoints
```

:::note
Currently, only the Sepolia testnet is supported.
The RPC endpoint must be an [archive node, not a full node](https://www.quicknode.com/guides/infrastructure/node-setup/ethereum-full-node-vs-archive-node).
:::

## 2. Build Your AVS

Compile AVS contracts and offchain binaries before running a devnet or simulating tasks. 

In the project directory, run: 

```
devkit avs build
```

## 3. Run AVS Tests

Run offchain unit tests and onchain contract tests to ensure your business logic and smart contracts are functioning correctly
before deploying.

In the project directory, run: 

```
devkit avs test
```

## 4. Test AVS

DevKit provides two options for testing AVS functionality: 
* Running a local Devnet to simulate the full AVS environment. 
* Triggering task execution to simulate how a task is submitted, processed, and validated. 

### Local Devnet

Test and iterate without needing to interact with testnet or mainnet. Devkit:
* Spins up a local Devnet and deploys contracts, registers operators, and runs offchain infrastructure. 
* Automatically funds wallets (`operator_keys` and `submit_wallet`) if balances are below 10 ETH.

:::important
Ensure your Docker daemon is running before launching local Devnet.
:::

Devkit forks Ethereum Sepolia using the fork URL (provided by you) and a block number. We recommend specifying the fork URL
in a [`.env` file](#1-set-the-rpc-endpoint-url). The `.env` file takes precedence over `config/context/devnet.yaml`. 

In your project directory, run:
```
devkit avs devnet start
```

Devnet management commands listed below.

| Command                | Description                                                   |
|------------------------|---------------------------------------------------------------|
| `start`                | Start local Docker containers and contracts                   |
| `stop`                 | Stop and remove containers from the AVS project               |
| `list`                 | List active containers and their ports                        |
| `stop --all`           | Stops all devkit devnet containers that are currently running |
| `stop --project.name`  | Stops the specified project devnet                            |
| `stop --port`          | Stops the specified port (for example, `stop --port 8545`)    |

###  Simulate Task Execution

Trigger task execution through your AVS to simulate how a task would be submitted, processed, and validated. Useful for 
testing end-to-end behavior of your AVS logic in a local environment. Devkit enables: 

* Simulating the full lifecycle of task submission and execution.
* Validating both off-chain and on-chain logic.
* Reviewing detailed execution results.

From your project directory, run:

```
devkit avs call signature="(uint256,string)" args='(5,"hello")'
```

Optionally, submit tasks directly to the on-chain TaskMailbox contract via a frontend or another method for more realistic
testing scenarios.

Next:

[Publish Task-based AVS](publish-task-based-avs-release.md)

:::tip
Optional DevKit commands are described in the [DevKit repo](https://github.com/Layr-Labs/devkit-cli).
:::

---

---
title: Publish Task-based AVS
sidebar_position: 3
---

DevKit publishes your AVS release to the `ReleaseManager` contract which makes it available for operators to upgrade to.

Prerequisites:

[Build and Test Locally](build-test-locally.md)

## Setting Release Metadata URI

You must set a release metadata URI before publishing releases. The metadata URI provides important information about your 
release to Operators.

To set the metadata URI for your Operator Sets:

```
# Set metadata URI for operator set 0
devkit avs release uri --metadata-uri "https://example.com/metadata.json" --operator-set-id 0

# Set metadata URI for operator set 1
devkit avs release uri --metadata-uri "https://example.com/metadata.json" --operator-set-id 1
```

Required Flags:

* `--metadata-uri` The URI pointing to your release metadata
* `--operator-set-id` The operator set ID to configure

Optional Flags:

* `--avs-address` AVS address (uses context if not provided)

## Publishing Release

Before publishing a release, ensure you have:

* Built your AVS with `devkit avs build`
* A running DevNet
* Properly configured registry in your context (or specify the command parameter)
* [Set release metadata URI for your Operator Sets](#setting-release-metadata-uri) 

:::important
The `upgrade-by-time` must be in the future. Operators have until the specified timestamp to upgrade to the new version. 
DevNet must be running before publishing.
:::

In your product directory, run: 

```
devkit avs release publish  --upgrade-by-time 1750000000
```

Required Flags:

* `--upgrade-by-time` Unix timestamp by which operators must upgrade

Optional Flags:

* `--registry` Registry for the release (defaults to context)

### Example

```
devkit avs release publish \
--upgrade-by-time <future-timestamp> \
--registry <ghcr.io/avs-release-example>
```

:::tip
Optional DevKit commands are described in the [DevKit repo](https://github.com/Layr-Labs/devkit-cli).
:::

## Advertise to Operators

Advertise to Operators that your AVS is an Hourglass AVS. Operators use the [Hourglass CLI (`hgctl`)](../../../operators/howto/run-task-based-avs.md) to streamline operations of Hourglass AVS.

---

---
title: Get Started Building a Task-based AVS
sidebar_position: 1
---

To get started: 

1. Install DevKit

    ```
    curl -fsSL https://raw.githubusercontent.com/Layr-Labs/devkit-cli/main/install-devkit.sh | bash
    ```

    For more installation options, refer to the [DevKit repo Readme](https://github.com/Layr-Labs/devkit-cli).

2. Verify the installation 

    ```
    devkit --help
    ```

3. Scaffold your AVS project 

    ```
    devkit avs create my-avs-project ./
    ```

    :::note
    On macOS and Debian, running the `avs create` installs all required dependencies and version numbers automatically. For other OSs, 
    manual installation of software prerequisites is required. For software prerequisites, refer to the [DevKit repo Readme](https://github.com/Layr-Labs/devkit-cli).
    :::

4. Implement your AVS task logic in `main.go`. 

Next: 

[Build and Test Locally](build-test-locally.md)

---

---
sidebar_position: 2
title: Implement onchain components
---

To build an AVS, the minimum set of functionality to be defined in the [AVS contracts](../../concepts/avs-contracts.md) is:
* [Registering AVS metadata](../build/register-avs-metadata.md)
* [Create Operator Sets](../build/operator-sets/create-operator-sets.md)
    * [Creating and modifying Strategy composition](../build/operator-sets/modify-strategy-composition.md)
* [Managing registered Operators](../build/manage-registered-operators.md)
    * [Responding to Operator registrations](../build/manage-registered-operators.md#respond-to-operator-registrations-to-operator-sets)
    * [Deregistering Operators](../build/manage-registered-operators.md#deregister-operators-from-or-respond-to-operator-deregistrations-from-operator-sets)
* [Distributing Rewards](../build/submit-rewards-submissions) 


---

---
sidebar_position: 1
title: Get started
---

:::note

We are in the process of updating our samples to include Rewards and Slashing capabilities. The Hello World AVS example will be
updated as soon as possible. Use Hello World AVS now to get familiar with EigenLayer. 

For more information on Rewards and Slashing, refer to the [Rewards](https://github.com/eigenfoundation/ELIPs/blob/main/ELIPs/ELIP-001.md) and [Slashing](https://github.com/eigenfoundation/ELIPs/blob/main/ELIPs/ELIP-002.md) ELIPs,
and [Rewards](../../../concepts/rewards/rewards-concept.md) and [Slashing](../../concepts/slashing/slashing-concept-developers) documentation. 

For questions or support, reach out to us using the Intercom button on the bottom right side of this page or <a href="javascript:void(0)"  id="intercom_trigger_eldocs" >here</a>. 
We will promptly follow up with support!

:::

## Hello World AVS: Local Deployment
The [Hello World AVS](https://github.com/Layr-Labs/hello-world-avs) is a simple implementation designed to demonstrate the core mechanics of how AVSs work within the EigenLayer framework. This example walks you through the process of:
- Spinning up a local chain with EigenLayer contracts and AVS contracts preconfigured.
- Registering an Operator with both EigenLayer and the AVS.
- Consumer client requesting work to be done by the AVS.
- Operator listening picking up this request, performing it, and signing off on it.
- The AVS contract verifying the operator's work.

![Hello World Diagram](/img/avs/hello-world-diagram-v2.png)

## Key Components of Hello World AVS
- AVS Consumer: Requests a "Hello, ___" message to be generated and signed.
- AVS: Takes the request and emits an event for operators to handle.
- Operators: Picks up the request, generates the message, signs it, and submits it back to the AVS.
- Validation: Ensures the operator is registered and has the necessary stake, then accepts the submission.


## Code Walkthrough

The following sections highlight a few crucial components of the Hello World example that implement core AVS functionality. 

### AVS Contract

**[HelloWorldServiceManager.sol](https://github.com/Layr-Labs/hello-world-avs/blob/master/contracts/src/HelloWorldServiceManager.sol)**

The contract definition declares that it implements `ECDSAServiceManagerBase`, which allows it to inherit the core required functionality of `IServiceManager`. These contracts are included from the [eigenlayer-middleware repo](https://github.com/Layr-Labs/eigenlayer-middleware/tree/dev/docs#eigenlayer-middleware-docs) and are [required components](https://github.com/Layr-Labs/eigenlayer-middleware/tree/dev/docs#system-components) for any AVS.

```sol
contract HelloWorldServiceManager is ECDSAServiceManagerBase, IHelloWorldServiceManager {
    using ECDSAUpgradeable for bytes32;
```

The following functions are responsible for the "business logic" of the AVS. In the case of hello world the business logic includes managing the lifecycle of a "task" (creation and response) with a simple `name` string value.
```sol
function createNewTask(
    string memory name
) external returns (Task memory) {
    // create a new task struct
    Task memory newTask;
    newTask.name = name;
    newTask.taskCreatedBlock = uint32(block.number);

    // store hash of task on-chain, emit event, and increase taskNum
    allTaskHashes[latestTaskNum] = keccak256(abi.encode(newTask));
    emit NewTaskCreated(latestTaskNum, newTask);
    latestTaskNum = latestTaskNum + 1;

    return newTask;
}

function respondToTask(
    Task calldata task,
    uint32 referenceTaskIndex,
    bytes memory signature
) external {
    // check that the task is valid, hasn't been responded to yet, and is being responded in time
    require(
        keccak256(abi.encode(task)) == allTaskHashes[referenceTaskIndex],
        "supplied task does not match the one recorded in the contract"
    );
    require(
        allTaskResponses[msg.sender][referenceTaskIndex].length == 0,
        "Operator has already responded to the task"
    );

    // The message that was signed
    bytes32 messageHash = keccak256(abi.encodePacked("Hello, ", task.name));
    bytes32 ethSignedMessageHash = messageHash.toEthSignedMessageHash();
    bytes4 magicValue = IERC1271Upgradeable.isValidSignature.selector;
    if (!(magicValue == ECDSAStakeRegistry(stakeRegistry).isValidSignature(ethSignedMessageHash,signature))){
        revert();
    }

    // updating the storage with task responses
    allTaskResponses[msg.sender][referenceTaskIndex] = signature;

    // emitting event
    emit TaskResponded(referenceTaskIndex, task, msg.sender);
}
```

### Contract Deployment Scripts

**[HelloWorldDeployer.s.sol](https://github.com/Layr-Labs/hello-world-avs/blob/master/contracts/script/HelloWorldDeployer.s.sol)**

The deployment of the HelloWorld contracts associates the quorums and their asset strategies to the AVS.

```sol
token = new ERC20Mock();
helloWorldStrategy = IStrategy(StrategyFactory(coreDeployment.strategyFactory).deployNewStrategy(token));

quorum.strategies.push(
    StrategyParams({strategy: helloWorldStrategy, multiplier: 10_000})
);
```

### Off-chain Operator Code


**[index.ts](https://github.com/Layr-Labs/hello-world-avs/blob/master/operator/index.ts)**

The following snippets of Operator code manage Operator registration to core EigenLayer protocol, registration to the Hello World AVS, listening and responding to tasks.

```sol
// Register Operator to EigenLayer core contracts and Hello World AVS
const registerOperator = async () => {
    
    // Registers as an Operator in EigenLayer.
    try {
        const tx1 = await delegationManager.registerAsOperator({
            __deprecated_earningsReceiver: await wallet.address,
            delegationApprover: "0x0000000000000000000000000000000000000000",
            stakerOptOutWindowBlocks: 0
        }, "");
        await tx1.wait();
        console.log("Operator registered to Core EigenLayer contracts");
    }
    
    ...
    
    
    const tx2 = await ecdsaRegistryContract.registerOperatorWithSignature(
        operatorSignatureWithSaltAndExpiry,
        wallet.address
    );
    await tx2.wait();
    console.log("Operator registered on AVS successfully");
};

// Listen for new task events on-chain
const monitorNewTasks = async () => {

    helloWorldServiceManager.on("NewTaskCreated", async (taskIndex: number, task: any) => {
        console.log(`New task detected: Hello, ${task.name}`);
        await signAndRespondToTask(taskIndex, task.taskCreatedBlock, task.name);
    });
    console.log("Monitoring for new tasks...");
};



// Generate Hello, Name message string
const signAndRespondToTask = async (taskIndex: number, taskCreatedBlock: number, taskName: string) => {
    const message = `Hello, ${taskName}`;
    const messageHash = ethers.solidityPackedKeccak256(["string"], [message]);
    const messageBytes = ethers.getBytes(messageHash);
    const signature = await wallet.signMessage(messageBytes);

    console.log(`Signing and responding to task ${taskIndex}`);

    const operators = [await wallet.getAddress()];
    const signatures = [signature];
    const signedTask = ethers.AbiCoder.defaultAbiCoder().encode(
        ["address[]", "bytes[]", "uint32"],
        [operators, signatures, ethers.toBigInt(await provider.getBlockNumber()-1)]
    );

    const tx = await helloWorldServiceManager.respondToTask(
        { name: taskName, taskCreatedBlock: taskCreatedBlock },
        taskIndex,
        signedTask
    );
    await tx.wait();
    console.log(`Responded to task.`);
};


```


### Off-chain Task Generator

**[createNewTasks.ts](https://github.com/Layr-Labs/hello-world-avs/blob/master/operator/createNewTasks.ts)**

The following Typescript code generates new tasks at a random interval. This entity that generates tasks for the AVS is also referred to as the "AVS Consumer".

```sol

// Create a New Task (a new name to be signed as "hello, name")
async function createNewTask(taskName: string) {
  try {
    // Send a transaction to the createNewTask function
    const tx = await helloWorldServiceManager.createNewTask(taskName);
    
    // Wait for the transaction to be mined
    const receipt = await tx.wait();
    
    console.log(`Transaction successful with hash: ${receipt.hash}`);
  } catch (error) {
    console.error('Error sending transaction:', error);
  }
}

```



## Local Deployment Test

Please follow the steps under [Local Devnet Deployment](https://github.com/Layr-Labs/hello-world-avs?tab=readme-ov-file#local-devnet-deployment) to deploy an instance of Hello World locally on your machine.



---

---
sidebar_position: 8
title: Get Support
---

If you have any questions or comments throughout the AVS development process, you can get support by reaching out to us using 
the Intercom button on the bottom right side of this page. We will promptly follow up with support!

---

---
sidebar_position: 1
title: Onboard to AVS Dashboard
---

The AVS Dashboard (also known as AVS Marketplace) lists registered AVSs. 

<img src="/img/avs-marketplace.png" width="75%" style={{ margin: '50px'}}>
</img>

:::important
The AVS Marketplace is not yet available on Sepolia or Hoodi testnets. 
:::

## Adding a listing

To display an AVS on the [AVS Marketplace](https://app.eigenlayer.xyz/avs), invoke `updateAVSMetadataURI` on the [AllocationManager core contract](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/AllocationManager.md).

For information on the expected format and metadata requirements, refer to [Register AVS Metadata](../build/register-avs-metadata.md).

Once invoked, the data is indexed within about 20 minutes, and the metadata is displayed on the AVS Dashboard for Holesky.
[The EigenLayer Mainnet Dashboard Onboarding Form is required to display on the AVS Dashboard for mainnet](#mainnet-dashboard-onboarding). 

## Updating a listing 

If you deploy a new contract for your AVS, remove the previous listing by invoking `updateAVSMetadataURI` on the [AllocationManager core contract](https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/docs/core/AllocationManager.md)
value of null. For example, `updateAVSMetadataURI("")`.

The listing will be removed from the AVS Marketplace cache within one hour.

### getOperatorRestakedStrategies

To provide the list of Strategies that an Operator has restaked with a AVS, the [`getOperatorRestakedStrategies`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/testnet-sepolia/docs/core/RewardsCoordinator.md#createavsrewardssubmission) function must
be implemented. Implementing `getOperatorRestakedStrategies` enables the AVS to have its total restaked value displayed on the UI.
Given an operator, the function:
- Retrieve the Operator's quorum bitmap from the `RegistryCoordinator.sol` contract.
- Retrieve the addresses of the strategies for each quorum in the quorum bitmap

`getOperatorRestakedStrategies` makes no guarantee on whether the Operator has shares for a strategy in an Operator Set
or the uniqueness of each element in the returned array. The offchain service is responsible for that validation. 

```solidity
function getOperatorRestakedStrategies(address operator) external view returns (address[] memory) {
        bytes32 operatorId = registryCoordinator.getOperatorId(operator);
        uint192 operatorBitmap = registryCoordinator.getCurrentQuorumBitmap(operatorId);

        if (operatorBitmap == 0 || registryCoordinator.quorumCount() == 0) {
            return new address[](0);
        }

        // Get number of strategies for each quorum in operator bitmap
        bytes memory operatorRestakedQuorums = BitmapUtils.bitmapToBytesArray(operatorBitmap);
        uint256 strategyCount;
        for(uint256 i = 0; i < operatorRestakedQuorums.length; i++) {
            strategyCount += stakeRegistry.strategyParamsLength(uint8(operatorRestakedQuorums[i]));
        }

        // Get strategies for each quorum in operator bitmap
        address[] memory restakedStrategies = new address[](strategyCount);
        uint256 index = 0;
        for(uint256 i = 0; i < operatorRestakedQuorums.length; i++) {
            uint8 quorum = uint8(operatorRestakedQuorums[i]);
            uint256 strategyParamsLength = stakeRegistry.strategyParamsLength(quorum);
            for (uint256 j = 0; j < strategyParamsLength; j++) {
                restakedStrategies[index] = address(stakeRegistry.strategyParamsByIndex(quorum, j).strategy);
                index++;
            }
        }
        return restakedStrategies;        
    }
```
### getRestakeableStrategies

To list all supported restakeable Strategies for the AVS on the UI, the [`getRestakeableStrategies`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/testnet-sepolia/docs/core/RewardsCoordinator.md#createavsrewardssubmission) function must be implemented.

```solidity
function getRestakeableStrategies() external view returns (address[] memory) {
        uint256 quorumCount = registryCoordinator.quorumCount();

        if (quorumCount == 0) {
            return new address[](0);
        }
        
        uint256 strategyCount;
        for(uint256 i = 0; i < quorumCount; i++) {
            strategyCount += stakeRegistry.strategyParamsLength(uint8(i));
        }

        address[] memory restakedStrategies = new address[](strategyCount);
        uint256 index = 0;
        for(uint256 i = 0; i < _registryCoordinator.quorumCount(); i++) {
            uint256 strategyParamsLength = _stakeRegistry.strategyParamsLength(uint8(i));
            for (uint256 j = 0; j < strategyParamsLength; j++) {
                restakedStrategies[index] = address(_stakeRegistry.strategyParamsByIndex(uint8(i), j).strategy);
                index++;
            }
        }
        return restakedStrategies;
    }

```

For a reference implemetation, refer to [ServiceManagerBase.sol](https://github.com/Layr-Labs/eigenlayer-middleware/blob/mainnet/src/ServiceManagerBase.sol).

## Mainnet Dashboard onboarding
To complete the process of onboarding your AVS to mainnet AVS Marketplace Dashboard, submit the [EigenLayer Mainnet Dashboard Onboarding Form](https://forms.gle/8BJSntA3eYUnZZgs8).

---

---
sidebar_position: 1
title: Obtain Testnet ETH
---

The [Obtaining testnet ETH and liquid staking tokens (LSTs)](../../../restakers/restaking-guides/testnet/obtaining-testnet-eth-and-liquid-staking-tokens-lsts.md) topic describes how to obtain testnet ETH and LSTs for
testing AVSs.

---

---
sidebar_position: 4
title: Test AVS
---
:::note 
AVS Devnet is currently in Public Alpha and is rapidly being upgraded. Features may be added, removed or otherwise improved or modified,
and interfaces will have breaking changes. To report any issues, raise a [GitHub issue](https://github.com/Layr-Labs/avs-devnet/issues).
:::

Use AVS Devnet to test AVSs locally. AVS Devnet includes: 
* A CLI tool for easy configuration, deployment, and management of local devnets.
* Kurtosis integration to provide a standardized way to spin up local Ethereum environments with core EigenLayer contracts.
* Consensus and Execution clients to simulate production-like environments.
* Block Explorer integration for visualizing blockchain activity using a preconfigured [Blockscout explorer](https://github.com/blockscout/blockscout).
* Funded Operators with keys to enable creation of operator accounts with preloaded funds and private keys for testing staking, delegation, and other interactions.
* Tailored configurations for deployment, testing, and debugging.

To install and use, refer to the [avs-devnet README](https://github.com/Layr-Labs/avs-devnet).

---

---
sidebar_position: 4
title: AVS Developer Security Best Practices
---

## AVS Developer Security Best Practices


- Containers should be able to run with least privilege. Least privilege is AVS-dependent. AVS team should outline these 
privileges as part of the operator onboarding docs. If privileges are not specified, operators need to ask the AVS team directly.
- Emit runtime (logs) including security events
- Use Minimal Base Images
    - Use [ko Go containers](https://ko.build/) or similar to build distro-less minimal images. This reduces the attack surface significantly!
- Release updated images with security patches  (for base OS etc ).
- Do not store key material on the container (refer to key management docs).
- Your default user id should start with AVS-NAME-randomness to ensure there are no conflicts with the host.
- Ensure ECDSA keys utilized by AVS are solely for updates, such as modifying IP and port details within a smart contract. These keys should not hold funds. A role-based approach in smart contract design can address this issue effectively.
- AVS team should [sign their images](https://docs.docker.com/engine/security/trust/) for any releases, including upgrades
    - If they publish to Docker, Docker will show the verified badge next to the image.
    - Tag new releases via updated images.
- Establish communication channels (Discord, TG)  with operators. This ensures coordinating upgrades occurs with minimal friction.
- Operators should be in control of upgrades to their AVS software. Avoid software upgrade patterns where an agent checks for updated software and automatically upgrades the software. 
- Release Notes should explain new features including breaking changes / new hardware requirements etc.




# Key Security Considerations for Developers

When working with keys for nodes in an AVS, it is essential to consider the security aspects associated with key access and decryption. Keys should be encrypted either using a password or passphrase, understanding the unique security concerns posed by different access layers is crucial. By proactively addressing these concerns, you can enhance the overall security and integrity of the keys within your system:

- **Prompt for the passphrase and store it in memory:**
    
    In this scenario, the input must remain hidden to prevent the secret phrase from being stored in the terminal session or used buffer. Attackers might search for this secret in the buffer history. The key should not be stored locally or remotely unless encrypted via the AVS's proprietary methods.
    
- **Request the path to a file containing the passphrase:**
    
    Here, buffer vulnerability issues are absent unless the secret is printed or logged. However, an attacker with access to the machine running the AVS could potentially access this file.
    
- **Retrieve the key remotely:**
    
    Encrypting the validator key offers markedly improved protection when the decryption passphrase is stored remotely. Since the passphrase is not located within the validator client's storage, obtaining an unencrypted key from on-disk data becomes impossible. Instead, an attacker would need to execute considerably more advanced attacks, such as extracting the decrypted key from memory or impersonating the validator client process to receive the decryption key.
    
    Nonetheless, despite the increased difficulty, a sophisticated attack could still potentially acquire the validator key. Moreover, the user may inadvertently sign undesirable messages.
    
- **Utilize remote signers:**
    
    Employing remote signers involves delegating the signing process to an external service or device, which can offer additional security layers. The users are responsible for the availability and security of the remote signers, however, it is crucial to establish secure communication channels and verify the trustworthiness of the remote signer to prevent unauthorized access or tampering.

Supporting both local and remote signer methods is a good practice. 

[Web3signer](https://docs.web3signer.consensys.net/) is a remote signer that includes the following features:

- Open-source signing service developed under the Apache 2.0 license, developed by Consensys, and written in Java. 
- Capable of signing on multiple platforms using private keys stored in an external vault, or encrypted on a disk.
- Can sign payloads using secp256k1 and BLS12-381 signing keys (AWS HSM can't at the moment, spring 2023).
- Web3Signer uses REST APIs, and all the major Ethereum Consensus clients support it.

## Key Management Recommendation for Developers

The AVS can implement a feasible and sufficient method of loading the keys. This is asking for a path to a keystore folder. This keystore needs to follow some structure that AVS knows how to read. Currently [eigenlayer-cli](https://github.com/Layr-Labs/eigenlayer-cli) supports creation of encrypted ecdsa and bn254 keys in the [web3 secret storage](https://ethereum.org/en/developers/docs/data-structures-and-encoding/web3-secret-storage/) format. 


:::note

By keys, we refer to any kind of secret, either in plain text or encrypted.

:::

The path to this keystore folder can be provided via an environment variable or argument. 

---

---
sidebar_position: 2
title: EigenLayer SDKs
---

The EigenLayer SDKs wrap common EigenLayer AVS operations and are designed for AVS developers. 
* [EigenLayer Go SDK](https://github.com/Layr-Labs/eigensdk-go)
* [EigenLayer Rust SDK](https://github.com/Layr-Labs/eigensdk-rs)

---

---
sidebar_position: 1
title: Multichain Parameters
---

Protocol parameters for multichain verification include: 

* [Mutable parameters that require monitoring](#mutable-parameters)
* [Immutable parameters](#immutable-parameters)
* [Configurable parameters](#configurable-parameters)

## Mutable Parameters

| Parameter                            | Controlled By                  | Update Frequency                | Impact                            | Monitoring Event                                                          |
|--------------------------------------|--------------------------------|---------------------------------|-----------------------------------|---------------------------------------------------------------------------|
| Operator Tables                      | EigenLabs (during Preview)     | Weekly + force updates          | Certificate verification validity | `CertificateVerifier.StakeTableUpdated`                                   |
| Operator Keys                        | Operators                      | Updates with Operator Table     | Certificate signature validation  | `KeyRegistrar.KeyRegistered/Deregistered`                                 |
| Stake Weights                        | `OperatorTableCalculator`      | Per table update                | Verification thresholds           | Custom events in your calculator                                          |
| Operator Registration/Deregistration | Verifiable Service + Operators | On-demand                       | Available Operators for tasks     | `AVSRegistrar.OperatorRegistered` and `AVSRegistrar.OperatorDeregistered` |
| Slashing/Ejections                   | EigenLayer Core                | On-demand (immediate transport) | Operator validity and weights     | `AllocationManager.OperatorSlashed`                                         |

## Immutable Parameters

| Parameter          | Set By             | Description                                                       |
|--------------------|--------------------|-------------------------------------------------------------------|
| Operator Set ID     | Verifiable service | Cryptographic curve and operator list hash                        |
| Contract Addresses  | EigenLayer Core    | `CertificateVerifier`, `OperatorTableUpdater` addresses per chain |
| Chain Support       | EigenLayer Core    | Which chains support multichain verification                      |

## Configurable Parameters

| Parameter               | Configured By      | Options                                             | Configured Where                                    |
|-------------------------|--------------------|-----------------------------------------------------|-----------------------------------------------------|
| Staleness Period        | Verifiable service | 0 (no expiry) or must exceed table update frequency | `CrossChainRegistry`                                | 
| Minimum Stake Weight    | Verifiable service | Any uint256 value                                   | `CrossChainRegistry`                                |
| Target Chains           | Verifiable service | Any supported chain IDs                             | `CrossChainRegistry`                                |
| Verification Thresholds | Consumers          | Proportional % or nominal amounts                   | Consumer integration with `CertificateVerifier`     |
| Custom Stake Weighting  | Verifiable service | Override `calculateOperatorTable()` with any logic  | `OperatorTableCalculator` contract for Operator Set |


---

---
sidebar_position: 2
title: Developer Resources
---

:::note
We are in the process of updating our samples, SDKs, and the EigenLayer CLI to include Rewards and Slashing capabilities. The samples, SDKs, and CLI will be
updated as soon as possible. Use the samples now to get familiar with EigenLayer.
For more information on Rewards and Slashing, [Rewards](../../concepts/rewards/rewards-concept.md) and [Slashing](../concepts/slashing/slashing-concept-developers) documentation.
For questions or support, reach out to us using the Intercom button on the bottom right side of this page or <a href="javascript:void(0)"  id="intercom_trigger_eldocs" >here</a>.
We will promptly follow up with support!
:::

### Developer Samples
* [Awesome AVS](https://github.com/Layr-Labs/awesome-avs)
* [Hello World AVS](https://github.com/Layr-Labs/hello-world-avs)
* [Incredible Squaring AVS](https://github.com/Layr-Labs/incredible-squaring-avs)
* [devQuickstart](https://github.com/Layr-Labs/devQuickstart)

### SDKs
These SDKs are wrappers on top of common EigenLayer AVS operations designed to save you time as an AVS builder:
* [EigenLayer Go SDK](https://github.com/Layr-Labs/eigensdk-go)
* [EigenLayer Rust SDK](https://github.com/Layr-Labs/eigensdk-rs)

### EigenLayer Core Repos
* [EigenLayer Contracts](https://github.com/Layr-Labs/eigenlayer-contracts)
* [EigenLayer Middleware](https://github.com/Layr-Labs/eigenlayer-middleware)
* [EigenLayer CLI](https://github.com/Layr-Labs/eigenlayer-cli)
* [EigenDA](https://github.com/Layr-Labs/eigenda)

### Developer Tooling
- [Othentic](https://www.othentic.xyz) - Library of components for AVS builders.
- [Layer](https://www.layer.xyz/) - Containerized Autonomous Verifiable Services (CAVS) via Web Assembly.
- [AltLayer Wizard](https://wizard.altlayer.io/) - AVS-as-a-Service platform.
- [Gadget](https://github.com/webb-tools/gadget) - A framework for building modular AVS and Tangle Blueprints.