# Symbiotic

Symbiotic is a generalized shared security system enabling decentralized networks to bootstrap powerful, fully sovereign ecosystems.

<!--
Sitemap:
- [Symbiotic](/get-started/): Get started with Symbiotic's shared security system
- [What is Symbiotic?](/get-started/what/overview): Symbiotic is a shared security protocol designed to create a marketplace for economic security. It enables networks that need security to access it from those...
- [Networks](/get-started/what/participants/networks): Networks are fundamental components of the Symbiotic protocol that consume economic security and drive the demand for staking. They represent decentralized...
- [Operators](/get-started/what/participants/operators): Operators are entities running infrastructure for decentralized networks within and outside of the Symbiotic ecosystem. The Symbiotic protocol creates a...
- [Curators](/get-started/what/participants/curators): Curators set and maintain a vault's policy. They choose how stake is spread across networks and operators, which slashing flow applies, and who can deposit....
- [Vaults](/get-started/what/components/vaults): A vault is the on chain container that holds collateral and connects it to networks. Each vault holds a single collateral token, keeps track of who has...
- [Slashing](/get-started/what/components/slashing): Operators have stake assigned to them in each network they serve. Every network defines rules for correct behavior, such as producing valid blocks, signing...
- [Rewards](/get-started/what/components/rewards): Symbiotic can be considered an exchange hub between basically 3 parties: stakers, operators, and networks.
- [Relay SDK](/get-started/what/relay): The Symbiotic Relay SDK is the trust layer for data and computation.
- [Use Cases](/get-started/use-cases/): Explore how teams ship on top of Symbiotic's shared security and Relay attestations.
- [Bridges and Cross-chain Messaging](/get-started/use-cases/bridges-cross-chain-messaging): Stake-backed validator attestations for bridge state, DVNs, and cross-domain proofs.
- [Oracle Networks and Data Feeds](/get-started/use-cases/oracle-networks-data-feeds): Price, rate, and event oracles with custom resolvers and slashing rules.
- [General Attestation Layers](/get-started/use-cases/general-attestation-layers): Stake-secured attestations for arbitrary computations and events that trigger on-chain actions.
- [Decentralized Compute and AI Verification](/get-started/use-cases/decentralized-compute-ai-verification): "Decentralized Docker" or AI inference jobs producing proofs and Relay attestations.
- [Liquidity Management](/get-started/use-cases/liquidity-management): Use Symbiotic Relay attestations for liquidity management, rebalancing, and cross-chain treasury workflows.
- [Chain Agnostic Applications](/get-started/use-cases/chain-agnostic-applications): Appchains often spin up bespoke validator sets, multisigs or custom messaging paths per use case (governance messages, bridges, feeds). Each new route brings...
- [Insurance and Guarantees](/get-started/use-cases/insurance-and-guarantees): insurance, guarantees, and onchain risk transfer secured by slashable capital
- [Relay Quickstart](/get-started/developers/relay-quickstart): Symbiotic Super Sum spins up a relay network that runs simple sum computations. Schedule a job on any supported chain and the result is posted to every...
- [Developers Hub](/get-started/developers/developers-hub): Find role-specific integration paths, tools, APIs, ABIs, events, hints, and AI resources for building with Symbiotic.
- [Addresses](/get-started/resources/addresses): A comprehensive list of Symbiotic official smart contract deployments.
- [Bug Bounty](/get-started/resources/audits): Bug bounty program: Cantina - $500,000 (Core & Rewards)
- [Risks](/get-started/resources/risks): The following document contains a list of notes how to make the overall operation process safer for everyone.
- [Points Program](/get-started/resources/points-program): Symbiotic Points reward participants that provide useful economic security through the protocol. They are earned by depositing collateral into vaults and, in...
- [Analytics](/get-started/resources/analytics-and-apis): Live dashboards for monitoring Symbiotic vaults, rewards, and users.
- [Ecosystem](/get-started/resources/ecosystem): Explore Symbiotic ecosystem participants, including networks, curators, and operators using shared security.
- [Universal Staking](/learn/): Universal Staking is more than just restaking. Instead of merely reusing staked assets to secure multiple networks, it introduces a flexible coordination layer...
- [Network](/learn/core-concepts/network): In Symbiotic, a Network is any protocol that requires a decentralized infrastructure network to deliver a service in the crypto economy, such as enabling...
- [Operator](/learn/core-concepts/operator): Operators run the software that keeps decentralized networks alive. They include node operators or validators that run consensus and network-specific binaries,...
- [Vault](/learn/core-concepts/vault): A vault is the on-chain container that holds collateral and connects it to networks. Each vault holds a single collateral token, tracks deposits and...
- [Curator](/learn/core-concepts/curator): Curators set and maintain a vault's policy. They decide how stake is spread across networks and operators, what kind of slashing flow applies, and who can...
- [Rewards](/learn/core-concepts/rewards): Rewards are payments that Networks make to vault participants in exchange for security and work. Rewards are distributed using historical snapshots of vault...
- [Slashing](/learn/core-concepts/slashing): Slashing is how a Network penalizes operators for provable misbehavior. A Network's middleware sends a slashing request to the vault; the vault's Slasher...
- [Registries and Opt-ins](/learn/mechanics/registries-and-opt-ins): Registries give Networks and Operators a canonical on-chain identity that the rest of Symbiotic can reference.
- [Epochs and Delays](/learn/mechanics/epochs-and-delays): Epochs are the time rules of Symbiotic. They tell you when validator sets update, when withdrawal requests can be claimed, and how long captured guarantees...
- [Voting Power](/learn/relay/voting-power): The VotingPowerProvider is the Relay contract that turns delegated Symbiotic stake into operator voting power inside a validator set. It sits between Symbiotic...
- [Valset (Validator Set)](/learn/relay/valset): The validator set is the current list of operators and their weights that a network uses for signing and verification during a given epoch. In Relay, this is...
- [Secure Attestations](/learn/relay/secure-attestations): Secure attestations are stake-backed signatures over a message hash that contracts can verify against the active validator set header.
- [Settlement](/learn/relay/settlement): Settlement is the on-chain endpoint for Relay. It stores validator set headers (operators, keys, weights, thresholds) per network / subnetwork / epoch and...
- [Instant Liquidity](/liquid-lane/): Symbiotic Instant Liquidity enables redemptions for illiquid or time-locked assets through curator-managed vault liquidity and onchain RFQ flows.
- [Capital Efficiency Analysis](/liquid-lane/capital-efficiency-analysis): Compare liquidity buffers, DEX pools, and Symbiotic instant liquidity vaults for tokenized RWA redemptions and capital-efficient yield generation.
- [Introduction](/integrate/): Symbiotic is a shared security protocol that enables networks to access economic security from stakers. The protocol supports multiple participant roles, each...
- [Get Started](/integrate/networks/): This guide walks you through integrating your network with Symbiotic. Follow these steps to register your network, set up security, and start receiving stake...
- [Quickstart: Network with Staking](/integrate/networks/minimal-network): This guide sets up a minimal Hoodi testnet environment so you can validate production flows on testnet.
- [Network Contract](/integrate/networks/network-contract): Register your network using the NetworkRegistry smart contract. The registered address serves as your management address for interacting with Symbiotic vaults...
- [Submit Metadata](/integrate/networks/submit-metadata): The Symbiotic UI displays TVL, allocations, and relationships between curators, vaults, operators, and networks. To make your entity visible on the UI, submit...
- [Deploy Pre-deposit Vault](/integrate/networks/pre-deposit): You may want to curate or deploy vaults yourself in these cases:
- [Distribute Rewards](/integrate/networks/rewards): Networks use Rewards system to compensate Stakers, Operators, and Curators for providing security and network operation.
- [Slashing](/integrate/networks/slashing): Integrate Symbiotic slashing flows, resolvers, veto slashers, burners, and operator accountability checks.
- [Relay On-Chain](/integrate/networks/relay-onchain): The Symbiotic Relay system implements a complete signature aggregation workflow from validator set derivation through on-chain commitment of the ValSetHeader...
- [Relay Off-Chain](/integrate/networks/relay-offchain): :::warning The code is a work in progress and not production ready yet. Breaking changes may occur in code updates, and backward compatibility is not...
- [Helpful Core Contracts' Endpoints](/integrate/networks/helpful-core-contracts-endpoints): This page lists useful functions for networks across Symbiotic Core contracts.
- [Get Started](/integrate/operators/): Operators run network infrastructure and process logic provided by networks. This guide walks you through the operator lifecycle in Symbiotic.
- [Register Operator](/integrate/operators/register-operator): Register your operator using the OperatorRegistry smart contract. The registered address serves as your management address for opting into vaults and networks...
- [Submit Metadata](/integrate/operators/submit-metadata): The Symbiotic UI displays TVL, allocations, and relationships between curators, vaults, operators, and networks. To make your entity visible on the UI, submit...
- [Opt Into Networks and Vaults](/integrate/operators/opt-ins): Before you can start receiving delegations, complete two opt-in steps:
- [Claim Rewards](/integrate/operators/claim-rewards): Operators claim fees from Rewards.sol using the claimOperatorFees entrypoint for Vault Snapshot rewards. Find the up-to-date Rewards contract address on the...
- [Helpful Core Contracts' Endpoints](/integrate/operators/helpful-core-contracts-endpoints): This page lists useful functions for operators across Symbiotic Core contracts.
- [Get Started](/integrate/curators/): This guide walks you through the curator lifecycle in Symbiotic. You'll deploy a vault, manage allocations, and earn fees from managing depositors' funds.
- [Deploy Vault](/integrate/curators/deploy-vault): Symbiotic is a highly modular protocol with many separate parts and more coming in the future. This guide describes possible vault deployment configurations.
- [Submit Metadata](/integrate/curators/submit-metadata): The Symbiotic UI displays TVL, allocations, and relationships between curators, vaults, operators, and networks. To make your entity visible on the UI, submit...
- [Manage Allocations](/integrate/curators/manage-allocations): Learn how curators manage network and operator allocations for Symbiotic vaults.
- [Manage & Claim Fees](/integrate/curators/registry-and-fees): The vault.owner() sets the curator in CuratorRegistry. This links a vault to the curator address that will manage fee settings and claim curator fees.
- [Vault Wrapping](/integrate/curators/vault-wrapping): Sometimes, due to design choices for security guarantees or interaction flow optimization, you can't implement your ideas in a standard way. In these cases,...
- [Helpful Core Contracts' Endpoints](/integrate/curators/helpful-core-contracts-endpoints): This page lists useful functions for curators across Symbiotic Core contracts.
- [CLI](/integrate/builders-researchers/cli): Symbiotic CLI (symb) is a command-line tool for reading on-chain data and interacting with Symbiotic Core smart contracts.
- [Events](/integrate/builders-researchers/events): This page provides a complete overview of event handling and math across the Symbiotic system.
- [Hints](/integrate/builders-researchers/hints): Symbiotic core contracts simplify integration for networks and products with different stake utilization goals. One key simplification is flexibility to...
- [AI Resources](/integrate/builders-researchers/ai-resources)
- [Get Started](/integrate/builders-researchers/): Build applications on top of Symbiotic and access protocol data. Use these resources to integrate Symbiotic into your project.
- [Relay](/learn/relay/): Learn how Symbiotic Relay provides stake-backed attestations, validator sets, voting power, and settlement.
- [ABIs And Bindings](/integrate/builders-researchers/abis-and-bindings): Find generated ABIs and TypeScript bindings for integrating with Symbiotic smart contracts and protocol tooling.
- [APIs](/integrate/builders-researchers/apis): Use Symbiotic API endpoints to fetch protocol data, build dashboards, and improve integrations.
- [Relay Quickstart](/learn/relay/dev-workflow): This quickstart walks through the developer workflow that the repo enables: spinning up Symbiotic Core locally, preparing vaults and operators, wiring...
-->

# Shared security for Proof of Stake Networks

Symbiotic is a modular shared security protocol that turns stake into a flexible marketplace for economic security, while Relay extends it into a universal verification layer so any protocol can inherit stake-backed security, define custom slashing and rewards, and verify outcomes across chains without bootstrapping its own validator set.

<div style={{ margin: "48px 0" }}>
  <FeatureSpotlight
    eyebrow="Relay SDK Beta"
    title="Relay Beta SDK is live"
    description="Spin up the attestation network and stake operators in minutes. The Relay tutorial guides you through bootstrapping the beta SDK, wiring shared security, and finalizing messages across chains."
    icon={
          <svg width="32" height="32" viewBox="0 0 32 32" fill="none" stroke="currentColor">
              <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth="2"
                  d="M6 11l10-7 10 7v10l-10 7-10-7V11z"
              />
              <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth="2"
                  d="M11 14.5l5 3 5-3"
              />
              <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth="2"
                  d="M11 19l5 3 5-3"
              />
          </svg>
      }
    accentColor="#8b5cf6"
    href="/get-started/developers/relay-quickstart"
    ctaLabel="Launch Relay SDK"
    secondaryHref="/get-started/use-cases"
    secondaryLabel="Explore use cases"
  />
</div>

With BLS aggregation and optional ZK compression to keep verification costs flat at scale, Relay connects stakers, operators, and on-chain settlement so builders can coordinate large validator sets, codify slashing conditions as on-chain resolvers, and trigger programmable outcomes everywhere — bridges, oracles, rollups, AI networks, and more.

<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: '24px', marginTop: '32px' }}>
  <Card1
    title="Learn"
    description="Learn what Symbiotic is and how restaking works. Understand the core concepts behind Symbiotic Core and prepare for the integration"
    icon={
    <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
    </svg>
  }
    href="/learn"
  />

  <Card1
    title="Integrate"
    description="Get hands-on experience with the Relay SDK - a modular set of on-chain / off-chain components to implement Proof of Stake"
    icon={
    <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
    </svg>
  }
    href="/integrate"
  />

  <Card1
    title="Analytics and APIs"
    description="Obtain ecosystem's insights from already built dashboards or build your own ones"
    icon={
      <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
          />
      </svg>
  }
    href="/get-started/resources/analytics-and-apis"
  />

  <Card1
    title="Symbiotic Points"
    description="Deep dive into Symbiotic Points distribution mechanics"
    icon={
      <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
          />
      </svg>
  }
    href="/get-started/resources/points-program"
  />
</div>

# **What is Symbiotic?**

Symbiotic is a shared security protocol designed to create a marketplace for economic security. It enables networks that need security to access it from those who have assets to stake, creating an efficient ecosystem where stake can be shared and utilized across multiple networks. Through its flexible architecture, stake providers can maximize their returns while networks can obtain the security guarantees they need.

## **Key Components and Relations**

### **Core Participants**

![General overview](/img/overview-1.png)

* **Stakers**: Entities looking to earn rewards by providing their assets as a stake through vault deposits. They can be individual token holders, institutions, or liquid (re)staking protocols. Stakers deposit funds into specialized smart contracts (vaults) managed by curators who handle delegation decisions.
* **Networks**: Systems that need economic security to operate safely. These can be Layer 1 blockchains, Layer 2 solutions, or other decentralized systems that require stake-based security guarantees.
* **Operators**: Professional entities that maintain network infrastructure by running validators, nodes, or other required systems. They receive stake allocations to perform their duties and are responsible for network operations.
* **Curators**: Entities that design and maintain a vault’s risk and allocation policy. They decide how stake is distributed across networks and operators, which slashing and withdrawal settings apply, and who can deposit into the vault.

### **Participant Connections**

The core participants are connected through a sophisticated infrastructure layer. At the heart of these connections are Vaults, which serve as the primary interface between all participants.

Symbiotic coordinates and manages interactions in this ecosystem by:

* Enabling Stakers to deposit their assets into Vaults, where Curators manage delegation strategies and approve qualified Operators.
* Facilitating Networks' access to security by connecting them with Vaults and their associated stake.
* Allowing Operators to receive stake allocations through Curator-managed Vaults to perform their network duties.

This interconnected system is monitored by Resolvers, who validate activities and ensure security across all connections. In the following sections, we'll explore the key infrastructure components.

### **System Relations**

The Symbiotic protocol facilitates several critical interactions between participants, creating a robust and efficient security marketplace. Here's how these key components work together:

### **Stake Accounting**

![Vault-centric view](/img/overview-2.png)

1. Stakers deposit their assets into vaults
2. Each vault is managed by a curator who controls stake allocation
3. Curators delegate stake to qualified operators who run network infrastructure
4. A single vault can serve multiple networks simultaneously, allowing efficient stake distribution across different operators

The stake delegation system has important characteristics:

* Assets remain securely locked in the vaults without actual transfer
* Stake delegation works through an accounting system only
* Assets can only leave the vault through:
  * Original staker withdrawals
  * Validated slashing events from networks

### **Network Operations**

![Network-centric view](/img/overview-3.png)

Networks work with multiple vaults simultaneously, allowing them to aggregate security from different sources. This flexible architecture enables operators to accumulate a stake across different vaults, while networks can calculate their total stake by combining delegation from various vault sources.

### **Slashing process**

![Slashing process](/img/overview-4.png)

1. Networks can initiate the slashing of operators by interacting with vaults where operators have a stake
2. Networks can choose which vaults to slash from if an operator has a stake in multiple vaults
3. Resolvers act as validators of slashing events with veto power

Resolvers can be automated contracts, slashing committees, dispute resolution frameworks, multisig wallets, or DAO governance systems. Networks and vault curators agree on which resolvers to use (or not to use any resolver at all) and slashing terms. During slashing, networks choose vaults to slash from, resolvers review the event and can veto invalid slashing attempts.

## **Benefits of the Architecture**

* Capital Efficiency: Assets can be utilized across multiple networks simultaneously
* Flexibility: Networks can customize their security model through different vault compositions
* Risk Management: Stake can be isolated or shared based on specific security requirements
* Scalability: The modular design allows for easy integration of new networks and operators

This architecture creates a sustainable ecosystem where security providers (stakers and operators) and security consumers (networks) can interact efficiently while maintaining their specific requirements and risk preferences.

# **Networks**

Networks are fundamental components of the Symbiotic protocol that consume economic security and drive the demand for staking. They represent decentralized systems that require validation and security guarantees for their operations. As consumers of economic security, networks work in conjunction with other protocol elements to create customized security configurations that best suit their specific requirements.

What makes networks particularly powerful is their ability to choose different security models - whether direct security, shared security with other networks, or hybrid approaches - while maintaining sovereignty through the immutable core protocol. This flexibility allows any decentralized product to establish robust security from day one.

## **Technical Architecture of Networks**

From a technical perspective, a network in Symbiotic consists of two main components:

### **1. On-chain Components**

![Network on-chain part](/img/networks-1-get-started.png)

The on-chain part of a network consists of two distinct entities:

* **Network Identity**: Represented by an Ethereum address, which can be:
  * An Externally Owned Account (EOA)
  * A Multi-Signature wallet
  * A Decentralized Autonomous Organization (DAO)
* **Network Middleware**: A set of smart contracts that serves as the crucial interface between Symbiotic Core contracts and the network itself. Its responsibilities include:
  * Managing operator selection and stake allocation
  * Implementing slashing mechanisms
  * Managing validator sets
  * Handling reward distribution to operators and vaults

### **2. Off-chain Components**

![Network off-chain part](/img/networks-2-get-started.png)

The off-chain part consists of:

* Client software run by network operators
* Network-specific validation logic
* Integration systems that connect with the on-chain middleware
* The Symbiotic Relay SDK binaries, if in place

## **Network Middleware Deep Dive**

Network Middleware is distinct from the network itself and plays a crucial role in the ecosystem. While a network is represented by an address, the middleware is always a set of contracts deployed on Ethereum, and / or other chains. This separation serves several important purposes:

* It provides a standardized interface for interacting with Symbiotic Core contracts
* It handles all staking-related operations and state management
* It enables flexible implementation of network-specific logic while maintaining compatibility with the core protocol

### **Interaction with Symbiotic Protocol**

![Network middleware](/img/networks-3-get-started.svg)

The interaction between networks, middleware, and the Symbiotic protocol follows a specific flow:

* **Stake Management**: Networks interact with multiple vaults to:
  * Receive stake delegations
  * Set delegation limits
  * Process slashing events
  * Distribute rewards to stakers
* **Operator Management**: The middleware handles:
  * Operator selection based on stake
  * Validator set updates
  * Performance monitoring and slashing conditions

### **Middleware Development**

![Middleware SDK](/img/middleware-sdk.svg)

Building the network middleware from scratch can be challenging due to the complex responsibilities of managing operators, stakes, and security mechanisms while ensuring perfect reliability. Networks can rely on the [Relay SDK](https://github.com/symbioticfi/relay), a framework for executing and managing all these actions.

### **Key Features of the Relay SDK**

* **Universal Attestation Framework:** Any data, any computation, any chain → one system for proof generation.
* **Verifiable on-chain:** Proofs are backed by staked validators, ensuring economic security.
* **Fully modular SDK:** Developers integrate using lightweight clients in Go, Rust, or TypeScript.
* **Chain-agnostic:** Works across L1s, L2s, and rollups; interoperable with all EVM chains. Cosmos support is available out of the box via a dedicated adapter.
* **Programmable & application-agnostic:** Plugs into any smart-contract workflow; attestations act as a generic trigger for programmable outcomes.

# **Operators**

Operators are entities running infrastructure for decentralized networks within and outside of the Symbiotic ecosystem. The Symbiotic protocol creates a registry of operators, logs interactions with the protocol, and protocol participants can attach credentials and other data to operator entities. In the initial version, this encompasses operator entity metadata provided by the operators themselves, as well as data created by interacting with the Symbiotic protocol, such as:

* Networks that the operator opted into
* Associated vaults and restaked collateral from vaults
* Historical logs of slashings and all other interactions with the Symbiotic ecosystem

An important benefit of the Symbiotic protocol and its enshrined vault system is the ability for operators to receive a stake from different partners (through vaults) to the same set of node infrastructure per supported network. This system allows node operators to acquire the stake from a diverse set of stakers with differing risk profiles without needing to set up isolated infrastructure for them.

![operator-rel](/img/operators-get-started.png)

In the future, we envision the Symbiotic protocol to contain a rich set of verifiable data and curated credentials about node operators. This will enable future networks using Symbiotic to source security for their use case to utilize innovative and maximally capital-efficient reputation-based operator selection mechanisms.

## **Network Integration**

An operator opts into a network in order to provide specific services. Each network independently decides whether to include that operator in the active set, based on criteria such as reputation, performance history, stake delegated to the operator, and any network specific requirements.

Operators can take different forms depending on the network. They may be node operators or validators that run the consensus algorithm for L1s, maintain network specific binaries, and produce or sign messages for bridging, oracles, and other middleware. They can also be strategy operators such as risk managers or AI agents whose task is to execute a defined DeFi strategy efficiently under the rules of the network. In all cases, once admitted, operators are responsible for meeting uptime, correctness, and security expectations, and failures can result in removal from the active set and slashing according to the network policy.

## **Slashing**

The operator’s stake becomes active and subject to slashing immediately after the opt-in process to both the network and the vault. However, the corresponding role in the vault can apply the timelock for allocating a stake for additional guarantees for operators. The slashing process is implemented in the vault’s Slasher module.

[See Slashing Details](/learn/core-concepts/slashing)

## **Rewards**

Operators provide services to networks, as discussed. This can include running consensus clients and other binaries, managing DeFi strategies, or operating offchain infrastructure that the network depends on. In return, they need to be compensated for the risk and operational effort they take. Networks pay operators using the revenues they generate from offering their services to external clients, from protocol fees, or from token inflation earmarked for security and operations. Symbiotic provides a flexible rewards framework that routes these payments to operators and stakers, so incentives align with the work being performed on each network.

[See Operator Rewards Details](/learn/core-concepts/rewards)

# **Curators**

Curators set and maintain a vault’s policy. They choose how stake is spread across networks and operators, which slashing flow applies, and who can deposit. Stakers pick a vault because they trust the curator’s discipline on risk and timing. While in single‑operator vaults the operator may act as curator, immutable vaults remove ongoing curator control after deployment.

## Responsibilities

A curator turns a staking strategy into on‑chain parameters and keeps the vault aligned as conditions change. They select a Delegator type and apply per‑network and per‑operator limits or shares so allocations match the stated thesis. They choose a Slasher (instant or vetoed) and, for vetoed flows, may appoint a resolver set. They configure the Burner to define outcomes for slashed collateral. At deployment, they also set the vault epoch and access control logic, keeping deposits public or allowlisted.

![curators-1.png](/img/curators-1.png)

## Curator Types

Curators are the entities responsible for risk management in Symbiotic vaults, so they need a clear view of the inherent risks of each network they underwrite. In practice, curators can take several forms: liquid funds allocating capital across networks and operators, node operators who understand infrastructure and liveness risk first-hand, LRT / LST issuers extending their own risk frameworks into restaking, or specialized risk-management firms that design conservative, policy-driven strategies for third parties.

## Tools and Strategy

Together, the Slasher, Epoch and withdrawals, Delegator, and Burner define how the vault takes risk, how fast it can react, and what happens when things go wrong. Getting these right is essential to keeping the vault’s behavior aligned with its stated risk profile.

### Slasher

The Slasher defines how and when collateral can be penalized when networks report misbehavior.

Curators choose between instant slashing, where penalties are applied as soon as a valid proof is delivered, and vetoed slashing, where a resolver set has a short window to challenge or veto a proposed slash. Instant slashing is cleaner and faster, but less forgiving if monitoring is imperfect. Vetoed flows add an extra layer of human or hybrid review, at the cost of latency and some operational overhead. The slashing mode should match the vault’s risk profile and the curator’s ability to monitor incidents in real time.

![curators-2.png](/img/curators-2.png)

### Epochs and Withdrawals

The vault epoch ties together guarantees, slashing timing, and liquidity for stakers. Withdrawals are directly tied to this: how quickly users can fully exit the vault depends on the epoch duration and where they are inside that cycle.

Curators pick an epoch length that comfortably covers the network’s own epoch/finality, any veto window, and the time needed to execute slashes. A longer epoch usually means stronger guarantees (more time to observe and act) but slower reaction for withdrawals and reallocations. A shorter epoch improves responsiveness but leaves less room for disputes. Withdrawal mechanics should be aligned with this: conservative vaults accept slower exit in exchange for robust slashing, while more aggressive ones may prioritize faster liquidity and shorter epochs.

![curators-3.png](/img/curators-3.png)

### Delegator

The Delegator encodes the allocation strategy and defines how stake is spread across networks and operators.

Curators choose a Delegator type based on the structure of the vault. For a single network and a single operator, the Delegator can simply route all stake to that operator. For a single network with multiple operators, the Delegator can enforce how stake is restaked across those operators, for example by applying ceilings for each one or by targeting specific operator shares. For multiple networks, the Delegator first decides how much stake each network receives, then how that stake is divided among the operators inside each network. These parameters are how curators express diversification rules, concentration limits, and risk budgets for each network and each operator on chain. In practice, most of the portfolio work a curator performs is captured in how they configure and update the Delegator over time.

One example is the “Multiple Networks, Multiple Operators” vault, which, as the name suggests, allows delegations to several operators across different networks, and lets stake be restaked across those networks.

![curators-4.png](/img/curators-4.png)

### Burner

The Burner decides **what happens to slashed collateral** once a penalty is applied.

Curators can route slashed funds to different sinks: pure burn (reduce supply), redistribution to remaining stakers, funding an insurance backstop, or sending value back to affected networks. This choice affects incentives: harsh burns are strong deterrents but fully socialize losses, while redirecting part of the slash to an insurance or remediation pool can help absorb shocks more gracefully. The Burner configuration should be consistent with how the vault markets itself: pure risk-taking, conservative insurance-like, or somewhere in between.

![curators-5.png](/img/curators-5.png)

# **Vaults**

A vault is the on chain container that holds collateral and connects it to networks. Each vault holds a single collateral token, keeps track of who has deposited and who can withdraw, and exposes the configuration points that let curators define how delegation, slashing, and rewards work. Delegation itself is purely an accounting layer: collateral stays inside the vault and only leaves when users withdraw or when a valid slashing event is executed.

## Core modules

Every Symbiotic vault is built from a small set of modules:

1. **Accounting (Vault)**: deposits, withdrawals, epochs, and penalties
2. **Delegation (Delegator)**: stake per network and per operator, based on curator policy
3. **Slashing (Slasher)**: checks and applies penalties requested by networks

![Vault Core Modules](/img/vault-core-modules.png)

## Accounting

### Deposits

Any address that passes the vault access policy can deposit the collateral token. By depositing, a staker opts into that vault’s strategy and risk profile.

The vault:

* records the deposit
* updates the user balance and total active stake
* keeps collateral in the vault contract

Each vault uses a single collateral token. Multi asset exposure is achieved by using multiple vaults.

![Vault Deposits](/img/vault-deposits.png)

### Withdrawals and epochs

Withdrawals use an epoch based flow. The goal is to let users exit while keeping operator stake stable inside each epoch.

At a high level:

1. A user submits a withdrawal request at any time.
2. The request becomes claimable after the end of the next vault epoch.
3. Until that epoch boundary, the requested amount is still eligible for slashing.

Epoch length is chosen at deployment and stays constant. Longer epochs give more time for networks to report misbehavior but make withdrawals slower. Shorter epochs make exits faster but leave less room for disputes.

![Vault Withdraw](/img/vault-withdraw.png)

## Delegation

Delegation is how a vault’s stake becomes effective security for networks and operators.

Curators:

* choose which networks the vault supports
* set limits or target shares per network and per operator
* select a Delegator type that matches the vault thesis

The Delegator looks at the vault active balance, which operators and networks opted into this vault, and the configured limits or shares. From this it returns how much stake a given operator has for a given network at a point in time.

Different Delegator types cover patterns like:

* one operator across many networks
* many operators inside one network
* multiple networks and multiple operators in a single portfolio

The vault holds collateral in one place. The Delegator decides how that collateral is counted as stake across Symbiotic.

## Slashing

When an operator breaks the rules, part of the vault collateral can be penalized.

Networks do not slash directly. They send a slashing request to the Slasher module that includes which network or subnetwork is affected, which operator is at fault, how much to penalize, and which snapshot this refers to.

The Slasher:

1. Checks that the request is fresh enough and consistent with the vault guarantees.
2. Verifies that there is enough stake tied to that snapshot to cover the penalty.
3. If valid, applies the penalty to vault balances and calls the configured Burner to decide where penalized collateral goes, for example a burn, redistribution to users, a treasury, or an insurance pool.

Some configurations apply valid slashes immediately. Others introduce a short review window where a resolver can veto or challenge.

![Vault Slashing](/img/vault-slashing.png)

## Rewards

Vaults do not hard code rewards. They only provide stake that secures networks and operators.

Each network decides:

* how stakers and operators are paid
* whether rewards come from fees, external clients, token inflation, or a mix
* which reward contracts or extensions they use

Symbiotic’s rewards framework gives networks standard ways to send value back to stakers, who provide collateral and take slashing risk, and to operators, who run the services the network depends on.

## Vault types

Vaults are configurable templates for different strategies and use cases.

Anyone who holds the collateral token can deposit, subject to any global caps the curator defines. These are usually used for broad, permissionless participation.

**Private vaults**

Only allowlisted addresses can deposit. LRT and LST providers, funds, or DAOs often run private vaults, aggregate user funds on their own balance sheet, and then allocate across several Symbiotic vaults on behalf of their users.

# **Slashing**

Operators have stake assigned to them in each network they serve. Every network defines rules for correct behavior, such as producing valid blocks, signing messages only once per slot, or executing a strategy within specified limits. If an operator fails to perform these services according to the rules, the network middleware can raise a slashing request against them. On Ethereum, for example, this includes faults like double signing.
The Slasher module is an optional component of the Vault structure that handles the enforcement of slashing penalties. It doesn't perform slashings by itself but processes the requests received from the network middlewares.

## **How it Works**

In general, when a network fetches the stakes at some point in time, called the "capture timestamp", it receives the guarantee that the received amounts of collateral will be slashable during one epoch after it. Hence, the Slasher module always checks that the capture timestamp is not older than one epoch when executing the slashing.

In case of restaking, the guarantee might not be valid because of other networks' slashing. There is nothing to do about it because it's the nature of restaking itself.

![guarantee of slashing](/img/guarantee-of-slashing.png)

Like the Delegator module, the Slasher module also has a types mechanic, where different Slasher types may be used for various purposes. Currently, there are two types (position indexes in the list below correspond to the on-chain types):

### **0. Slasher**

This type performs an instant execution of the slashing request when received and validated. It is a simple and easy-to-understand implementation. However, it has too low flexibility compared with the next Slasher type.

![instant slashing](/img/instant-slasher-started.png)

### **1. VetoSlasher**

VetoSlasher is a more complex type whose goal is to provide an in-house mechanism to handle a smooth transition for both networks and stakers from the just deployed versions of the networks to the battle-tested ones without additional development risks.

Its flow consists of three stages:

1. Request of the slashing, which is performed by the network middleware and validated by the VetoSlasher contract
2. Veto phase, whose duration is set during the vault's deployment, when the resolver (if set by the network) can veto the request
3. Execution of the slashing, which can be performed only by the network middleware if the veto was not issued

![veto slashing](/img/veto-slasher-started.png)

## **Burner**

Once slashing is approved and enforced, the actual processing of the affected stake is delegated to a configurable Burner contract. This contract determines what happens to the slashed tokens – whether they are unwrapped (e.g., from LSTs), burned, or even redistributed. For the example Burner, see the [wstETH unwrap / burn implementation](https://github.com/symbioticfi/burners/blob/main/src/contracts/burners/wstETH_Burner.sol).

# **Rewards**

Symbiotic can be considered an exchange hub between basically 3 parties: stakers, operators, and networks.

* The stakers provide capital for the operators to use in favor of the networks
* The operators provide maintenance of the networks’ liveness in a valid manner
* The networks receive a security for their products depending on the economic side provided by the stakers and on the functioning side provided by the operators

Based on these exchange statements, it can be seen that the stakers and the operators provide services to the networks. Therefore, the networks are responsible for giving them something in exchange, and these are **rewards**.

![rewards](/img/rewards-distribution.png)

## **Rewards Distribution**

Symbiotic Core contracts don’t contain the rewards logic enshrined. However, they provide enough data for external contracts to be able to create a rewards distribution, so anyone can create their own implementation of it.

Rewards can be divided into staker and operator rewards:

* The staker rewards can be provided depending purely on the provided stake’s value (the representation of value can differ from the standard $ view depending on alignment / token distribution / other factors)
* The operator rewards can be provided depending on the economic factors similar to the above ones and on the operators’ performance metrics (e.g., number of tasks completed / liveness / validators’ distribution)

![tech-rewards](/img/tech-rewards.png)

We provide en extensive framework implementation to facilitate rewards distribution.

[See Rewards Integration Guide](../../../integrate/networks/rewards)

### **Staker rewards**

Stakers provide the collateral that backs operators’ actions on each network. By depositing into a vault, they are taking on the risk that operators or networks may misbehave and that part of their stake could be slashed. In return, they should be compensated for supplying this economic security and for locking capital into a specific strategy or risk profile.

Networks pay stakers using the value they generate. This can come from protocol revenues such as fees and spreads, from payments made by external clients who consume the network’s services, or from token inflation that is explicitly allocated to security and growth. Through Symbiotic’s rewards contracts, these streams are routed back to stakers in a way that matches the vault’s configuration and the networks it secures.

### **Operator Rewards**

Operators keep validators online, run middleware binaries, sign messages for bridging and oracle updates, or execute DeFi strategies on behalf of a network. Because they are spending time, capital, and operational effort to provide these services, they need to be compensated for them. Networks pay operators out of the value they generate, for example protocol fees, revenues from external clients that use their services, or token inflation allocated to operations and security.

Symbiotic’s rewards framework is flexible enough to route operator payments in different ways, for example:

* The network calculates rewards off chain and sends periodic batch transfers to operators.

* The network calculates rewards off chain and publishes a Merkle tree, allowing each operator to claim its own share.

* The network keeps reward accounting fully on chain inside its middleware and distributes rewards directly from that on chain state.

In every case, the goal is the same: make sure operators are paid in a way that matches the work they do and the risk they take.

# Relay SDK

## **The Framework for Stake-Secured Applications**

The Symbiotic Relay SDK is the trust layer for data and computation.

It turns any data, computation, or event into **money backed, stake secured attestations** that settle on chain and trigger programmable outcomes. With Relay you:

* **Reduce and keep costs constant at scale.** Validator-set verification uses BLS aggregation and optional ZK compression to keep EVM verify gas essentially flat, regardless of validator set size.
* **Put capital behind data.** Every attestation is secured by stake and can be subject to slashing.
* **Reduce integration friction.** One standardized attestation flow replaces bespoke oracles and middleware.
* **Automate across chains.** Verify once, then mint, swap, bridge, update feeds, or call adapters anywhere.

> Relay is the missing link between computation and consensus, the universal economically secured proof layer for the modular internet.

## The Problem that Relay Solves

Large validator sets became prohibitively expensive to verify across chains. Networks with hundreds of operators were facing millions per year in verification costs on Ethereum alone. At the same time, protocols that wanted to run multichain were pushed into Proof-of-Authority models because staking data was not available cross-chain in a usable, verifiable way.

## **How it Works**

1. ***Application Layer***

   Any app or service performs a task: fetching prices, running an AI model, or monitoring transactions.

2. ***Relay Network***

   Operators in the Relay Network generate cryptographic attestations that confirm the task was executed as claimed.

3. ***Relay Settlement***

   These attestations are verified on-chain using validator stakes within Symbiotic Core contracts.

4. ***On-Chain Action***

   Once verified, the attestation can trigger any programmable outcome:

   * Mint a token
   * Update a price feed
   * Trigger a bridge transaction
   * Perform a swap
   * Feed data into a DeFi protocol

![Figure 1 - Relay Flow for Cross-Chain Applications](/img/relay-overview-1.svg)

## **Key Value Proposition**

The Relay turns any external workload into a verifiable on-chain action. Networks plug in a lightweight client, inherit stake-backed security with slashing, and use a single attestation flow that works across chains and use cases. The result is less code to maintain, clearer guarantees, and a portable integration you can reuse everywhere.

### Relay Advantages

* **Cheaper at scale**
  Validator-set verification uses BLS aggregation (and optional ZK compression) to keep EVM verification costs essentially constant, independent of validator count. This removes the linear cost curve that made large decentralized sets impractical.
* **Ship faster**
  Replace bespoke middleware with a small client + SDK. Fewer contracts to write and audit → shorter path to mainnet.
* **Cross-chain by default**
  Verify and trigger outcomes on any EVM; plug into Hyperlane/DVN/others through adapters.
* **Stronger guarantees**
  Attestations are backed by staked validators with slashing. You inherit economic security instead of trusting a vendor or multisig.
* **Unified interface**
  One attestation format for any workload (AI, compute, data, bridge ops). No new pipeline per use case.
* **Smaller attack surface**
  Less custom glue code, fewer moving pieces, clearer trust model.
* **Deterministic programmability**
  Attestations can mint, swap, bridge, update feeds, call adapters → compose like Lego across verticals.
* **Cost predictability**
  Pay for attestation + on-chain verify; avoid standing infra and surprise ops costs.
* **Vendor neutrality**
  Bring your own operators/curators, swap them out, or add more. No lock-in.

### Relay Features

| Feature                                 | Benefit                                                                                                                                                                                     |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Universal Attestation Framework**     | Any data, any computation, any chain → one system for proof generation                                                                                                                      |
| **Verifiable On-Chain**                 | Proofs backed by staked validators, ensuring economic security                                                                                                                              |
| **Fully Modular SDK**                   | Developers integrate using lightweight clients in Go, Rust, or TypeScript                                                                                                                   |
| **Chain-Agnostic**                      | Works across L1s, L2s, and rollups; interoperable with all EVMs. Cosmos integration is available out of the box through a dedicated [SDK](https://github.com/symbioticfi/cosmos-relay-sdk). |
| **Programmable & Application-Agnostic** | Plugs into any smart contract workflow; attestations act as a generic trigger for programmable outcomes.                                                                                    |

## System Architecture

Every operator runs:

* A **Relay Sidecar** → connects to other relay nodes via a p2p network
* An **Application Node** → runs arbitrary code (AI, oracle, bridge, etc.) and communicates with the Sidecar through an API

Together, these produce **verifiable proofs of arbitrary work**, enabling **on-chain action triggers** and **outcome settlement**.

![Figure 2 - Architecture Overview](/img/relay-overview-2.png)

### How Relay Integrates with Symbiotic

Relay plugs into Symbiotic Vaults out of the box, so networks can adopt it immediately and still customize everything, including validator sets, quorum thresholds, collateral, and reward logic. The Relay contracts read staking state from the vaults each epoch to see who the active operators are and how much voting power they have.

The settlement contract receives this data, verifies the attestations, and then triggers the onchain outcome.

![Figure 3 - Symbiotic Core + Relay Composability](/img/relay-overview-3.svg)

# Use Cases

Symbiotic's shared security and Relay attestation layer enable a wide range of protocols. Explore a few high-impact patterns below.

<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: '24px', marginTop: '32px' }}>
  <Card2
    title="Bridges & Cross-Chain Networks"
    description="Stake-backed attestations for bridge state, DVNs, and cross-domain proofs."
    icon={
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
      <circle cx="6.5" cy="6.5" r="3.5" strokeWidth="1.8" />
      <circle cx="17.5" cy="6.5" r="3.5" strokeWidth="1.8" />
      <circle cx="12" cy="17.5" r="3.5" strokeWidth="1.8" />
      <path d="M9 6.5h6M7.5 8.7L10 15M16.5 8.7L14 15" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  }
    href="/get-started/use-cases/bridges-cross-chain-messaging"
  />

  <Card2
    title="Cloud & Compute - &#x22;Decentralized Docker&#x22;"
    description="Provision decentralized compute clusters that emit verifiable Relay attestations."
    icon={
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <rect x="3" y="6" width="18" height="12" rx="2" strokeWidth="1.8" />
          <path d="M7 9h10M7 12h6M7 15h4" strokeWidth="1.6" strokeLinecap="round" />
          <path d="M12 18v3" strokeWidth="1.6" strokeLinecap="round" />
          <path d="M9 21h6" strokeWidth="1.6" strokeLinecap="round" />
      </svg>
  }
    href="/get-started/use-cases/decentralized-compute-ai-verification"
  />

  <Card2
    title="Oracles & Data Feeds"
    description="Stake-secured feeds and event triggers with custom resolvers and slashing."
    icon={
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <circle cx="12" cy="12" r="8" strokeWidth="1.8" />
          <path d="M12 8v4l3 2" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
          <circle cx="12" cy="12" r="2" fill="currentColor" />
      </svg>
  }
    href="/get-started/use-cases/oracle-networks-data-feeds"
  />

  <Card2
    title="General Attestation Layers"
    description="Stake-backed attestations for arbitrary computation that trigger on-chain actions."
    icon={
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <polygon
              points="12 3 21 9 21 15 12 21 3 15 3 9"
              strokeWidth="1.8"
              strokeLinejoin="round"
          />
          <path
              d="M12 7v10M8 9.5l4 2.5l4-2.5"
              strokeWidth="1.6"
              strokeLinecap="round"
              strokeLinejoin="round"
          />
      </svg>
  }
    href="/get-started/use-cases/general-attestation-layers"
  />

  <Card2
    title="Use Relay with non-EVM chains"
    description="Route Symbiotic stake into non-EVM chain validator environments."
    icon={
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <path
              d="M12 3l7.5 4.5v9L12 21l-7.5-4.5v-9L12 3z"
              strokeWidth="1.8"
              strokeLinejoin="round"
          />
          <path
              d="M12 3v18M4.5 7.5l7.5 4.5l7.5-4.5"
              strokeWidth="1.6"
              strokeLinecap="round"
              strokeLinejoin="round"
          />
      </svg>
  }
    href="/get-started/use-cases/chain-agnostic-applications"
  />

  <Card2
    title="Liquidity Management"
    description="Unlock the liquidity sitting in the Symbiotic vault and turn it into production credit"
    icon={
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <circle cx="12" cy="12" r="9" strokeWidth="1.8" />
          <path
              d="M12 7.5v9M9.5 10C9.5 8.8 10.5 8 12 8c1.2 0 2 .6 2 1.5 0 1-1 1.5-2.5 1.5s-2.5.5-2.5 1.5c0 .9.9 1.5 2 1.5 1.3 0 2.5-.5 2.5-1.5"
              strokeWidth="1.6"
              strokeLinecap="round"
              strokeLinejoin="round"
          />
      </svg>
  }
    href="/get-started/use-cases/liquidity-management"
  />

  <Card2
    title="Insurance and Guarantees"
    description="Unlock the liquidity sitting in the Symbiotic vault and turn it into production credit"
    icon={
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <circle cx="12" cy="12" r="9" strokeWidth="1.8" />
          <path
              d="M12 7.5v9M9.5 10C9.5 8.8 10.5 8 12 8c1.2 0 2 .6 2 1.5 0 1-1 1.5-2.5 1.5s-2.5.5-2.5 1.5c0 .9.9 1.5 2 1.5 1.3 0 2.5-.5 2.5-1.5"
              strokeWidth="1.6"
              strokeLinecap="round"
              strokeLinejoin="round"
          />
      </svg>
  }
    href="/get-started/use-cases/insurance-and-guarantees"
  />
</div>

# Bridges and Cross-chain Messaging

## **Problem**

Cross chain protocols typically run isolated validator sets or oracle committees per route, which is expensive, slow, and does not scale. Costs grow with validator count, so verifying hundreds of operators on the EVM becomes prohibitive, while committee signatures and relayer hops add latency.

Security is fragmented because every bridge ships its own trust model and attack surface, and operators often have weak economic alignment with unclear slashing paths.

Finality differences across chains complicate safe verification, and each new chain or pair demands bespoke integrations, audits, and ongoing operations, creating vendor lock in and brittle user experience when messages are delayed or stuck.

## **Solution**

The Relay gives you one validation layer for everything: turn any cross-chain message into a **money backed, stake secured attestation** you can verify on any destination chain. You ship faster, spend less, and gain clearer guarantees.

Some of the Relay advantages can be found below:

* **Cheaper at scale.** BLS aggregation with optional ZK keeps EVM verify gas essentially flat, even with large validator sets.
* **Stronger security.** Attestations are backed by bonded stake with explicit slashing and configurable quorum.
* **Faster to market.** Lightweight client and SDK replace bespoke relayers and committees, reducing code and audits.
* **Portable across chains.** One attestation format, one verifier; add a chain by deploying the verifier and an adapter.
* **Works with existing stacks.** Thin adapters feed DVN, Hyperlane, governance, feeds, or your app logic.
* **Full control.** Customize validator sets, quorum thresholds, stake types and amounts, challenge windows, and slashing rules.

## **How it Works**

1. **Observe and package.** An event or message is observed on the source chain and packaged with block height, domain, nonce, and expiry.
2. **Attest and aggregate.** A configurable quorum of operators signs the package; signatures are aggregated with BLS and backed by bonded stake.
3. **Verify on destination.** The verifier contract checks quorum and weights, validates metadata, enforces replay and time bounds, and verifies the aggregate. With optional ZK, verification remains near constant in gas even as the validator set grows.
4. **Settle the outcome.** After verification, adapters execute the intended action: mint or burn, update a feed, trigger a bridge transfer, call governance or settlement, or hand a standard proof to DVN or Hyperlane. Each attestation emits a unique ID and events for auditability and monitoring.

![Flow](/img/cross-chain-1.svg)

<GetInTouchButton />

## **Application Examples**

1. **Economic-secured bridge (DVN, ISM, etc.) for LSTs/stablecoins**

Asset issuers use their governance token as slashable collateral to secure bridging routes and enforce mint/burn discipline.

2. **Cross-chain collateralized lending**

Let users borrow on Chain A while holding collateral on Chain B, with Relay attestations guaranteeing state and liquidations.

3. **Canonical mint/burn across rollups**

Fast, verifiable attestations to burn on the origin and mint on the destination to keep a single canonical supply for tokens.

4. **Cross-chain governance execution**

Pass a proposal on the home chain and execute upgrades or parameter changes on connected chains via attested messages.

5. **DEX settlement & order routing**

Attest trade fills or intent resolutions on one chain and finalize accounting on another without custom oracles.

6. **NFT & identity portability**

Verifiably transfer ownership/metadata across chains for collections, game items, or credentials.

7. **Cross-chain payments & payouts**

Batch attest deposits/withdrawals to move balances instantly between chains for wallets, fintech, and exchanges.

## References

* [Bridges Cross Chain Networks](https://www.notion.so/Bridges-Cross-Chain-Networks-28b81c079c178048aa47caed85bcdbc9?pvs=21)
* [Build DVN backed by Symbiotic’s Economic Security Framework](https://www.notion.so/Build-DVN-backed-by-Symbiotic-s-Economic-Security-Framework-27081c079c1780c185dee9212d1702b3?pvs=21)
* [Github Relay Contracts](https://github.com/symbioticfi/relay-contracts)

# Oracle Networks and Data Feeds

## **Problem**

Most oracle systems are rigid and permissioned, with fixed committees and bespoke integrations per chain. Expanding coverage is expensive, updates can be slow or stale, and manipulation risk remains due to weak incentives, limited slashing, MEV at publication time, and unclear dispute processes. Portability across chains is poor and auditability is fragmented.

## **Solution**

Relay acts as a **universal oracle engine**. Any approved operator can fetch off-chain data and produce a **stake-backed attestation** that is:

* **Verifiable on chain** with BLS aggregation and anti-replay.
* **Backed by bonded validators** with explicit slashing for bad data, equivocation, or missed SLAs.
* **Programmable** via schemas for prices, TWAPs, risk scores, proof-of-reserves, or custom metrics.
* **Cheaper at scale** by batching many feed updates into one verification.
* **Composable across EVMs** and compatible with CCIP-style routing through thin adapters.
* **Auditable** with on-chain receipts and clear freshness guarantees.

## How it Works

1. **Register and bond.** Operators join the feed and lock stake as collateral.
2. **Define the feed.** You set what data to track, how often to update, how to combine sources, and the service levels.
3. **Collect and compute.** Operators fetch data from chosen sources and calculate the feed’s current value.
4. **Attest.** Each operator signs the result with timing and round details.
5. **Aggregate.** The signatures are combined into a single proof for that update window.
6. **Verify on chain.** A verifier checks that enough staked operators signed, the update is fresh, and it is not a replay.
7. **Publish or trigger.** The value is written on chain or passed to protocols that use it.
8. **Dispute and slash.** If an update is wrong, late, or inconsistent, anyone can dispute within a window and dishonest operators are slashed.

![Flow](/img/oracle-networks-1.svg)

<GetInTouchButton />

## Application Examples

1. **DeFi price feeds**

Pull quotes from major CEX and DEX venues, compute a median or short TWAP with venue weighting and outlier filters, then attest the value with a timestamp and deviation flag. Set a heartbeat and a max staleness window so lending and perp engines only accept fresh rounds. If an attested value is outside the allowed deviation band or uses stale sources, operators are slashable and the adapter will refuse the update.

2. **Perp funding and index price**

Define an index basket per asset, sample every few seconds, and publish round values on a fixed cadence. Funding is derived from index minus mark with clamps and a rolling window, then attested and verified on chain so funding transfers and insurance accounting execute deterministically. Any missing interval or conflicting rounds within the window is disputable and can lead to slashing.

3. **Proof of reserves**

Bonded operators produce a **stake-backed, verifiable attestation** of total reserves versus circulating liabilities, with timestamp, heartbeat, and deviation guards. The attestation is checked on chain for quorum and freshness; misreporting, conflicting rounds, or missed SLAs can be **slashed** against bonded collateral. After verification, adapters gate mint and burn so supply cannot exceed attested reserves, pause on staleness, and record every round for auditability.

4. **LST risk score**

Compute a composite score from on chain metrics such as pool depth, oracle deviation to spot, withdrawal queue length, historical depeg distance, and validator set concentration. Publish the score on a regular cadence with thresholds that protocols map to collateral factors or caps. Large moves require multiple consecutive rounds to prevent whipsaw, while clear breaches can immediately tighten risk parameters.

5. **NFT floor price**

Aggregate bids and sales from leading marketplaces, remove wash trades and self matches, and compute a robust floor using median of top bids with liquidity filters. Per collection feeds are attested with collection id, floor, and liquidity score; NFT backed lending vaults use the value with conservative haircuts and a freshness check. If market data is thin, the adapter can hold the last good value until quorum resumes.

6. **CCIP routing data**

Publish per chain gas prices, route health, and token exchange rates that cross chain routers consume to select paths and set fees. Attest route liveness and recent failure counts so routers can avoid degraded links. Deviation guards and freshness windows ensure routers never act on stale or manipulated signals.

## References

* [Oracles Data Feeds](https://www.notion.so/Oracles-Data-Feeds-28b81c079c1780d284fff271a7b9e7f0?pvs=21)
* [EXTERNAL GUIDE Symbiotic Relay SDK](https://www.notion.so/EXTERNAL-GUIDE-Symbiotic-Relay-SDK-1f981c079c17802090f6db09a4b7b7e2?pvs=21)

# General Attestation Layers

## **Problem**

Off-chain agents and many L2 systems do not have a native trust layer. You cannot easily prove that a check was performed, a condition held true, or a message is safe to act on. Current approaches are permissioned, costly to extend, and lack clear economic guarantees or dispute paths.

## **Solution**

Relay lets any agent or system produce a **stake-backed, verifiable attestation** about external state or completed actions. Attestations are checked on chain for quorum, freshness, and consistency, and bad behavior is slashable. Once verified, adapters can trigger actions such as mint, transfer, unlock, vote, or update state. One receipt format and one verifier work across L1s and rollups, so you can add new domains without rebuilding trust from scratch.

## How it Works

1. **Register and bond.** Agents or operators enroll for a task and lock stake that can be slashed.
2. **Define the condition.** Specify what must be checked, the cadence or event trigger, and the dispute window.
3. **Observe and decide.** Agents perform the check or computation and determine the outcome.
4. **Attest and aggregate.** Agents sign the result with timing and context, and signatures are combined into one proof.
5. **Verify on chain.** A verifier checks quorum, stake weight, freshness, and anti-replay.
6. **Trigger action.** An adapter executes the approved action or writes the result for other contracts to consume.

![Flow](/img/decentralize-network-1.svg)

<GetInTouchButton />

## Application Examples

1. **L2 fast finality**

Operators attest that an L2 block or batch is safe after specific checks, giving near-instant usable finality for bridges and apps while full finality catches up.

2. **Autonomous agent receipts**

AI or automation agents attest to tasks they performed such as compliance checks, data validation, or workflow steps, unlocking funds or advancing pipelines only when receipts pass verification.

3. **Uptime and SLA monitors**

Watchdogs attest liveness and performance of services such as sequencers or keepers and automatically apply penalties, rebates, or failover when thresholds are missed.

4. **Decentralized sequencer**

A set of bonded operators attest that a given L2 block or batch is available, correctly ordered, and built under the declared rules. The attestation is stake-backed and verified on chain, then a small adapter accepts the batch, releases bridge messages, or advances state. Misbehavior such as equivocation, censorship beyond policy, invalid ordering, or missed slots can be disputed and slashed. You also get usable fast-finality receipts for bridges, liveness SLAs with automatic failover, and optional hooks to enforce fairness policies (e.g., inclusion lists or MEV limits) via the same attestation flow.

5. **Circuit-breaker signals**

Publish slash-backed alerts for depeg risk, abnormal volatility, or halted markets that protocols use to tighten limits or pause actions.

## References

* [General Attestation Layers](https://www.notion.so/General-Attestation-Layers-28b81c079c178072af48f99f444266c6?pvs=21)
* [Relay Collateral](https://www.notion.so/Relay-Collateral-28b81c079c1780bb99e7e7cf66a0e15f?pvs=21)

# Decentralized Compute and AI Verification

## **Problem**

Decentralized compute today is **costly, brittle, and easy to game**. Most systems rely on ad-hoc coordinators, TEEs, or multisig committees that don’t provide chain-agnostic, slashing-enforced guarantees. Notable shortcomings include:

* **High cost:** bespoke committees/light clients per network, many sig verifications on-chain, custom relayers, repeated audits, and over-provisioned capacity drive unit economics up.
* **Attack surface:** forged results, equivocation (conflicting outputs), replay of old results, censorship/withholding, collusion among runners, coordinator DoS, key compromise, MEV/front-running on result publication, and TEE quote spoofing without on-chain anchoring.
* **Weak incentives:** runners often have little or no bonded stake; slashing paths are unclear or social, so bad behavior is cheap.
* **Operational opacity & lock-in:** logs and receipts are off-chain/opaque, integrations are bespoke per chain or vendor, and portability is poor.

## **Solution**

Relay turns each off chain computation, including container jobs, into a stake backed, verifiable receipt. These receipts can be checked on chain and, once approved, automatically trigger payments, unlocks, or workflow steps. There are no custom committees or heavy coordination, only clear proof that a job was done, with built in penalties for cheating or missed deadlines, lower costs at scale, and portability across any cloud or chain.

Some of the Relay advantages can be found below:

* **Usage-based, provable billing:** verifiable receipts include runtime/metrics so you can meter, invoice, and settle on-chain per job or per epoch.
* **SLA enforcement:** late, missing, or conflicting results are objectively slashable; clients get deterministic inclusion and dispute windows.
* **Lower verification cost:** aggregate many job receipts once per epoch → one on-chain verify for hundreds/thousands of tasks.
* **Input/Output integrity:** bind container image digest, parameters, data CIDs, and output/artifact hashes into the receipt to prevent tampering or replay.
* **TEE or ZK, your choice:** attach a TEE quote hash or a zk proof of execution when available; Relay’s stake guarantees still secure the base path.
* **Multi-cloud portability:** same receipt format and Verifier across L1s/rollups; run workers on any infra (K8s, bare-metal, cloud) without vendor lock-in.
* **Fair marketplace for runners:** bonded operators with reputations and slashing create credible supply; optional per-capability whitelists (GPU, RAM, CUDA).
* **Composable callbacks:** post-verify adapters can release escrow, mint compute credits, advance workflows, or trigger subsequent jobs.

## How it Works

1. **Register and bond**: Operators enroll for the compute task, publish keys and capabilities, and lock stake that can be slashed.
2. **Submit job**: The client posts a job with an input commitment that binds image or runtime, parameters, and data.
3. **Execute off chain**: A worker runs the job. A small Sidecar measures runtime and resources, and derives an output commitment for results and artifacts.
4. **Attest**: Operators sign a job receipt that includes task id, job id, input hash, output hash, metrics, epoch, and nonce. Receipts can also include a TEE quote hash or a zk proof.
5. **Aggregate**: Receipts are BLS-aggregated and optionally batched per epoch to amortize costs.
6. **Verify on chain**: The Verifier contract checks quorum, stake weight, freshness, and anti-replay.
7. **Trigger action**: After verification, an Adapter releases escrow or payment, mints compute credits, advances a workflow, or calls back the app.
8. **Challenge and slash**: Within the challenge window anyone can submit evidence of fraud, equivocation, replay, or missed SLA. Proven faults slash operator stake and can revert or remediate actions per policy.

![Flow](/img/decentralized-compute-1.svg)

<GetInTouchButton />

## Application Examples

1. **AI inference marketplace**

Each inference container runs a Relay Sidecar that signs an attestation with: model ID/version, input hash, output hash, latency, and compute meter. Buyers verify the attestation on-chain before releasing payment; misbehavior can be slashed against the operator’s staked collateral.

2. **Model training and fine-tuning**

Trainers emit Relay attestations at checkpoints (per epoch or per N steps) containing dataset/version hashes and metrics (loss/accuracy). Milestone payouts stream only when the on-chain verifier accepts the attested checkpoint; failed or missing checkpoints pause funding and can trigger slashing.

3. **ZK prover network**

Prover nodes attach Relay to the proving container. When a proof is generated, the Sidecar signs an attestation with the proof commitment and job ID. The consumer contract verifies both: (1) the proof itself and (2) the Relay signature tied to a bonded operator, then releases payment atomically.

4. **Indexing and ETL pipelines**

Indexers process ranges (e.g., blocks 10M–10.1M) and emit Relay attestations with range coverage, schema version, and result checksum. Consumers (subgraphs, data apps) pay per attested range and can reconstruct a full index by verifying a sequence of signed ranges from a quorum.

5. **Edge Compute**

Edge devices process shards of a job and sign shard-level Relay attestations (shard ID, input/output hashes, timing). An aggregator contract verifies a threshold of shard attestations, reconstructs the job result, and then settles payments pro-rata; faulty shards are isolated and penalized.

## References

* [Cloud Compute Decentralized Docker](https://www.notion.so/Cloud-Compute-Decentralized-Docker-28b81c079c1780f59256daa4e8b090c9?pvs=21)
* [Relay Collateral](https://www.notion.so/Relay-Collateral-28b81c079c1780bb99e7e7cf66a0e15f?pvs=21)
* [Github Relay Contracts](https://github.com/symbioticfi/relay-contracts)

# Liquidity Management

## **Problem**

Overcollateralized designs trap capital and do not scale. Many eligible assets, especially RWAs, are illiquid or settle slowly, so redemptions either take a haircut through discounts and slippage or require waiting through withdrawal periods.

## **Solution**

Symbiotic lets you unlock the liquidity already sitting in the Symbiotic vault and turn it into production credit. No new collateral posted upfront. You get capital efficiency on day one while keeping real economic guarantees because the vault can be slashed if policy is breached.

For stablecoin issuers and lending markets this means instant liquidity for otherwise illiquid RWAs and smoother redemptions without forced discounts. For intent and execution use cases this means you can run the action now and settle later with a clear rebalance window. Fees flow to the operator on verified completion and the system enforces that the vault balance is restored on time, or slashing applies. The result is more volume, faster time to market, and stronger trust with borrowers and regulators since every action is covered by stake secured guarantees.

Symbiotic can also help bridge policy across chains through the Symbiotic Relay. It carries the attestation from the chain where users deposit to the chain where they receive access, so you can originate on any network and serve users everywhere with one verifier and one format. Add a new chain by deploying a thin adapter and keep your existing issuer or lending stack unchanged.

In short, Symbiotic turns idle vault liquidity into safe productive credit, gives you instant usability for slow to settle assets, and backs every promise with real money at risk.

## How it Works

Here’s the exact flow for Symbiotic using the Relay SDK for epoch management:

1. The network defines the vault to draw from, the rebalance window, and the payment rules.
2. The network slashes the Symbiotic vault to access liquidity for the action.
3. Liquidity is used for the intended purpose, to early-redeem illiquid RWAs or to fulfill an intent.
4. The associated operator executes the intent, and funds are delivered to the user

![Liquidity Management 1](/img/liquidity-management-1.svg)

5. The network manager or operator rebalances the Symbiotic vault by adding the collateral deposited by the user when expressing the intent.
6. The operator produces an attestation that the intent was executed and the user received the funds.
7. The settlement contract verifies the attestation and receives the current vault state for collateral valuation in the same epoch.
8. If policy is satisfied, the contract triggers payment to the operator or solver.
9. If policy fails or the restore window is missed, the operator or solver is slashed. If they have a protection layer in another Symbiotic vault, slashing is applied there according to policy.

![Liquidity Management 1](/img/liquidity-management-2.svg)

<GetInTouchButton />

## Application Examples

1. **Intent Fulfillment**

An application or network needs to execute a user intent, for example settling an order, bridging a payment leg, or performing a market action, without waiting for fresh collateral. The network designates a Symbiotic vault as the backstop, sets a restore window and payment rules, and draws liquidity by slashing the vault to execute the intent immediately so the user receives the funds or outcome.

The associated operator then produces an attestation that the intent was executed correctly and on time. The settlement contract verifies the attestation and, before the epoch ends, the manager or network admin replenishes the vault.

If everything checks out, the contract releases the operator fee. However, if the proof is missing, late, or inconsistent with the vault state, the operator is slashed. If the operator has a protection layer in another Symbiotic vault, slashing is applied there according to the configured rules.

2. **Illiquid RWA Early Redemption**

A stablecoin issuer or lender faces a redemption request while part of the reserves sit in illiquid or slow-to-settle RWAs. Instead of forcing users to wait through withdrawal periods, the issuer taps the Symbiotic vault as a secured liquidity buffer. The network defines the qualified vault, the maximum early redemption headroom, a restore window aligned to the RWA settlement horizon, and the fee model. Liquidity is drawn from the vault to pay the user immediately, in return for a small fee.

An operator or designated agent executes the redemption flow and produces an attestation that the user received funds. The settlement contract verifies the attestation and, before the epoch ends, reads the current vault state to confirm the required collateral is present for that same epoch. The network manager must deposit the funds back into the Symbiotic vault before the epoch ends; once that balance is observed in-epoch, the contract releases the operator’s fee and the restore window closes. If the deposit is not observed before epoch end, slashing applies to the responsible party or their protection layer.

## References

* [Relay Collateral](https://www.notion.so/Relay-Collateral-28b81c079c1780bb99e7e7cf66a0e15f?pvs=21)

# Chain Agnostic Applications

## **Problem**

Appchains often spin up bespoke validator sets, multisigs or custom messaging paths per use case (governance messages, bridges, feeds). Each new route brings another committee, relayer and audit. Latency creeps in through off chain hops, costs grow with validator counts, and security fragments across custom trust assumptions. Native finality and slashing exist, but slashing paths for cross chain outcomes are typically indirect or out of band, and every extra chain or pairing demands new glue code and operations.

## **Solution**

Relay gives appchains a single validation layer for cross chain outcomes. It turns any source chain event into a stake secured attestation that your appchain can verify natively (as a module, contract or runtime component) and act on immediately.

Why this is a fit for any appchains:

* **Cheaper at scale.** BLS aggregation and optional ZK keep on chain verification costs close to constant even as the operator set grows. This is especially useful when you need to verify large validator sets or frequent updates coming from ecosystems like Ethereum.
* **Clearer guarantees.** Attestations are backed by bonded stake and explicit slashing rules in Symbiotic. You define the quorum, weights and signing conditions that must be met for your appchain to accept an update.
* **Faster to production.** A thin adapter (native module, precompile or contract) replaces ad hoc relayers or custom committees. You deploy a single verifier on your appchain and wire it directly into your application logic and state transition rules.
* **Portable across stacks.** One attestation format, many destinations. The same cryptographic proof can be verified on an appchain today and on an EVM rollup, L2 or other execution environment tomorrow, without redesigning your security model.
* **Composable with existing bridges.** You can keep using existing bridging stacks (IBC, light clients, CCIP style routers or custom bridges) where they shine, and feed Relay attestations into modules that need external state with explicit slashable guarantees. Proofs can also be handed off to existing routing or governance logic.
* **Operator control.** You can customize validator sets, quorum thresholds, stake types, challenge windows and slashing rules per appchain or even per message route, aligning Relay’s security model with each application’s specific risk profile.

## How it Works

1. **Observe & package.** Off-chain Relay nodes watch a source chain, pick up your event / message, and package it with `{source domain, block/height, nonce, expiry}`.
2. **Attest & aggregate.** A configurable quorum of operators signs. Signatures are aggregated with BLS and linked to bonded stake in Symbiotic.
3. **Verify on your appchain.** Your appchain verifies the attestation through a light verifier provided by the Relay SDK as a module, contract or runtime component. It checks weights and quorum, metadata, replay protection and the aggregate signature. With optional ZK, verify cost remains close to flat as the operator set grows.
4. **Settle the outcome.** After verification, an adapter module or contract executes. It can mint or burn, update a price feed, finalize a bridge transfer, trigger governance or emit an event for downstream modules. The pattern is the same across stacks so you wire Relay into your appchain using the primitives that are native to your environment.

![Chain Agnostic Applications](/img/chain-agnostic-applications.svg)

## Application Examples

1. **Secure your L1 consensus at genesis (no bootstrap from 0)**

   Launch without resorting to a centralized multisig or a tiny, weak validator set. Your chain imports slashable economic security directly from a Symbiotic vault: the Relay delivers an attested operator set and weights; your adapter maps those weights to consensus voting power and emits `ValidatorUpdates`. Mis-attestations are slashable at the vault, so security is real on day one - no “trust us until we decentralize” phase.

   <p />

   **Why it matters**: you avoid the bootstrapping trap, ship safely on day 1, and can
   progressively add native stake over time (dual-sourcing security or switching entirely when
   ready).

2. **Canonical mint and burn across two L1s**

   Keep a single canonical supply without bespoke multisigs. Burns on Chain A are attested through Relay. Your adapter on Chain B verifies and mints with nonces and expiries for replay protection.

3. **DEX settlement and intent routing across L1s**

   Resolve on Chain A, finalize accounting on Chain B. The adapter verifies once and updates balances / positions in your DEX or settlement module.

4. **Cross domain oracle or state feeds into an appchain module**

   Import external state for example LST rates or rollup headers into an oracle or system module on your appchain. Relay provides explicit slashable guarantees together with fixed expiries and clear challenge windows.

# Insurance and Guarantees

## **Problem**

Insurance is one of the oldest and most powerful financial primitives, yet in crypto it remains fragmented, capital inefficient, and difficult to scale.

Most onchain insurance protocols rely on isolated capital pools, bespoke claim processes, and manual governance decisions that slow payouts and limit composability. Underwriters face unclear risk exposure and opaque slashing paths, while policyholders must trust protocol-specific logic and resolver committees.

As more real-world assets, credit, and undercollateralized lending move onchain, the lack of programmable, economically enforced guarantees becomes a bottleneck. Protocols struggle to offer credible assurances against default, hacks, oracle failures, or slashing events without overcollateralization or trusted intermediaries.

Traditional insurance structures do not map cleanly to onchain systems, and existing designs fail to leverage the new primitives introduced by staking: slashable collateral, automated redistribution, and shared economic security.

## **Solution**

Symbiotic enables a new class of fully programmable insurance and guarantee products, where coverage is enforced by bonded capital and claims are settled through transparent, onchain mechanisms.

Instead of isolated pools and bespoke logic, insurance protocols can leverage Symbiotic’s universal staking primitives to build reusable, modular risk products backed by collateral.

Some of the key advantages can be found below:

* **Economic enforcement by design.** Claims are paid from bonded stake with explicit slashing and redistribution rules.
* **Capital efficiency.** Reuse existing vault liquidity, create risk tranches, or stack multiple guarantees on the same capital.
* **Automation at scale.** Claims, payouts, and penalties can be triggered programmatically via oracles, middleware, or committees.
* **Composable guarantees.** The same vaults can back insurance, credit guarantees, bridge security, or protocol risk.
* **Flexible trust models.** Mix automated triggers with human resolvers, governance, or legal agreements where required.
* **Permissionless or compliant.** Support both open, onchain insurance and permissioned, institution-grade structures.

## **How it Works**

1. **Capital is staked.** Underwriters deposit assets into Symbiotic vaults, providing slashable risk capital in exchange for yield.
2. **Coverage is issued.** Insurance protocols define policy terms, premiums, coverage limits, and triggers using middleware built on Symbiotic.
3. **Risk is monitored.** Oracles, onchain signals, or offchain monitors track events such as hacks, defaults, depegs, or protocol failures.
4. **Claims are triggered.** Claims can be triggered automatically, submitted manually, or gated by resolver committees.
5. **Assessment and settlement.** If a claim is approved, vault capital is slashed and redistributed to policyholders according to predefined rules.

<GetInTouchButton />

### Mapping Insurance to Symbiotic

| Primitive        | Description                            | Symbiotic Implementation                                                |
| ---------------- | -------------------------------------- | ----------------------------------------------------------------------- |
| Risk Capital     | Capital pools backing insurance claims | Vaults managed by curators, holding slashable collateral from restakers |
| Underwriters     | Capital providers earning premiums     | Restakers depositing into vaults and assuming risk                      |
| Policyholders    | Users purchasing coverage              | Can be represented via dedicated, permissioned, or tokenized vaults     |
| Premiums         | Fees paid for coverage                 | Upfront payments, streaming rewards, or continuous slashing             |
| Risk Scoring     | Pricing and eligibility logic          | Integrated into curator or protocol-level pricing models                |
| Coverage Terms   | Scope, limits, triggers                | Middleware contracts, or hybrid onchain/offchain agreements             |
| Claims Process   | How claims are initiated               | Automated triggers or manual submission flows                           |
| Claim Assessment | Validation of claims                   | Resolver committees, governance, oracles, or hybrid systems             |
| Oracles          | External data feeds                    | Decentralized oracle networks, optionally secured by Symbiotic          |
| Reinsurance      | Secondary protection layer             | Dedicated reinsurance vaults covering multiple risk pools               |

## References

* [Github Relay Contracts](https://github.com/symbioticfi/relay-contracts)

# Relay Quickstart

Symbiotic Super Sum spins up a relay network that runs simple sum computations. Schedule a job
on any supported chain and the result is posted to every supported destination chain.

![relay-network.png](/img/relay-network.png)

::::steps

## Clone Repository & Install Dependencies

Clone the Symbiotic Super Sum repository, initialize its submodules, and install the dependencies.

```bash [bash]
git clone https://github.com/symbioticfi/symbiotic-super-sum.git
cd symbiotic-super-sum
git submodule update --init --recursive
npm install
```

The `symbiotic-super-sum/` directory is created and includes initialized submodules.

## Generate Network Configuration

Generate the local network definition and helper artifacts Docker uses to start the stack.

```bash [bash]
./generate_network.sh
```

The script prompts for operator counts and creates a new `temp-network/` directory with `docker-compose.yml` and writable data directories.

## Start Network

Launch the Anvil chains, deployer, and relay services defined in the generated Compose file.

```bash [bash]
docker compose --project-directory temp-network up -d
```

This command launches the network services in Docker containers.

```bash [Expected output]
symbiotic-super-sum % docker compose --project-directory temp-network up -d
[+] Running 9/9
✔ Network temp-network_symbiotic-network  Created                                                                                                                                                                   0.1s
✔ Container symbiotic-anvil-settlement    Healthy                                                                                                                                                                   4.2s
✔ Container symbiotic-anvil               Healthy                                                                                                                                                                   4.2s
✔ Container symbiotic-deployer            Exited                                                                                                                                                                  128.5s
✔ Container symbiotic-genesis-generator   Exited                                                                                                                                                                  138.2s
✔ Container symbiotic-relay-1             Started                                                                                                                                                                 138.4s
✔ Container symbiotic-relay-2             Started                                                                                                                                                                 138.4s
✔ Container symbiotic-sum-node-1          Started                                                                                                                                                                 138.6s
✔ Container symbiotic-sum-node-2          Started
```

<Details summary="Additional commands">
  Check status:

  ```bash [bash]
  docker compose --project-directory temp-network ps
  ```

  View logs:

  ```bash [bash]
  # View all logs
  docker compose --project-directory temp-network logs -f

  # View specific service logs
  docker compose --project-directory temp-network logs -f anvil
  docker compose --project-directory temp-network logs -f anvil-settlement
  docker compose --project-directory temp-network logs -f deployer
  docker compose --project-directory temp-network logs -f genesis-generator
  docker compose --project-directory temp-network logs -f relay-sidecar-1
  docker compose --project-directory temp-network logs -f sum-node-1
  ```

  Stop the network:

  ```bash [bash]
  docker compose --project-directory temp-network down
  ```

  Clean up data:

  ```bash [bash]
  docker compose --project-directory temp-network down -v
  rm -rf temp-network
  ```
</Details>

## Create Task

Submit a sum task to the network.

```bash [bash]
taskID=$(cast send --rpc-url http://127.0.0.1:8545 --json \
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
0x4826533B4897376654Bb4d4AD88B7faFD0C98528 \
"createTask(uint256,uint256)" 33 9 | jq -r '.logs[0].topics[1]')
```

This creates a task for the network, which later collects the required number of attestations and broadcasts the result to every supported destination chain.

## Verify Task Result

It is possible to verify result on the first chain:

```bash [bash]
result=$(cast call --rpc-url http://127.0.0.1:8545 \
0x4826533B4897376654Bb4d4AD88B7faFD0C98528 \
"responses(bytes32)" $taskID)
cast decode-abi --json "data()(uint48,uint256)" $result
```

It is also possible to verify result on the second chain:

```bash [bash]
result=$(cast call --rpc-url http://127.0.0.1:8546 \
0x5FC8d32690cc91D4c39d9d3abcBD16989F875707 \
"responses(bytes32)" $taskID)
cast decode-abi --json "data()(uint48,uint256)" $result
```

This prints the task result with the corresponding timestamp.

```bash [Expected output]
symbiotic-super-sum % result=$(cast call --rpc-url http://127.0.0.1:8545 \
0x4826533B4897376654Bb4d4AD88B7faFD0C98528 \
"responses(bytes32)" $taskID)
cast decode-abi --json "data()(uint48,uint256)" $result
[
    1754052445,
    42
]
```

## Build!

<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: '24px', marginTop: '32px' }}>
  <Card1
    title=""
    description="Get hands-on experience with the Relay SDK - a modular set of on-chain / off-chain components to implement Proof of Stake"
    icon={
      <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor">
          <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
          />
      </svg>
  }
    href="/integrate/networks/"
  />
</div>

::::

# Developers Hub

## Integrate

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Networks"
    description="Use Symbiotic infrastructure to integrate a stake-backed security for your protocol."
    icon={
          <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
              <rect
                  x="8"
                  y="8"
                  width="32"
                  height="32"
                  rx="2"
                  stroke="currentColor"
                  strokeWidth="2"
                  fill="none"
              />
              <rect
                  x="12"
                  y="12"
                  width="24"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="18"
                  width="20"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="24"
                  width="16"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="30"
                  width="18"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
          </svg>
      }
    href="/integrate/networks"
  />

  <Card1
    title="Operators"
    description="Help Networks' products to stay reliable and earn rewards."
    icon={
          <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
              <rect
                  x="8"
                  y="8"
                  width="32"
                  height="32"
                  rx="2"
                  stroke="currentColor"
                  strokeWidth="2"
                  fill="none"
              />
              <rect
                  x="12"
                  y="12"
                  width="24"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="18"
                  width="20"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="24"
                  width="16"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="30"
                  width="18"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
          </svg>
      }
    href="/integrate/curators"
  />

  <Card1
    title="Curators"
    description="Manage Symbiotic depositors' funds and earn fees."
    icon={
          <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
              <rect
                  x="8"
                  y="8"
                  width="32"
                  height="32"
                  rx="2"
                  stroke="currentColor"
                  strokeWidth="2"
                  fill="none"
              />
              <rect
                  x="12"
                  y="12"
                  width="24"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="18"
                  width="20"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="24"
                  width="16"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="30"
                  width="18"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
          </svg>
      }
    href="/integrate/operators"
  />
</div>

## Use Tools

# Addresses

A comprehensive list of Symbiotic official smart contract deployments.

## Core

::::code-group

<div data-title="Mainnet">
  | Contract                                                                                               | Address                                                                                                                                                 | Source Code                                                                                                                                                                                      |
  | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | [VaultFactory](https://etherscan.io/address/0xAEb6bdd95c502390db8f52c8909F703E9Af6a346)                | <AddressWithCopy address="0xAEb6bdd95c502390db8f52c8909F703E9Af6a346" scan="https://etherscan.io/address/0xAEb6bdd95c502390db8f52c8909F703E9Af6a346" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/VaultFactory.sol" label="VaultFactory" />                                 |
  | [DelegatorFactory](https://etherscan.io/address/0x985Ed57AF9D475f1d83c1c1c8826A0E5A34E8C7B)            | <AddressWithCopy address="0x985Ed57AF9D475f1d83c1c1c8826A0E5A34E8C7B" scan="https://etherscan.io/address/0x985Ed57AF9D475f1d83c1c1c8826A0E5A34E8C7B" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/DelegatorFactory.sol" label="DelegatorFactory" />                         |
  | [SlasherFactory](https://etherscan.io/address/0x685c2eD7D59814d2a597409058Ee7a92F21e48Fd)              | <AddressWithCopy address="0x685c2eD7D59814d2a597409058Ee7a92F21e48Fd" scan="https://etherscan.io/address/0x685c2eD7D59814d2a597409058Ee7a92F21e48Fd" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/SlasherFactory.sol" label="SlasherFactory" />                             |
  | [NetworkRegistry](https://etherscan.io/address/0xC773b1011461e7314CF05f97d95aa8e92C1Fd8aA)             | <AddressWithCopy address="0xC773b1011461e7314CF05f97d95aa8e92C1Fd8aA" scan="https://etherscan.io/address/0xC773b1011461e7314CF05f97d95aa8e92C1Fd8aA" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/NetworkRegistry.sol" label="NetworkRegistry" />                           |
  | [NetworkMiddlewareService](https://etherscan.io/address/0xD7dC9B366c027743D90761F71858BCa83C6899Ad)    | <AddressWithCopy address="0xD7dC9B366c027743D90761F71858BCa83C6899Ad" scan="https://etherscan.io/address/0xD7dC9B366c027743D90761F71858BCa83C6899Ad" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/service/NetworkMiddlewareService.sol" label="NetworkMiddlewareService" /> |
  | [OperatorRegistry](https://etherscan.io/address/0xAd817a6Bc954F678451A71363f04150FDD81Af9F)            | <AddressWithCopy address="0xAd817a6Bc954F678451A71363f04150FDD81Af9F" scan="https://etherscan.io/address/0xAd817a6Bc954F678451A71363f04150FDD81Af9F" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/OperatorRegistry.sol" label="OperatorRegistry" />                         |
  | [OperatorVaultOptInService](https://etherscan.io/address/0xb361894bC06cbBA7Ea8098BF0e32EB1906A5F891)   | <AddressWithCopy address="0xb361894bC06cbBA7Ea8098BF0e32EB1906A5F891" scan="https://etherscan.io/address/0xb361894bC06cbBA7Ea8098BF0e32EB1906A5F891" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/service/OptInService.sol" label="OperatorVaultOptInService" />            |
  | [OperatorNetworkOptInService](https://etherscan.io/address/0x7133415b33B438843D581013f98A08704316633c) | <AddressWithCopy address="0x7133415b33B438843D581013f98A08704316633c" scan="https://etherscan.io/address/0x7133415b33B438843D581013f98A08704316633c" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/service/OptInService.sol" label="OperatorNetworkOptInService" />          |
  | [VaultConfigurator](https://etherscan.io/address/0x29300b1d3150B4E2b12fE80BE72f365E200441EC)           | <AddressWithCopy address="0x29300b1d3150B4E2b12fE80BE72f365E200441EC" scan="https://etherscan.io/address/0x29300b1d3150B4E2b12fE80BE72f365E200441EC" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/VaultConfigurator.sol" label="VaultConfigurator" />                       |
</div>

<div data-title="Hoodi">
  | Contract                                                                                                     | Address                                                                                                                                                       | Source Code                                                                                                                                                                                      |
  | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | [VaultFactory](https://hoodi.etherscan.io/address/0x407A039D94948484D356eFB765b3c74382A050B4)                | <AddressWithCopy address="0x407A039D94948484D356eFB765b3c74382A050B4" scan="https://hoodi.etherscan.io/address/0x407A039D94948484D356eFB765b3c74382A050B4" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/VaultFactory.sol" label="VaultFactory" />                                 |
  | [DelegatorFactory](https://hoodi.etherscan.io/address/0x890CA3f95E0f40a79885B7400926544B2214B03f)            | <AddressWithCopy address="0x890CA3f95E0f40a79885B7400926544B2214B03f" scan="https://hoodi.etherscan.io/address/0x890CA3f95E0f40a79885B7400926544B2214B03f" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/DelegatorFactory.sol" label="DelegatorFactory" />                         |
  | [SlasherFactory](https://hoodi.etherscan.io/address/0xbf34bf75bb779c383267736c53a4ae86ac7bB299)              | <AddressWithCopy address="0xbf34bf75bb779c383267736c53a4ae86ac7bB299" scan="https://hoodi.etherscan.io/address/0xbf34bf75bb779c383267736c53a4ae86ac7bB299" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/SlasherFactory.sol" label="SlasherFactory" />                             |
  | [NetworkRegistry](https://hoodi.etherscan.io/address/0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9)             | <AddressWithCopy address="0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9" scan="https://hoodi.etherscan.io/address/0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/NetworkRegistry.sol" label="NetworkRegistry" />                           |
  | [NetworkMiddlewareService](https://hoodi.etherscan.io/address/0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3)    | <AddressWithCopy address="0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3" scan="https://hoodi.etherscan.io/address/0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/service/NetworkMiddlewareService.sol" label="NetworkMiddlewareService" /> |
  | [OperatorRegistry](https://hoodi.etherscan.io/address/0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548)            | <AddressWithCopy address="0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548" scan="https://hoodi.etherscan.io/address/0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/OperatorRegistry.sol" label="OperatorRegistry" />                         |
  | [OperatorVaultOptInService](https://hoodi.etherscan.io/address/0x95CC0a052ae33941877c9619835A233D21D57351)   | <AddressWithCopy address="0x95CC0a052ae33941877c9619835A233D21D57351" scan="https://hoodi.etherscan.io/address/0x95CC0a052ae33941877c9619835A233D21D57351" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/service/OptInService.sol" label="OperatorVaultOptInService" />            |
  | [OperatorNetworkOptInService](https://hoodi.etherscan.io/address/0x58973d16FFA900D11fC22e5e2B6840d9f7e13401) | <AddressWithCopy address="0x58973d16FFA900D11fC22e5e2B6840d9f7e13401" scan="https://hoodi.etherscan.io/address/0x58973d16FFA900D11fC22e5e2B6840d9f7e13401" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/service/OptInService.sol" label="OperatorNetworkOptInService" />          |
  | [VaultConfigurator](https://hoodi.etherscan.io/address/0x94c344E816A53D07fC4c7F4a18f82b6Da87CFc8f)           | <AddressWithCopy address="0x94c344E816A53D07fC4c7F4a18f82b6Da87CFc8f" scan="https://hoodi.etherscan.io/address/0x94c344E816A53D07fC4c7F4a18f82b6Da87CFc8f" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/3b6add23921d89dc364458b94e1c35bfb6736e27/src/contracts/VaultConfigurator.sol" label="VaultConfigurator" />                       |
</div>

<div data-title="Sepolia">
  | Contract                                                                                                       | Address                                                                                                                                                         | Source Code                                                                                                                                                                                      |
  | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | [VaultFactory](https://sepolia.etherscan.io/address/0x407A039D94948484D356eFB765b3c74382A050B4)                | <AddressWithCopy address="0x407A039D94948484D356eFB765b3c74382A050B4" scan="https://sepolia.etherscan.io/address/0x407A039D94948484D356eFB765b3c74382A050B4" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/f38f1b16b8207dcff55d681a0d5ba28c66e785c8/src/contracts/VaultFactory.sol" label="VaultFactory" />                                 |
  | [DelegatorFactory](https://sepolia.etherscan.io/address/0x890CA3f95E0f40a79885B7400926544B2214B03f)            | <AddressWithCopy address="0x890CA3f95E0f40a79885B7400926544B2214B03f" scan="https://sepolia.etherscan.io/address/0x890CA3f95E0f40a79885B7400926544B2214B03f" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/f38f1b16b8207dcff55d681a0d5ba28c66e785c8/src/contracts/DelegatorFactory.sol" label="DelegatorFactory" />                         |
  | [SlasherFactory](https://sepolia.etherscan.io/address/0xbf34bf75bb779c383267736c53a4ae86ac7bB299)              | <AddressWithCopy address="0xbf34bf75bb779c383267736c53a4ae86ac7bB299" scan="https://sepolia.etherscan.io/address/0xbf34bf75bb779c383267736c53a4ae86ac7bB299" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/f38f1b16b8207dcff55d681a0d5ba28c66e785c8/src/contracts/SlasherFactory.sol" label="SlasherFactory" />                             |
  | [NetworkRegistry](https://sepolia.etherscan.io/address/0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9)             | <AddressWithCopy address="0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9" scan="https://sepolia.etherscan.io/address/0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/f38f1b16b8207dcff55d681a0d5ba28c66e785c8/src/contracts/NetworkRegistry.sol" label="NetworkRegistry" />                           |
  | [NetworkMiddlewareService](https://sepolia.etherscan.io/address/0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3)    | <AddressWithCopy address="0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3" scan="https://sepolia.etherscan.io/address/0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/f38f1b16b8207dcff55d681a0d5ba28c66e785c8/src/contracts/service/NetworkMiddlewareService.sol" label="NetworkMiddlewareService" /> |
  | [OperatorRegistry](https://sepolia.etherscan.io/address/0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548)            | <AddressWithCopy address="0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548" scan="https://sepolia.etherscan.io/address/0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/f38f1b16b8207dcff55d681a0d5ba28c66e785c8/src/contracts/OperatorRegistry.sol" label="OperatorRegistry" />                         |
  | [OperatorVaultOptInService](https://sepolia.etherscan.io/address/0x95CC0a052ae33941877c9619835A233D21D57351)   | <AddressWithCopy address="0x95CC0a052ae33941877c9619835A233D21D57351" scan="https://sepolia.etherscan.io/address/0x95CC0a052ae33941877c9619835A233D21D57351" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/f38f1b16b8207dcff55d681a0d5ba28c66e785c8/src/contracts/service/OptInService.sol" label="OperatorVaultOptInService" />            |
  | [OperatorNetworkOptInService](https://sepolia.etherscan.io/address/0x58973d16FFA900D11fC22e5e2B6840d9f7e13401) | <AddressWithCopy address="0x58973d16FFA900D11fC22e5e2B6840d9f7e13401" scan="https://sepolia.etherscan.io/address/0x58973d16FFA900D11fC22e5e2B6840d9f7e13401" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/f38f1b16b8207dcff55d681a0d5ba28c66e785c8/src/contracts/service/OptInService.sol" label="OperatorNetworkOptInService" />          |
  | [VaultConfigurator](https://sepolia.etherscan.io/address/0xD2191FE92987171691d552C219b8caEf186eb9cA)           | <AddressWithCopy address="0xD2191FE92987171691d552C219b8caEf186eb9cA" scan="https://sepolia.etherscan.io/address/0xD2191FE92987171691d552C219b8caEf186eb9cA" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/f38f1b16b8207dcff55d681a0d5ba28c66e785c8/src/contracts/VaultConfigurator.sol" label="VaultConfigurator" />                       |
</div>

::::

## Rewards

::::code-group

<div data-title="Mainnet">
  | Contract                                                                                    | Address                                                                                                                                                 | Source Code                                                                                                                              |
  | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
  | [Curator Registry](https://etherscan.io/address/0xF75D8d8F790178F0d7F2ee7656874567d382C21e) | <AddressWithCopy address="0xF75D8d8F790178F0d7F2ee7656874567d382C21e" scan="https://etherscan.io/address/0xF75D8d8F790178F0d7F2ee7656874567d382C21e" /> | <OpenActionButton path="https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/CuratorRegistry.sol" label="CuratorRegistry" /> |
  | [FeeRegistry](https://etherscan.io/address/0x3E5a669F673712Bf72De956608E89D36561cbAf1)      | <AddressWithCopy address="0x3E5a669F673712Bf72De956608E89D36561cbAf1" scan="https://etherscan.io/address/0x3E5a669F673712Bf72De956608E89D36561cbAf1" /> | <OpenActionButton path="https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/FeeRegistry.sol" label="FeeRegistry" />         |
  | [Rewards](https://etherscan.io/address/0xa13e65cA0FeFa52cCb9615108fF400EF4806866B)          | <AddressWithCopy address="0xa13e65cA0FeFa52cCb9615108fF400EF4806866B" scan="https://etherscan.io/address/0xa13e65cA0FeFa52cCb9615108fF400EF4806866B" /> | <OpenActionButton path="https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/Rewards.sol" label="Rewards" />                 |
</div>

<div data-title="Hoodi">
  | Contract                                                                                          | Address                                                                                                                                                       | Source Code                                                                                                                              |
  | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
  | [Curator Registry](https://hoodi.etherscan.io/address/0x0fbd01C89F4B12475A67204FF4e18E809839B7b4) | <AddressWithCopy address="0x0fbd01C89F4B12475A67204FF4e18E809839B7b4" scan="https://hoodi.etherscan.io/address/0x0fbd01C89F4B12475A67204FF4e18E809839B7b4" /> | <OpenActionButton path="https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/CuratorRegistry.sol" label="CuratorRegistry" /> |
  | [FeeRegistry](https://hoodi.etherscan.io/address/0x4804a29f16E25cE1BcBd802547445012fa7e0051)      | <AddressWithCopy address="0x4804a29f16E25cE1BcBd802547445012fa7e0051" scan="https://hoodi.etherscan.io/address/0x4804a29f16E25cE1BcBd802547445012fa7e0051" /> | <OpenActionButton path="https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/FeeRegistry.sol" label="FeeRegistry" />         |
  | [Rewards](https://hoodi.etherscan.io/address/0x2A49C0B7154919eA2453aA190A014994A5C87D84)          | <AddressWithCopy address="0x2A49C0B7154919eA2453aA190A014994A5C87D84" scan="https://hoodi.etherscan.io/address/0x2A49C0B7154919eA2453aA190A014994A5C87D84" /> | <OpenActionButton path="https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/Rewards.sol" label="Rewards" />                 |
</div>

<div data-title="Sepolia">
  | Contract                                                                                                         | Address                                                                                                                                                         | Source Code                                                                                                                                                                                                                  |
  | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [DefaultStakerRewardsFactory](https://sepolia.etherscan.io/address/0xE6381EDA7444672da17Cd859e442aFFcE7e170F0)   | <AddressWithCopy address="0xE6381EDA7444672da17Cd859e442aFFcE7e170F0" scan="https://sepolia.etherscan.io/address/0xE6381EDA7444672da17Cd859e442aFFcE7e170F0" /> | <OpenActionButton path="https://github.com/symbioticfi/rewards/blob/f4537d9207a05fdb3fee32f8c102506d5f2484c6/src/contracts/defaultStakerRewards/DefaultStakerRewardsFactory.sol" label="DefaultStakerRewardsFactory" />       |
  | [DefaultOperatorRewardsFactory](https://sepolia.etherscan.io/address/0x8D6C873cb7ffa6BE615cE1D55801a9417Ed55f9B) | <AddressWithCopy address="0x8D6C873cb7ffa6BE615cE1D55801a9417Ed55f9B" scan="https://sepolia.etherscan.io/address/0x8D6C873cb7ffa6BE615cE1D55801a9417Ed55f9B" /> | <OpenActionButton path="https://github.com/symbioticfi/rewards/blob/7844a6ceaf4d740c7083a37e410194c1ef7867d3/src/contracts/defaultOperatorRewards/DefaultOperatorRewardsFactory.sol" label="DefaultOperatorRewardsFactory" /> |
</div>

::::

## Burners

::::code-group

<div data-title="Mainnet">
  | Contract                                                                                       | Address                                                                                                                                                 | Source Code                                                                                                                                                                              |
  | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [BurnerRouterFactory](https://etherscan.io/address/0x99F2B89fB3C363fBafD8d826E5AA77b28bAB70a0) | <AddressWithCopy address="0x99F2B89fB3C363fBafD8d826E5AA77b28bAB70a0" scan="https://etherscan.io/address/0x99F2B89fB3C363fBafD8d826E5AA77b28bAB70a0" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/7e887e75beb17e0c2c4df8396ee58dd6e0dd853e/src/contracts/router/BurnerRouterFactory.sol" label="BurnerRouterFactory" /> |
  | [wstETH\_Burner](https://etherscan.io/address/0xdCaC890b14121FD5D925E2589017Be68C2B5B324)       | <AddressWithCopy address="0xdCaC890b14121FD5D925E2589017Be68C2B5B324" scan="https://etherscan.io/address/0xdCaC890b14121FD5D925E2589017Be68C2B5B324" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/7e887e75beb17e0c2c4df8396ee58dd6e0dd853e/src/contracts/burners/wstETH_Burner.sol" label="wstETH_Burner" />            |
  | [rETH\_Burner](https://etherscan.io/address/0x89e3915C9Eb07D1bfF5d78e24B28d409dba9B272)         | <AddressWithCopy address="0x89e3915C9Eb07D1bfF5d78e24B28d409dba9B272" scan="https://etherscan.io/address/0x89e3915C9Eb07D1bfF5d78e24B28d409dba9B272" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/7e887e75beb17e0c2c4df8396ee58dd6e0dd853e/src/contracts/burners/rETH_Burner.sol" label="rETH_Burner" />                |
  | [mETH\_Burner](https://etherscan.io/address/0x919C4329Ed4D4A72c72c126ff8AE351C1E7Ce231)         | <AddressWithCopy address="0x919C4329Ed4D4A72c72c126ff8AE351C1E7Ce231" scan="https://etherscan.io/address/0x919C4329Ed4D4A72c72c126ff8AE351C1E7Ce231" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/7e887e75beb17e0c2c4df8396ee58dd6e0dd853e/src/contracts/burners/mETH_Burner.sol" label="mETH_Burner" />                |
  | [swETH\_Burner](https://etherscan.io/address/0x1Aca33aE8f57E2cdADd0375875AE12fb08c54529)        | <AddressWithCopy address="0x1Aca33aE8f57E2cdADd0375875AE12fb08c54529" scan="https://etherscan.io/address/0x1Aca33aE8f57E2cdADd0375875AE12fb08c54529" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/7e887e75beb17e0c2c4df8396ee58dd6e0dd853e/src/contracts/burners/swETH_Burner.sol" label="swETH_Burner" />              |
  | [sfrxETH\_Burner](https://etherscan.io/address/0xBe5821dB563311750f6295E3CDB40aBbDBfF0c4b)      | <AddressWithCopy address="0xBe5821dB563311750f6295E3CDB40aBbDBfF0c4b" scan="https://etherscan.io/address/0xBe5821dB563311750f6295E3CDB40aBbDBfF0c4b" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/7e887e75beb17e0c2c4df8396ee58dd6e0dd853e/src/contracts/burners/sfrxETH_Burner.sol" label="sfrxETH_Burner" />          |
  | [ETHx\_Burner](https://etherscan.io/address/0xCd669361D629380A70338d613D29c6F3a28A2B50)         | <AddressWithCopy address="0xCd669361D629380A70338d613D29c6F3a28A2B50" scan="https://etherscan.io/address/0xCd669361D629380A70338d613D29c6F3a28A2B50" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/7e887e75beb17e0c2c4df8396ee58dd6e0dd853e/src/contracts/burners/ETHx_Burner.sol" label="ETHx_Burner" />                |
</div>

<div data-title="Hoodi">
  | Contract                                                                                             | Address                                                                                                                                                       | Source Code                                                                                                                                                                              |
  | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [BurnerRouterFactory](https://hoodi.etherscan.io/address/0xF619c99D166224B4AC008b14Cc67ac72C2E91D8a) | <AddressWithCopy address="0xF619c99D166224B4AC008b14Cc67ac72C2E91D8a" scan="https://hoodi.etherscan.io/address/0xF619c99D166224B4AC008b14Cc67ac72C2E91D8a" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/7e887e75beb17e0c2c4df8396ee58dd6e0dd853e/src/contracts/router/BurnerRouterFactory.sol" label="BurnerRouterFactory" /> |
  | [wstETH\_Burner](https://hoodi.etherscan.io/address/0xd80732420fF1C62A21bA11c83377F7a5d69AEF26)       | <AddressWithCopy address="0xd80732420fF1C62A21bA11c83377F7a5d69AEF26" scan="https://hoodi.etherscan.io/address/0xd80732420fF1C62A21bA11c83377F7a5d69AEF26" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/7e887e75beb17e0c2c4df8396ee58dd6e0dd853e/src/contracts/burners/wstETH_Burner.sol" label="wstETH_Burner" />            |
  | [rETH\_Burner](https://hoodi.etherscan.io/address/0xC1F81485E05cc91EC1eBF556455de54F58675278)         | <AddressWithCopy address="0xC1F81485E05cc91EC1eBF556455de54F58675278" scan="https://hoodi.etherscan.io/address/0xC1F81485E05cc91EC1eBF556455de54F58675278" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/7e887e75beb17e0c2c4df8396ee58dd6e0dd853e/src/contracts/burners/rETH_Burner.sol" label="rETH_Burner" />                |
</div>

<div data-title="Sepolia">
  | Contract                                                                                               | Address                                                                                                                                                         | Source Code                                                                                                                                                                              |
  | ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [BurnerRouterFactory](https://sepolia.etherscan.io/address/0x32e2AfbdAffB1e675898ABA75868d92eE1E68f3b) | <AddressWithCopy address="0x32e2AfbdAffB1e675898ABA75868d92eE1E68f3b" scan="https://sepolia.etherscan.io/address/0x32e2AfbdAffB1e675898ABA75868d92eE1E68f3b" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/60a5eb87f196b62d48406b45cc3b19ef4be0e906/src/contracts/router/BurnerRouterFactory.sol" label="BurnerRouterFactory" /> |
  | [wstETH\_Burner](https://sepolia.etherscan.io/address/0x58D347334A5E6bDE7279696abE59a11873294FA4)       | <AddressWithCopy address="0x58D347334A5E6bDE7279696abE59a11873294FA4" scan="https://sepolia.etherscan.io/address/0x58D347334A5E6bDE7279696abE59a11873294FA4" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/60a5eb87f196b62d48406b45cc3b19ef4be0e906/src/contracts/burners/wstETH_Burner.sol" label="wstETH_Burner" />            |
  | [mETH\_Burner](https://sepolia.etherscan.io/address/0xE7845Dd89F8b93924A279e58E448c5a8e7aCE675)         | <AddressWithCopy address="0xE7845Dd89F8b93924A279e58E448c5a8e7aCE675" scan="https://sepolia.etherscan.io/address/0xE7845Dd89F8b93924A279e58E448c5a8e7aCE675" /> | <OpenActionButton path="https://github.com/symbioticfi/burners/blob/60a5eb87f196b62d48406b45cc3b19ef4be0e906/src/contracts/burners/mETH_Burner.sol" label="mETH_Burner" />                |
</div>

::::

## Hooks

::::code-group

<div data-title="Mainnet">
  | Contract                                                                                                  | Address                                                                                                                                                 | Source Code                                                                                                                                                                                                                   |
  | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [FullRestakeDecreaseHook](https://etherscan.io/address/0x0786ef079A0Fc3A2D9e62bf2E8c7aeF86B62d70A)        | <AddressWithCopy address="0x0786ef079A0Fc3A2D9e62bf2E8c7aeF86B62d70A" scan="https://etherscan.io/address/0x0786ef079A0Fc3A2D9e62bf2E8c7aeF86B62d70A" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/fullRestakeDelegator/FullRestakeDecreaseHook.sol" label="FullRestakeDecreaseHook" />                  |
  | [NetworkRestakeDecreaseHook](https://etherscan.io/address/0xe46d876BA2F3C991F3AC3321B8C0A1c323ef8bCf)     | <AddressWithCopy address="0xe46d876BA2F3C991F3AC3321B8C0A1c323ef8bCf" scan="https://etherscan.io/address/0xe46d876BA2F3C991F3AC3321B8C0A1c323ef8bCf" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/networkRestakeDelegator/NetworkRestakeDecreaseHook.sol" label="NetworkRestakeDecreaseHook" />         |
  | [NetworkRestakeRedistributeHook](https://etherscan.io/address/0x8A76a3b791D9cfCD17304D31e04304A54Bf07845) | <AddressWithCopy address="0x8A76a3b791D9cfCD17304D31e04304A54Bf07845" scan="https://etherscan.io/address/0x8A76a3b791D9cfCD17304D31e04304A54Bf07845" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/networkRestakeDelegator/NetworkRestakeRedistributeHook.sol" label="NetworkRestakeRedistributeHook" /> |
  | [OperatorSpecificDecreaseHook](https://etherscan.io/address/0xCc7Fd9B9A37ba1e2b30243Ce5A52BDB1f56B006a)   | <AddressWithCopy address="0xCc7Fd9B9A37ba1e2b30243Ce5A52BDB1f56B006a" scan="https://etherscan.io/address/0xCc7Fd9B9A37ba1e2b30243Ce5A52BDB1f56B006a" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/operatorSpecificDelegator/OperatorSpecificDecreaseHook.sol" label="OperatorSpecificDecreaseHook" />   |
</div>

<div data-title="Hoodi">
  | Contract                                                                                                        | Address                                                                                                                                                       | Source Code                                                                                                                                                                                                                   |
  | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [FullRestakeDecreaseHook](https://hoodi.etherscan.io/address/0x3224d9DF887ABdC10c1bCcECfd9EFC29A638a3E3)        | <AddressWithCopy address="0x3224d9DF887ABdC10c1bCcECfd9EFC29A638a3E3" scan="https://hoodi.etherscan.io/address/0x3224d9DF887ABdC10c1bCcECfd9EFC29A638a3E3" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/fullRestakeDelegator/FullRestakeDecreaseHook.sol" label="FullRestakeDecreaseHook" />                  |
  | [NetworkRestakeDecreaseHook](https://hoodi.etherscan.io/address/0x2C78B3A5de76161aee8e37d0E3b0E0EBb12BacCc)     | <AddressWithCopy address="0x2C78B3A5de76161aee8e37d0E3b0E0EBb12BacCc" scan="https://hoodi.etherscan.io/address/0x2C78B3A5de76161aee8e37d0E3b0E0EBb12BacCc" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/networkRestakeDelegator/NetworkRestakeDecreaseHook.sol" label="NetworkRestakeDecreaseHook" />         |
  | [NetworkRestakeRedistributeHook](https://hoodi.etherscan.io/address/0x45B188aBE45820aE130A2844649Faeb225096596) | <AddressWithCopy address="0x45B188aBE45820aE130A2844649Faeb225096596" scan="https://hoodi.etherscan.io/address/0x45B188aBE45820aE130A2844649Faeb225096596" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/networkRestakeDelegator/NetworkRestakeRedistributeHook.sol" label="NetworkRestakeRedistributeHook" /> |
  | [OperatorSpecificDecreaseHook](https://hoodi.etherscan.io/address/0xF8ee812cc1E7C8eE94395E510098b36ff458E77d)   | <AddressWithCopy address="0xF8ee812cc1E7C8eE94395E510098b36ff458E77d" scan="https://hoodi.etherscan.io/address/0xF8ee812cc1E7C8eE94395E510098b36ff458E77d" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/operatorSpecificDelegator/OperatorSpecificDecreaseHook.sol" label="OperatorSpecificDecreaseHook" />   |
</div>

<div data-title="Sepolia">
  | Contract                                                                                                          | Address                                                                                                                                                         | Source Code                                                                                                                                                                                                                   |
  | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [FullRestakeDecreaseHook](https://sepolia.etherscan.io/address/0x088c40869954806Cd1580eda3C2d866104d0b118)        | <AddressWithCopy address="0x088c40869954806Cd1580eda3C2d866104d0b118" scan="https://sepolia.etherscan.io/address/0x088c40869954806Cd1580eda3C2d866104d0b118" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/fullRestakeDelegator/FullRestakeDecreaseHook.sol" label="FullRestakeDecreaseHook" />                  |
  | [NetworkRestakeDecreaseHook](https://sepolia.etherscan.io/address/0x4EeA7269BC42feA87B4E92F4E4f7bCAF3dC81875)     | <AddressWithCopy address="0x4EeA7269BC42feA87B4E92F4E4f7bCAF3dC81875" scan="https://sepolia.etherscan.io/address/0x4EeA7269BC42feA87B4E92F4E4f7bCAF3dC81875" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/networkRestakeDelegator/NetworkRestakeDecreaseHook.sol" label="NetworkRestakeDecreaseHook" />         |
  | [NetworkRestakeRedistributeHook](https://sepolia.etherscan.io/address/0x5425D1604a4e01C34996cb662d831E0dEF66C210) | <AddressWithCopy address="0x5425D1604a4e01C34996cb662d831E0dEF66C210" scan="https://sepolia.etherscan.io/address/0x5425D1604a4e01C34996cb662d831E0dEF66C210" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/networkRestakeDelegator/NetworkRestakeRedistributeHook.sol" label="NetworkRestakeRedistributeHook" /> |
  | [OperatorSpecificDecreaseHook](https://sepolia.etherscan.io/address/0xeae1fCEe58Bd5c3EE9185b34E9f4481faB8FA939)   | <AddressWithCopy address="0xeae1fCEe58Bd5c3EE9185b34E9f4481faB8FA939" scan="https://sepolia.etherscan.io/address/0xeae1fCEe58Bd5c3EE9185b34E9f4481faB8FA939" /> | <OpenActionButton path="https://github.com/symbioticfi/hooks/blob/71ea3cea348fc4407766181f2183fee137442c63/src/contracts/operatorSpecificDelegator/OperatorSpecificDecreaseHook.sol" label="OperatorSpecificDecreaseHook" />   |
</div>

::::

## Periphery

::::code-group

<div data-title="Mainnet">
  | Contract                                                                                             | Address                                                                                                                                                 | Source Code                                                                                                                                                                                     |
  | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [DefaultCollateralMigrator](https://etherscan.io/address/0x8F152FEAA99eb6656F902E94BD4E7bCf563D4A43) | <AddressWithCopy address="0x8F152FEAA99eb6656F902E94BD4E7bCf563D4A43" scan="https://etherscan.io/address/0x8F152FEAA99eb6656F902E94BD4E7bCf563D4A43" /> | <OpenActionButton path="https://github.com/symbioticfi/periphery/blob/9cc6d3b6947dddadb66b2a9f8d8981c618be65e8/src/contracts/DefaultCollateralMigrator.sol" label="DefaultCollateralMigrator" /> |
</div>

<div data-title="Sepolia">
  | Contract                                                                                                     | Address                                                                                                                                                         | Source Code                                                                                                                                                                                     |
  | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [DefaultCollateralMigrator](https://sepolia.etherscan.io/address/0xD6BE794b3761fd2bA23fB054F1Fe1606Ae35de4e) | <AddressWithCopy address="0xD6BE794b3761fd2bA23fB054F1Fe1606Ae35de4e" scan="https://sepolia.etherscan.io/address/0xD6BE794b3761fd2bA23fB054F1Fe1606Ae35de4e" /> | <OpenActionButton path="https://github.com/symbioticfi/periphery/blob/30ba028f683cfaa83c4a1338a44064702c531387/src/contracts/DefaultCollateralMigrator.sol" label="DefaultCollateralMigrator" /> |
</div>

::::

## Hints

::::code-group

<div data-title="Mainnet">
  :::warning
  The hints provision contracts weren't audited and should be used only for gas costs **optimisation** purposes.
  :::

  | Contract                                                                                      | Address                                                                                                                                                 | Source Code                                                                                                                                                                      |
  | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [OptInServiceHints](https://etherscan.io/address/0xe58ED8D0788BD93d665552409Dc60d43c9E6A29f)  | <AddressWithCopy address="0xe58ED8D0788BD93d665552409Dc60d43c9E6A29f" scan="https://etherscan.io/address/0xe58ED8D0788BD93d665552409Dc60d43c9E6A29f" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/OptInServiceHints.sol" label="OptInServiceHints" /> |
  | [VaultHints](https://etherscan.io/address/0xeaDDC9F93a7d7B845084a30Da09400f0170fC9BC)         | <AddressWithCopy address="0xeaDDC9F93a7d7B845084a30Da09400f0170fC9BC" scan="https://etherscan.io/address/0xeaDDC9F93a7d7B845084a30Da09400f0170fC9BC" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/VaultHints.sol" label="VaultHints" />               |
  | [BaseDelegatorHints](https://etherscan.io/address/0xa298E96FE9bD30cA6801d35Ba28f6d1C004123c7) | <AddressWithCopy address="0xa298E96FE9bD30cA6801d35Ba28f6d1C004123c7" scan="https://etherscan.io/address/0xa298E96FE9bD30cA6801d35Ba28f6d1C004123c7" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/DelegatorHints.sol" label="BaseDelegatorHints" />   |
  | [SlasherHints](https://etherscan.io/address/0x234148646D8C1762C793FD04385AfAD94998a4C7)       | <AddressWithCopy address="0x234148646D8C1762C793FD04385AfAD94998a4C7" scan="https://etherscan.io/address/0x234148646D8C1762C793FD04385AfAD94998a4C7" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/SlasherHints.sol" label="SlasherHints" />           |
  | [VetoSlasherHints](https://etherscan.io/address/0x653815A6E2Accd3AE3eDC41d48Bec9192D5B8651)   | <AddressWithCopy address="0x653815A6E2Accd3AE3eDC41d48Bec9192D5B8651" scan="https://etherscan.io/address/0x653815A6E2Accd3AE3eDC41d48Bec9192D5B8651" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/SlasherHints.sol" label="VetoSlasherHints" />       |
</div>

<div data-title="Hoodi">
  :::warning
  The hints provision contracts weren't audited and should be used only for gas costs **optimisation** purposes.
  :::

  | Contract                                                                                            | Address                                                                                                                                                       | Source Code                                                                                                                                                                        |
  | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [OptInServiceHints](https://hoodi.etherscan.io/address/0x5a573b5Ecb9a1B988b0488B1B5A4B4B200536E39)  | <AddressWithCopy address="0x5a573b5Ecb9a1B988b0488B1B5A4B4B200536E39" scan="https://hoodi.etherscan.io/address/0x5a573b5Ecb9a1B988b0488B1B5A4B4B200536E39" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/OptInServiceHints.sol" label="OptInServiceHints" />   |
  | [VaultHints](https://hoodi.etherscan.io/address/0x43C29B90e651860EB2963D54a40C371C75630c39)         | <AddressWithCopy address="0x43C29B90e651860EB2963D54a40C371C75630c39" scan="https://hoodi.etherscan.io/address/0x43C29B90e651860EB2963D54a40C371C75630c39" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/VaultHints.sol" label="VaultHints" />                 |
  | [BaseDelegatorHints](https://hoodi.etherscan.io/address/0x88c5519016FC6F5F8dC53eb299fce691b8174C34) | <AddressWithCopy address="0x88c5519016FC6F5F8dC53eb299fce691b8174C34" scan="https://hoodi.etherscan.io/address/0x88c5519016FC6F5F8dC53eb299fce691b8174C34" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/BaseDelegatorHints.sol" label="BaseDelegatorHints" /> |
  | [SlasherHints](https://hoodi.etherscan.io/address/0x9C3F0Beb3A1Dfae975cE42571b7EE57dd3179351)       | <AddressWithCopy address="0x9C3F0Beb3A1Dfae975cE42571b7EE57dd3179351" scan="https://hoodi.etherscan.io/address/0x9C3F0Beb3A1Dfae975cE42571b7EE57dd3179351" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/SlasherHints.sol" label="SlasherHints" />             |
  | [VetoSlasherHints](https://hoodi.etherscan.io/address/0x2012926262F5104DD2DADA544cB0DeE438a734F1)   | <AddressWithCopy address="0x2012926262F5104DD2DADA544cB0DeE438a734F1" scan="https://hoodi.etherscan.io/address/0x2012926262F5104DD2DADA544cB0DeE438a734F1" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/VetoSlasherHints.sol" label="VetoSlasherHints" />     |
</div>

<div data-title="Sepolia">
  :::warning
  The hints provision contracts weren't audited and should be used only for gas costs **optimisation** purposes.
  :::

  | Contract                                                                                              | Address                                                                                                                                                         | Source Code                                                                                                                                                                        |
  | ----------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [OptInServiceHints](https://sepolia.etherscan.io/address/0x22C505eFf313CDd959e9D2240b6238F25ad8831b)  | <AddressWithCopy address="0x22C505eFf313CDd959e9D2240b6238F25ad8831b" scan="https://sepolia.etherscan.io/address/0x22C505eFf313CDd959e9D2240b6238F25ad8831b" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/OptInServiceHints.sol" label="OptInServiceHints" />   |
  | [VaultHints](https://sepolia.etherscan.io/address/0x6e86527667e576FCf3425617C92E4c913375Ce97)         | <AddressWithCopy address="0x6e86527667e576FCf3425617C92E4c913375Ce97" scan="https://sepolia.etherscan.io/address/0x6e86527667e576FCf3425617C92E4c913375Ce97" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/VaultHints.sol" label="VaultHints" />                 |
  | [BaseDelegatorHints](https://sepolia.etherscan.io/address/0xA9500049fCfbE767Dcc5E7A4a6bb6e2E0c523e2A) | <AddressWithCopy address="0xA9500049fCfbE767Dcc5E7A4a6bb6e2E0c523e2A" scan="https://sepolia.etherscan.io/address/0xA9500049fCfbE767Dcc5E7A4a6bb6e2E0c523e2A" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/BaseDelegatorHints.sol" label="BaseDelegatorHints" /> |
  | [SlasherHints](https://sepolia.etherscan.io/address/0xfd530c42e3e5507bB6fA81881817121e6256A32A)       | <AddressWithCopy address="0xfd530c42e3e5507bB6fA81881817121e6256A32A" scan="https://sepolia.etherscan.io/address/0xfd530c42e3e5507bB6fA81881817121e6256A32A" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/SlasherHints.sol" label="SlasherHints" />             |
  | [VetoSlasherHints](https://sepolia.etherscan.io/address/0xAb888A61684C20B96aDCD3F36B458574eb69f6a2)   | <AddressWithCopy address="0xAb888A61684C20B96aDCD3F36B458574eb69f6a2" scan="https://sepolia.etherscan.io/address/0xAb888A61684C20B96aDCD3F36B458574eb69f6a2" /> | <OpenActionButton path="https://github.com/symbioticfi/core/blob/9c48ef17b8b973383667517a7db7131e44a811b8/src/contracts/hints/VetoSlasherHints.sol" label="VetoSlasherHints" />     |
</div>

::::

## Legacy

### Vaults

::::code-group

<div data-title="Mainnet">
  | Contract                                                                                              | Address                                                                                                                                                 | Source Code                                                                                                               |
  | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
  | [DefaultCollateralFactory](https://etherscan.io/address/0x1BC8FCFbE6Aa17e4A7610F51B888f34583D202Ec)   | <AddressWithCopy address="0x1BC8FCFbE6Aa17e4A7610F51B888f34583D202Ec" scan="https://etherscan.io/address/0x1BC8FCFbE6Aa17e4A7610F51B888f34583D202Ec" /> | <OpenActionButton path="https://etherscan.io/address/0x1BC8FCFbE6Aa17e4A7610F51B888f34583D202Ec#code" label="Etherscan" /> |
  | [DefaultCollateral: wstETH](https://etherscan.io/address/0xC329400492c6ff2438472D4651Ad17389fCb843a)  | <AddressWithCopy address="0xC329400492c6ff2438472D4651Ad17389fCb843a" scan="https://etherscan.io/address/0xC329400492c6ff2438472D4651Ad17389fCb843a" /> | <OpenActionButton path="https://etherscan.io/address/0xC329400492c6ff2438472D4651Ad17389fCb843a#code" label="Etherscan" /> |
  | [DefaultCollateral: cbETH](https://etherscan.io/address/0xB26ff591F44b04E78de18f43B46f8b70C6676984)   | <AddressWithCopy address="0xB26ff591F44b04E78de18f43B46f8b70C6676984" scan="https://etherscan.io/address/0xB26ff591F44b04E78de18f43B46f8b70C6676984" /> | <OpenActionButton path="https://etherscan.io/address/0xB26ff591F44b04E78de18f43B46f8b70C6676984#code" label="Etherscan" /> |
  | [DefaultCollateral: wBETH](https://etherscan.io/address/0x422F5acCC812C396600010f224b320a743695f85)   | <AddressWithCopy address="0x422F5acCC812C396600010f224b320a743695f85" scan="https://etherscan.io/address/0x422F5acCC812C396600010f224b320a743695f85" /> | <OpenActionButton path="https://etherscan.io/address/0x422F5acCC812C396600010f224b320a743695f85#code" label="Etherscan" /> |
  | [DefaultCollateral: rETH](https://etherscan.io/address/0x03Bf48b8A1B37FBeAd1EcAbcF15B98B924ffA5AC)    | <AddressWithCopy address="0x03Bf48b8A1B37FBeAd1EcAbcF15B98B924ffA5AC" scan="https://etherscan.io/address/0x03Bf48b8A1B37FBeAd1EcAbcF15B98B924ffA5AC" /> | <OpenActionButton path="https://etherscan.io/address/0x03Bf48b8A1B37FBeAd1EcAbcF15B98B924ffA5AC#code" label="Etherscan" /> |
  | [DefaultCollateral: mETH](https://etherscan.io/address/0x475D3Eb031d250070B63Fa145F0fCFC5D97c304a)    | <AddressWithCopy address="0x475D3Eb031d250070B63Fa145F0fCFC5D97c304a" scan="https://etherscan.io/address/0x475D3Eb031d250070B63Fa145F0fCFC5D97c304a" /> | <OpenActionButton path="https://etherscan.io/address/0x475D3Eb031d250070B63Fa145F0fCFC5D97c304a#code" label="Etherscan" /> |
  | [DefaultCollateral: swETH](https://etherscan.io/address/0x38B86004842D3FA4596f0b7A0b53DE90745Ab654)   | <AddressWithCopy address="0x38B86004842D3FA4596f0b7A0b53DE90745Ab654" scan="https://etherscan.io/address/0x38B86004842D3FA4596f0b7A0b53DE90745Ab654" /> | <OpenActionButton path="https://etherscan.io/address/0x38B86004842D3FA4596f0b7A0b53DE90745Ab654#code" label="Etherscan" /> |
  | [DefaultCollateral: sfrxETH](https://etherscan.io/address/0x5198CB44D7B2E993ebDDa9cAd3b9a0eAa32769D2) | <AddressWithCopy address="0x5198CB44D7B2E993ebDDa9cAd3b9a0eAa32769D2" scan="https://etherscan.io/address/0x5198CB44D7B2E993ebDDa9cAd3b9a0eAa32769D2" /> | <OpenActionButton path="https://etherscan.io/address/0x5198CB44D7B2E993ebDDa9cAd3b9a0eAa32769D2#code" label="Etherscan" /> |
  | [DefaultCollateral: ETHx](https://etherscan.io/address/0xBdea8e677F9f7C294A4556005c640Ee505bE6925)    | <AddressWithCopy address="0xBdea8e677F9f7C294A4556005c640Ee505bE6925" scan="https://etherscan.io/address/0xBdea8e677F9f7C294A4556005c640Ee505bE6925" /> | <OpenActionButton path="https://etherscan.io/address/0xBdea8e677F9f7C294A4556005c640Ee505bE6925#code" label="Etherscan" /> |
  | [DefaultCollateral: ENA](https://etherscan.io/address/0xe39B5f5638a209c1A6b6cDFfE5d37F7Ac99fCC84)     | <AddressWithCopy address="0xe39B5f5638a209c1A6b6cDFfE5d37F7Ac99fCC84" scan="https://etherscan.io/address/0xe39B5f5638a209c1A6b6cDFfE5d37F7Ac99fCC84" /> | <OpenActionButton path="https://etherscan.io/address/0xe39B5f5638a209c1A6b6cDFfE5d37F7Ac99fCC84#code" label="Etherscan" /> |
  | [DefaultCollateral: sUSDe](https://etherscan.io/address/0x19d0D8e6294B7a04a2733FE433444704B791939A)   | <AddressWithCopy address="0x19d0D8e6294B7a04a2733FE433444704B791939A" scan="https://etherscan.io/address/0x19d0D8e6294B7a04a2733FE433444704B791939A" /> | <OpenActionButton path="https://etherscan.io/address/0x19d0D8e6294B7a04a2733FE433444704B791939A#code" label="Etherscan" /> |
  | [DefaultCollateral: WBTC](https://etherscan.io/address/0x971e5b5D4baa5607863f3748FeBf287C7bf82618)    | <AddressWithCopy address="0x971e5b5D4baa5607863f3748FeBf287C7bf82618" scan="https://etherscan.io/address/0x971e5b5D4baa5607863f3748FeBf287C7bf82618" /> | <OpenActionButton path="https://etherscan.io/address/0x971e5b5D4baa5607863f3748FeBf287C7bf82618#code" label="Etherscan" /> |
  | [DefaultCollateral: tBTC](https://etherscan.io/address/0x0C969ceC0729487d264716e55F232B404299032c)    | <AddressWithCopy address="0x0C969ceC0729487d264716e55F232B404299032c" scan="https://etherscan.io/address/0x0C969ceC0729487d264716e55F232B404299032c" /> | <OpenActionButton path="https://etherscan.io/address/0x0C969ceC0729487d264716e55F232B404299032c#code" label="Etherscan" /> |
  | [DefaultCollateral: LsETH](https://etherscan.io/address/0xB09A50AcFFF7D12B7d18adeF3D1027bC149Bad1c)   | <AddressWithCopy address="0xB09A50AcFFF7D12B7d18adeF3D1027bC149Bad1c" scan="https://etherscan.io/address/0xB09A50AcFFF7D12B7d18adeF3D1027bC149Bad1c" /> | <OpenActionButton path="https://etherscan.io/address/0xB09A50AcFFF7D12B7d18adeF3D1027bC149Bad1c#code" label="Etherscan" /> |
  | [DefaultCollateral: osETH](https://etherscan.io/address/0x52cB8A621610Cc3cCf498A1981A8ae7AD6B8AB2a)   | <AddressWithCopy address="0x52cB8A621610Cc3cCf498A1981A8ae7AD6B8AB2a" scan="https://etherscan.io/address/0x52cB8A621610Cc3cCf498A1981A8ae7AD6B8AB2a" /> | <OpenActionButton path="https://etherscan.io/address/0x52cB8A621610Cc3cCf498A1981A8ae7AD6B8AB2a#code" label="Etherscan" /> |
  | [DefaultCollateral: ETHFI](https://etherscan.io/address/0x21DbBA985eEA6ba7F27534a72CCB292eBA1D2c7c)   | <AddressWithCopy address="0x21DbBA985eEA6ba7F27534a72CCB292eBA1D2c7c" scan="https://etherscan.io/address/0x21DbBA985eEA6ba7F27534a72CCB292eBA1D2c7c" /> | <OpenActionButton path="https://etherscan.io/address/0x21DbBA985eEA6ba7F27534a72CCB292eBA1D2c7c#code" label="Etherscan" /> |
  | [DefaultCollateral: FXS](https://etherscan.io/address/0x940750A267c64f3BBcE31B948b67CD168f0843fA)     | <AddressWithCopy address="0x940750A267c64f3BBcE31B948b67CD168f0843fA" scan="https://etherscan.io/address/0x940750A267c64f3BBcE31B948b67CD168f0843fA" /> | <OpenActionButton path="https://etherscan.io/address/0x940750A267c64f3BBcE31B948b67CD168f0843fA#code" label="Etherscan" /> |
  | [DefaultCollateral: LBTC](https://etherscan.io/address/0x9C0823D3A1172F9DdF672d438dec79c39a64f448)    | <AddressWithCopy address="0x9C0823D3A1172F9DdF672d438dec79c39a64f448" scan="https://etherscan.io/address/0x9C0823D3A1172F9DdF672d438dec79c39a64f448" /> | <OpenActionButton path="https://etherscan.io/address/0x9C0823D3A1172F9DdF672d438dec79c39a64f448#code" label="Etherscan" /> |
  | [DefaultCollateral: SWELL](https://etherscan.io/address/0x544f45485418341C1a2B3a44404F12302277fFFC)   | <AddressWithCopy address="0x544f45485418341C1a2B3a44404F12302277fFFC" scan="https://etherscan.io/address/0x544f45485418341C1a2B3a44404F12302277fFFC" /> | <OpenActionButton path="https://etherscan.io/address/0x544f45485418341C1a2B3a44404F12302277fFFC#code" label="Etherscan" /> |
  | [DefaultCollateral: MANTA](https://etherscan.io/address/0x594380c06552A4136E2601F89E50b3b9Ad17bd4d)   | <AddressWithCopy address="0x594380c06552A4136E2601F89E50b3b9Ad17bd4d" scan="https://etherscan.io/address/0x594380c06552A4136E2601F89E50b3b9Ad17bd4d" /> | <OpenActionButton path="https://etherscan.io/address/0x594380c06552A4136E2601F89E50b3b9Ad17bd4d#code" label="Etherscan" /> |
</div>

<div data-title="">
  <div />
</div>

::::

### Rewards

::::code-group

<div data-title="Mainnet">
  | Contract                                                                                               | Address                                                                                                                                                 | Source Code                                                                                                                                                                                                            |
  | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [DefaultStakerRewardsFactory](https://etherscan.io/address/0x290CAB97a312164Ccf095d75D6175dF1C4A0a25F) | <AddressWithCopy address="0x290CAB97a312164Ccf095d75D6175dF1C4A0a25F" scan="https://etherscan.io/address/0x290CAB97a312164Ccf095d75D6175dF1C4A0a25F" /> | <OpenActionButton path="https://github.com/symbioticfi/rewards/blob/6cca0f6564bb2a9fbc61a546ddb54b0caf6fa788/src/contracts/defaultStakerRewards/DefaultStakerRewardsFactory.sol" label="DefaultStakerRewardsFactory" /> |
</div>

<div data-title="Sepolia">
  | Contract                                                                                                       | Address                                                                                                                                                         | Source Code                                                                                                                                                                                                            |
  | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | [DefaultStakerRewardsFactory](https://sepolia.etherscan.io/address/0x70C618a13D1A57f7234c0b893b9e28C5cA8E7f37) | <AddressWithCopy address="0x70C618a13D1A57f7234c0b893b9e28C5cA8E7f37" scan="https://sepolia.etherscan.io/address/0x70C618a13D1A57f7234c0b893b9e28C5cA8E7f37" /> | <OpenActionButton path="https://github.com/symbioticfi/rewards/blob/7844a6ceaf4d740c7083a37e410194c1ef7867d3/src/contracts/defaultStakerRewards/DefaultStakerRewardsFactory.sol" label="DefaultStakerRewardsFactory" /> |
</div>

::::

# Bug Bounty

Bug bounty program: [Cantina - $500,000](https://cantina.xyz/bounties/acca29a4-d405-4405-a3b3-8c3feb10d1e3) (Core & Rewards)

## Audits - Security Reviews

| Auditor                                           | Scope                                                                         | Date              | Report                                                                                                                                                                                   |
| ------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <Entity id="ackee" />                             | [Rewards V2](https://github.com/symbioticfi/rewards-v2)                       | 01-2026           | <ReportActions path="https://github.com/symbioticfi/rewards-v2/blob/main/audits/Ackee-RewardsV2.pdf" label="Ackee Rewards V2 report" />                                                  |
| <Entity id="bailsec" />                           | [Rewards V2](https://github.com/symbioticfi/rewards-v2)                       | 11-2025           | <ReportActions path="https://github.com/symbioticfi/rewards-v2/blob/main/audits/Bailsec-RewardsV2.pdf" label="Bailsec Rewards V2 report" />                                              |
| <Entity id="cyfrin" />                            | [Relay Contracts (BLS12-381)](https://github.com/symbioticfi/relay-contracts) | 12-2025           | <ReportActions path="https://github.com/symbioticfi/relay-contracts/blob/main/audits/Cyfrin-RelayContracts-BLS12381.pdf" label="Cyfrin Relay Contracts (BLS12-381) report" />            |
| <Entity id="sigmaPrime" />                        | [Relay Contracts](https://github.com/symbioticfi/relay-contracts)             | 09-2025           | <ReportActions path="https://github.com/symbioticfi/relay-contracts/blob/main/audits/SigmaPrime-RelayContracts%26Network.pdf" label="Sigma Prime Relay Contracts & Network report" />    |
| <Entity id="cyfrin" />                            | [Relay Contracts](https://github.com/symbioticfi/relay-contracts)             | 09-2025           | <ReportActions path="https://github.com/symbioticfi/relay-contracts/blob/main/audits/Cyfrin-RelayContracts%26Network.pdf" label="Cyfrin Relay Contracts & Network report" />             |
| <Entity id="sherlock" label="Sherlock Contest" /> | [Relay Contracts](https://github.com/symbioticfi/relay-contracts)             | 07-2025           | <ReportActions path="https://github.com/symbioticfi/relay-contracts/blob/main/audits/Sherlock-RelayContracts%26Network.pdf" label="Sherlock Relay Contracts & Network contest report" /> |
| <Entity id="bailsec" />                           | [Relay Contracts](https://github.com/symbioticfi/relay-contracts)             | 05-2025           | <ReportActions path="https://github.com/symbioticfi/relay-contracts/blob/main/audits/Bailsec-RelayContracts.pdf" label="Bailsec Relay Contracts review" />                               |
| <Entity id="statemind" label="Statemind AI" />    | [Relay Contracts](https://github.com/symbioticfi/relay-contracts)             | 05-2025           | <ReportActions path="https://github.com/symbioticfi/relay-contracts/blob/main/audits/StatemindAI-RelayContracts.pdf" label="Statemind AI Relay Contracts review" />                      |
| <Entity id="sigmaPrime" />                        | [Network](https://github.com/symbioticfi/network)                             | 09-2025           | <ReportActions path="https://github.com/symbioticfi/network/blob/main/audits/SigmaPrime-RelayContracts%26Network.pdf" label="Sigma Prime Network report" />                              |
| <Entity id="cyfrin" />                            | [Network](https://github.com/symbioticfi/network)                             | 09-2025           | <ReportActions path="https://github.com/symbioticfi/network/blob/main/audits/Cyfrin-RelayContracts%26Network.pdf" label="Cyfrin Network report" />                                       |
| <Entity id="sherlock" label="Sherlock Contest" /> | [Network](https://github.com/symbioticfi/network)                             | 07-2025           | <ReportActions path="https://github.com/symbioticfi/network/blob/main/audits/Sherlock-RelayContracts%26Network.pdf" label="Sherlock Network contest report" />                           |
| <Entity id="cantina" label="Cantina Contest" />   | [Core](https://github.com/symbioticfi/core)                                   | 09-2024           | <ReportActions path="https://github.com/symbioticfi/core/blob/main/audits/Cantina-Core.pdf" label="Cantina Core contest report" />                                                       |
| <Entity id="certora" />                           | [Core](https://github.com/symbioticfi/core)                                   | 09-2024           | <ReportActions path="https://github.com/symbioticfi/core/blob/main/audits/Certora-Core.pdf" label="Certora Core audit report" />                                                         |
| <Entity id="ottersec" />                          | [Core](https://github.com/symbioticfi/core)                                   | 09-2024           | <ReportActions path="https://github.com/symbioticfi/core/blob/main/audits/OtterSec-Core%26Rewards.pdf" label="OtterSec Core & Rewards report" />                                         |
| <Entity id="chainsecurity" />                     | [Core](https://github.com/symbioticfi/core)                                   | 08-2024           | <ReportActions path="https://github.com/symbioticfi/core/blob/main/audits/ChainSecurity-Core.pdf" label="ChainSecurity Core audit report" />                                             |
| <Entity id="zellic" />                            | [Core](https://github.com/symbioticfi/core)                                   | 07-2024           | <ReportActions path="https://github.com/symbioticfi/core/blob/main/audits/Zellic-Core.pdf" label="Zellic Core audit report" />                                                           |
| <Entity id="statemind" />                         | [Core](https://github.com/symbioticfi/core)                                   | 06-2024 - 12-2024 | <ReportActions path="https://github.com/symbioticfi/core/blob/main/audits/Statemind-Core%26Rewards.pdf" label="Statemind Core & Rewards audit report" />                                 |
| <Entity id="ottersec" />                          | [Rewards V1](https://github.com/symbioticfi/rewards)                          | 09-2024           | <ReportActions path="https://github.com/symbioticfi/rewards/blob/main/audits/OtterSec-Core%26Rewards.pdf" label="OtterSec Rewards V1 audit report" />                                    |
| <Entity id="chainsecurity" />                     | [Rewards V1](https://github.com/symbioticfi/rewards)                          | 08-2024           | <ReportActions path="https://github.com/symbioticfi/rewards/blob/main/audits/ChainSecurity-Rewards.pdf" label="ChainSecurity Rewards V1 audit report" />                                 |
| <Entity id="statemind" />                         | [Rewards V1](https://github.com/symbioticfi/rewards)                          | 06-2024 - 12-2024 | <ReportActions path="https://github.com/symbioticfi/rewards/blob/main/audits/Statemind-Core%26Rewards.pdf" label="Statemind Rewards V1 audit report" />                                  |
| <Entity id="chainsecurity" />                     | [Burners](https://github.com/symbioticfi/burners)                             | 08-2024           | <ReportActions path="https://github.com/symbioticfi/burners/blob/main/audits/ChainSecurity-Burners.pdf" label="ChainSecurity Burners audit report" />                                    |
| <Entity id="statemind" />                         | [Hooks](https://github.com/symbioticfi/hooks)                                 | 08-2024           | <ReportActions path="https://github.com/symbioticfi/hooks/blob/main/audits/Statemind-Hooks.pdf" label="Statemind Hooks audit report" />                                                  |
| <Entity id="chainsecurity" />                     | [Periphery](https://github.com/symbioticfi/periphery)                         | 08-2024           | <ReportActions path="https://github.com/symbioticfi/periphery/blob/main/audits/ChainSecurity-Periphery.pdf" label="ChainSecurity Periphery audit report" />                              |
| <Entity id="chainsecurity" />                     | [Legacy Vaults](https://github.com/symbioticfi/collateral)                    | 05-2024           | <ReportActions path="https://github.com/symbioticfi/collateral/blob/main/audits/ChainSecurity_DefaultCollateral.pdf" label="ChainSecurity Legacy Vaults audit report" />                 |
| <Entity id="statemind" />                         | [Legacy Vaults](https://github.com/symbioticfi/collateral)                    | 04-2024           | <ReportActions path="https://github.com/symbioticfi/collateral/blob/main/audits/Statemind_DefaultCollateral.pdf" label="Statemind Legacy Vaults audit report" />                         |

# Risks

The following document contains a list of notes how to make the overall operation process safer for everyone.

## For Networks

* **Collateral value:** choose collateral with real economic value (e.g., ETH) and alignment to your protocol; otherwise profit from attacking you can exceed the cost or griefing becomes cheap.

* **Vault diversification:** use a diversified set of Vaults; otherwise a single Vault failure can rapidly cut stake.
  * Ensure third-party **Vaults’ Curators** are trustworthy for the diversification you target.

* **Veto/epoch spacing:** avoid `VetoSlasher` veto duration that is too close to the vault epoch duration.
  * Example safe config: Vault Epoch 7d, Network Epoch 3d, Veto Duration 1d (leaves 2d to execute).

* **Epoch duration vs capture windows:** set Vault Epoch noticeably greater than `validatorSetCaptureDelay` + Network Epoch duration + Network slashing window.
  * Example: Vault Epoch 14d, capture delay 15m, Network Epoch 5d, `maxSlashRequestDelay` 2d, Veto 2d, `maxSlashExecutionDelay` 2d ⇒ ~3d buffer.

* **Vault deployment completeness:** ensure Delegator and Slasher are set (`Vault.isInitialized()`). Missing pieces can return unsupported stake data or prevent slashing.

* **Operator diversification:** diversify operators to avoid a concentrated attack surface.
  * Prefer trustworthy operators, especially in small validator sets.

* **Neighbor network risk:** only restake alongside networks you trust; a malicious neighbor can slash shared stake and wipe your security.

* **Stake readings:** `stakeAt()` functions count pending slashings as real stake. Cover this in middleware based on [Vault type](/learn/core-concepts/vault#delegator-types) and slashing logic.

* **Slash ordering:** execute slashing requests for a single operator in capture-timestamp order to avoid reverts and under-slashing.

* **Epoch length limit:** Slashers do not support Vault Epoch Duration greater than the current timestamp (~55 years); long epochs may break slashing.

## For Curators

* **Use valuable collateral:** otherwise networks may refuse it as economic security while you claim operational costs.

* **Pick sensible epoch duration (24h–30d):** extremes deter networks or stakers.

* **Keep veto shorter than vault epoch:** networks need time to slash; long veto close to epoch length blocks security guarantees.

* **Work with trustworthy networks:** malicious networks can slash stakers’ money and damage your reputation.
  * Ensure rewards they provide have real value.

* **Work with trustworthy operators:** poor operator behavior risks staker funds and your reputation; diversify stake across operators where appropriate.

* **Avoid invalid/deprecative contract states** under your management.

* **Redeploy after 100% slashing:** repeated full slashings leave the Vault unusable.

* **Fee-on-transfer collateral breaks redistribution mechanics:** expect losses if you try to redistribute slashed funds with such tokens.

## For Stakers

* **Deposit valuable collateral:** avoid low-value or predatory tokens to reduce loss risk.

* **Choose trustworthy vault curators:** an honest, immutable, permissionless setup reduces burn/steal/lock risk.

* **Use a trustworthy burner:** suitability depends on collateral.
  * Immutable burner contracts fit some assets; a dead address may be unsuitable for LSTs where third parties have incentives to lock supply.

* **Trust the vault’s networks:** malicious networks can slash your entire delegated stake.
  * Prefer networks offering valuable rewards.
  * Prefer networks with trustworthy resolvers to prevent invalid slashes.

* **Pick meaningful epoch durations (≤ ~1 year):** very long epochs can lock funds too long.

* **Know deposits are instantly slashable:** new deposits can be slashed by existing events without rewards; align deposits with your yield strategy and vault state.

## For Operators

* **Work with trustworthy vault curators:** dishonest curators can destabilize vaults you vouch for, harming reputation and stake.

* **Serve trustworthy networks:** malicious networks can slash stake under your management and still fail to pay meaningful rewards, wasting time and costs.

# **Points Program**

Symbiotic Points reward participants that provide useful economic security through the protocol. They are earned by depositing collateral into vaults and, in Season 2, by delegating that collateral to secure networks.

You can view your points by connecting your wallet at `https://app.symbiotic.fi`. If you participate through wrappers such as LRTs, some or all of your points may be shown in the provider’s own interface instead of the Symbiotic app.

Participation in the Points Program is subject to Symbiotic’s Terms of Use, Points Program Terms, and Risk Factor Disclosure Statement.

## Seasons

### Season 1: Pre-Deposit phase

Season 1 covers the initial rollout of Symbiotic from June 2024 until the deployment of feature complete core contracts on Ethereum mainnet.

During this phase, Pre-Deposit (default collateral) vaults were deployed for assets such as wstETH, mETH, wBTC and others. These vaults did not yet delegate stake to networks. Depositors earned points based mainly on the size and duration of their collateral. Over this period, Pre-Deposit vaults accumulated roughly 2B USD of TVL.

### Season 2: Actively delegated stake

Season 2 starts with the mainnet deployment of core contracts. From this point, vaults can be deployed that delegate collateral to operators on Symbiotic networks.

Season 2 is designed as a transition from idle collateral into fully deployed security. The key changes are:

* Delegated collateral earns a higher points rate than idle collateral in Pre-Deposit vaults
* Points for Pre-Deposit vaults continue at a lower rate and are intended to phase out over time
* Depositors are encouraged to move into actively delegated vaults curated by LRTs, operators, institutions and network foundations

If you use Symbiotic via an LRT, your provider may manage this migration on your behalf. If you deposit directly, the Symbiotic app guides you through moving from Pre-Deposit vaults to actively delegated vaults.

## Who Earns Points

Points are assigned on a per-network basis and then split across three groups:

1. The network itself
2. Operators on that network
3. Vaults that delegate stake to the network and their depositors

Networks can receive up to 5% of total allocated points, while allocating another up to 5% to operators. The remaining points go to vaults, where curators can charge an additional admin fee of up to 5%, with the rest distributed to depositors pro rata to their share of the vault’s TVL.

This ensures that all contributors to shared security are rewarded, while the strongest incentives remain aligned with staked capital.

![Symbiotic Structure](/img/symbiotic-points-structure.jpg)

## How Points Are Calculated in Season 2 and Points 2.1

Points 2.1 refines Season 2 by tying rewards more tightly to how capital is actually deployed and how safely it is used.

At a high level, each network receives:

`
Points per hour = NetworkStake × PointsRate × 0.001`

`PointsRate = MiningRate × SecurityRate`

Everything is computed per network, then split to networks, operators, and vaults as described above.

### Mining Rate: stake relative to target

Each network has a target stake, in USD terms. This is the amount of collateral that is considered appropriate for its security needs.

* When a network is below its target stake, the mining rate is high and each extra unit of stake earns close to the maximum number of points
* As the network approaches and exceeds its target, the mining rate is reduced so additional stake earns fewer or no extra points

This discourages over-staking on a single network purely for points and helps push capital toward networks that still need security.

![Mining Rate](/img/mining-rate.png)

### Security Rate: how stake is used and distributed

The security rate measures how risk aware a network’s stake is. It combines two ideas:

1. Restaking score of the underlying vaults
2. How decentralised stake is across those vaults

### Restaking score

Restaking is measured as the ratio between:

`Restaking ratio = Total delegated stake of the vault / Vault TVL`

A higher ratio means the same collateral is used to secure more networks. This can be capital efficient, but also increases potential correlated slashing risk.

Points 2.1 uses a target restaking ratio (currently 3). Around this ratio, the restaking score is high. When a vault’s ratio climbs significantly above this, its restaking score falls quickly. This affects both:

* The network’s security rate if it relies heavily on that vault
* The vault’s own share of points from the network, since vault rewards are multiplied by their restaking score

![Restaking score](/img/restaking-score.png)

### Stake decentralisation across vaults

To avoid having one vault dominate a network’s security, Points 2.1 uses a decentralisation score derived from the complement of the Herfindahl–Hirschman Index. It ranges from 0 (all stake effectively in a single vault) to 1 (stake spread across many vaults).

The security rate is a stake-weighted combination of restaking scores and this decentralisation score. Networks that rely on sane restaking and multiple vaults earn a higher security rate and therefore more points for the same amount of stake.

## Vault Behaviour and Delegation

From the perspective of a depositor, the main rules are simple:

* Points are only accrued on collateral that is actively delegated from a vault to networks
* The effective points per unit of collateral depend on how much of the vault’s TVL is delegated, how many networks it supports, and how aggressive its restaking ratio is

This implies:

* A well-utilised delegated vault will generally earn more points than a Pre-Deposit vault
* A vault that barely delegates, or that is very concentrated on a single network, may earn fewer points than a better balanced alternative
* A vault that pushes its restaking ratio far above the target can see its points reduced, even if it holds a large TVL

The Symbiotic app shows vault-level information such as TVL, delegated stake, and expected points, to help depositors choose where to allocate collateral.

## Pre-Deposit Vaults and Migration

Season 1 Pre-Deposit vaults remain part of the system in Season 2, but with reduced incentives. They continue to earn points at a lower rate for a transition period. Over time, rewards are intended to shift more fully toward vaults that actively delegate stake to networks.

A typical migration path for a direct depositor is:

1. Withdraw or migrate from a Pre-Deposit vault
2. Deposit into an Actively Delegated vault
3. The curator allocates stake from that vault across one or more networks
4. Points accrue based on delegated stake and each network’s points rate under Points 2.1

Wrappers and LRTs may perform equivalent steps internally for their users.

## Tracking Your Points

You can track your points directly in the Symbiotic app by connecting your wallet.

For a more detailed view under Points 2.1, including how your capital is distributed across networks and vaults and how that affects your effective points rate, you can also use the Symbiotic Points dashboards on Dune.

# **Analytics**

Symbiotic exposes a set of public dashboards that track the protocol’s growth, rewards, and users in real time. This page aggregates the main views so teams can quickly monitor what matters without rebuilding queries from scratch.

All dashboards are updated live and can be filtered by time range, chain, vault, or other parameters directly in the UI.

## 1. Protocol overview

### 1.1 Core protocol stats

**Dashboard:** https://dune.com/symbiotic/symbiotic-core-stats

This view is the main entry point for Symbiotic protocol health. It typically includes:

* Total value locked (TVL) across all vaults
* Distribution of TVL by collateral, vault type, and chain
* Number of active vaults, networks, and operators
* Historical evolution of TVL and activity over time

Use this dashboard to answer questions like:

* How fast is Symbiotic growing?
* Which assets and vaults are driving most of the TVL?
* How many networks and operators are active at any point in time?

### 1.2 Network analytics

**Dashboard:** https://analytics.symbiotic.fi/

This analytics workspace provides a more granular breakdown of networks consuming Symbiotic security, including:

* Per-network secured value / stake backed by Symbiotic
* Restaking ratios and economic security per network
* How stake is sourced (which vaults and collaterals back each network)
* Network activity over time (captures, attestations, messages, etc., depending on integration)

It’s the right place when you need per-network views rather than aggregate protocol numbers—for example, to see how much security a specific network is consuming and how that evolves over time.

## 2. Rewards

### 2.1 Rewards paid via Symbiotic

**Dashboard:** https://dune.com/symbiotic/symbiotic-rewards

This dashboard tracks how rewards flow through the protocol:

* Total rewards paid over time
* Rewards by vault and by network
* Breakdown by asset / reward token (e.g. native tokens, points, incentives)
* Historical reward schedules and emission trends

Use this to:

* Understand which vaults or networks are currently incentivized
* Compare reward intensity across different configurations
* Monitor the effectiveness of incentive programs over time

## 3. Users and stakers

### 3.1 Symbiotic stakers overview

**Dashboard:** https://dune.com/symbiotic/symbiotic-users

This dashboard focuses on user behavior and the staking side of the protocol:

* Number of unique stakers interacting with Symbiotic
* Growth of new addresses over time
* Distribution of stake per user (small vs large stakers)
* Activity across chains and vaults

It gives a high-level picture of how broad and diversified the staker base is.

### 3.2 New vs. returning users (point 2.1)

**Dashboard section:** see section 2.1 on https://dune.com/symbiotic/symbiotic-users

This section highlights:

* New stakers entering the protocol in each time period
* Returning stakers that continue to deposit, restake, or interact
* Basic retention dynamics (how many users come back after their first interaction)

This view is useful for:

* Measuring how well incentive programs convert into long-term stakers
* Understanding if growth is driven mostly by net-new users or by existing users increasing positions
* Tracking the “stickiness” of the protocol over time

***

If you need, we can later add more specialized dashboards here (e.g. per-network analytics, specific vault families, or integration-specific views) and group them under additional sections.

# **Ecosystem**

## Networks

<div className="entity-grid">
  <div className="entity-card">
    <Entity id="ditto" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/dittonetwork/middleware-sdk" label="Ditto middleware SDK" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="capxCloud" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/Capx-AI/Capx-Cloud" label="Capx Cloud architecture" />

      <OpenActionButton path="https://github.com/Capx-AI/capxcloud-operator-checklist" label="Capx Cloud operator checklist" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="tanssi" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/moondance-labs/tanssi-symbiotic" label="Tanssi Symbiotic" />

      <OpenActionButton path="https://github.com/moondance-labs/claim-tanssi-operator-rewards-on-symbiotic" label="Tanssi rewards claim" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="cycle" />
  </div>

  <div className="entity-card">
    <Entity id="human" />
  </div>

  <div className="entity-card">
    <Entity id="kalypso" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/marlinprotocol/kalypso-symbiotic-data-bridge" label="Kalypso data bridge" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="radius" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/radiusxyz/symbiotic-middleware-contract" label="Radius middleware" />

      <OpenActionButton path="https://github.com/radiusxyz/symbiotic-relay" label="Radius relay" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="mevCommit" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/primev/mev-commit/tree/main/contracts/contracts/validator-registry/middleware" label="mev-commit middleware" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="hyperlane" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/hyperlane-xyz/middleware-sdk" label="Hyperlane middleware" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="hyve" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/thehyve-ai/hyve-symbiotic-middleware" label="Hyve middleware" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="routerXtend" />
  </div>

  <div className="entity-card">
    <Entity id="cap" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/cap-labs-dev/cap-contracts" label="Cap Symbiotic contracts" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="k3" />
  </div>

  <div className="entity-card">
    <Entity id="symbiosis" />
  </div>

  <div className="entity-card">
    <Entity id="ibtc" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/DLC-link/dlc-symbiotic" label="iBTC symbiotic middleware" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="bolt" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/chainbound/bolt" label="Bolt symbiotic middleware" />
    </div>
  </div>

  <div className="entity-card">
    <Entity id="lombard" />
  </div>

  <div className="entity-card">
    <Entity id="solv" />
  </div>

  <div className="entity-card">
    <Entity id="zklink" />
  </div>

  <div className="entity-card">
    <Entity id="catalysis" />
  </div>

  <div className="entity-card">
    <Entity id="spark" />
  </div>

  <div className="entity-card">
    <Entity id="manta" />

    <div className="ai-actions">
      <OpenActionButton path="https://github.com/Manta-Network/manta-fp" label="Manta FP" />

      <OpenActionButton path="https://github.com/Manta-Network/manta-fp-aggregator" label="Manta FP aggregator" />
    </div>
  </div>
</div>

## Curators

<div className="entity-grid">
  <div className="entity-card">
    <Entity id="gauntlet" />
  </div>

  <div className="entity-card">
    <Entity id="etherfi" />
  </div>

  <div className="entity-card">
    <Entity id="renzo" />
  </div>

  <div className="entity-card">
    <Entity id="mevcapital" />
  </div>

  <div className="entity-card">
    <Entity id="re7labs" />
  </div>

  <div className="entity-card">
    <Entity id="concrete" />
  </div>

  <div className="entity-card">
    <Entity id="credio" />
  </div>

  <div className="entity-card">
    <Entity id="cp0x" />
  </div>

  <div className="entity-card">
    <Entity id="stakestone" />
  </div>

  <div className="entity-card">
    <Entity id="hyperithm" />
  </div>
</div>

## Operators

<div className="entity-grid">
  <div className="entity-card">
    <Entity id="p2p" />
  </div>

  <div className="entity-card">
    <Entity id="piertwo" />
  </div>

  <div className="entity-card">
    <Entity id="kiln" />
  </div>

  <div className="entity-card">
    <Entity id="nodeinfra" />
  </div>

  <div className="entity-card">
    <Entity id="luganodes" />
  </div>

  <div className="entity-card">
    <Entity id="chorusOne" />
  </div>

  <div className="entity-card">
    <Entity id="a41" />
  </div>

  <div className="entity-card">
    <Entity id="blockdaemon" />
  </div>

  <div className="entity-card">
    <Entity id="rockx" />
  </div>

  <div className="entity-card">
    <Entity id="alchemy" />
  </div>

  <div className="entity-card">
    <Entity id="blockscape" />
  </div>

  <div className="entity-card">
    <Entity id="pareto" />
  </div>

  <div className="entity-card">
    <Entity id="hashkey" />
  </div>

  <div className="entity-card">
    <Entity id="quantnode" />
  </div>

  <div className="entity-card">
    <Entity id="blockandbones" />
  </div>

  <div className="entity-card">
    <Entity id="stakely" />
  </div>

  <div className="entity-card">
    <Entity id="nansen" />
  </div>

  <div className="entity-card">
    <Entity id="stakefish" />
  </div>

  <div className="entity-card">
    <Entity id="stakecapital" />
  </div>
</div>

# **Universal Staking**

Universal Staking is more than just restaking. Instead of merely reusing staked assets to secure multiple networks, it introduces a flexible coordination layer for sharing collateral across a wide range of use cases beyond Proof-of-Stake (PoS) implementations.

## **Traditional Shared Security**

At its core, shared security is the alignment of incentives, either horizontally across multiple participants or vertically across layers within the same system. This foundational primitive unlocks a modular design space. Horizontally, it enables networks to tap into pooled economic security, accelerating decentralization in a capital-efficient way. Vertically, it turns existing tokens into multi-purpose assets, like using governance tokens to secure sequencing layers.

By making data around validator performance, node distribution, operator quality, and security effectiveness transparent and programmable, it reduces coordination friction and lowers the barrier to deploying decentralized infrastructure.

But shared security is just the beginning. While it allows networks to inherit trust more efficiently, it is often implemented in narrow, use-specific ways. What comes next is a broader coordination layer, one where capital can flow dynamically between networks and applications, supporting diverse forms of security, utility, and risk underwriting with customizable rules and shared infrastructure.

## **The Universal Staking Framework**

Through engaging with hundreds of builders over the last few months and launching 16 networks on mainnet, we realized that the underlying concept of shared security can be leveraged in ways far beyond what restaking and traditional shared security infrastructure envisioned. What started as a way to coordinate stakers and networks around Proof-of-Stake security revealed a broader design space for incentive alignment and capital coordination.

Universal Staking, as developed through Symbiotic, builds on this insight. It generalizes the shared security model into a modular coordination layer that can be applied across use cases, not just for securing consensus, but also for underwriting risk, bootstrapping new protocols, and aligning incentives between diverse actors. For example, lending markets can use it to backstop bad debt, enabling stakers to opt into specific risk profiles with customizable terms. This is no longer just about securing networks, but about unlocking new forms of programmable trust between capital and applications.

While the chart below shows that staking has outpaced total crypto market growth since 2021, it also underscores how early we still are. Symbiotic is built to push beyond traditional staking by allowing projects to bootstrap security from external assets, design modular staking systems, and apply staking to use cases like risk underwriting and insurance. The goal is not just to scale staking’s footprint, but to evolve it into a coordination layer for capital, security, and incentive alignment across the onchain economy.

![](/img/symbiotic-blog-staking.png)

### **Key Metrics**

* Staking grew from 2.99% to 11.56% of total crypto market cap since 2021.
* Restaking emerged from 0 to nearly 1% of total crypto market cap in under 2 years.
* While crypto market cap grew 22% YoY since 2021, staking and restaking quietly doubled that at 45%.
* At the current trajectory, staking + restaking will reach 50% of crypto market cap in ~8.4 years (around early 2033).

*data from [**DefiLlama**](https://defillama.com/), [**StakingRewards**](https://www.stakingrewards.com/), and [**Coingecko**](https://www.coingecko.com/)*

## **Universal Staking Use Cases**

### **Native Staking**

Native staking refers to the use of a protocol’s own token to secure and coordinate activity within its ecosystem. While traditionally tied to Proof-of-Stake consensus or governance, Universal Staking reframes native tokens as programmable trust assets, acting as flexible primitives for enabling coordination, enforcing rules, and aligning incentives across modular systems.

**Expanded Utility**

* Programmable Trust Layers: Native tokens are no longer limited to gas payments or voting power. They can encode slashing conditions, distribute rewards, and coordinate behaviors across trust-minimized components.
* Incentive Systems: Models like vote-escrow and revenue sharing allow protocols to design long-term alignment between users, contributors, and applications.
* Composable Security: Projects such as Hyperlane show how native staking can be combined with staking on Symbiotic to enforce custom slashing logic and strengthen inter-network security assumptions.
* Mesh Security and Cross-Ecosystem Coordination: Native tokens can participate in broader security meshes, where the same asset secures appchains, messaging layers, oracle networks, and more, all at once.

**Example**

Hyperlane uses HYPER for native staking to encode programmable trust logic within its modular interchain stack. Through Symbiotic, HYPER holders can stake their tokens and secure core components like ISMs. For a deeper look into how Universal Staking powers native trust models, [**check out our blog post on Hyperlane.**](https://blog.symbiotic.fi/hyperlane-native-staking-powered-by-symbiotic/)

### **Insurance and Guarantees**

Universal Staking enables programmable collateralization to underwrite risks beyond protocol security, e.g., lending, insurance, or structured financial products. Capital can be orchestrated through slashing conditions, acting as automated enforcement mechanisms.

**Expanded Utility**

* Bad Debt Protection: Inspired by Aave's vision for shared insurance pools, protocols can create bad debt backstops by pooling staked capital and shared economic security from across the ecosystem. DAOs, curators and lending markets can customize slashing triggers based on default conditions or liquidity thresholds.
* Other Structured Products:
  * Downtime insurance for validators and node operators.
  * MEV protection funds, where actors stake against misbehavior and get slashed for proven attacks.

### **PoS Implementations, as in Traditional Shared Security**

The most familiar application of Universal Staking. It brings PoS-style security to specific infrastructure components, allowing shared security to be applied at a modular level.

**Expanded Utility**

* **Interoperability protocols** (such as bridges and messaging layers): Stakers post collateral to guarantee message correctness and transaction finality across chains. Slashing enforces honest relaying.
* **Oracles:** Stake is used to guarantee accuracy or uptime for price feeds and other data. Misbehavior or failure to deliver correct data can trigger slashing. This extends to MEV-resistant oracle designs and similar integrity-critical systems.
* **Sequencers and rollups:** Rollups increasingly rely on shared sequencer and operator sets to decentralize. Universal Staking provides a pooled security layer that helps these systems bootstrap trust assumptions without needing to launch a native token or maintain an isolated validator set.

## **Conclusion**

Shared security introduced a powerful primitive. It allowed systems to align incentives and inherit trust without needing to bootstrap from scratch. By enabling networks to coordinate around pooled security, it lowered the capital barrier to decentralization and helped scale early rollups, appchains, and infrastructure layers.

Universal Staking is the natural next step. It does not replace shared security but expands its reach. By generalizing the concept beyond validator coordination, it applies the same principles to a broader set of use cases. This includes native staking, risk underwriting, insurance, MEV protection, and incentive design.

The result is a flexible and modular coordination layer. Capital, incentives, and enforcement can now be orchestrated across a wide range of applications. The same mechanism that once secured chains can now secure infrastructure, protocols, and entire ecosystems.

Symbiotic is the programmable layer that makes this possible. It enables builders to design staking flows, slashing conditions, and validator sets, while continuously enforcing the rules.

Universal Staking takes the core promise of shared security and evolves it into a universal building block for the next generation of crypto systems, now fully accessible through the Symbiotic framework.

# **Network**

![network](/img/network-overview-learn.png)

In Symbiotic, a Network is any protocol that requires a decentralized infrastructure network to deliver a service in the crypto economy, such as enabling developers to launch decentralized applications by validating and ordering transactions, providing off-chain data to applications, or providing users with guarantees about cross-network interactions.

Decentralized infrastructure networks can utilize Symbiotic to flexibly source their security in the form of operators and economic backing. In some cases, protocols may consist of multiple sub-networks with different infrastructure roles. The Symbiotic protocol’s modular design allows developers of such protocols to define the rules of engagement that participants need to opt into for any of these sub-networks.

## **Technical Overview**

In Symbiotic, networks are represented through a network address (either a contract or multisig) and a middleware, which can incorporate custom and slashing logic. The core protocol’s fundamental functionalities encompass slashing operators and rewarding both stakers and operators.

Middleware contracts integrate with Symbiotic Core for stake capture, validator set management, slashing, and optional rewards accounting. Optional means that rewards logic can live in the middleware, while the Network always defines the existence, funding, and source of rewards.

The network also has its own operator set, which provides services to the network. The network’s software produces work, emits messages to be attested, and participates in epochs. Here the network admin defines voting power rules and thresholds, message formats, participation and liveness requirements, dispute inputs, and Relay compatibility if it wants cross chain verification.

## **Epoch**

A network epoch (let’s name it `NETWORK_EPOCHNETWORK_EPOCH`) is a period while a certain operator set, obtained given the captured stake, operates for the good of the network. The epoch plus the vault’s veto and execute phases’ durations should not exceed the duration of the vault’s epoch to ensure that withdrawals do not impact the captured stake (however, the conditions can be softer in practice).

[See Vault Accounting Details](/learn/core-concepts/vault#accounting-and-epochs)

![Learn Network 2](/img/learn-network-2.png)

A valid operator set means the validator set captured for the current network epoch is the reference set used for verification and slashing during that epoch. While it remains valid, on chain checks verify signatures against that set and its associated weights, and any slashing decisions are made with respect to those same weights.

## **Staking**

The vault allocates stakes by setting limits for networks and operators.

Let the Vault be *V*, the Delegator module of the vault is *D* and the Slasher module is *S*.

[See Stake Allocating Details](/learn/core-concepts/vault#delegation)

Given the current active balance of the vault and the limits, we can capture the stake for the subsequent network epoch: `networkOperatorStake=D.stake(network,operator)`

### **Subnetworks**

Instead of creating multiple instances of a network, the Symbiotic protocol allows the creation of multiple subnetworks within the same network. This is similar to an operator having multiple keys instead of creating several instances of the operator. All limits, stakes, and slashing requests are handled by subnetworks, not the main network. This approach diversifies the network’s stake across different staking mechanics. For example, one subnetwork can have high limits and a trusted resolver in the Slasher module, while another subnetwork can have lower limits but no resolver in the Slasher module.

The final ID is just a concatenation of the network’s address and the provided `identifier`, so collision is not possible.

For simplicity, we sometimes omit the presence of subnetworks and just use the term network.

### **Limits**

Limits are set in the vault, and the network cannot control this process (unless the vault is managed by the network). However, the implementation prevents the vault from removing previously given slashing guarantees.

Additionally, the network can limit the maximum amount of stake it wants to use via the `D.setMaxNetworkLimit()` method.

### **Staking Lifecycle:**

1. The network registers by calling `NetworkRegistry.registerNetwork()`.
2. Operators register by calling `OperatorRegistry.registerOperator()`.
3. The operators must opt into the vault and the network.
4. Stakers deposit funds into the vault.
5. The network sets a maximum stake amount for the vault by calling `D.setMaxNetworkLimit(identifier, amount)`.
6. The `NETWORK_LIMIT_SET_ROLE` holder defines the stake limit for the network.
7. The `OPERATOR_NETWORK_LIMIT_SET_ROLE` holder defines the stake limit for the operator-network pair.

The current stake amount cannot be withdrawn for at least one epoch, although this restriction does not apply to cross-slashing.

### **Operator Set**

The network has the flexibility to configure an operator set within the middleware, later to be used as a validator set (a.k.a. valset) for its validating.

![Learn Network 3](/img/learn-network-3.png)

The following functions could be useful:

* `D.stakeAt(subnetwork, operator, timestamp, hints)`: Determines minimum stake eligibility. Note that the sum of operators’ stakes may exceed the network’s total stake, depending on the network’s and operators’ limits in the delegator module.
* `OptInService.isOptedInAt(operator, subnetwork, timestamp, hint)`: Checks the opt-in status.

## **Slashing**

[See Slashing Details](/learn/core-concepts/slashing)

For each operator, the network can obtain its stake which will be valid during $d=vaultEpochd$. Through its middleware, the Network initiates slashing when provable misbehavior occurs according to Network‑defined rules. Slashing protects stakers from dishonest or idle operators and protects Networks from operators taking stake without performing required work. Symbiotic Core enforces objective bounds so only stake guaranteed at capture can be burned.

A slashing request must reference a capture timestamp that is no more than one vault epoch old, not exactly equal to the epoch boundary. Requests can arrive at any time within this sliding window. Requiring equality would cause legitimate slashes to fail around boundaries.

Note that the actual slashed amount may be less than the requested one.

1. This may be influenced by cross-slashing.

![Learn-Network-4](/img/learn-network-4.png)

1. This may be influenced by slashings by the network itself, as the consequent valsets may depend on the stake used for the creation of the previous valsets.

![capture-timestamps-2](/img/learn-network-5.png)

1. In the case of a task-like system, where each task is backed by the corresponding operator’s stake, this may be influenced by slashings by the network itself if the operators have a pooled stake.

![capture-timestamps-3](/img/learn-network-6.png)

The network can slash the operator within the vault only if

1. The operator is opted into the vault
2. The operator is opted into the network

To initiate a slashing process, a network should call:

1. `slash(subnetwork, operator, amount, captureTimestamp, hints)` for the Slasher module.
2. `requestSlash(subnetwork, operator, amount, captureTimestamp, hints)` for the VetoSlasher module.

The module will check the provided guarantees at the $*captureTimestamp*$, denoted as $*G.*$ It also calculates cumulative slashings from the $captureTimestamp$ to the current moment, denoted as $*C*$. It is guaranteed that for every correct $captureTimestamp$, $C≤G$. The module will allow slashing no more than $G−C$ to justify the given guarantees.

## **Operating Lifecycle**

A network can use flexible mechanics to keep its operator set state up-to-date, e.g., it’s convenient to use a conveyor approach for updating the stakes while keeping slashing guarantees for every particular version of the operator set:

1. At the beginning of every epoch the network can capture the state from vaults and their stake amount (this doesn’t require any on-chain interactions).
2. After this, the network will have slashing guarantees for one vault epoch duration, so it can use this state at most for one vault epoch.
3. When the epoch finishes and a slashing incident has taken place, the network will have time equal to the vault epoch duration minus the network epoch to request-veto-execute slash and go back to step 1 in parallel.

![vault-conveyor](/img/learn-network-7.png)

## **Rewards**

See [Learn: Rewards](/learn/core-concepts/rewards) to learn more about reward distribution mechanisms.

## **Relay SDK Integration**

All of this can be cumbersome to scope, implement, and maintain from scratch. That is why Symbiotic provides the Relay SDK, a set of contracts and off chain components that let networks capture stake through Symbiotic, track operator sets and voting power, aggregate signatures, and plug into slashing without rebuilding their own verification layer.

Using the Relay SDK, a network can verify the same work across multiple EVM chains, aggregate operator signatures off chain and verify them once on chain, and significantly reduce verification costs while keeping its existing governance, message formats, and slashing rules unchanged.

# **Operator**

Operators run the software that keeps decentralized networks alive. They include node operators or validators that run consensus and network-specific binaries, sign messages for bridging and oracles, or strategy operators such as risk managers and AI agents that execute DeFi strategies on behalf of a network.

Within Symbiotic, operators can receive stake from different vaults and route it to the same set of nodes for a given network. The protocol maintains a registry of operators and records their activity so networks and curators can make informed choices. The registry covers which networks an operator has opted into, which vaults are connected and how much restaked collateral came from them, and a history of slashes and other on chain interactions.

This setup lets operators aggregate stake from many sources, including institutional vaults, operator specific vaults, or LRTs with different risk profiles, without spinning up separate infrastructure for each one. A single node stack per network can secure multiple partners, as long as all parties have opted in.

![operator-rel](/img/operators-get-started.png)

In Symbiotic, an operator is either an externally owned account or a contract registered in the OperatorRegistry.

## Operator onboarding

At a high level, onboarding an operator involves three steps.

1. Register the operator entity in the operator registry so it can be referenced by vaults and networks: Call `OperatorRegistry.registerOperator()` in `OperatorRegistry`.
2. Opt into the networks the operator wants to serve. Each network decides whether to include the operator in its active set based on criteria such as performance history, reputation, stake, and reliability. This is achieved by calling the `optIn()` method in `OperatorNetworkOptInService` .
3. Opt into the vaults that may allocate stake to that operator. This is achieved by calling the `optIn()` method in `OperatorVaultOptInService`. Curators then configure limits or shares so the Delegator can route stake to the operator within each network’s bounds. The address that holds `OPERATOR_NETWORK_SHARES_SET_ROLE` or `OPERATOR_NETWORK_LIMIT_SET_ROLE` for the vault assigns stake to the operator by calling either:
   * `D.setOperatorNetworkShares(...)`, or
   * `D.setOperatorNetworkLimit(...)`
     depending on the Delegator type used by the vault.

Stake becomes eligible for slashing only when the operator has opted into both the network and the vault at the time stake is captured for an epoch.

![operator-rel](/img/operators-onboarding.png)

## Working with Vaults and Networks

### Vaults

Vaults are where stake lives. Curators decide which operators are admissible for a vault and how much stake each one can receive. They set per operator limits or shares and may adjust them as conditions change. The Delegator module uses these settings, together with opt ins, to determine how much effective stake each operator has per network.

### Networks

Networks are where operators perform work. An operator opts into a network in order to validate it or to provide a defined service. Based on its own criteria, each network independently decides whether to include the operator in the active operator set. The network’s software produces work, emits messages or commitments to be attested, and participates in epochs. Here the network defines voting power rules and thresholds, message formats, participation and liveness requirements, dispute inputs, and how it integrates with the Relay if it needs cross chain verification.

### Aggregation

For a single network, an operator can combine stake from multiple vaults into one node stack as long as:

* the operator has opted into that network
* the operator has opted into those vaults
* curators have allocated stake to the operator within each network limit

This allows operators to build one hardened infrastructure per network and receive stake from many partners without fragmenting their setup.

### Subnetworks and Keys

Some networks split responsibilities into subnetworks. Limits, stake capture, and any penalties apply per subnetwork. Operators should plan key management and operations with that boundary in mind, for example by running distinct keys or processes per subnetwork where needed.

## Relay integration

All of the above can be implemented with custom network logic, but wiring cross chain verification, aggregation, and stake capture from scratch is complex. Symbiotic provides the Relay SDK so networks and operators can plug into a common framework instead.

If a network uses the Relay SDK:

* The Relay uses the operator registry and voting power from Symbiotic to build the operator set for that network.
* Operators can run a small Relay sidecar that helps collect signatures, aggregate them, and submit commitments so verification remains efficient across EVM chains.
* The same operator set and stake that secure the network can be reused to attest on multiple chains, reducing costs and integration effort while keeping the network’s governance and rules unchanged.

From the operator perspective, Relay integration mainly means running an additional, lightweight process that works alongside their existing nodes and keys, rather than rewriting their own cross chain logic.

## Penalties and Slashing

Once an operator has opted into a vault and a network, and stake has been captured for an epoch, that stake becomes subject to slashing according to the network rules and the vault configuration.

If an operator fails to perform services according to those rules, the network middleware can raise a slashing request against the operator’s stake. On Ethereum style systems this includes faults such as double signing or other consensus violations. The vault’s Slasher module validates slashing requests and, if they are correct and within the defined guarantees, applies penalties to the operator’s stake and invokes the vault’s Burner to decide what happens to the penalized collateral.

Some setups allow immediate execution of valid slashes, while others introduce a short veto or review window, depending on the Slasher type chosen by the curator and the network.

## Rewards

Operators need to be compensated for the services they provide and the risk they take. Networks pay operators from the value they generate, for example protocol fees, payments from external clients who use their services, or token inflation allocated to security and operations.

See [Learn: Rewards](/learn/core-concepts/rewards) to learn more about reward distribution mechanisms.

# **Vault**

A vault is the on-chain container that holds collateral and connects it to networks. Each vault holds a single collateral token, tracks deposits and withdrawals, and exposes policy hooks for delegation and slashing. Delegation is pure accounting: collateral remains in the vault and only leaves through user withdrawals or executed slashing.

Vaults are built from three core modules:

1. **Accounting (Vault)**: handles deposits, withdrawal requests and claims, epoch timing, and processing of penalized collateral.
2. **Delegation (Delegator):** applies curator limits or shares for each network and each operator and implements the stake distribution logic.
3. **Slashing (Slasher or VetoSlasher)**: validates slashing requests against captured guarantees and applies penalties.

![Learn Vault 1](/img/learn-vault-1.png)

Rewards are not built into vaults. Networks can leverage Symbiotic’s rewards contract template, which is designed to facilitate interactions with vaults and capture stake.

## Accounting and Epochs

### Lifecycle

Symbiotic makes most mechanics configurable but gives strict guarantees around the period when stake is slashable. The vault lifecycle revolves around four actions: deposit, withdraw, slash, and resolve. Collateral comes into the vault through deposits, can be requested for withdrawal, may be penalized through slashing, and is then processed according to the configured policy.

![Learn Vault 2](/img/learn-vault-2.png)

### Epochs

Epochs are a core mechanism that balance user liquidity with network security. Networks rely on operators having a stable amount of slashable stake during a period, while users want to request withdrawals at any time. Vaults achieve this with an epoch based withdrawal system rather than simple time delays.

Users can submit withdrawal requests at any time. Those requests are collected and become claimable after the end of the next vault epoch. Until that boundary, the requested amount remains eligible for slashing. Epochs are consecutive and all have the same length. The epoch length is set at vault deployment. A longer epoch gives more time to observe networks and execute slashes but slows withdrawals; a shorter epoch has the opposite effect.

Requested withdrawals therefore remain slashable until the next epoch boundary. This is what allows networks to rely on the guarantees they receive from stake captures.

### Deposits

Any address allowed by the vault access policy may deposit the collateral token. By depositing, a user opts into the vault configuration and curator, since the vault risk profile and returns depend on that management. Deposits increase the user balance and the vault active stake used for delegation and guarantees. Each vault is bound to a single collateral token.

![Learn Vault 3](/img/learn-vault-3.png)

### Withdrawals

Depositors can request withdrawals at any time. The process has two stages. First, the user submits a withdrawal request and the amount is marked as pending but remains slashable until the end of the next epoch. Second, after that next epoch ends, the user can claim funds at any time without further slashing risk. This keeps operator stake effectively stable within an epoch while giving users predictable exit timing.

![Learn Vault 4](/img/learn-vault-4.png)

## Delegation

Delegation translates vault balances and curator policy into effective stake for each network and each operator. The Delegator module lets each network set a maximum amount of stake it is willing to accept from a given vault, lets curators set per network and per operator limits or shares within those bounds, and aggregates all inputs to return the stake of a given operator on a given network at a given time.

Stake always depends on three elements:

1. the vault active stake, meaning funds that have not been fully withdrawn
2. operator opt ins to the vault and to the network
3. the limit that the network set for this vault

Some Delegator types also take per operator limits or shares into account. After a slashing event, Delegators do not automatically change limits. If automatic reactions are desired, they can be introduced through hooks.

![Learn Vault 5](/img/learn-vault-5.png)

### Delegator Types

Symbiotic supports several Delegator types to cover different delegation topologies.

1. **Network Restake Delegator**

   Allows restaking across multiple networks while keeping operators inside the same network independent from each other. Curators set a limit for each network within the network maximum and set shares for each operator. Operator stake in a network is the vault and network stake multiplied by the operator share over the sum of shares. This is convenient for liquid restaking providers or curators whose main role is to raise and allocate funds rather than operate nodes.

2. **Full Restake Delegator**

   Restakes across multiple networks and multiple operators at once. Curators set a limit for each network and a limit for each operator. Operator stake is capped by the active stake, the network limit, and the operator limit. This is useful for insurance style designs where a shared pool backs many parties.

3. **Operator Specific Delegator**

   A simplified version of the Network Restake type with a single operator per vault. Curators set only the network limit. Stake per network is capped by the active stake and the network limit. This lets an operator run its own vault with restaking across networks while giving networks more confidence that allocations are under the operator direct control.

4. **Operator Network Specific Delegator**

   The most conservative type with a single network and a single operator. Stake is capped by the active stake and the network maximum limit. From the network perspective this resembles a traditional single operator staking arrangement, although there can still be many vaults per network.

### Delegation Topologies

These Delegator types correspond to different combinations of how many networks and how many operators a vault can serve.

1. **Multi Network and Multi Operator (MN, MO)** gives maximum capital reuse and restaking with more shared risk.

![Learn Vault 6](/img/learn-vault-6.png)

2. **Multi Network and Single Operator (MN, SO)** gives operator specific vaults with strong operator isolation while still supporting restaking.

![Learn Vault 7](/img/learn-vault-7.png)

3. **Single Network and Multi Operator (SN, MO)** isolates network risk but shares operator risk and is often used by liquid staking providers or network treasuries.

![Learn Vault 8](/img/learn-vault-8.png)

4. **Single Network and Single Operator (SN, SO)** gives maximum isolation and minimum reuse and is often used for curator free or immutable arrangements.

![Learn Vault 9](/img/learn-vault-9.png)

| **Properties \ Delegation type** | **MN, MO**                                                                                    | **MN, SO**                                                              | **SN, MO**                                         | **SN, SO**                                                     |
| -------------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------------------- |
| Restaking supported              | ✅                                                                                            | ✅                                                                      | ❌                                                 | ❌                                                             |
| Potential curators               | LRT, Institutional restaking                                                                  | Operator                                                                | LST, Network DAO                                   | Users                                                          |
| User delegation model            | Delegate to the curator as an entity to use stake for multiple operators in multiple networks | Delegate to the operator as an entity to use stake in multiple networks | Delegate to curator to use stake in single network | Delegate to the operator in the network directly (No curators) |
| Stake isolation for networks     | ❌                                                                                            | ❌                                                                      | ✅                                                 | ✅                                                             |
| Stake isolation for operators    | ❌                                                                                            | ✅                                                                      | ❌                                                 | ✅                                                             |

## Slashing and Burner

### Slasher Module

The Slasher module enforces slashing penalties. It does not detect misbehavior itself; instead it processes slashing requests from network middleware.

A slashing request names the subnetwork, the operator, the amount to penalize, and a capture timestamp. The capture timestamp is the moment when the network fetched stake and received a guarantee that those amounts would remain slashable for one epoch. When executing a request, the Slasher checks that the capture timestamp is not older than one vault epoch and that the requested penalty does not exceed the remaining guarantee for that snapshot after previous slashes that used the same capture.

When a request arrives, the Slasher retrieves stake information from the Delegator and prior slashes for the same snapshot, validates that the request respects the guarantee, and if it is valid, updates internal state, notifies the Delegator where needed, and calls the vault and Burner to process the penalized collateral.

In restaking scenarios, guarantees can be affected by slashing that happened on other networks. This comes from the nature of restaking and cannot be fully avoided.

### Slasher Types

There are currently two Slasher types:

1. **Slasher**: executes valid slashing requests as soon as they are confirmed correct. It is simple and transparent but less flexible.

![Learn Vault 10](/img/learn-vault-10.png)

2. **VetoSlasher**: adds a veto period. The network middleware submits a request, the contract validates it, and then a resolver, if configured, has a window of time to veto the request. If no veto occurs, the middleware can execute the slash after the window expires. This design helps networks and stakers transition from early deployments to fully trusted settings with an extra layer of review.

![Learn Vault 11](/img/learn-vault-11.png)

### Burner

Once a slash is approved and executed, the Burner decides what happens to the penalized collateral. The Burner is a configurable contract that can unwrap tokens, burn them, redistribute them to users or well behaved operators, send them to a treasury or insurance pool, or forward them to custom logic. Burning is not mandatory and redistribution is a valid outcome.

![Learn Vault 12](/img/learn-vault-12.png)

## Rewards

Vaults do not define reward logic. They only provide the stake that secures networks and operators. Each network decides how staker and operator rewards are funded and delivered, for example from protocol fees, revenues from external clients, or token inflation. Symbiotic reward extensions give networks standard ways to distribute these flows, but the vault itself remains focused on holding collateral and enforcing guarantees.

## Vault Types and Access

Vaults are configurable templates. Different collateral tokens, epoch lengths, delegator types, access policies, and slashing settings produce different vault types. Each vault still holds a single collateral token; multi-asset exposure is achieved by using multiple vaults.

### Public and Private Vaults

Public vaults accept deposits from anyone who holds the collateral token, subject to any global caps defined by the curator. Private vaults accept deposits only from allowlisted addresses. Liquid restaking providers, liquid staking providers, funds, and institutions often run private vaults and allocate across several Symbiotic vaults on behalf of their users.

### Immutability Options

Vaults can be deployed in two broad ways. They can be immutable, with key parameters locked at deployment and no ongoing curator discretion, which reduces governance risk. They can also be upgradable within constrained surfaces, where certain parameters can be updated under defined rules. These choices, together with the Delegator type, slashing style, and access policy, define the risk and behavior profile of each vault in the Symbiotic ecosystem.

# **Curator**

Curators set and maintain a vault’s policy. They decide how stake is spread across networks and operators, what kind of slashing flow applies, and who can deposit. Stakers choose a vault because they trust the curator’s discipline on risk, timing, and counterparty selection.

In single-operator vaults, the operator can also act as curator. In immutable vaults, key parameters are locked at deployment, removing ongoing curator control: this reduces governance risk but also removes flexibility.

## Interactions and Vault Configuration

You don’t need every internal detail, but you should know the main pieces you are indirectly steering and the key functions involved.

* **Vault and VaultFactory / configurator**
  The vault holds collateral, tracks deposits and withdrawals, and enforces epoch-based exits. New vaults are typically created through a configurator that wraps the factories, for example a helper like `VaultConfigurator.create(initParams)` which, under the hood, calls `VaultFactory` and related factories to deploy the `Vault`, its `Delegator`, and its `Slasher`.
* **Delegator (stake allocation)**
  The Delegator decides how vault stake is allocated across networks and operators. As a curator you mainly use functions such as `setNetworkLimit()` to define how much stake this vault can send to a network, and `setOperatorNetworkLimit()` or `setOperatorNetworkShares()` to shape stake per operator, depending on the Delegator type.
* **Slasher (penalties)**
  The Slasher applies penalties when a network requests them (via a function like `slash()`). As curator you choose the Slasher type (instant or vetoed) and its timing parameters, such as the veto window, when you create the vault.
* **Burner (what happens to slashed collateral)**
  The Burner is a contract address you pass when the vault is created. It decides what happens to slashed collateral: burn, redistribute, send to a treasury or insurance pool, or route to custom logic.

You also rely on:

* an **OperatorRegistry** and **NetworkRegistry**, which define which operators and networks exist
* **opt-in services** (for example calls like `OperatorVaultOptInService.optIn(vault)` and `OperatorNetworkOptInService.optIn(network)`) so that operators can receive stake from your vault once you allocate it

## Vault Strategy

Think of your work in three phases: design, deploy, and wire.

### Design the policy

First, decide what the vault is supposed to do, in plain language:

* which networks you want to support
* how diversified or concentrated you want to be across operators
* ceilings per network and per operator
* whether slashing should be instant or have a short veto window
* how you expect rewards and risk to trade off

This is the document stakers and operators will read. Everything else is just encoding this policy on chain.

### Deploy the vault

Next, you create the actual vault and its modules in a single step with a configurator call, for example:

`solidity
(Vault vault, address delegator, address slasher) =
    VaultConfigurator.create(initParams);
`

In the `initParams` you choose, among other things:

* the collateral token
* the vault epoch duration
* the Delegator type (multi-network, single-network, operator-specific, etc.)
* the Slasher type (instant or vetoed) and, for vetoed flows, the veto duration
* the Burner contract that will handle slashed collateral
* access control, such as whether deposits are public or allowlisted

This is where you lock in the big structural choices: what the vault secures, how fast people can exit, which delegation topology it uses, and how slashing is handled.

### Wire stake limits and allocations

Once the vault exists, you configure how it actually allocates stake.

In practice that means:

* For each network you want to support, setting a vault-side limit with a call like `delegator.setNetworkLimit(subnetwork, amount)` which says “this vault can send up to this much stake to this network or subnetwork”.
* After operators have opted into your vault and into those networks, setting their allocations using, depending on the Delegator type: `setOperatorNetworkLimit(subnetwork, operator, amount)` for hard caps, or `setOperatorNetworkShares(subnetwork, operator, shares)` for share-based routing.

These limit and share calls are the core knobs you use to express your strategy on chain.

## Managing Stake

Once the vault is live, your job is mostly careful, occasional adjustments rather than constant tweaking.

Typical ongoing actions:

* revisiting network limits and operator allocations if performance, risk, or demand changes
* nudging the strategy toward more or less concentration, by changing limits or shares rather than redeploying the entire vault
* keeping the written policy up to date with any material changes you make on chain

You generally do **not** need to touch the factories again. Most day-to-day stewardship happens through the Delegator functions that set limits and shares, and through off-chain communication when you add or remove networks and operators.

## Risk and Timing

Even with a good strategy, the details of timing and partners matter. A few simple checks go a long way.

### Collateral and reward quality

* Make sure the collateral token you pick at vault creation has clear economic value and reasonable liquidity.
* Prefer networks that offer rewards that match the risk taken: protocol fees, revenues from external clients, or controlled token inflation with a clear purpose.

If the collateral is low quality and networks do not pay fairly, you risk running a vault that takes real slashing risk while barely compensating stakers.

### Epochs and veto windows

* The vault epoch duration you set at creation defines how long withdrawals take and how long stake remains slashable after it is “captured” by a network.
* If you choose a vetoed Slasher, keep the veto window well below the vault epoch. Networks need time to detect misbehavior, submit a slash, and wait out the veto period before the vault epoch ends.

A simple mental model:

> network’s own epoch and proof delay
>
> plus the veto window (if any)
>
> plus the time it takes to submit and finalize the slash
>
> should fit comfortably inside the vault epoch

If that does not hold, networks may not be able to slash in time, and the economic guarantees you think you are providing become weaker.

### Network and operator choices

The settings you choose in `setNetworkLimit`, `setOperatorNetworkLimit`, and `setOperatorNetworkShares` express your risk appetite.

* Treat the network limit as a risk budget for that network. Conservative vaults use lower limits and fewer networks; more aggressive vaults use higher limits and more networks, but should be explicit about correlated risk.
* When you allocate to operators, avoid over-concentrating on a single one unless that is very clearly part of the thesis. Slashing events will hit stakers in proportion to those allocations.

Your operator and network choices affect not just returns, but your reputation as a curator.

### Contract health and extreme cases

* Be careful when changing access control and deposit limits to avoid locking the vault unintentionally.
* If the vault ever experiences a full (one hundred percent) slashing event, it is often cleaner to deploy a new vault, rather than trying to reuse the same one repeatedly. The history stays clear and future stakers know exactly what they are opting into.
* If you use fee-on-transfer collateral together with redistribution of slashed funds, be aware that the fee logic will introduce unavoidable losses during redistribution; that trade-off should be explicit in your policy.

## Vault Profiles

The same contracts and functions can describe very different vault “shapes”. Two common ones:

### Diversified and conservative

* Several networks with moderate network limits
* Many operators, each with modest per-operator limits or fairly even shares
* A vetoed Slasher with a resolver set and a longer vault epoch
* Focus on capital preservation and strong guarantees over maximum throughput

### Throughput and concentration

* Fewer networks with higher network limits
* A smaller set of top-tier operators with larger limits or shares
* An instant Slasher and a medium or shorter epoch
* Focus on fast settlement, high utilization, and more aggressive risk taking

You can treat these as anchor points and position your own vault somewhere in between, depending on who it is for.

## When active curation is minimal or not needed

Some vault designs intentionally minimize ongoing curator work.

* **Single-network, single-operator designs** often use a Delegator type that effectively hard-codes the network and operator at creation time. After a basic network limit is set, there may be little left to adjust.
* **Immutable, pre-configured vaults** are created once with a fixed configuration and no roles that can change core behavior later. Users opt into a static design rather than a curator’s future decisions.

In those cases, your job as the original curator is mostly to make sure the initial configuration and documentation are correct and to be transparent that the vault will not change over time.

# **Rewards**

Rewards are payments that Networks make to vault participants in exchange for security and work. Rewards are distributed using historical snapshots of vault state, so each participant is paid based on the exact state of the vault at the chosen timestamp.

Rewards may come from protocol fees, scheduled token emissions, external client payments, or amounts routed from slashing (via Burner policy). Symbiotic does **not** dictate the economics; it provides the on-chain contracts that make accurate distribution and claims possible.

![rewards-flow (1).png](/img/rewards-flow.png)

## Rewards mechanism overview

The Rewards system enables Networks to distribute rewards to vault participants using historical snapshots of vault activity. This ensures rewards are calculated from the exact state of vault participation at a specific timestamp, with fees applied according to the rates active at that time.

:::info
Rewards support two mechanisms: `VaultSnapshotRewards` and `CumulativeMerkleRewards`. While `CumulativeMerkleRewards` implements common approach for arbitrary token distributions, this article focuses on `VaultSnapshotRewards`, as it is deeply integrated into Symbiotic vaults, including operator and curator fee splits and direct on-chain calculations based on vault shares.
:::

## Registries

### FeeRegistry

`FeeRegistry` stores fee configurations. It manages three fee types:

* **Operator fees**
* **Curator fees**
* **Protocol fees**

Fee configuration uses a two-level hierarchy with default rates and network-specific overrides. When a distribution is created, the registry returns the fee rates that were active at the distribution timestamp.

### CuratorRegistry

`CuratorRegistry` manages vault-to-curator mappings. Each vault has one curator at any time. The curator can configure and claim fees for a vault, with authorization following this order:

1. Vault owner sets the initial curator.
2. The current curator can update curator settings.
3. If no curator exists, the vault owner can set a new curator.

## Rewards contract interface

The `Rewards` contract provides a unified interface for the reward mechanisms.

### Core functions

`claimRewards()`
Routes reward claims to the appropriate mechanism based on the encoded reward type. For snapshot-based rewards, it extracts the vault snapshot data and processes the claim.

`distributionToTotalAmount()`
Calculates the total amount required to fund a distribution including protocol fees. This helps Networks determine the correct total amount when they want a specific net distribution.

`totalToDistributionAmount()`
Performs the reverse calculation, converting a total amount back to the net distribution amount after protocol fees.

## How rewards are distributed

Networks or their authorized middleware distribute rewards by calling the snapshot distribution function with a historical timestamp. The process follows these steps:

1. **Validate entities**: confirm network and vault registration
2. **Capture historical state**: query the vault’s total active shares at the distribution timestamp
3. **Calculate fee splits**: use `FeeRegistry` to fetch the curator and operator fee rates active at that timestamp
4. **Store the distribution**: record net amounts for each participant type in the distribution

## How participants claim rewards

### Stakers

Stakers claim their proportional share based on vault shares at the distribution timestamp:

`(staker shares / total shares) × reward amount`

### Operators

Operators claim fees based on the delegator type:

* **NetworkRestake**: proportional to the operator’s network shares
* **OperatorSpecific/OperatorNetworkSpecific**: full amount for designated operators
* **FullRestake**: no operator fees

### Curators

Curators claim accumulated fees through the claim function. `CuratorRegistry` validates that only the current curator can claim these fees.

## Fee calculation model

The system uses a fee deduction model where fees are subtracted from the gross amount provided by the distributor:

1. Protocol fees are deducted first.
2. Curator fees are calculated using historical rates from `FeeRegistry`.
3. Operator fees are calculated using historical rates from `FeeRegistry`.
4. Net staker amount is the remaining distribution amount after curator and operator fees.

:::info
The registry system ensures fee configurations and curator permissions are properly tracked over time. This allows the Rewards system to calculate distributions accurately for any historical timestamp, preserving fairness and consistency for all participants.
:::

# **Slashing**

Slashing is how a Network penalizes operators for provable misbehavior. A Network’s middleware sends a slashing request to the vault; the vault’s Slasher module checks timing and amount constraints; if the request is valid, the vault reduces the operator’s effective stake and forwards the penalized collateral to a Burner, which applies the vault’s policy (burn, redistribute, route, etc.). The goal is for penalties to be **executable**, **bounded**, and **auditable**.

## Slasher module

The Slasher is the vault module that enforces penalties. It does not detect faults itself. Instead it:

* reads stake data from the Delegator (how much stake an operator had in a subnetwork at a given time)
* reads its own internal record of previous slashes for the same snapshot
* validates a new request against those guarantees
* if valid, updates its internal records, informs the Delegator if needed, and calls the vault/Burner to handle the tokens

A vault can be deployed with one of three slashing modes:

* **No slashing** — slasher address is zero; the vault can never be slashed
* **Slasher** — instant execution as soon as a valid request arrives
* **VetoSlasher** — a request plus a short veto window, then execution if no veto occurs

Once chosen at deployment, the slashing model for a vault is fixed.

The shared flag `isBurnerHook` controls whether the Burner must be invoked on each slashing event (for example, to unwrap derivatives or forward to another contract).

## Capture timestamp and guarantees

Networks do not slash against arbitrary state. They first **capture** stake at a particular time, then slash against that snapshot.

When a Network fetches stake at some point in time (the *capture timestamp*), it receives a guarantee that the captured amount of collateral will remain slashable for **one vault epoch** after that timestamp. When the Slasher later executes a request, it checks:

1. The capture timestamp is not older than one epoch. If it is, the request is considered stale and rejected.
2. The requested amount does not exceed the remaining guarantee for that capture after accounting for any earlier slashes that used the same snapshot.

This is what makes slashes bounded: you cannot request more than the guarantee tied to that capture.

In restaking setups, a slash on one Network can reduce the guarantee left for others, because they share collateral. That is a property of restaking, not a bug in the Slasher. The capture bound still applies: across all Networks together, you cannot take more than was guaranteed at that snapshot.

## Execution flow

Every penalty follows the same basic flow, regardless of Slasher type.

1. **Submit**

   Network middleware calls the Slasher with a slashing request that includes the subnetwork, operator, amount, and capture timestamp.

2. **Check**

   The Slasher pulls stake data for that capture from the Delegator, aggregates previous slashes for the same snapshot from its own storage, and verifies:

   * freshness (capture within one epoch), and
   * bounds (requested amount ≤ remaining guarantee).

3. **Optional veto (VetoSlasher only)**

   If the vault uses VetoSlasher, the request enters a veto period. For `vetoDuration` seconds after creation, any configured resolver can veto the request. A `resolverSetEpochsDelay` parameter controls how long it takes for newly set resolvers to become active, measured in vault epochs.

4. **Apply**

   If the request passes checks (and veto, if applicable), the Slasher:

   * records the penalty so future requests against the same capture see reduced remaining guarantee
   * triggers any Delegator hook if configured
   * calls the vault/Burner to actually process the penalized collateral

## Slasher types

**Slasher (instant)**

A straightforward module: validate and execute in a single step. There is no on-chain dispute window. This is appropriate when fault conditions and evidence are clear and mature, and the Network is comfortable with immediate penalties.

![Learn Vault 10](/img/learn-vault-10.png)

**VetoSlasher**

Adds an on-chain review window. The flow is “request → veto window → execution”:

* Request: middleware submits and VetoSlasher validates.
* Veto: resolvers have `vetoDuration` seconds to veto.
* Execution: if no veto is recorded, the Network calls execute and the penalty is applied.

`resolverSetEpochsDelay` enforces that new resolvers only become active after a minimum number of vault epochs, giving users a chance to exit before a change in the dispute set takes effect.

![Learn Vault 11](/img/learn-vault-11.png)

**No slashing**

Slasher is set to address(0). The vault cannot be slashed at all. This degrades the economic security guarantees for Networks and should be an explicit design choice.

## Burner

Once a slash is approved, the Slasher delegates the token handling to the Burner. The Burner defines what happens to penalized collateral. Typical patterns include:

* unwrapping derivative collateral and burning the underlying
* redistributing all or part of the penalty to stakers or well-behaving operators
* sending funds to a treasury or insurance pool
* locking tokens or routing them to another contract for protocol-specific logic

The Burner is configured per vault at deployment and is not automatically changed by slashing events. Burning is optional; redistribution is a valid outcome if it matches the vault’s policy.

## Participation and isolation

A slashing request only applies if, at the capture timestamp:

* the operator had opted into both the vault and the Network (including the relevant subnetwork), and
* the Delegator reports positive effective stake for that operator in that subnetwork.

If either condition fails, the request is rejected. This ensures Networks cannot accidentally penalize non-participants.

Whether a slash affects only one Network or multiple depends on the vault’s delegation model:

* **Single-Network / single-operator vaults** give strong isolation: a penalty for one Network does not spill over to others because the collateral is not reused.
* **Multi-Network restaking vaults** share collateral across Networks. A penalty in one Network reduces what remains for others, but each individual penalty is still capped by its capture-time guarantee and checked by the Slasher.

## Timing constraints

To keep slashing executable, the following must fit inside the vault epoch:

* the Network’s own epoch and finality / detection delay
* any off-chain time to build and submit a slashing request
* the veto period (`vetoDuration`), if using VetoSlasher
* the time to send and finalize the execution transaction

If downstream systems (for example, a dispute layer) require longer resolution, the vault’s `epochDuration` should be set high enough so that valid slashes can still be committed and executed before the guarantee expires.

# **Registries and Opt-ins**

## Registries

Registries give Networks and Operators a canonical on-chain identity that the rest of Symbiotic can reference.

### NetworkRegistry

Stores all Networks that can receive stake, be captured, and issue slashes or rewards. A Network registers once (for example via `registerNetwork()`), then:

* can be discovered by vaults, operators, and tooling
* can be linked to its middleware, which is the only address allowed to send slashing and rewards requests on its behalf

Only registered Networks can set per-vault limits and interact with Slasher and Delegator modules.

### OperatorRegistry

Stores all Operators (EOAs or contracts) that can receive stake and be slashed. After registering (for example via `registerOperator()`), that operator ID is used everywhere:

* opt-in services track operator–vault and operator–network opt-ins
* vault Delegators use it when returning effective stake
* slashers reference it when enforcing penalties

Unregistered operators cannot be allocated stake.

(Other registries such as token or collateral registries are used similarly: they define which assets are valid and how they are handled, but they do not change the opt-in rules.)

## Opt-ins

Opt-ins establish **consent and scope**. They define which combinations of vault, operator, and network are actually allowed to interact, so that:

* a Network can only penalize stake that was explicitly made available to it
* a vault can only allocate to operators that agreed to serve it
* an operator can only be evaluated for Networks it chose to join

This keeps slashing and rewards precise and prevents accidental penalties.

### Opt-in surfaces

Opt-ins live at the contact points between roles:

* **Operator → Vault** via `OperatorVaultOptInService`

  The operator opts into a specific vault (and can later opt out). Without this, the vault cannot
  allocate stake to that operator.

* **Operator → Network** via `OperatorNetworkOptInService`

  The operator opts into a Network (and its subnetworks) it is willing to serve.

* **Network → Vault** via the vault’s Delegator

  The Network expresses willingness to accept stake from a vault by setting a per-vault maximum,
  e.g. `setMaxNetworkLimit(subnetwork, maxStake)`.

* **Vault → Network and Operator** via Delegator configuration

  The curator allocates stake by setting non-zero limits or shares for a Network and for each
  operator inside that Network (for example `setNetworkLimit()`, `setOperatorNetworkLimit()`, or
  `setOperatorNetworkShares()` depending on Delegator type).

**Eligibility rule**

An operator is actually eligible for stake in a given Network through a given vault only if, at the relevant timestamp:

* the operator is opted into that vault
* the operator is opted into that Network
* the Network has set a non-zero max limit for that vault
* the vault’s Delegator has a non-zero limit or share for that operator in that Network

If any of these are missing, the Delegator returns zero stake and the Slasher will reject penalties for that pair.

### Timing and capture

Opt-ins are time-aware. All checks are evaluated at the **capture timestamp** the Network includes in its request:

* when a Network captures stake at time *T*, it receives a guarantee that the reported amounts remain slashable for one vault epoch after *T*
* when a slashing request is executed, the Slasher verifies that the capture timestamp is no older than one vault epoch and that all required opt-ins and limits were in place at that time

Opt-outs and limit changes are **forward-looking**:

* if an operator opts out today, a Network can still slash for misbehavior tied to a capture from yesterday, as long as the capture is still inside the epoch window
* new captures taken after the opt-out will see zero stake and cannot be used for future penalties

### Lifecycle and revocation

Each participant can change its opt-ins at any time:

* operators can opt in / opt out of vaults and Networks (or invalidate signatures)
* Networks can raise or lower per-vault max limits
* curators can adjust per-network and per-operator limits and shares

These changes affect **future** captures and allocations. Previously captured guarantees remain valid until they age out of the epoch window. This prevents last-minute exits from making valid penalties impossible to execute.

## Vault access vs opt-ins

Deposit access and opt-ins are separate:

* vault-level settings such as `depositWhitelist`, `depositLimit`, and their admin roles control **who can deposit** and **how much collateral** can be active
* opt-ins and Delegator limits control **who can be allocated stake** and **who can be captured, rewarded, or slashed**

A private, allowlisted vault still requires proper opt-ins and Delegator configuration before any operator can receive stake. A public vault can accept deposits from anyone but will not actually expose those deposits to a Network or operator unless all relevant opt-ins and limits are in place.

# **Epochs and Delays**

Epochs are the time rules of Symbiotic. They tell you when validator sets update, when withdrawal requests can be claimed, and how long captured guarantees stay slashable. Grouping changes at epoch boundaries keeps the stake that networks rely on stable and easy to verify.

## Vault Epochs

Each vault has an **epoch duration** set at deployment (`epochDuration`). All epochs for that vault:

* are consecutive and equal length
* use the same duration unless the curator later increases it

Vault epochs drive two things:

1. When queued withdrawals become claimable
2. The maximum look-back window for slashing previously captured guarantees

### Withdrawal Timing

Withdrawals are a two-step, epoch-based process.

* A user submits a withdrawal request at time `t` inside epoch `k`.
* The request becomes claimable **after epoch `k+1` ends**.

If the epoch length is `E`:

* the effective delay from request to claim is in `[E, 2E)` depending on when in the epoch the user requested
* until the boundary at the end of epoch `k+1`, the requested funds remain slashable

After that boundary, the withdrawal can be claimed and is no longer subject to new slashes.

### Capture and Slashing Window

Networks do not slash against live state; they slash against **captures**.

* A **captureTimestamp** is the time a Network uses to snapshot stake and validator sets.
* At capture, the Network receives a guarantee that the captured amounts remain slashable for one **vault epoch** after that timestamp.

When a slashing request is executed, the Slasher enforces:

1. **Freshness**

   If the capture is older than one epoch at execution time, the request is rejected: `now − captureTimestamp ≤ vaultEpoch`

2. **Bounded amount**

   Let

   * `G` = guarantee captured at `captureTimestamp`
   * `C` = cumulative slashes already applied for that same capture

   <p>Then any new slash must satisfy: `slashAmount ≤ G − C`</p>

This anchors penalties to a specific snapshot and prevents double-charging or overshooting the guarantee.

## Network Epochs and Buffers

Vault epochs need to be large enough to contain the **end-to-end slashing path** for a Network.

Roughly:

`validatorSetCaptureDelay + networkEpoch + vetoWindow + executionWindow  ≪  vaultEpoch`

Where:

* `validatorSetCaptureDelay` – time to produce and publish the operator set / stake snapshot
* `networkEpoch` – how often your network rotates or commits a new set
* `vetoWindow` – VetoSlasher review period, if used
* `executionWindow` – operational buffer to actually call the Slasher and finalize the transaction

If the sum approaches the vault epoch, captures risk expiring before penalties can be executed. Either shrink the network-side timings or use a vault with a longer epoch.

### Lifecycle Notes

Epoch changes and events interact like this:

* Freshness checks use the **current** vault epoch at verification time, not the epoch duration that was in effect when the capture was taken.
* Withdrawals are slashable until the first boundary where they become claimable (end of epoch `k+1` for a request in epoch `k`).

### Examples

**7-day vault epoch, mid-epoch withdrawal**

* `E = 7 days`.
* User requests withdrawal on day 2 of epoch `k`.
* Claim is possible right after epoch `k+1` ends → between 7 and 14 days from the request, depending on where in the epoch they requested.
* Funds remain slashable until that boundary.

**Safe timing for slashing**

* Vault epoch `E = 8 days`.
* `validatorSetCaptureDelay = 6h`, `networkEpoch = 24h`, `vetoWindow = 12h`, `executionWindow = 6h`.
* Total = 48h, well below 8 days → captures stay fresh and enforceable with plenty of margin.

# **Voting Power**

The `VotingPowerProvider` is the Relay contract that turns **delegated Symbiotic stake** into **operator voting power** inside a validator set. It sits between Symbiotic Core (vaults, operators, networks) and the Relay settlement layer, and exposes a clean interface for:

* which operators are in the validator set
* how much voting power each one has
* what that power was at a specific timestamp (for verifying old decisions)

This is what Relay uses to build validator sets and what Settlement uses to verify signatures.

### Inputs

At a high level, VotingPowerProvider pulls three kinds of data:

* **Stake and vault state** from Symbiotic Core (how much collateral each operator has in which vaults / networks).
* **Onboarding / filtering modules**, e.g.
  * OperatorsWhitelist / OperatorsBlacklist / OperatorsJail – which operators are even allowed in the set
  * SharedVaults / OperatorVaults – which vaults are considered for this network
  * MultiToken / OpNetVaultAutoDeploy – which tokens and “auto-created” vaults are in scope
* **Voting power calculators**, which define how raw stake → voting power.

The public view methods (like `getOperatorVotingPower` and `getOperatorVotingPowerAt`) are what off-chain tooling and Relay’s `ValSetDriver` actually call when they derive the active set and its weights.

## From Delegated Stake to Voting Power

The core idea: **delegated stake is the input**, but the contract lets you pick the function that maps “stake” to “voting power”.

Some standard derivations:

* **Equal** – every opted-in operator gets the same power, regardless of stake. Useful for “one node, one vote” or PoA-style governance.
* **Linear** – power proportional to stake. This is the vanilla PoS model: double the effective stake, double the voting power.
* **Capped / concave** – diminishing returns at higher stake. You can cap per-operator power or use a concave function to stop one operator from dominating the set even if they bring a lot of collateral.
* **Behavior-aware** – adjust weights based on uptime, freshness, or custom performance metrics. In practice you’d compute a “score” off-chain and feed it in via weights or parameters that sit on top of the base calculators.

`VotingPowerProvider` achieves this through a plug-in set of **VotingPowerCalculators**. The repo ships with several that you can compose or chain:

* `EqualStakeVPCalc`
* `NormalizedTokenDecimalsVPCalc` – normalize all tokens to 18 decimals
* `PricedTokensChainlinkVPCalc` – convert different tokens to a common value using Chainlink price feeds
* `WeightedTokensVPCalc` – apply token-level weights
* `WeightedVaultsVPCalc` – apply vault-level weights (e.g. “this vault counts 1.2×, that one 0.8×”)

Networks can pick a simple single calculator (e.g. “linear stake using normalized decimals”) or a pipeline (“normalize decimals → price everything in ETH → apply vault weights”).

## Multi-Token Considerations

In practice, stake can come from multiple collaterals across several vaults:

* LST A, LRT B, native token, etc.
* different decimals and potentially different prices

`VotingPowerProvider` does **not** impose one global rule here; it just provides building blocks. The network defines:

* which tokens are accepted (via MultiToken module and supported-token registration)
* how each token is converted into a single comparable number (e.g. price feeds, fixed haircuts, or simple 1:1)
* whether some tokens or vaults get higher or lower weight in the final voting power

The end result is a single voting power number per operator that already bakes in all these decisions.

## Quorum and Time Variation

Once voting power is defined, the network can reason about **quorums** and **thresholds**:

* decisions might require > 50% or ≥ 2/3 of total voting power
* some sub-protocols (e.g. light client, DA, bridge) can have their own minimum voting power requirements

Voting power is **time-varying**:

* stake moves in and out of vaults
* operators join, leave, or are jailed / unregistered
* token prices change if you use price-based calculators
* off-chain behavior metrics change over time

To keep things tractable, most networks **update the validator set once per epoch** and use that snapshot for all decisions in that period. Relay’s contracts are built around this:

* `ValSetDriver` uses `VotingPowerProvider` to derive the validator set at a chosen genesis and at subsequent epochs.
* `Settlement` verifies signatures against exactly that compressed validator set header, so verifiers and networks agree on which power distribution applied.

This gives you a clean, epoch-by-epoch history of “who had how much power when”.

## With and Without Relay

You can think of `VotingPowerProvider` as the **Relay version** of what a custom middleware might do.

* **Without Relay**
  Your own middleware reads vault accounting and Delegator state directly from Symbiotic Core, applies your stake → voting power rules off-chain, and uses that to drive your protocol. You still need to handle cross-chain verification and efficient proof formats yourself.
* **With Relay**
  `VotingPowerProvider` is the on-chain oracle of voting power for the Relay network. Relay’s off-chain sidecar and ValSetDriver:
  * read operator/vault data from Symbiotic Core
  * call `VotingPowerProvider` to get per-operator voting power
  * compress that into a validator set header
  * commit it into `Settlement`, which is then used to verify aggregated signatures on any connected chain

In other words: `VotingPowerProvider` is where you **define what “power” means** for your network, and Relay takes that definition and turns it into a cheap, verifiable validator set you can reuse everywhere.

# **Valset (Validator Set)**

The **validator set** is the current list of operators and their weights that a network uses for signing and verification during a given epoch. In Relay, this is represented by a **validator set header** that ValSetDriver helps derive and then commit to the Settlement contracts.

At any moment in an epoch, the validator set answers three questions:

* which operators are active
* which keys they use to sign
* how much **voting power** each one has (as computed by the VotingPowerProvider)

Applications and Settlement never recompute this themselves – they read the committed header and verify signatures against it.

## Epoch Formation

`ValSetDriver` is the on-chain “driver” the Relay binary uses to derive validator sets epoch by epoch. At the start of each network epoch (or whenever the network decides to rotate), the off-chain Relay nodes:

1. **Discover eligible operators**
   * Read operator/vault relationships and voting power from `VotingPowerProvider`.
   * Respect onboarding modules (whitelist/blacklist/jail, shared vs operator vaults, multi-token rules) so only **registered and permitted** operators are considered.
   * Filter to operators that have opted into the network and meet minimum power / inclusion constraints configured in `VotingPowerProvider`.
2. **Select active key material**
   * Fetch cryptographic keys for these operators from `KeyRegistry` (BLS BN254 or ECDSA secp256k1).
   * Enforce key requirements: tags, key types, and quorum / threshold rules as configured via `ValSetDriver`.
3. **Assign weights**
   * Call `VotingPowerProvider` to get each operator’s **voting power** for this network (stake → power, token weights, vault weights, etc.).
   * Apply any network-side caps (e.g. max power per operator, max validator count) that `ValSetDriver` exposes for Relay config.
4. **Fix the decision threshold**
   * Choose a decision rule like `> 50%` or `≥ 2/3` of total voting power.
   * Encode this into the header metadata so `Settlement` and applications know what constitutes a valid quorum for verification.
5. **Produce a compact header**
   * Compress: operator IDs, keys (or key hashes), weights, epoch number, network id, and the chosen threshold into a **ValSetHeader**.
   * Compute a `headerHash = keccak256(abi.encode(header))` (conceptually – exact struct is handled inside the contracts).

This header is what gets committed on-chain and later used by `Settlement` and apps to verify aggregated signatures.

## Storage and Rotation

`ValSetDriver` and `Settlement` together manage **storage and rotation** of validator sets:

* **Epoch-based rotation**
  * `ValSetDriver` tracks **epoch timing** and exposes the current epoch start / duration to Relay nodes.
  * At each epoch boundary, Relay derives a new validator set and sends its header to the Settlement contracts.
* **On-chain storage**
  * Settlement stores the current header (and usually some history) in **compressed form**, keyed by epoch or sequence.
  * The driver and Settlement together act as the on-chain source of truth: “for epoch N, these are the validators, weights, and threshold”.
* **Design constraint**
  * Network epochs should be long enough that the whole path
    “observe stake → compute voting power → derive set → aggregate signatures → post header”
    reliably fits inside the epoch window, otherwise headers risk arriving late.

## Cross-chain Commitment

Relay is designed to support **multiple chains** from a single validator set.

* `ValSetDriver` holds configuration for:
  * which `Settlement` contracts (replicas) exist on which chain IDs
  * verification type (Simple vs ZK) and per-replica parameters (e.g. quorum thresholds, gas-oriented constraints)
* For each epoch, the Relay binary:
  * derives one validator set header
  * commits that same header to all configured Settlement replicas

Applications on any of those chains read the **same header**, so verification of a given message is consistent everywhere.

## Enforcement and Verification

Once a header is committed, it becomes the **reference set** for signature checks until the next epoch’s header replaces it.

* **Verification contracts**
  * Settlement uses either `SimpleVerifier` (compressed full set verification, good up to ~125 validators) or `ZKVerifier` (zkSNARK-based proof) to check that an aggregated signature meets the threshold for the committed set.
* **Enforcement properties**
  * If a signature is produced using a key that is **not in the header**, verification fails – the key has no registered voting power for that epoch.
  * If the aggregated signature does not correspond to a subset of validators whose **total voting power ≥ threshold**, verification fails.
  * If a malicious or misconfigured app tries to verify against an old header, it will only succeed if that header is still the one committed for the relevant epoch / sequence.

From the network’s perspective, that means:

* you get deterministic, epoch-by-epoch validator sets derived from Symbiotic stake and operator status
* anyone on any connected chain can cheaply verify that “this message was signed by enough power in the active set for epoch N” using only the committed header and the verifier contracts.

So, if **VotingPowerProvider** defines *how much* power each operator has, **ValSetDriver + Settlement** define *which set* is active at a given time and enforce that only that set – with its weights and threshold – can authorize decisions.

# **Secure Attestations**

Secure attestations are **stake-backed signatures over a message hash** that contracts can verify against the active validator set header.

Concretely:

* The **validator set** for epoch `e` is fixed by a committed header (operators, keys, weights, threshold).
* Operators in that set sign a **message hash**.
* An aggregator combines these signatures into an aggregate proof.
* A **Settlement** contract on the destination chain verifies the proof against the header for epoch `e`.

## Message Contents (typical)

The protocol doesn’t hardcode a single message struct, but in practice you want something like:

* `networkId` – Relay network identifier
* `subnetworkId` – optional, for partitioned logic
* `epoch` or `valsetId` – which validator set header must be used
* `payloadType` – enum or tag (bridge, checkpoint, oracle, etc.)
* `payloadHash` – hash of the actual data your app cares about
* `dstChainId` – EVM chain where this will be verified
* `dstApp` or `dstContract` – target contract / app identifier
* `expiry` – timestamp or block after which the attestation is invalid
* `nonce` – monotonically increasing per channel / app

You encode this structure, compute `messageHash = keccak256(encodedMessage)`, and **only `messageHash` is signed** by operators.

## Aggregation and Verification

The flow is:

1. **Build the message**

   Middleware or the app constructs the message struct, fills `epoch`, `dstChainId`, `dstApp`, `nonce`, `expiry`, etc., and computes `messageHash`.

2. **Operators sign**

   Each operator in the **current validator set for `epoch`** signs `messageHash` with its registered key (BLS or ECDSA, depending on your Relay config).

3. **Aggregate off-chain**

   An aggregator collects signatures and:

   * for the **Simple** path:
     * aggregates BLS signatures into `sigmaAgg`
     * builds a participant bitmap / list
   * for the **ZK** path:
     * uses the individual signatures and weights to generate a zk proof that “signers’ voting power ≥ threshold for header H and messageHash M”

4. **Submit to Settlement**

   On the destination chain, the aggregator (or any relayer) calls something like:

   * `settlement.verifyAndConsume(message, epoch, sigmaAgg, participants)` for Simple, or
   * `settlement.verifyAndConsume(message, epoch, zkProof)` for ZK.

5. **On-chain check**

   Settlement:

   * loads the **validator set header** for `epoch`
   * reconstructs keys and weights from that header
   * runs either:
     * **SimpleVerifier**: check BLS aggregate against the participants and ensure their summed voting power ≥ threshold
     * **ZKVerifier**: check the proof that encodes both signature validity and power ≥ threshold

   If verification passes, your app logic (bridge, rollup, oracle, etc.) is allowed to execute.

## Safety Properties

Secure attestations are tied down in a few specific ways:

* **Bound to a validator set**
  The message includes `epoch` (or a valset ID). Settlement only verifies against the header stored for that epoch. An attestation for epoch `e` cannot be validated against the header for epoch `e+1`.
* **Bound to destination**
  `dstChainId` and `dstApp` are part of the signed payload. The same hash cannot be replayed on a different chain or different contract because the signature is over the full encoded message.
* **Replay protection**
  Your app (or Settlement integration) tracks:
  * `nonce`: reject messages with a nonce ≤ lastSeenNonce for that channel / app
  * `expiry`: reject messages whose expiry is in the past
* **Slashable misbehavior**

  If operators sign:

  * two different payloads for the same `(networkId, subnetworkId, epoch, nonce)`
  * or obviously invalid content (e.g. violates your protocol’s invariants),

  that evidence can be fed into your Network’s middleware, which then submits a **slashing
  request** to the relevant vaults in Symbiotic. The economic backing for those keys is what makes
  the attestation “secure”.

So in short: a secure attestation is a message bound to a specific epoch, network, and destination, proven on-chain to have signatures from enough stake-weighted operators in that epoch’s validator set.

# **Settlement**

Settlement is the on-chain endpoint for Relay. It stores validator set headers (operators, keys, weights, thresholds) per network / subnetwork / epoch and verifies aggregated signatures (attestations) against those headers on the chains where apps live. Applications don’t talk to `VotingPowerProvider` or `ValSetDriver` directly; they call Settlement to check whether enough of the current validator set signed a given message.

### Contract responsibilities

Settlement instances (one per Relay network per chain) are responsible for:

* **Committing headers**

  Accept compressed validator set headers (for example, once per epoch) and store them keyed by `(network, subnetwork, epoch)`.

* **Verifying attestations**

  Given:

  * a message (or hash)
  * an epoch / header ID
  * an aggregate signature or zk proof

  Verifier checks:

  * the proof matches the message
  * the participating validators’ total voting power is at least the threshold from the header

  If both hold, it returns success so the calling app can continue.

### Multi-chain

The same validator set can secure multiple chains. Each chain runs its own Settlement instance, and the Relay committer posts the same header to all replicas. Applications on different chains therefore verify against identical validator sets and thresholds for a given epoch, even though verification is performed locally on each chain.

### Cost model (intuition)

Costs stay near-flat in validator set size. Header updates are small, infrequent writes because a compressed header is stored once per epoch. Verifying an attestation requires a single aggregate check: with the Simple verifier this is one BLS aggregate pairing plus summing the listed signers’ weights, while with the ZK verifier it is one zkSNARK verification where the signer set and weight check are already encoded in the proof. You pay per attestation, not per validator.

### Failures

Verification fails (returns false / reverts) if:

* the referenced epoch or header is not committed or does not match the network
* the proof is invalid or does not match the message hash
* the signing validators’ total voting power is below the threshold

In all of these cases, the application must not execute the gated action (no unlock, no finalize, no state update).

# Overview

Symbiotic’s **Instant Liquidity** product enables **redemptions** for otherwise illiquid or time-locked assets by sourcing liquidity from **curator-managed Symbiotic vaults**. Symbiotic’s collateral management infrastructure facilitates market makers to use vault liquidity for the sole purpose of quoting, filling, and natively processing redemptions via an **onchain RFQ workflow**.

Vault LPs underwriting this product stand to earn the spread from these redemption flows while continuing to receive base yield on idle funds through DeFi adapters such as Morpho, as well as additional yield from exposure to Symbiotic networks.

The Instant Liquidity product is designed for RWAs and crypto derivative assets (e.g. RWA, Liquid Staking Tokens, Vault receipt tokens) where primary liquidity is episodic constrained (e.g. withdrawal queues, redemption windows, vault lockups), and where market makers can price duration in exchange for composable yield for vault depositors supplying short-term liquidity.

![General overview](/img/LL-1.png)

## About Symbiotic V2

Symbiotic is a modular collateral and yield infrastructure that lets institutions and applications deploy, manage, and route productive assets across onchain market structures. Backed by Pantera and Paradigm, Symbiotic is built to make collateral *programmable*: vaults, curators, and adapters can be composed to create market-specific risk and yield profiles.

Instant Liquidity is one example of this broader “Collateral Markets” strategy, following the successful collaboration with Cap, where Symbiotic powers >$250m of collateral underwriting borrowers like Susquehanna, M11 Credit, and others. It uses curator-managed, yield-generating vault collateral to underwrite redemption flows for assets whose native liquidity is episodic or time-locked, turning productive collateral into reliable, onchain liquidity while preserving base yield and risk controls.

## Key Facts

|                         |                                                                                                                                                                                                                                                |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Capital Usage**       | LP capital sits in curator-managed vaults earning base yield from lending markets (and/or delegating to Symbiotic networks) and is deployed when market makers draw liquidity to fill redemptions.                                             |
| **Vault LP Yield**      | Yield generated from market maker usage of vault liquidity (fees/spread share), driven by redemption demand (early exits and liquidations) + base yield from DeFi lending and Symbiotic networks.                                              |
| **Typical Duration**    | Vaults on average have a 14 day lockup period, but a curator may still service liquidity for an RWA redemption that exceeds this window. It is up to curators to manage this based on their different liquidity and risk management practices. |
| **Eligible Collateral** | USDC (Cohort 0) + wETH & wBTC/cbBTC & other stablecoins (Cohort 1 onwards)                                                                                                                                                                     |
| **Risks**               | • Product-related risks (duration, liquidity, operational)<br />• Infrastructure-related risks (smart contracts, front- and backend (API), oracle)                                                                                              |
| **Settlement**          | • Native redemption with asset issuer<br />• A second market maker-triggered RFQ sale of the asset                                                                                                                                              |

## Supported Assets

* **Cohort 0**

| Asset     | Issuer | Fund Manager / Operator   | Accepted Collateral |
| --------- | ------ | ------------------------- | ------------------- |
| mGLOBAL   | Midas  | Fasanara Capital          | USDC                |
| mF-ONE    | Midas  | Fasanara Capital          | USDC                |
| mROX      | Midas  | RockawayX                 | USDC                |
| mTBILL    | Midas  | Midas                     | USDC                |
| mRe7YIELD | Midas  | Re7                       | USDC                |
| mAPOLLO   | Midas  | Apollo Crypto             | USDC                |
| mEDGE     | Midas  | Edge Capital (UltraYield) | USDC                |
| mXRP      | Midas  | Hyperithm                 | USDC                |
| mEVUSD    | Midas  | Everstake                 | USDC                |

*Further collateral assets and redemption assets will be added in the future. Interested teams can get in touch with Symbiotic to support specific assets for redemptions or as collateral.*

## Detailed Flow

<aside>
  This example outlines the swap and redemption flow for a USD-denominated RWA settled in USDC. It is possible to use other stablecoins that serve as RWA subscription asset for servicing these flows. Additionally, this product is planned to expand to service ETH- and BTC-based derivatives, which would be serviced by ETH- and BTC-based collateral respectively.
</aside>

![General overview](/img/LL-2.svg)

At first, the market maker deploys a Symbiotic USDC vault, which can be done easily through the Symbiotic frontend and factory, and decides to allocate the collateral to a DeFi Strategy while it is not in use.

This vault is associated with a “Market Maker Symbiotic Contract” that facilitates the execution logic and redemption flow.

The redemption flow is divided into six steps:

1. An asset manager requests an RWA swap through a specific frontend or RFQ system such as the Symbiotic RFQ.
2. The market maker has integrated the RFQ API and receives the request. They can then bid by signing an order and submitting it to the RFQ backend, as with any other exchange.
3. The market maker triggers the transfer of USDC to the asset manager.
4. The Market Maker Symbiotic Contract pulls the required USDC from the Symbiotic vault.
5. The asset manager sends the RWA to the Symbiotic contract.
6. The USDC is released to the asset manager atomically.

![General overview](/img/LL-3.svg)

At this point, the market maker Symbiotic contract holds the RWA, and it needs to be redeemed for the underlying vault asset, USDC. This can be done in two different ways:

1. The market maker acquires the RWA into their own portfolio and assumes the duration risk.
2. The market maker redeems the RWA with the issuer. During this period, the RWA continues earning its intrinsic APY.

## Value Propositions

* **Real yield, not points farming**: returns come from real demand for liquidity (instant redemptions and liquidations).
* **Institutional-grade exposure through delegation**: LPs benefit from deploying collateral assets (stablecoins/WETH/WBTC) into curator-managed vaults, without needing to run RFQ quoting infrastructure themselves.
* **Risk-managed allocations**: curators set asset-specific parameters (limits, counterparties, additional allocations to Symbiotic networks and external lending markets) to control how capital is used.
* **Distribution & integrations**: the product is designed to plug into wallets, vaults, and RWA issuance/redemption flows, aggregating demand into a single quoting surface.

## Reward Profile

Vault depositors stand to earn a blend of three distinct yield sources, depending on the exposure and strategy of their vault’s curator:

* **Servicing redemption:** The Instant Liquidity product enables vault depositors to earn part of the spread market makers achieve by acquiring discounted assets through RFQ bids and native protocol redemptions (or secondary auctions).
* **Liquidity buffer earning base yield:** Symbiotic’s collateral management infrastructure enables programmable deployment of collateral to earn base yield while no redemptions are serviced.
* **Long-duration exposure:** vault collateral can be delegated Symbiotic networks, such as underwriting Nexus Mutual to earn on DeFi cover premiums.

## Risk Profile

Vaults utilizing the Instant Liquidity product and associated infrastructure are exposed to risks that may differ depending on the vault curators allocations to adapters, the serviced redemption assets, as well as vault-associated bidding strategies in the RFQ process.

*Product-related Risks*

* **Duration risk**
  * Underlying asset prices may move in unfavorable directions (NAV impairment) leading to loss of value when natively redeeming.
* **Lending adapter liquidity risk**
  * Allocations to Symbiotic DeFi adapters determine how much vault capital is deployed e.g. into lending markets to earn a base yield. Lending market utilization spikes can affect liquidity available for RWA redemptions and vault withdrawals.
* **Duration mismatch liquidity risk**
  * If the vault’s withdrawal delay is shorter than the underlying asset’s redemption window, liquidity may not be available in time to service withdrawals from vault depositors.
* **Operational risk**
  * Curator and RFQ participant-controlled keys and infrastructure determine allocation strategies and bids being placed and can in the case of compromise or mishandling lead to unexpected outcomes. The flow of funds is constraint by Symbiotic core contracts and Instant Liquidity-related adapters limiting the surface area.
* **RWA liquidity and settlement risk**
  * For some asset types, native redemption paths may be gated meaning ability to redeem may extend beyond expected dates or face illiquidity for other issuer-related reasons.

<aside>
  *The combination of assumed duration risk and curator-driven liquidity management may create race conditions for vault depositors withdrawing as NAV impairment losses are not socialized (in V1 of Instant Liquidity). Curators have the responsibility to manage their allocations sensibly and keep their LPs informed on their strategies and performance. LPs should due diligence their vault curators, as well as monitor their positions and underlying vault allocations accordingly.*
</aside>

*Infrastructure-related Risks*

* **Smart contract, front- and backend infrastructure risk** (Symbiotic core contracts, UI and API infrastructure)
* **Oracle provider-related risks** (asset prices and NAV reporting)

## Who This Is For

* **Asset issuers** looking to expand distribution, improve secondary liquidity, and provide instant redemptions for tokenized products without relying on expensive liquidity incentives or idle capital buffers.
* **Institutional LPs** (capital providers) who want to earn yield from instant-redemption liquidity demand.
* **Vault curators** who can underwrite parameters, select/whitelist market makers, and manage allocations to service redemptions, as well as to low-risk DeFi opportunities for idle capital, and Symbiotic networks for additional exposure.
* **Market makers** that seek to place bids for discounted assets to service redemptions or liquidations, while tapping into onchain vault liquidity.

# Capital Efficiency Analysis

## Executive Summary

As tokenized real-world assets (RWAs) scale toward institutional adoption, liquidity provision for secondary market trading is a central bottleneck. Issuers offering USD-denominated products face a recurring design question: how should they service redemptions? Three broad approaches exist — maintaining a liquidity buffer, seeding DEX liquidity pools per asset, or more recently: deploying a curator-managed instant liquidity vault through Symbiotic’s infrastructure.

This article dives into the design choices comparing capital efficiency differences for an illustrative issuer managing two RWA funds, with a shared $10M USDC liquidity budget. Instant redemptions from Midas’ mHYPER and mF-ONE were used to model the different scenarios and swap flows.

Using scenario analysis grounded in observed redemption data and current DeFi lending yields, the results are stark: an idle buffer (that allocates idle capital to a lending market) can earn up to 6.5%, but reduces the intrinsic APY of the vault strategy or asset. A DEX LP can earn up to 5%, but remains exposed to the risky asset for most of the time and requires double the capital, despite offering weaker liquidity guarantees. Meanwhile, Symbiotic’s instant liquidity product can generate 9%+ without even accounting for additional yield paid by Symbiotic applications on top of it.

Note: this analysis only takes into account 2 assets. With a broader set of assets, the yield gap between Symbiotic’s approach and the idle buffer would likely increase substantially.

## The Liquidity Problem in Tokenized RWAs

Most tokenized assets — from private credit to alternative strategies — feature episodic or time-locked primary liquidity: structured redemption windows, T+3 to T+90+ settlement cycles, NAV-based queues, or gated redemptions. An investor wishing to exit before a window reopens or a DeFi protocol needing to liquidate have no natural counterpart. This creates a structural demand for secondary liquidity infrastructure — a mechanism that guarantees an exit at or near NAV at any time.

The market for tokenized RWAs has reached over $30b in asset value as of May 2026, but secondary market depth remains thin for most non-treasury assets. Real liquidity, as Bryan Choe from RWA.xyz notes, "comes from exits, either through a clearly defined redemption mechanism or a deep secondary market with willing buyers". For issuers, how that liquidity is capitalized determines not just the user experience, but the annual cost — or return — on tens of millions in reserved USDC.

## Scenario Setup

The analysis models an issuer with two USD-denominated RWA funds and $10M of available capital to build liquidity for those assets. The assets span a range of durations and yields, calibrated using real product data from Midas assets.

| Asset | Proxy       | Instant Fee | Redemption Window | Intrinsic APY | Observed Instant Redeem % |
| ----- | ----------- | ----------- | ----------------- | ------------- | ------------------------- |
| RWA-1 | mHYPER-like | 0.50%       | T+3               | 8.00%         | 22%                       |
| RWA-2 | mF-ONE-like | 1.00%       | T+35              | 9.50%         | 43%                       |

The proxy data comes from Midas’ frontend and from onchain events emitted by the protocol.

## Approach 1: Idle Liquidity Buffer

The simplest approach is a manually managed USDC reserve. The issuer holds $10M in USDC (or short-duration equivalents) earmarked for redemptions. Bots or staff monitor inflows and manually release funds when requests arrive.

**Capital efficiency problem:** An idle buffer can only allocate capital to highly liquid yield sources, e.g., Morpho, and is almost always embedded into the asset itself. This means the capital cannot be shared across multiple assets. It also reduces the intrinsic APY of the strategy, as part of the capital remains structurally underutilized.

![General overview](/img/CA-1.png)

The buffer does provide full coverage flexibility — $5M per asset can, in principle, absorb any single-asset redemption surge. But the capital never works dynamically: it remains limited to highly liquid yield sources and cannot be efficiently shared across assets, reducing overall capital efficiency relative to more productively deployed alternatives.

### **Outcome on $10M ($5M per asset):**

| Income/Cost Item                                   | Amount                   |
| -------------------------------------------------- | ------------------------ |
| Base lending yield (4% on idle capital via Morpho) | +$290,000                |
| Redemption spread income                           | +$361,068                |
| **Net annual return**                              | **+$651,068 (6.5% APY)** |

![General overview](/img/CA-2.png)

![General overview](/img/CA-3.png)

## Approach 2: DEX Liquidity Pools (RWA ↔ USDC)

![General overview](/img/CA-4.png)

An alternative is to seed secondary market DEX pools — one per asset — so that token holders can swap RWA tokens for USDC at any time. The issuer (or a subsidized LP) deposits $2.5M worth of USDC into each pool, structured as a 50/50 RWA/USDC pair.

However, the structural inefficiencies of this model compound quickly and make liquidity guarantees unreliable at scale.

### Siloed Capital

Each pool locks dedicated USDC liquidity per asset. If redemption demand concentrates in one fund — for example, mF-ONE following a macro event — only the liquidity available in that specific pool can absorb exits. Liquidity sitting idle in other pools cannot be dynamically redirected, even if unused. In practice, this fragments capital across asset boundaries despite redemption demand being highly unpredictable.

### Continuous Exposure to Underlying Asset Risk

The LP remains exposed to the underlying RWA risk at all times. Half of the capital is directly allocated to the RWA itself, meaning LPs bear the underlying credit, duration, and NAV risk of the asset. Yet despite taking that exposure, the total LP return can still underperform simply holding the RWA directly.

This occurs because the AMM structure continuously sells appreciating RWA exposure back into USDC as arbitrageurs rebalance the pool. The LP captures swap fees, but systematically gives up part of the asset appreciation.

### Impermanent Loss from NAV Drift

RWA tokens are yield-bearing instruments whose NAV increases continuously over time. AMMs mechanically rebalance inventory as prices move, which forces LPs to sell portions of the appreciating asset into stablecoins during NAV appreciation.

Our analysis assumes arbitrage opportunities are executed whenever the pool price trades 2% below NAV, while trades stop occurring once slippage exceeds 3%. In practice, this creates a structurally adverse environment for LPs: profitable arbitrage continuously extracts value from the pool during normal NAV appreciation, while stressed redemption periods still fail to guarantee deep liquidity once pool depth deteriorates.

### Liquidity Is Still Not Guaranteed

Despite requiring substantial idle capital, DEX liquidity still provides weak guarantees during periods of concentrated exits. Once slippage thresholds are breached, trading activity effectively stops and the pool becomes unusable for meaningful redemptions. In other words, LPs take continuous exposure to the underlying asset while still failing to guarantee reliable liquidity during stress scenarios.

### Opportunity Cost

Half of the pool capital remains in USDC rather than fully deployed into the underlying strategy. While this USDC could earn base lending yield on protocols such as Morpho, the return is materially lower than the intrinsic yield of the RWA itself. This creates a direct drag on overall strategy performance.

The result is a structurally inefficient system where LPs absorb underlying RWA risk, impermanent loss, fragmented liquidity, and idle capital costs — while still earning a total APY that can underperform simply holding the underlying asset directly.

### **Outcome on $10M:**

| Income/Cost Item      | Amount                  |
| --------------------- | ----------------------- |
| Swap fee income       | +$30,688                |
| RWA Intrinsic APY     | +$454,917               |
| Arbitrage fees        | +$30,738                |
| **Net annual return** | **$516,343 (5.2% APY)** |

![General overview](/img/CA-5.png)

## Approach 3: Instant Liquidity Vault

![General overview](/img/CA-6.png)

Through Symbiotic’s instant liquidity product, curators can launch USDC vaults to service instant redemptions across multiple RWA assets simultaneously. This vault provides a capital facility to acquire RWA tokens at a discount via an on-chain RFQ (Request for Quote) mechanism or via a fixed discount set per asset by the curator. The acquired RWA tokens are then redeemed at NAV with the underlying issuer during the standard redemption window by the curator — and the spread is shared between them and vault LPs.

### How the Vault Works

1. A token holder requests an instant exit (through UI/API or aggregators).
2. Market makers bid, sign an on-chain order, and the vault receives RWA token at a discount when winning the auction (e.g., 0.5%)
3. USDC is drawn by the Symbiotic vault via the Market Maker Symbiotic Contract.
4. USDC settles atomically to the token holder.
5. The curator redeems the RWA with the issuer at NAV from smart contract custody (e.g. at T+3 or T+35 days) earning the spread minus funding cost.
6. Vault LPs receive a share of the spread; idle capital earns base yield via DeFi adapters (e.g. to Morpho).

### Capital Efficiency Advantages

**Shared pool, dynamic allocation.** A single $10M USDC vault covers the two RWA assets. If one asset faces a $5M redemption surge, the vault deploys up to its limit regardless of which asset is in demand — unlike DEX pools where each silo is capped at $2.5M USDC. The curator sets per-asset limits, but the base liquidity is shared.

**Earning while idle.** The Symbiotic infrastructure routes idle vault capital to DeFi lending adapters (e.g., Morpho) to earn base yield.

**Spread income from redemption flows.** The vault receives a share of the instant redemption discount.

**No impermanent loss.** The vault operates via a blind RFQ auction, not as an AMM. There is no constant-product curve continuously rebalancing against NAV appreciation. Capital enters as USDC and exits as USDC (with spread captured), eliminating the structural IL drag that plagues DEX LPs.

### **Outcome on $10M:**

| Income/Cost Item                                                  | Amount                   |
| ----------------------------------------------------------------- | ------------------------ |
| Base lending yield (4% on idle capital via Morpho)                | +$311,641                |
| Redemption spread income                                          | +$401,292                |
| Intrinsic RWA yield while deployed (variable, depending on asset) | +$176,717                |
| **Net annual return**                                             | **+$889,651 (8.9% APY)** |

![General overview](/img/CA-7.png)

![General overview](/img/CA-8.png)

## Side-by-Side Comparison

| Metric                      | Idle Buffer             | DEX Pools (4×)    | Symbiotic Vault       |
| --------------------------- | ----------------------- | ----------------- | --------------------- |
| Available Capital           | $10M                    | $10M              | $10M                  |
| Max single-asset coverage   | $5M                     | $2.5M (USDC side) | $10M                  |
| Base lending yield          | +$290,000               | 0                 | +$311,641             |
| Spread / fee income         | +$361,068               | +$30,688          | +$401,292             |
| Intrinsic yield on deployed | (reduces intrinsic APY) | +$454,917         | +$176,717             |
| Other yield sources         | No                      | No                | Yes (apps & adapters) |
| **Net annual return**       | **+$651,068**           | **+$516,343**     | **+$889,651**         |
| **Effective APY**           | **6.5%**                | **5.2%**          | **8.9%**              |
| Per-asset capital siloing   | Yes                     | Yes (4×)          | No                    |
| Exposure to Risky Asset     | Yes                     | Yes               | Minimal               |
| Manual ops required         | High                    | Medium            | Low                   |

The vault outperforms the idle buffer by **+$239K/year** and DEX pools by **+$373K/year** on the same $10M capital base, while providing stronger liquidity guarantees and maintaining minimal exposure to the risky asset.

## Risk Considerations for the Vault Approach

The instant liquidity vault model introduces its own risk profile:

* **Duration risk.** If an RWA's NAV declines before native redemption completes (e.g., credit event), the vault bears the shortfall between the USDC advanced and NAV recovered. This risk is priced into the fee structure and managed by curator-set per-asset limits.
* **Lending adapter liquidity risk.** Capital deployed in Morpho may face withdrawal friction during utilization spikes, potentially limiting available liquidity for redemptions.
* **Duration mismatch.** A vault with a 14-day withdrawal lockup cannot guarantee instant liquidity for vault *depositors* if it has committed capital to a 35-day redemption cycle (e.g., mF-ONE). Curators must actively manage this mismatch.
* **Curator concentration.** The model depends on curator-managed parameter-setting and market maker selection. LP exposure to curator quality is material.

These risks are manageable — and are partially compensated by the spread income that prices them. They represent the normal tradeoff of a yield-bearing model vs. the zero-risk, zero-return idle buffer.

## The Issuer Perspective

For an RWA issuer, the instant liquidity vault also produces structural benefits beyond the LP P\&L:

1. **Reduced issuer overhead.** The vault and curator handle redemption logistics. The issuer doesn’t need to maintain idle capital or directly manage the redemption facility.
2. **Competitive product differentiation.** Offering credible instant redemption is a meaningful distribution advantage. Institutional and semi-institutional investors increasingly require it.
3. **Scalable across products.** A single vault can be authorized to service multiple issuer products simultaneously, with the curator managing per-asset risk parameters — eliminating the need to build separate liquidity infrastructure per fund.

## Conclusion

The three approaches reflect three fundamentally different relationships between idle capital and productive yield. The idle buffer treats liquidity as a pure cost center. The DEX approach attempts to generate yield through AMM fees but fails on structural grounds — the economics of AMM LP provision simply do not work for low-volume, yield-bearing, permissioned RWA tokens. The instant liquidity vault turns the same $10M reserve into a productive, multi-asset, dynamically allocated machine: earning base lending yield on idle capital, capturing redemption spreads when deployed, and accruing intrinsic asset yield during the redemption window. For any issuer managing a portfolio of USD-denominated tokenized funds with meaningful redemption demand, the instant liquidity vault is the dominant capital allocation.

# Introduction

Symbiotic is a shared security protocol that enables networks to access economic security from stakers. The protocol supports multiple participant roles, each with different integration paths.

Choose your role below to get started with integration.

## Prerequisites

Before you begin, install these tools:

* **Git** - Download codebases ([Download](https://git-scm.com/downloads))
* **Foundry** - Interact with EVM contracts ([Download](https://book.getfoundry.sh/getting-started/installation))
* **Python** - Run scripts ([Download](https://www.python.org/downloads))

## Counterparties

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Networks"
    description="Use Symbiotic infrastructure to integrate a stake-backed security for your protocol."
    icon={
          <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
              <rect
                  x="8"
                  y="8"
                  width="32"
                  height="32"
                  rx="2"
                  stroke="currentColor"
                  strokeWidth="2"
                  fill="none"
              />
              <rect
                  x="12"
                  y="12"
                  width="24"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="18"
                  width="20"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="24"
                  width="16"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="30"
                  width="18"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
          </svg>
      }
    href="/integrate/networks"
  />

  <Card1
    title="Operators"
    description="Help networks keep their products reliable and earn rewards."
    icon={
          <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
              <rect
                  x="8"
                  y="8"
                  width="32"
                  height="32"
                  rx="2"
                  stroke="currentColor"
                  strokeWidth="2"
                  fill="none"
              />
              <rect
                  x="12"
                  y="12"
                  width="24"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="18"
                  width="20"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="24"
                  width="16"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="30"
                  width="18"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
          </svg>
      }
    href="/integrate/operators"
  />

  <Card1
    title="Curators"
    description="Manage Symbiotic depositors' funds and earn fees."
    icon={
          <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
              <rect
                  x="8"
                  y="8"
                  width="32"
                  height="32"
                  rx="2"
                  stroke="currentColor"
                  strokeWidth="2"
                  fill="none"
              />
              <rect
                  x="12"
                  y="12"
                  width="24"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="18"
                  width="20"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="24"
                  width="16"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="30"
                  width="18"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
          </svg>
      }
    href="/integrate/curators"
  />

  <Card1
    title="Builders / Researchers"
    description="Build on top of Symbiotic and access protocol data."
    icon={
          <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
              <rect
                  x="8"
                  y="8"
                  width="32"
                  height="32"
                  rx="2"
                  stroke="currentColor"
                  strokeWidth="2"
                  fill="none"
              />
              <rect
                  x="12"
                  y="12"
                  width="24"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="18"
                  width="20"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="24"
                  width="16"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="30"
                  width="18"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
          </svg>
      }
    href="/integrate/builders-researchers"
  />
</div>

# Get Started

This guide walks you through integrating your network with Symbiotic. Follow these steps to register your network, set up security, and start receiving stake allocations.

::::steps

## Network Contract

Register your network's management address in the Symbiotic system.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Quickstart: Network with Staking"
    description="Get familiar with Protocol: deploy a minimal network, middleware and vault-operator-staker setup"
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/minimal-network"
  />

  <Card1
    title="Network Contract"
    description="Deploy production-ready Network contract"
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/network-contract"
  />
</div>

## Submit Metadata

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Submit a PR with your network's metadata to make it visible on the Symbiotic UI."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/submit-metadata"
  />
</div>

## Set Up Pre-deposit Vault (Optional)

If you need a self-curated vault, deploy and configure it.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Deploy Pre-deposit Vault"
    description="Configure and deploy a self-curated vault for your network."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/curators/deploy-vault"
  />

  <Card1
    title="Submit Vault's Metadata"
    description="Submit your vault's metadata after deployment."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/curators/submit-metadata"
  />
</div>

## Integrate Rewards

Rewards are essential for healthy protocol economics. Learn how to integrate Symbiotic rewards.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Integrate Symbiotic rewards to distribute rewards to stakers."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/rewards"
  />
</div>

## Integrate Slashing

Slashing protects your protocol by penalizing misbehavior. Learn how slashing works in Symbiotic.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Implement slashing to secure your network and penalize misbehavior."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/slashing"
  />
</div>

## Implement On-Chain Components

Build your on-chain integration using Symbiotic's Relay framework.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Use Relay Contracts"
    description="Build stake-secured applications using Symbiotic Relay. Learn how to construct Relay-compatible smart contracts."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/relay-onchain"
  />

  <Card1
    title="Set Your Middleware"
    description="Configure your middleware to perform slashings and rewards distributions using the `Network.sol` contract."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/network-contract#manage-your-network"
  />
</div>

## Implement Off-Chain Components

Build your off-chain application using Relay Sidecar.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Use Relay Sidecar"
    description="Build your Relay App using the Sidecar architecture."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/relay-offchain"
  />
</div>

::::

# Quickstart: Network with Staking

This guide sets up a minimal Hoodi testnet environment so you can validate production flows on testnet.

:::info
Although this walkthrough uses externally owned accounts (EOAs) for Network and Middleware, the sequence of on-chain actions outside of the Network and Middleware is the same as if those accounts were production smart contracts.
:::

## Prerequisites

Prepare 6 EOAs for simulation:

* **Network**: network identity account
* **Middleware**: set by the network to handle reward distribution and vault opt-ins
* **Vault Curator**: sets up the vault and allocates shares
* **Operator**: receives delegated stake
* **Two Test Stakers**: deposit collateral

:::::steps

### Register Network & Set Middleware

For both transactions, originator (`msg.sender`) is the network address.

1. Register your network in `NetworkRegistry` via `registerNetwork()`.  ([Sample Tx](https://hoodi.etherscan.io/tx/0x2da545af56094c2dbd7e49dfb838915b84e889ea341dae812483ee7c6840c196))
2. Set the middleware address in `NetworkMiddlewareService` via `setMiddleware(middleware)`.  ([Sample Tx](https://hoodi.etherscan.io/tx/0xf57a8e2fe75a9453620c0b2903165a34be9bc20749dc36b966f169e7f8f963ac))

### Create Vault & Register Operator

1. [Create a vault](https://app.hoodi.symbiotic.fi/create) using `wstETH` as collateral.
   * Sample Vault address: `0xb29BAD40B00587dE1145C7862F96746f043b9daD`  ([Sample Tx](https://hoodi.etherscan.io/tx/0x94ad7d76fc41e75528b1d2bbc0496c5664e59900c07f5e8bfa81505cca88d45b))
2. Register operator in `OperatorRegistry` via `registerOperator()`   ([Sample Tx](https://hoodi.etherscan.io/tx/0xc6ff4fabf604325e2357963004f4f96dceefec6e874edbec75677d827fbc507b))
3. Opt operator into Network using `OperatorNetworkOptInService` via `optIn()`  ([Sample Tx](https://hoodi.etherscan.io/tx/0xa116a2e7e7386019147b2952ad59fb169d2043f49088098dfc82c2422ecdd83d))
4. Opt operator into Vault using `OperatorVaultOptInService` via `optIn()`  ([Sample Tx](https://hoodi.etherscan.io/tx/0x81daac1756eb1ca3e5a35f10a356ff7487e0ce1b60fdbf91c05ac11dbfd42eea))
5. Allocate shares in Delegator via `setOperatorNetworkShares()`  ([Sample Tx](https://hoodi.etherscan.io/tx/0xe2ceee91cebadc1c1abf11fbad9b40d32604f00695282cc082a6796bc889376b))
6. (Optional) Submit PRs with metadata (network, vault, operator) to the [metadata-hoodi](https://github.com/symbioticfi/metadata-hoodi/) repo. Examples: [13](https://github.com/symbioticfi/metadata-hoodi/pull/13), [14](https://github.com/symbioticfi/metadata-hoodi/pull/14), [15](https://github.com/symbioticfi/metadata-hoodi/pull/15)

:::info
If you complete step 6, entities and their interactions will be reflected on [app.hoodi.symbiotic.fi](https://app.hoodi.symbiotic.fi).
:::

### Vault Opt-In (Network)

1. Opt-in to vault by calling Delegator via `setMaxNetworkLimit`  ([Sample Tx](https://hoodi.etherscan.io/tx/0x99f6a276c558184a6a5f325a25c1432f10d391d7e26207ffa8aaf1dd9a791efa))
2. From emitted event, extract `subnetwork ID`

Using the **Vault Admin** address: accept opt-in by calling Delegator via `setNetworkLimit`  ([Sample Tx](https://hoodi.etherscan.io/tx/0x3918e61998aff1dc637f15ac3fe9024d6da9f0ef299a40f0b49c12eb623ad249))

:::::

When finished, 2 test stakers should be able to deposit to the wstETH vault.

# Network Contract

Register your network using the `NetworkRegistry` smart contract. The registered address serves as your management address for interacting with Symbiotic vaults to accept stake allocations.

We provide a [network repository](https://github.com/symbioticfi/network) that simplifies registration and makes management more secure. It includes the `Network.sol` contract and tooling to manage it.

The `Network.sol` contract extends [OpenZeppelin](https://www.openzeppelin.com/)'s [`TimelockController.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/TimelockController.sol) with additional functionality to define delays for `(exact target | exact selector)` or `(any target | exact selector)` pairs.

## Prerequisites

:::steps

#### Clone the repository

```bash [bash]
git clone --recurse-submodules https://github.com/symbioticfi/network.git
cd network
```

#### Install dependencies

```bash [bash]
npm install
```

:::

## Deploy Network and Register

The deployment scripts support two scenarios:

1. Deploy a network only (opt into vaults later)
2. Deploy a network with vault opt-ins

:::info
The `Network.sol` contract automatically registers itself on deployment.
:::

### Pure Network Deployment

:::steps

##### Open [`DeployNetwork.s.sol`](https://github.com/symbioticfi/network/blob/main/script/DeployNetwork.s.sol) and configure these settings:

```solidity [DeployNetwork.s.sol]
// Name of the Network
string NAME = "My Network";
// Default minimum delay (will be applied for any action that doesn't have a specific delay yet)
uint256 DEFAULT_MIN_DELAY = 3 days;
// Cold actions delay (a delay that will be applied for major actions like upgradeProxy and setMiddleware)
uint256 COLD_ACTIONS_DELAY = 14 days;
// Hot actions delay (a delay that will be applied for minor actions like setMaxNetworkLimit and setResolver)
uint256 HOT_ACTIONS_DELAY = 0;
// Admin address (will become executor, proposer, and default admin by default)
address ADMIN = 0x0000000000000000000000000000000000000000;

// Optional

// Metadata URI of the Network
string METADATA_URI = "";
// Salt for deterministic deployment
bytes11 SALT = "SymNetwork";
```

##### Edit the configuration fields, then run:

```bash [bash]
forge script script/DeployNetwork.s.sol --rpc-url <RPC_URL> --private-key <PRIVATE_KEY> --etherscan-api-key <ETHERSCAN_API_KEY> --broadcast --verify
```

:::

### Network Deployment With Opt-ins

:::steps

##### Open [`DeployNetworkForVaults.s.sol`](https://github.com/symbioticfi/network/blob/main/script/DeployNetworkForVaults.s.sol) and configure these settings:

```solidity [DeployNetworkForVaults.s.sol]
// Name of the Network
string NAME = "My Network";
// Default minimum delay (will be applied for any action that doesn't have a specific delay yet)
uint256 DEFAULT_MIN_DELAY = 3 days;
// Cold actions delay (a delay that will be applied for major actions like upgradeProxy and setMiddleware)
uint256 COLD_ACTIONS_DELAY = 14 days;
// Hot actions delay (a delay that will be applied for minor actions like setMaxNetworkLimit and setResolver)
uint256 HOT_ACTIONS_DELAY = 0;
// Admin address (will become executor, proposer, and default admin by default)
address ADMIN = 0x0000000000000000000000000000000000000000;
// Vault address to opt-in to (multiple vaults can be set)
address[] VAULTS = [0x0000000000000000000000000000000000000000];
// Maximum amount of delegation that network is ready to receive (multiple vaults can be set)
uint256[] MAX_NETWORK_LIMITS = [0];
// Resolver address (optional, is applied only if VetoSlasher is used) (multiple vaults can be set)
address[] RESOLVERS = [0x0000000000000000000000000000000000000000];

// Optional

// Subnetwork Identifier (multiple subnetworks can be used, e.g., to have different resolvers for the same network)
uint96 SUBNETWORK_ID = 0;
// Metadata URI of the Network
string METADATA_URI = "";
// Salt for deterministic deployment
bytes11 SALT = "SymNetwork";
```

##### Edit the configuration fields, then run:

```bash [bash]
forge script script/DeployNetworkForVaults.s.sol --rpc-url <RPC_URL> --private-key <PRIVATE_KEY> --etherscan-api-key <ETHERSCAN_API_KEY> --broadcast --verify
```

:::

## Manage Your Network

Use these five predefined action scripts:

* [SetMaxNetworkLimit](https://github.com/symbioticfi/network/blob/main/script/actions/SetMaxNetworkLimit.s.sol) - set a new maximum network limit for the vault
* [SetResolver](https://github.com/symbioticfi/network/blob/main/script/actions/SetResolver.s.sol) - set the resolver for the vault (only if the vault uses VetoSlasher)
* [SetMiddleware](https://github.com/symbioticfi/network/blob/main/script/actions/SetMiddleware.s.sol) - set the middleware
* [UpgradeProxy](https://github.com/symbioticfi/network/blob/main/script/actions/UpgradeProxy.s.sol) - upgrade the proxy (network itself)
* [ArbitraryCall](https://github.com/symbioticfi/network/blob/main/script/actions/ArbitraryCall.s.sol) - make a call to any contract with any data

All actions follow a similar pattern. Here's how to use [SetMaxNetworkLimit](https://github.com/symbioticfi/network/blob/main/script/actions/SetMaxNetworkLimit.s.sol) as an example:

:::steps

##### Open [SetMaxNetworkLimit.s.sol](https://github.com/symbioticfi/network/blob/main/script/actions/SetMaxNetworkLimit.s.sol) and configure these settings:

```solidity [SetMaxNetworkLimit.s.sol]
// Address of the Network
address NETWORK = 0x0000000000000000000000000000000000000000;
// Address of the Vault
address VAULT = 0x0000000000000000000000000000000000000000;
// Maximum amount of delegation that network is ready to receive
uint256 MAX_NETWORK_LIMIT = 0;
// Delay for the action to be executed
uint256 DELAY = 0;

// Optional

// Subnetwork Identifier (multiple subnetworks can be used, e.g., to have different max network limits for the same network)
uint96 SUBNETWORK_IDENTIFIER = 0;
// Salt for TimelockController operations
bytes32 SALT = "SetMaxNetworkLimit";
```

##### Edit the configuration fields, then choose an operation:

* `runS()` - schedule an action
* `runE()` - execute an action
* `runSE()` - schedule and execute an action (only if the delay is zero)

##### Run the operation:

* To execute the script with an EOA:

  ```bash [bash]
  forge script script/actions/SetMaxNetworkLimit.s.sol:SetMaxNetworkLimit --sig "runS()" --rpc-url <RPC_URL> --private-key <PRIVATE_KEY> --broadcast
  ```

* To get transaction calldata for a [Safe](https://app.safe.global/) multisig:

  ```bash [bash]
  forge script script/actions/SetMaxNetworkLimit.s.sol:SetMaxNetworkLimit --sig "runS()" --rpc-url <RPC_URL> --sender <MULTISIG_ADDRESS> --unlocked
  ```

  The logs will show a `callData` field like this:

  ```bash [Expected output]
  callData:0x01d5062a00000000000000000000000025ed2ee6e295880326bdeca245ee4d8b72c8f103000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000005365744d61784e6574776f726b4c696d697400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004423f752d500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002b6700000000000000000000000000000000000000000000000000000000
  ```

  In [Safe](https://app.safe.global/) Transaction Builder:

  1. Enable "Custom data"
  2. Enter the **Network's address** as the target address
  3. Use the `callData` (e.g., `0x01d5062a0000000000000000000000...`) received earlier as the `Data (Hex encoded)`

:::

## Update Delays

Every network action is protected by a delay (from zero to infinity).

Use these update delay scripts for the actions above, plus additional ones:

* [SetMaxNetworkLimitUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/SetMaxNetworkLimitUpdateDelay.s.sol)
* [SetResolverUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/SetResolverUpdateDelay.s.sol)
* [SetMiddlewareUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/SetMiddlewareUpdateDelay.s.sol)
* [UpgradeProxyUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/UpgradeProxyUpdateDelay.s.sol)
* [HotActionsUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/HotActionsUpdateDelay.s.sol) - update a delay for [SetMaxNetworkLimitUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/SetMaxNetworkLimitUpdateDelay.s.sol) and [SetResolverUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/SetResolverUpdateDelay.s.sol)
* [ColdActionsUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/ColdActionsUpdateDelay.s.sol) - update a delay for [SetMiddlewareUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/SetMiddlewareUpdateDelay.s.sol) and [UpgradeProxyUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/UpgradeProxyUpdateDelay.s.sol)
* [DefaultUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/DefaultUpdateDelay.s.sol) - update a delay for unconstrained actions
* [ArbitraryUpdateDelay](https://github.com/symbioticfi/network/blob/main/script/update-delay/ArbitraryCallUpdateDelay.s.sol) - update a delay for an arbitrary call:
  * set a delay for the exact target address and the exact selector
  * set a delay for any target address and the exact selector (by setting target address to `0x0000000000000000000000000000000000000000`)

For usage examples, see [Manage Your Network](/integrate/networks/network-contract#manage-your-network).

***

## Dashboard

:::warning
Work-in-progress, use with caution.
:::

The `Network.sol` contract inherits [OpenZeppelin](https://www.openzeppelin.com/)'s `TimelockController`, which inherits `AccessControl`. You can't determine the full state (operation statuses or role holders) using only RPC calls.

Use the Network Dashboard to:

* Get delays for all operations
* Get holders of any role
* Get scheduled/executed operations
* Schedule/execute arbitrary actions

:::info
Network Dashboard UI: https://network-sage-rho.vercel.app/
:::

***

## Next Steps

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Submit Metadata"
    description="Submit your network's metadata to make it visible on the Symbiotic UI."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/submit-metadata"
  />
</div>

# Submit Metadata

The [Symbiotic UI](https://app.symbiotic.fi/deposit) displays TVL, allocations, and relationships between curators, vaults, operators, and networks. To make your entity visible on the UI, submit its metadata to the corresponding repository.

After you submit metadata, the Symbiotic team reviews and merges it. Once merged, your data appears on the UI.

## Add a New Entity Template

### Choose a Repository

| Chain   | URL                                             |
| ------- | ----------------------------------------------- |
| Mainnet | https://github.com/symbioticfi/metadata-mainnet |
| Hoodi   | https://github.com/symbioticfi/metadata-hoodi   |

### Repository Structure

The repository is organized as follows:

```
repository/
├── vaults/
│   ├── 0x<address>/
│   │   ├── info.json
│   │   └── logo.png (optional)
├── networks/
├── operators/
├── tokens/
```

Each entity is identified by its Ethereum address (`0x...`), and its data is stored in a folder named after the address. Inside this folder, include a file `info.json` containing metadata, and optionally, an icon file `logo.png`.

***

### Steps to Add a New Entity

**Note: After your PR is submitted, email your PR link to verify@symbiotic.fi from your official business email (domain must match that of your entity website) to allow us to confirm your identity ahead of merging your PR.**

1. **Determine the entity type**:
   * Decide whether the entity belongs to `vaults`, `networks`, `operators`, `tokens` or `points`.
   * If the entity is a `vault`, ensure its collateral token entity is registered in the `tokens` folder before adding the vault metadata. If not, add the token first.
2. **Register the entity in the registry**:
   * Before adding metadata for vaults, networks, or operators, ensure that they are registered in their respective registries. You can find the current registry contract addresses in the [Addresses page](/get-started/resources/addresses). Unregistered entities will not be accepted.
3. **Create a new folder**:
   * Navigate to the appropriate directory for the entity type.
   * Create a folder named after the Ethereum address (e.g., `0x1234567890abcdef1234567890abcdef12345678`).
4. **Add the `info.json` file**:
   * Include metadata in the specified format (see below).
5. **(Optional) Add an icon file**:
   * If available, include a `logo.png` file with the entity’s logo.

The Symbiotic team reviews your PR after automated checks pass. If approved, it will be merged into the repository.

***

### File Format: `info.json`

The `info.json` file must follow this structure:

#### Required Fields

* `name` (string): The name of the entity.
* `description` (string): A brief description of the entity.
* `tags` (array of strings): Tags categorizing the entity.
* `links` (array of objects): External links related to the entity.

#### Fields for Points

* `type` (string): The type of the point (e.g., "network").
* `decimals` (number): The number of decimal places for the point.

#### Supported `links` Types

Each link should include:

* `type`: The type of the link. Supported values are:
  * `website`: The official website of the entity.
  * `explorer`: A blockchain explorer link for the entity's Ethereum address or contract.
  * `docs`: Documentation related to the entity.
  * `example`: Example use cases or tutorials.
  * `externalLink`: A link to be shown below the entity's name.
* `name`: A user-friendly name for the link.
* `url`: The URL of the resource.

### Icon File: `logo.png` (Optional)

If you want to include an icon for the entity, follow these guidelines:

* **File Name**: `logo.png`
* **Dimensions**: 256x256 pixels
* **Format**: PNG

Place the `logo.png` file in the same folder as the `info.json` file.

***

### Validation

Before submitting your PR, ensure the following:

1. The Ethereum address is valid:
   * It must start with `0x` and be exactly 42 characters long.
2. The `info.json` file is valid:
   * Use a JSON validator, such as [https://jsonlint.com/](https://jsonlint.com/).
3. The `logo.png` file (if included) meets the size requirement of **256x256 pixels**.

***

### Submitting the Pull Request

Once your files are added to the repository, create a Pull Request with the following details:

1. **Entity Type**: Specify the type (vault, network, operator, token).
2. **Ethereum Address**: Provide the address of the entity.
3. **Description**: Summarize the entity’s purpose and data.

#### Example PR Description

```
Added new token entity: 0x1234567890abcdef1234567890abcdef12345678

- **Name**: USDT
- **Description**: USDT is a stablecoin pegged to the US Dollar, widely used for trading and liquidity in cryptocurrency markets.
- **Tags**: stablecoin, usdt
- **Links**:
  - [Website](https://tether.to/)
  - [Etherscan](https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7)
  - [Tether Documentation](https://docs.tether.to/)
- **CMC ID**: 825
- **Permit Name**: USDT Permit Token
- **Permit Version**: 1
- **Icon**: Included (256x256 px)
```

***

### Review and Approval

Your PR will be reviewed to ensure:

* The `info.json` file has all required fields and valid data.
* The `logo.png` file (if included) meets the requirements.
* The metadata is accurate and well-structured.
* The submitter of the PR is from the entity in question (verified via an email with your PR link to verify@symbiotic.fi from your official business email)

After approval, your changes will be merged into the repository.

## Add a Network

:::steps

##### Create a new folder in the `/networks` directory

##### Create a new json file in the folder with the following structure:

```json [info.json]
{
    "name": "My Network",
    "description": "My Network is a network that allows you to stake your tokens and earn rewards.",
    "tags": ["network", "staking"],
    "links": [{ "type": "website", "name": "Website", "url": "https://mynetwork.com" }]
}
```

##### Save a logo of the Network to `logo.png` of 256x256 pixels size

:::

## Add Points

:::steps

##### Create a new folder in the `/points` directory

##### Create a new json file in the folder with the following structure:

```json [info.json]
{
    "name": "My Points",
    "description": "My Points is a points system that allows you to earn rewards.",
    "tags": ["points", "staking"],
    "links": [{ "type": "website", "name": "Website", "url": "https://mypoints.com" }]
}
```

##### Save a logo of the Points to `logo.png` of 256x256 pixels size

:::

## Add a Pre-deposit Vault

See the [vault metadata submission guide](/integrate/curators/submit-metadata) for details.

## Next Steps

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Deploy a Pre-deposit Vault"
    description="Use this guide if you need to curate or deploy the Vault by yourself."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/pre-deposit"
  />

  <Card1
    title="Rewards"
    description="Learn how to integrate Symbiotic rewards into your system."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/rewards"
  />
</div>

# Deploy Pre-deposit Vault

You may want to curate or deploy vaults yourself in these cases:

* A DAO-controlled vault with your network's native asset as collateral
* Your network needs a specific vault configuration for onboarding

See the [vault deployment guide](/integrate/curators/deploy-vault) for details.

## Next Steps

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Rewards"
    description="Learn how to integrate Symbiotic Rewards into your system."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/rewards"
  />
</div>

# Distribute Rewards

Networks use Rewards system to compensate Stakers, Operators, and Curators for providing security and network operation.

This guide highlights practical steps and contract touchpoints to distribute and claim rewards.

To reproduce this flow, follow the [Quickstart: Network with Staking](/integrate/networks/minimal-network) guide first.

***

The rewards implementation is available in the [Symbiotic Rewards Repository](https://github.com/symbioticfi/rewards-v2). There are 3 smart contracts:

* **Rewards**: Main contract for distributions and claims.
* **FeeRegistry**: Registry for operator and curator fees.
* **CuratorRegistry**: Registry mapping vaults to curators.

## Vault Snapshot Rewards

![Network rewards distribution diagram](/img/rewards-fee-split.png)

Vault Snapshot Rewards implement **fully on-chain**, snapshot-based distributions using historical vault fee split and state at specific timestamps.

:::info
The distribution and claim operations must be handled separately for each vault.
:::

Actions ([Contract](https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/VaultSnapshotRewards.sol) | [Interface](https://github.com/symbioticfi/rewards-v2/blob/main/src/interfaces/IVaultSnapshotRewards.sol)):

* **Distribution entrypoint**: `distributeVaultSnapshotRewards()` - used by network to distribute rewards.
* **Claim entrypoints** for stakers, operators and curators:
  * `claimVaultSnapshotRewards()`
  * `claimOperatorFees()`
  * `claimCuratorFees()`

:::info
Both network and its middleware can distribute Vault Snapshot rewards.
:::

### Reward Workflow

:::info
Reward distribution is a regular routine. Unlike DeFi farms that distribute rewards continuously, networks distribute rewards periodically (for example, weekly).
:::

Rewards contract addresses are listed on the [Addresses](/get-started/resources/addresses#rewards) page.

::::steps

#### Distribute Rewards

For `msg.sender`, use the Network Middleware account (see [Quickstart: Network with Staking](/integrate/networks/minimal-network)).

* Increase token allowance  ([Sample Tx](https://hoodi.etherscan.io/tx/0x51b48ffe641da09b8975a3bc670b77b7dd1b62c1d6028770cc569bcbe4404987))
* Distribute rewards by calling `Rewards` via `distributeVaultSnapshotRewards()`  ([Sample Tx](https://hoodi.etherscan.io/tx/0xca0ce507a5e93230c848cf5a4b261714847500fef5203b27dbc49dcbe78b8d1a))

#### Verify on Symbiotic dApp

Open the [Vault Page](https://app.hoodi.symbiotic.fi/vault/0xb29BAD40B00587dE1145C7862F96746f043b9daD). Find Vault Reward data and claimed rewards in the corresponding section.

#### Staker Flow

* [Acquire wstETH](https://stake-hoodi.testnet.fi/wrap)  ([Sample Tx](https://hoodi.etherscan.io/tx/0xe799b1611a19cc4ad9c8bc1d61cd328c1f54218c78a5b18f9b559c8791d5b876))
* Deposit to Vault (via UI) ([Tx 1](https://hoodi.etherscan.io/tx/0xe622a7bfd0c17e76f92da77a8ce378aebf5e32443e2fb4f78363871efab51531), [Tx 2](https://hoodi.etherscan.io/tx/0x0ebe2fedef0443d38ee7e933600b3f16139d87d31dbed627cd9fe314effddb33))
* Claim Rewards via `claimVaultSnapshotRewards` ([Sample Tx](https://hoodi.etherscan.io/tx/0x0f9d5d14772999320b88b45ad40f6764054a56993386f0d0d709ff7a2fcd7c8e))

#### Curator and Operator flows

* The `vault.owner()` registers the curator in `CuratorRegistry`
* Curator sets curator and operator fees in `FeeRegistry`.
* Curator and operator claim via `Rewards.sol`

For more details, see [Curator: Manage & Claim Fees](/integrate/curators/registry-and-fees#claim-process) and [Operator: Claim Rewards](/integrate/operators/claim-rewards).

::::

### Production considerations

This guide uses testnet and simplified EOAs for ease of replication. In production, plan the security-aware setup accordingly.

* [Implement Middleware](/integrate/networks/network-contract), do not use EOA or multisig
* Expect fees to be deducted from the amount distributed. To perform fee-related calculations, use [FeeRegistry and Rewards methods](/integrate/curators/registry-and-fees#fee-related-calculations)

## Next Steps

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Slashing"
    description="Learn how to integrate the slashing mechanism into your system if needed."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/slashing"
  />

  <Card1
    title="Relay On-Chain"
    description="Proceed to developing your protocol's on-chain components using Relay smart contracts."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/relay-onchain"
  />
</div>

# Slashing

[Read Learn first](/learn/core-concepts/slashing)

Slashing is a penalty mechanism that deters operators from breaking their commitments. Violations include failing to complete tasks properly or accurately. Slashing typically burns or redistributes the operator's staked funds.

## **Slasher Module**

Each Symbiotic Vault has an immutably set `Slasher` module implementation. There are three possible implementation choices:

1. **No Slasher** - no slashing can occur within the Vault

2. **Instant Slasher (`TYPE = 0`)** - allows networks to immediately slash funds in a FIFO order

3. **Veto Slasher (`TYPE = 1`)** - supports a veto process over a pre-defined veto period, where designated **Resolvers** can cancel the slashing request

Each Slasher module contains a `slashableStake(subnetwork, operator, captureTimestamp, hints)` function that returns the amount of collateral still slashable for the given `captureTimestamp` at the current moment.

:::warning
The provided slashable collateral amount may be inaccurate in practice when the vault uses **restaking** (multiple networks may slash the same amount of collateral).
:::

:::info
When executing a slashing request, funds are transferred to an immutably set `Vault.burner()`.
:::

### Slashing Guarantees

Each Symbiotic Vault has an epoch duration (obtained via `Vault.epochDuration()`), which determines the withdrawal delay and provides a period during which slashing guarantees are held.

The following inequality must hold:

<div align="center">
  <code>executeSlashTimestamp - captureTimestamp \<= epochDuration</code>
</div>

### Slasher (Type 0)

The slasher instantly executes slashing requests when received and validated.

```solidity [NetworkSlasher.sol]
import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
import {ISlasher} from "@symbioticfi/core/src/interfaces/slasher/ISlasher.sol";
import {Subnetwork} from "@symbioticfi/core/src/contracts/libraries/Subnetwork.sol";

address slasher = IVault(vault).slasher();
bytes32 subnetwork = Subnetwork.subnetwork(NETWORK, IDENTIFIER);
ISlasher(slasher).slash(
    subnetwork,
    operator,
    amount,
    captureTimestamp,
    hints
)
```

Parameters:

* `subnetwork` - full identifier of the subnetwork (address of the network concatenated with the uint96 identifier)
* `operator` - address of the operator
* `amount` - amount of the collateral to slash
* `captureTimestamp` - time point when the stake was captured
* `hints` - hints for checkpoints' indexes

:::info
Call this function from `NetworkMiddlewareService.middleware(network)`.
:::

### VetoSlasher (Type 1)

The flow consists of three stages:

1. Request Slashing
2. Veto Slashing
3. Execute Slashing (if not vetoed)

Let’s assume the veto duration period is set to **5 days** and the epoch duration is set to **7 days**.

::::steps

#### Day 1 - Request Slashing

```solidity [NetworkSlasher.sol]
import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
import {IVetoSlasher} from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol";
import {Subnetwork} from "@symbioticfi/core/src/contracts/libraries/Subnetwork.sol";

address slasher = IVault(vault).slasher();
bytes32 subnetwork = Subnetwork.subnetwork(NETWORK, IDENTIFIER);
uint256 slashIndex = IVetoSlasher(slasher).requestSlash(
    subnetwork,
    operator,
    amount,
    captureTimestamp,
    hints
)
```

This call succeeds only if the following inequality holds:

<div align="center">
  <code>requestSlashTimestamp + vetoDuration - captureTimestamp \<= epochDuration</code>
</div>

:::info
`NetworkMiddlewareService.middleware(network)` should call this function.
:::

#### Days 1 to 5 - Veto Slashing

```solidity [Resolver]
IVetoSlasher(slasher).vetoSlash(slashIndex, hints)
```

:::info
Call this function from `VetoSlasher.resolver(subnetwork, hint)`.
:::

#### Days 6 to 7 - Execute Slashing

If the slashing request wasn't vetoed:

```solidity [NetworkSlasher.sol]
IVetoSlasher(slasher).executeSlash(
    slashIndex,
    hints
)
```

:::info
`NetworkMiddlewareService.middleware(network)` should call this function.
:::

::::

## Resolvers

If a vault uses a VetoSlasher, there is a veto phase (duration set during vault deployment) when the resolver can veto the request.

Networks can set the resolver via `IVetoSlasher(slasher).setResolver(identifier, resolver, hints)`.

:::note
The first time you set the resolver, it applies immediately. Otherwise, the update applies after `VetoSlasher.resolverSetEpochsDelay()` epochs.
:::

## Next Steps

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Relay On-Chain"
    description="Proceed to developing your protocol's on-chain components using Relay smart contracts."
    icon={
          <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
              <rect
                  x="8"
                  y="8"
                  width="32"
                  height="32"
                  rx="2"
                  stroke="currentColor"
                  strokeWidth="2"
                  fill="none"
              />
              <rect
                  x="12"
                  y="12"
                  width="24"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="18"
                  width="20"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="24"
                  width="16"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="30"
                  width="18"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
          </svg>
      }
    href="/integrate/networks/relay-onchain"
  />
</div>

# Relay On-Chain

The Symbiotic Relay system implements a complete signature aggregation workflow from validator set derivation through on-chain commitment of the ValSetHeader data structure. This enables provable attestation checks on any chain for arbitrary data signed by the validator set quorum.

The system provides a modular smart contract framework that lets you manage validator sets dynamically, handle cryptographic keys, aggregate signatures, and commit cross-chain state.

## Architecture

Symbiotic provides a set of predefined smart contracts representing the following modules:

* [`VotingPowerProvider`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/) - provides basic data about operators, vaults, and their voting power, enabling various onboarding schemes
* [`KeyRegistry`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/key-registry/) - verifies and manages operators' keys; currently, these key types are supported:
  * [`BlsBn254`](https://github.com/symbioticfi/relay-contracts/blob/main/src/libraries/keys/KeyBlsBn254.sol) ([signature verification](https://github.com/symbioticfi/relay-contracts/blob/main/src/libraries/sigs/SigBlsBn254.sol))
  * [`EcdsaSecp256k1`](https://github.com/symbioticfi/relay-contracts/blob/main/src/libraries/keys/KeyEcdsaSecp256k1.sol) ([signature verification](https://github.com/symbioticfi/relay-contracts/blob/main/src/libraries/sigs/SigEcdsaSecp256k1.sol))
* [`ValSetDriver`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/valset-driver/) - used by the off-chain part of Symbiotic Relay for validator set derivation and maintenance
* [`Settlement`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/settlement/) - requires committing a compressed validator set (header) each epoch, but allows verifying signatures made by the validator set; currently supports the following verification mechanics:
  * [`SimpleVerifier`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/settlement/sig-verifiers/SigVerifierBlsBn254Simple.sol) - requires the whole validator set as an input during verification, but in a compressed and efficient way, making it the best choice for up to 125 validators
  * [`ZKVerifier`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/settlement/sig-verifiers/SigVerifierBlsBn254ZK.sol) - uses ZK verification made with [gnark](https://github.com/Consensys/gnark), allowing larger validator sets with an almost constant verification gas cost

:::info
For Symbiotic Core's `NetworkMiddlewareService` contract, set the `VotingPowerProvider` contract as the middleware.
:::

### Permissions

Relay contracts have three ready-to-use permission models:

* [`OzOwnable`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/common/permissions/OzOwnable.sol) - allows setting an owner address that can perform permissioned actions
  * Based on [OpenZeppelin's `Ownable` contract](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol)
* [`OzAccessControl`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/common/permissions/OzAccessControl.sol) - enables role-based permissions for each action
  * Based on [OpenZeppelin's `AccessControl` contract](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/AccessControl.sol)
  * Roles can be assigned to function selectors using `_setSelectorRole(bytes4 selector, bytes32 role)`
* [`OzAccessManaged`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/common/permissions/OzAccessManaged.sol) - controls which callers can access specific functions
  * Based on [OpenZeppelin's `AccessManaged` contract](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/manager/AccessManager.sol)

To use these permission models, inherit one of the above contracts and add the `checkPermission` modifier to functions that require access control.

:::info
Only one permission model can be used at a time.
:::

#### Examples

##### ValSetDriver with OzOwnable

```solidity [MyValSetDriver.sol]
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import {ValSetDriver} from "../src/modules/valset-driver/ValSetDriver.sol";
import {OzOwnable} from "../src/modules/common/permissions/OzOwnable.sol";
import {IEpochManager} from "../src/interfaces/modules/valset-driver/IEpochManager.sol";
import {IValSetDriver} from "../src/interfaces/modules/valset-driver/IValSetDriver.sol";

contract MyValSetDriver is ValSetDriver, OzOwnable {
    function initialize(
        ValSetDriverInitParams memory valSetDriverInitParams,
        address owner
    ) public virtual initializer {
        __ValSetDriver_init(valSetDriverInitParams);
        __OzOwnable_init(ozOwnableInitParams);
    }
}
```

##### Settlement with OzAccessControl

```solidity [MySettlement.sol]
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import {Settlement} from "../src/modules/settlement/Settlement.sol";
import {OzAccessControl} from "../src/modules/common/permissions/OzAccessControl.sol";
import {ISettlement} from "../src/interfaces/modules/settlement/ISettlement.sol";

contract MySettlement is Settlement, OzAccessControl {
    bytes32 public constant SET_SIG_VERIFIER_ROLE = keccak256("SET_SIG_VERIFIER_ROLE");
    bytes32 public constant SET_GENESIS_ROLE = keccak256("SET_GENESIS_ROLE");

    function initialize(
        SettlementInitParams memory settlementInitParams,
        address defaultAdmin
    ) public virtual initializer {
        __Settlement_init(settlementInitParams);

        _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);

        _setSelectorRole(ISettlement.setSigVerifier.selector, SET_SIG_VERIFIER_ROLE);
        _setSelectorRole(ISettlement.setGenesis.selector, SET_GENESIS_ROLE);
    }
}
```

### VotingPowerProvider Extensions

Multiple voting power extensions can be combined to achieve different properties of the VotingPowerProvider:

* [`OperatorsWhitelist`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/extensions/OperatorsWhitelist.sol) - only whitelisted operators can register
* [`OperatorsBlacklist`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/extensions/OperatorsBlacklist.sol) - blacklisted operators are unregistered and are forbidden to return back
* [`OperatorsJail`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/extensions/OperatorsJail.sol) - operators can be jailed for some amount of time and register back after that
* [`SharedVaults`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/extensions/SharedVaults.sol) - shared (with other networks) vaults (like the ones with NetworkRestakeDelegator) can be added
* [`OperatorVaults`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/extensions/OperatorVaults.sol) - vaults that are attached to a single operator can be added
* [`MultiToken`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/extensions/MultiToken.sol) - possible to add new supported tokens on the go
* [`OpNetVaultAutoDeploy`](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/extensions/OpNetVaultAutoDeploy.sol) - enable auto-creation of the configured by you vault on each operator registration
* Ready bindings are also available for [slashing](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/extensions/BaseSlashing.sol) and [rewards](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/extensions/BaseRewards.sol)

#### Examples

##### Single-Operator Vaults Added by Owner

```solidity [MyVotingPowerProvider.sol]
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import {VotingPowerProvider} from "../src/modules/voting-power/VotingPowerProvider.sol";
import {OzOwnable} from "../src/modules/common/permissions/OzOwnable.sol";
import {EqualStakeVPCalc} from "../src/modules/voting-power/common/voting-power-calc/EqualStakeVPCalc.sol";
import {OperatorVaults} from "../src/modules/voting-power/extensions/OperatorVaults.sol";

contract MyVotingPowerProvider is VotingPowerProvider, OzOwnable, EqualStakeVPCalc, OperatorVaults {
    constructor(address operatorRegistry, address vaultFactory) VotingPowerProvider(operatorRegistry, vaultFactory) {}

    function initialize(
        VotingPowerProviderInitParams memory votingPowerProviderInitParams,
        OzOwnableInitParams memory ozOwnableInitParams
    ) public virtual initializer {
        __VotingPowerProvider_init(votingPowerProviderInitParams);
        __OzOwnable_init(ozOwnableInitParams);
    }
}
```

##### Shared Vaults Whitelisted under AccessControl

```solidity [MyVotingPowerProvider.sol]
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import {VotingPowerProvider} from "../src/modules/voting-power/VotingPowerProvider.sol";
import {OzAccessControl} from "../src/modules/common/permissions/OzAccessControl.sol";
import {EqualStakeVPCalc} from "../src/modules/voting-power/common/voting-power-calc/EqualStakeVPCalc.sol";
import {SharedVaults} from "../src/modules/voting-power/extensions/SharedVaults.sol";
import {OperatorsWhitelist} from "../src/modules/voting-power/extensions/OperatorsWhitelist.sol";
import {ISharedVaults} from "../src/interfaces/modules/voting-power/extensions/ISharedVaults.sol";

contract MyVotingPowerProvider is VotingPowerProvider, OzAccessControl, EqualStakeVPCalc, SharedVaults, OperatorsWhitelist {
    bytes32 public constant REGISTER_SHARED_VAULT = keccak256("REGISTER_SHARED_VAULT");
    bytes32 public constant UNREGISTER_SHARED_VAULT = keccak256("UNREGISTER_SHARED_VAULT");
    bytes32 public constant SET_WHITELIST_STATUS = keccak256("SET_WHITELIST_STATUS");
    bytes32 public constant WHITELIST_OPERATOR = keccak256("WHITELIST_OPERATOR");
    bytes32 public constant UNWHITELIST_OPERATOR = keccak256("UNWHITELIST_OPERATOR");

    constructor(address operatorRegistry, address vaultFactory) VotingPowerProvider(operatorRegistry, vaultFactory) {}

    function initialize(
        VotingPowerProviderInitParams memory votingPowerProviderInitParams,
        address defaultAdmin
    ) public virtual initializer {
        __VotingPowerProvider_init(votingPowerProviderInitParams);

        _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
        _setSelectorRole(ISharedVaults.registerSharedVault.selector, REGISTER_SHARED_VAULT);
        _setSelectorRole(ISharedVaults.unregisterSharedVault.selector, UNREGISTER_SHARED_VAULT);
        _setSelectorRole(ISharedVaults.setWhitelistStatus.selector, SET_WHITELIST_STATUS);
        _setSelectorRole(ISharedVaults.whitelistOperator.selector, WHITELIST_OPERATOR);
        _setSelectorRole(ISharedVaults.unwhitelistOperator.selector, UNWHITELIST_OPERATOR);
    }

    function _registerOperatorImpl(
        address operator
    ) internal virtual override(VotingPowerProvider, OperatorsWhitelist) {
        super._registerOperatorImpl(operator);
    }
}
```

### VotingPowerProvider Power Calculators

`VotingPowerProvider` always inherits a virtual [VotingPowerCalculators](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/common/voting-power-calc/) contracts that has to be implemented in the resulting contract.
Symbiotic provides several stake-to-votingPower conversion mechanisms you can separately or combine:

* [EqualStakeVPCalc](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/common/voting-power-calc/EqualStakeVPCalc.sol) - voting power is equal to stake
* [NormalizedTokenDecimalsVPCalc](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/common/voting-power-calc/NormalizedTokenDecimalsVPCalc.sol) - all tokens' decimals are normalized to 18
* [PricedTokensChainlinkVPCalc](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/common/voting-power-calc/PricedTokensChainlinkVPCalc.sol) - voting power is calculated using Chainlink price feeds
* [WeightedTokensVPCalc](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/common/voting-power-calc/WeightedTokensVPCalc.sol) - voting power is affected by configured weights for tokens
* [WeightedVaultsVPCalc](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/common/voting-power-calc/WeightedVaultsVPCalc.sol) - voting power is affected by configured weights for vaults

#### Examples

##### Chainlink-Priced Stake with Token-/Vault-Specific Weights

```solidity [MyVotingPowerProvider.sol]
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import {VotingPowerProvider} from "../src/modules/voting-power/VotingPowerProvider.sol";
import {PricedTokensChainlinkVPCalc} from
    "../src/modules/voting-power/common/voting-power-calc/PricedTokensChainlinkVPCalc.sol";
    import {OzOwnable} from "../src/modules/common/permissions/OzOwnable.sol";
import {WeightedTokensVPCalc} from "../src/modules/voting-power/common/voting-power-calc/WeightedTokensVPCalc.sol";
import {WeightedVaultsVPCalc} from "../src/modules/voting-power/common/voting-power-calc/WeightedVaultsVPCalc.sol";
import {VotingPowerCalcManager} from "../src/modules/voting-power/base/VotingPowerCalcManager.sol";

contract MyVotingPowerProvider is VotingPowerProvider, OzOwnable, PricedTokensChainlinkVPCalc, WeightedTokensVPCalc, WeightedVaultsVPCalc {
    constructor(address operatorRegistry, address vaultFactory) VotingPowerProvider(operatorRegistry, vaultFactory) {}

    function initialize(
        VotingPowerProviderInitParams memory votingPowerProviderInitParams,
        OzOwnableInitParams memory ozOwnableInitParams
    ) public virtual initializer {
        __VotingPowerProvider_init(votingPowerProviderInitParams);
        __OzOwnable_init(ozOwnableInitParams);
    }

    function stakeToVotingPowerAt(
        address vault,
        uint256 stake,
        bytes memory extraData,
        uint48 timestamp
    )
        public
        view
        override(VotingPowerCalcManager, PricedTokensChainlinkVPCalc, WeightedTokensVPCalc, WeightedVaultsVPCalc)
        returns (uint256)
    {
        return super.stakeToVotingPowerAt(vault, stake, extraData, timestamp);
    }

    function stakeToVotingPower(
        address vault,
        uint256 stake,
        bytes memory extraData
    )
        public
        view
        override(VotingPowerCalcManager, PricedTokensChainlinkVPCalc, WeightedTokensVPCalc, WeightedVaultsVPCalc)
        returns (uint256)
    {
        return super.stakeToVotingPower(vault, stake, extraData);
    }
}
```

:::note
If too many extensions/additions are implemented, the contract may exceed the maximum bytecode size. In this case, try adding `via-ir` flag with low number of optimizer runs for Solidity compiler.
:::

## Deployment

The deployment tooling is in the [`script/`](https://github.com/symbioticfi/relay-contracts/tree/main/script) folder. It consists of [`RelayDeploy.sol`](https://github.com/symbioticfi/relay-contracts/tree/main/script/RelayDeploy.sol) Foundry script template and [`relay-deploy.sh`](https://github.com/symbioticfi/relay-contracts/tree/main/script/relay-deploy.sh) bash script (Relay smart contracts use external libraries, so it's not currently possible to use solely Foundry script for multi-chain deployment).

* [`RelayDeploy.sol`](https://github.com/symbioticfi/relay-contracts/tree/main/script/RelayDeploy.sol) - abstract base that wires common Symbiotic Core helpers and exposes four deployment hooks: KeyRegistry, VotingPowerProvider, Settlement, and ValSetDriver
* [`relay-deploy.sh`](https://github.com/symbioticfi/relay-contracts/tree/main/script/relay-deploy.sh) - orchestrates per-contract multi-chain deployments (uses Python to parse `toml` file)

The script deploys Relay modules under [OpenZeppelin's TransparentUpgradeableProxy](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/transparent/TransparentUpgradeableProxy.sol) using [CreateX](https://github.com/pcaversaccio/createx), providing better control for production deployments and simpler approaches for development.

::::steps

### Configure on-chain deployment

Implement your `MyRelayDeploy.sol` ([see example](https://github.com/symbioticfi/relay-contracts/tree/main/script/examples/MyRelayDeploy.sol)):

* Include the deployment configuration of your Relay modules
* Implement all virtual functions of `RelayDeploy.sol`
* In the constructor, input the path of the `toml` file
* Use additional helpers such as `getCore()`, `getKeyRegistry()`, `getVotingPowerProvider()`, etc. (see full list in [`RelayDeploy.sol`](https://github.com/symbioticfi/relay-contracts/tree/main/script/RelayDeploy.sol))

### Choose multi-chain setup

Implement your `my-relay-deploy.toml` ([see example](https://github.com/symbioticfi/relay-contracts/tree/main/script/examples/my-relay-deploy.toml)):

* Include RPC URLs needed for deployment and specify which modules to deploy on which chains
* **Do not replace \[1234567890] placeholder with endpoint\_url = ""**
* Contracts are deployed in this order: 1. KeyRegistry 2. VotingPowerProvider 3. Settlement 4. ValSetDriver

### Run the deployment

Execute the deployment script, e.g.:

```bash [bash]
./script/relay-deploy.sh ./script/examples/MyRelayDeploy.sol ./script/examples/my-relay-deploy.toml --broadcast --ledger
```

:::note
Basic form is `./script/relay-deploy.sh <FoundryScript> <TomlConfig> <Any Foundry Flags>`
:::

At the end, your `toml` file will contain the addresses of the deployed Relay modules.

::::

## Integrate

Symbiotic Relay provides comprehensive tooling that works independently, so you can focus on your stake-backed application logic.

### Verify Message

Your application contract can verify any message using a validator set at any point in time via:

```solidity [MyApp.sol]
import {ISettlement} from "@symbioticfi/relay-contracts/src/interfaces/modules/settlement/ISettlement.sol";

function verifyMessage(bytes calldata message, uint48 epoch, bytes calldata proof) public returns (bool) {
    return ISettlement(SETTLEMENT).verifyQuorumSigAt(
            abi.encode(keccak256(message)),
            15, // default key tag - BN254
            (uint248(1e18) * 2) / 3 + 1, // default quorum threshold - 2/3 + 1
            proof,
            epoch,
            new bytes(0)
    );
}
```

:::note
You need to have a `Settlement` deployed on the verification chain first.
:::

### Use Validator Set Data

Your application contract can use the validator set at any point in time using [SSZ](https://ethereum.org/developers/docs/data-structures-and-encoding/ssz/) proof verification, for example:

```solidity [MyApp.sol]
import {ValSetVerifier} from "@symbioticfi/relay-contracts/src/libraries/utils/ValSetVerifier.sol";
import {Math} from "openzeppelin-contracts/contracts/utils/math/Math.sol";

function verifyOperatorVotingPower(
    ValSetVerifier.SszProof calldata validatorRootProof,
    uint256 validatorRootLocalIndex,
    bytes32 validatorSetRoot,
    ValSetVerifier.SszProof calldata operatorProof,
    address operator,
    ValSetVerifier.SszProof calldata votingPowerProof,
    uint256 votingPower
) public returns (bool) {
    return operatorProof.leaf == bytes32(uint256(uint160(operator)) << 96)
        && ValSetVerifier.verifyOperator(
        validatorRootProof, validatorRootLocalIndex, validatorSetRoot, operatorProof
    ) && votingPowerProof.leaf == bytes32(votingPower << (256 - (Math.log2(votingPower) / 8 + 1) * 8))
        && ValSetVerifier.verifyVotingPower(
        validatorRootProof, validatorRootLocalIndex, validatorSetRoot, votingPowerProof
    );
}
```

:::note
You need to have a `Settlement` deployed on the verification chain first.
:::

## Next Steps

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Relay Off-Chain"
    description="Proceed to the the development of your protocol's off-chain part using Relay."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/networks/relay-offchain"
  />
</div>

# Relay Off-Chain

:::warning
The code is a work in progress and not production ready yet. Breaking changes may occur in code updates, and backward compatibility is not guaranteed. Use with caution.
:::

The Symbiotic Relay operates as a distributed middleware layer that facilitates:

* Validator Set Management: Derives and maintains validator sets across different epochs based on on-chain state
* Signature Aggregation: Collects individual validator signatures and aggregates them using BLS signatures or zero-knowledge proofs
* Cross-Chain Coordination: Manages validator sets across multiple EVM-compatible blockchains

## Architecture

The relay consists of several key components:

* **P2P Layer**: Uses libp2p with GossipSub for decentralized communication
* **Signer Nodes**: Sign messages using BLS/ECDSA keys
* **Aggregator Nodes**: Collect and aggregate signatures with configurable policies
* **Committer Nodes**: Submit aggregated proofs to settlement chains
* **API Server**: Exposes gRPC API for external clients

For detailed architecture information, see [here](https://github.com/symbioticfi/relay/blob/dev/DEVELOPMENT.md).

## Configure

:::info
For a complete reference of all configuration options and command-line flags, see the [relay\_sidecar CLI documentation](https://github.com/symbioticfi/relay/tree/dev/docs/cli/relay/relay_sidecar.md).
:::

Create a `config.yaml` file with the following structure:

```yaml [config.yaml]
# Logging
log:
    level: "debug" # Options: debug, info, warn, error
    mode: "pretty" # Options: json, text, pretty

# Storage
storage-dir: ".data" # Directory for persistent data
circuits-dir: "" # Path to ZK circuits (optional, empty disables ZK proofs)

# API Server
api:
    listen: ":8080" # API server address
    verbose-logging: false # Enable verbose API logging

# Metrics (optional)
metrics:
    listen: ":9090" # Metrics endpoint address
    pprof: false # Enable pprof debug endpoints

# Driver Contract
driver:
    chain-id: 31337 # Chain ID where driver contract is deployed
    address: "0x..." # Driver contract address

# Secret Keys
secret-keys:
    - namespace: "symb" # Namespace for the key
      key-type: 0 # 0=BLS-BN254, 1=ECDSA
      key-id: 15 # Key identifier
      secret: "0x..." # Private key hex

    - namespace: "evm"
      key-type: 1
      key-id: 31337
      secret: "0x..."

    - namespace: "p2p"
      key-type: 1
      key-id: 1
      secret: "0x..."

# Alternatively, use keystore
# keystore:
#   path: "/path/to/keystore.json"
#   password: "your-password"

# Signal Configuration, used for internal messages and event queues
signal:
    worker-count: 10 # Number of signal workers
    buffer-size: 20 # Signal buffer size

# Cache Configuration, used for in memorylookups for db queries
cache:
    network-config-size: 10 # Network config cache size
    validator-set-size: 10 # Validator set cache size

# Sync Configuration, sync signatures and proofs over p2p to recover missing information
sync:
    enabled: true # Enable P2P sync
    period: 5s # Sync period
    timeout: 1m # Sync timeout
    epochs: 5 # Number of epochs to sync

# Key Cache, used for fast public key lookups
key-cache:
    size: 100 # Key cache size
    enabled: true # Enable key caching

# P2P Configuration
p2p:
    listen: "/ip4/0.0.0.0/tcp/8880" # P2P listen address
    bootnodes: # List of bootstrap nodes (optional)
        - /dns4/node1/tcp/8880/p2p/...
    dht-mode: "server" # Options: auto, server, client, disabled, default: server (ideally should not change)
    mdns: true # Enable mDNS local discovery (useful for local networks)

# EVM Configuration
evm:
    chains: # List of settlement chain RPC endpoints
        - "http://localhost:8545"
        - "http://localhost:8546"
    max-calls: 30 # Max calls in multicall batches

# Aggregation Policy
aggregation-policy-max-unsigners: 50 # Max unsigners for low-cost policy
```

### Configure via Command-Line Flags

You can override config file values with command-line flags:

```bash
./relay_sidecar \
  --config config.yaml \
  --log.level debug \
  --storage-dir /var/lib/relay \
  --api.listen ":8080" \
  --p2p.listen "/ip4/0.0.0.0/tcp/8880" \
  --driver.chain-id 1 \
  --driver.address "0x..." \
  --secret-keys "symb/0/15/0x...,evm/1/31337/0x..." \
  --evm.chains "http://localhost:8545"
```

### Configure via Environment Variables

Environment variables use the `SYMB_` prefix with underscores instead of dashes and dots:

```bash
export SYMB_LOG_LEVEL=debug
export SYMB_LOG_MODE=pretty
export SYMB_STORAGE_DIR=/var/lib/relay
export SYMB_API_LISTEN=":8080"
export SYMB_P2P_LISTEN="/ip4/0.0.0.0/tcp/8880"
export SYMB_DRIVER_CHAIN_ID=1
export SYMB_DRIVER_ADDRESS="0x..."

./relay_sidecar --config config.yaml
```

### Configuration Priority

Configuration is loaded in the following order (highest priority first):

1. Command-line flags
2. Environment variables (with `SYMB_` prefix)
3. Configuration file (specified by `--config`)

### Example

For reference, see how configurations are generated in the E2E setup:

```bash
# See the template in e2e/scripts/sidecar-start.sh (lines 11-27)
cat e2e/scripts/sidecar-start.sh
```

## Download and Run

Pre-built Docker images are available from Docker Hub:

:::steps

#### Pull the image

The latest image:

```bash [bash]
docker pull symbioticfi/relay:latest
```

Or a specific version:

```bash [bash]
docker pull symbioticfi/relay:<tag>
```

#### Run the relay sidecar

```bash [bash]
docker run -v $(pwd)/config.yaml:/config.yaml \
  symbioticfi/relay:latest \
  --config /config.yaml
```

:::

:::info
Docker Hub: https://hub.docker.com/r/symbioticfi/relay
:::

## API

The relay exposes both gRPC and HTTP/JSON REST APIs for interacting with the network:

### gRPC API

* [**API Documentation**](https://github.com/symbioticfi/relay/tree/dev/docs/api/v1/doc.md)
* [**Proto Definitions**](https://github.com/symbioticfi/relay/blob/dev/api/proto/v1/api.proto)
* [**Go Client**](https://github.com/symbioticfi/relay/tree/dev/api/client/v1/)
* [**Client Examples**](https://github.com/symbioticfi/relay/tree/dev/api/client/examples/)

### HTTP/JSON REST API Gateway

The relay includes an optional HTTP/JSON REST API gateway that translates HTTP requests to gRPC:

* [**Swagger File**](https://github.com/symbioticfi/relay/tree/dev/docs/api/v1/api.swagger.json)
* **Endpoints**: All gRPC methods accessible via RESTful HTTP at `/api/v1/*`

Enable via configuration:

```yaml [config.yaml]
api:
    http-gateway: true
```

Or via command-line flag:

```bash [bash]
./relay_sidecar --api.http-gateway=true
```

### Client Libraries

| Language   | Repository                                                           |
| ---------- | -------------------------------------------------------------------- |
| Go         | [relay](https://github.com/symbioticfi/relay/tree/dev/api/client/v1) |
| TypeScript | [relay-client-ts](https://github.com/symbioticfi/relay-client-ts)    |
| Rust       | [relay-client-rs](https://github.com/symbioticfi/relay-client-rs)    |

:::note
Use the HTTP gateway for language-agnostic access if needed.
:::

### Snippets

Check out multiple simple snippets how to use the clients mentioned above:

:::code-group

<div data-title="Go">
  ```go [myApp.go]
  import (
      relay "github.com/symbioticfi/relay/api/client/v1"
  )

  func main() {
      relayClient = relay.NewSymbioticClient(conn)

      epochInfos, _ := relayClient.GetLastAllCommitted(ctx, &relay.GetLastAllCommittedRequest{})
      suggestedEpoch := epochInfos.SuggestedEpochInfo.GetLastCommittedEpoch()

      signMessageResponse, _ := relayClient.SignMessage(ctx, &relay.SignMessageRequest{
          KeyTag:        15, // default key tag - BN254
          Message:       encode(taskId),
          RequiredEpoch: &suggestedEpoch,
      })

      listenProofsRequest := &relay.ListenProofsRequest{
          StartEpoch: suggestedEpoch,
      }
      proofsStream, _ := relayClient.ListenProofs(ctx, listenProofsRequest)
      aggregationProof = []byte{}
      while proofResponse, _ := proofsStream.Recv() {
          if proofResponse.GetRequestId() == signMessageResponse.GetRequestId() {
              aggregationProof = proofResponse.GetAggregationProof().GetProof()
              break
          }
      }

      appContract.CompleteTask(taskId, signMessageResponse.Epoch, aggregationProof)
  }
  ```
</div>

<div data-title="TypeScript">
  ```go [myApp.ts]
  import { createClient } from "@connectrpc/connect";
  import { SymbioticAPIService } from "@symbioticfi/relay-client-ts";
  import {
    GetLastAllCommittedRequestSchema,
    SignMessageRequestSchema,
    ListenProofsRequestSchema,
  } from "@symbioticfi/relay-client-ts";
  import { create } from "@bufbuild/protobuf";

  async function main() {
      const relayClient = createClient(SymbioticAPIService, transport);

      const getLastAllCommittedResponse = await relayClient.getLastAllCommitted(create(GetLastAllCommittedRequestSchema));
      const suggestedEpoch = getLastAllCommittedResponse.suggestedEpochInfo.lastCommittedEpoch;

      const signMessageRequest = create(SignMessageRequestSchema, {
          keyTag: 15, // default key tag - BN254
          message: encode(taskId),
          requiredEpoch: suggestedEpoch,
      });
      const signMessageResponse = await relayClient.signMessage(signMessageRequest);

      const listenProofsRequest = create(ListenProofsRequestSchema, { startEpoch: suggestedEpoch });
      const proofsStream = await relayClient.listenProofs(listenProofsRequest);
      let aggregationProof;
      for await (const proofResponse of proofsStream) {
          if (proofResponse.requestId === signMessageResponse.requestId) {
              aggregationProof = proofResponse.aggregationProof?.proof;
              break;
          }
      }

      await appContract.completeTask(taskId, signMessageResponse.epoch, aggregationProof);
  }
  ```
</div>

<div data-title="Rust">
  ```go [my_app.rs]
  use symbiotic_relay_client::generated::api::proto::v1::{
      GetLastAllCommittedRequest, SignMessageRequest, ListenProofsRequest,
      symbiotic_api_service_client::SymbioticApiServiceClient,
  };

  #[tokio::main]
  async fn main() -> Result<(), Box<dyn std::error::Error>> {
      let mut relay_client = SymbioticApiServiceClient::new(channel);

      let epoch_infos_response = relay_client.get_last_all_committed(tonic::Request::new(GetLastAllCommittedRequest {})).await?;
      let epoch_infos_data = epoch_infos_response.into_inner();
      let mut suggested_epoch = epoch_infos_data.suggested_epoch_info.last_committed_epoch;

     let sign_request = tonic::Request::new(SignMessageRequest {
          key_tag: 15, // default key tag - BN254
          message: encode(task_id).into(),
          required_epoch: suggested_epoch,
      });
      let sign_response = relay_client.sign_message(sign_request).await?;
      let sign_data = sign_response.into_inner();

      let listen_proofs_request = tonic::Request::new(ListenProofsRequest { start_epoch: suggested_epoch });
      let proofs_stream = relay_client.listen_proofs(listen_proofs_request).await?.into_inner();
      let mut aggregation_proof = None;
      while let Some(proof_response) = proofs_stream.next().await {
          match proof_response {
              Ok(proof_data) => {
                  if proof_data.request_id == sign_data.request_id {
                      if let Some(proof) = proof_data.aggregation_proof {
                          aggregation_proof = Some(proof.proof);
                          break;
                      }
                  }
              }
              Err(e) => { break; }
          }
      }

      appContract.complete_task(task_id, sign_data.epoch, aggregation_proof.unwrap()).await?;
  }
  ```
</div>

::::

## Integration Examples

For a complete end-to-end examples application using the relay, see:

| Repository                                                                | Description                                                   |
| ------------------------------------------------------------------------- | ------------------------------------------------------------- |
| [Symbiotic Super Sum](https://github.com/symbioticfi/symbiotic-super-sum) | A simple task-based network                                   |
| [Cosmos Relay SDK](https://github.com/symbioticfi/cosmos-relay-sdk)       | An application built using the Cosmos SDK and Symbiotic Relay |

## Next Steps

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title="Helpful Core Contracts' Endpoints"
    description="Check out core contracts' endpoints that may help you during integration."
    icon={
          <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
              <rect
                  x="8"
                  y="8"
                  width="32"
                  height="32"
                  rx="2"
                  stroke="currentColor"
                  strokeWidth="2"
                  fill="none"
              />
              <rect
                  x="12"
                  y="12"
                  width="24"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="18"
                  width="20"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="24"
                  width="16"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
              <rect
                  x="12"
                  y="30"
                  width="18"
                  height="3"
                  rx="1.5"
                  fill="currentColor"
                  opacity="0.3"
              />
          </svg>
      }
    href="/integrate/networks/helpful-core-contracts-endpoints"
  />
</div>

# Helpful Core Contracts' Endpoints

This page lists useful functions for networks across Symbiotic Core contracts.

| Function                                                                                                                                                                                                                                                            | Use-case                                                                                   |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| [`NetworkRegistry.registerNetwork()`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/INetworkRegistry.sol#L12)                                                                                                    | Register network                                                                           |
| [`Vault.isInitialized() → bool`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/vault/IVault.sol#L165)                                                                                                            | Check if the vault has set delegator and slasher before on-boarding as a valid Vault       |
| [`Vault.delegator() → address`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/vault/IVaultStorage.sol#L60)                                                                                                       | Get the Vault's delegator                                                                  |
| [`Vault.slasher() → address`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/vault/IVaultStorage.sol#L72)                                                                                                         | Get the Vault's slasher                                                                    |
| [`BaseDelegator.TYPE() → uint64`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/common/IEntity.sol#L17)                                                                                                          | Get the delegator's type (0 - NetworkRestake, 1 - FullRestake, etc.)                       |
| [`BaseDelegator.setMaxNetworkLimit(uint96 identifier, uint256 amount)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IBaseDelegator.sol#L158)                                                         | Set an amount of collateral you are ready to accept from the Vault (maximum network limit) |
| [`BaseDelegator.maxNetworkLimit(bytes32 subnetwork) → uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IBaseDelegator.sol#L125)                                                                 | Check the maximum network limit                                                            |
| [`BaseDelegator.stakeAt(bytes32 subnetwork, address operator, uint48 timestamp, bytes hints) → uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IBaseDelegator.sol#L137)                        | Get the operator's stake at the given timestamp                                            |
| [`BaseSlasher.TYPE() → uint64`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/common/IEntity.sol#L17)                                                                                                            | Get the slasher's type (0 - Slasher, 1 - VetoSlasher)                                      |
| [`BaseSlasher.slashableStake() → uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/slasher/IBaseSlasher.sol#L113)                                                                                          | Get the operator's still slashable stake captured at the given timestamp                   |
| [`Slasher.slash() → uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/slasher/ISlasher.sol#L55)                                                                                                            | Slash the operator                                                                         |
| [`VetoSlasher.requestSlash(bytes32 subnetwork, address operator, uint256 amount, uint48 captureTimestamp, bytes hints) -> uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/slasher/IVetoSlasher.sol#L213) | Request slashing of the operator                                                           |
| [`VetoSlasher.executeSlash(uint256 slashIndex, bytes hints) -> uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/slasher/IVetoSlasher.sol#L228)                                                            | Execute slashing of the operator                                                           |
| [`VetoSlasher.setResolver(uint96 identifier, address resolver, bytes hints)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/slasher/IVetoSlasher.sol#L245)                                                       | Set a resolver                                                                             |
| [`VetoSlasher.resolver(bytes32 subnetwork, bytes hint)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/slasher/IVetoSlasher.sol#L201)                                                                            | Check the resolver                                                                         |

# Get Started

Operators run network infrastructure and process logic provided by networks. This guide walks you through the operator lifecycle in Symbiotic.

::::steps

## Register Operator

Register your operator's management address in the Symbiotic system.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Register your operator's management address within the Symbiotic system."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/operators/register-operator"
  />
</div>

## Submit Metadata

Make your operator visible on the Symbiotic UI by submitting metadata.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Submit a PR with your operator's metadata to make it visible on the Symbiotic UI."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/operators/submit-metadata"
  />
</div>

## Opt Into Networks and Vaults

Opt into vaults and networks to start using funds allocated to you by curators.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Opt into the corresponding vaults and networks to start using funds allocated to you by curators."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/operators/opt-ins"
  />
</div>

## Claim Rewards

Claim operator rewards from the Rewards contract when distributions are available.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Claim operator rewards from the Rewards contract."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/operators/claim-rewards"
  />
</div>

::::

# Register Operator

Register your operator using the `OperatorRegistry` smart contract. The registered address serves as your management address for opting into vaults and networks to receive allocations.

## Using [Safe](https://app.safe.global/)

1. Open "Transaction builder"
2. Enter `OperatorRegistry` as the contract address
3. Select the `optIn()` method
4. Sign and send the transaction

## Verify Registration

Verify your registration on Etherscan:

1. Open the "Read Contract" tab in the `OperatorRegistry` contract
2. Open the `isEntity()` method
3. Enter your `OPERATOR_ADDRESS` in the `account` parameter
4. Click "Query" — it should return `True`

![Operator registration verification](/guides/img/opt-in/register-operator.png)

# Submit Metadata

The [Symbiotic UI](https://app.symbiotic.fi/deposit) displays TVL, allocations, and relationships between curators, vaults, operators, and networks. To make your entity visible on the UI, submit its metadata to the corresponding repository.

After you submit metadata, the Symbiotic team reviews and merges it. Once merged, your data appears on the UI.

## Add a New Entity Template

### Choose a Repository

| Chain   | URL                                             |
| ------- | ----------------------------------------------- |
| Mainnet | https://github.com/symbioticfi/metadata-mainnet |
| Hoodi   | https://github.com/symbioticfi/metadata-hoodi   |

### Repository Structure

The repository is organized as follows:

```
repository/
├── vaults/
│   ├── 0x<address>/
│   │   ├── info.json
│   │   └── logo.png (optional)
├── networks/
├── operators/
├── tokens/
```

Each entity is identified by its Ethereum address (`0x...`), and its data is stored in a folder named after the address. Inside this folder, include a file `info.json` containing metadata, and optionally, an icon file `logo.png`.

***

### Steps to Add a New Entity

**Note: After your PR is submitted, email your PR link to verify@symbiotic.fi from your official business email (domain must match that of your entity website) to allow us to confirm your identity ahead of merging your PR.**

1. **Determine the entity type**:
   * Decide whether the entity belongs to `vaults`, `networks`, `operators`, `tokens` or `points`.
   * If the entity is a `vault`, ensure its collateral token entity is registered in the `tokens` folder before adding the vault metadata. If not, add the token first.
2. **Register the entity in the registry**:
   * Before adding metadata for vaults, networks, or operators, ensure that they are registered in their respective registries. You can find the current registry contract addresses in the [Addresses page](/get-started/resources/addresses). Unregistered entities will not be accepted.
3. **Create a new folder**:
   * Navigate to the appropriate directory for the entity type.
   * Create a folder named after the Ethereum address (e.g., `0x1234567890abcdef1234567890abcdef12345678`).
4. **Add the `info.json` file**:
   * Include metadata in the specified format (see below).
5. **(Optional) Add an icon file**:
   * If available, include a `logo.png` file with the entity’s logo.

The Symbiotic team reviews your PR after automated checks pass. If approved, it will be merged into the repository.

***

### File Format: `info.json`

The `info.json` file must follow this structure:

#### Required Fields

* `name` (string): The name of the entity.
* `description` (string): A brief description of the entity.
* `tags` (array of strings): Tags categorizing the entity.
* `links` (array of objects): External links related to the entity.

#### Supported `links` Types

Each link should include:

* `type`: The type of the link. Supported values are:
  * `website`: The official website of the entity.
  * `explorer`: A blockchain explorer link for the entity's Ethereum address or contract.
  * `docs`: Documentation related to the entity.
  * `example`: Example use cases or tutorials.
  * `externalLink`: A link to be shown below the entity's name.
* `name`: A user-friendly name for the link.
* `url`: The URL of the resource.

### Icon File: `logo.png` (Optional)

If you want to include an icon for the entity, follow these guidelines:

* **File Name**: `logo.png`
* **Dimensions**: 256x256 pixels
* **Format**: PNG

Place the `logo.png` file in the same folder as the `info.json` file.

***

### Validation

Before submitting your PR, ensure the following:

1. The Ethereum address is valid:
   * It must start with `0x` and be exactly 42 characters long.
2. The `info.json` file is valid:
   * Use a JSON validator, such as [https://jsonlint.com/](https://jsonlint.com/).
3. The `logo.png` file (if included) meets the size requirement of **256x256 pixels**.

***

### Submitting the Pull Request

Once your files are added to the repository, create a Pull Request with the following details:

1. **Entity Type**: Specify the type (vault, network, operator, token).
2. **Ethereum Address**: Provide the address of the entity.
3. **Description**: Summarize the entity’s purpose and data.

#### Example PR Description

```
Added new token entity: 0x1234567890abcdef1234567890abcdef12345678

- **Name**: USDT
- **Description**: USDT is a stablecoin pegged to the US Dollar, widely used for trading and liquidity in cryptocurrency markets.
- **Tags**: stablecoin, usdt
- **Links**:
  - [Website](https://tether.to/)
  - [Etherscan](https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7)
  - [Tether Documentation](https://docs.tether.to/)
- **CMC ID**: 825
- **Permit Name**: USDT Permit Token
- **Permit Version**: 1
- **Icon**: Included (256x256 px)
```

***

### Review and Approval

Your PR will be reviewed to ensure:

* The `info.json` file has all required fields and valid data.
* The `logo.png` file (if included) meets the requirements.
* The metadata is accurate and well-structured.
* The submitter of the PR is from the entity in question (verified via an email with your PR link to verify@symbiotic.fi from your official business email)

After approval, your changes will be merged into the repository.

## Add an Operator

:::steps

##### Create a new folder in the `/operators` directory

##### Create a new json file in the folder with the following structure:

```json [info.json]
{
    "name": "My Operator",
    "description": "My Operator",
    "tags": ["operator"],
    "links": [{ "type": "website", "name": "Website", "url": "https://myoperator.com" }]
}
```

##### Save a logo of the Operator to `logo.png` of 256x256 pixels size

:::

# Opt Into Networks and Vaults

Before you can start receiving delegations, complete two opt-in steps:

* Opt-in to networks you want to interact with
* Opt-in to vaults you plan to receive delegations from, including operator-specific vaults

:::note
Some networks may require additional registration steps through their middleware systems. These network-specific requirements vary and are not covered in this document.
:::

## Opt-in to Network

### Using [Safe](https://app.safe.global/)

1. Open "Transaction builder"
2. Enter `OperatorNetworkOptInService` as the contract address
3. Select the `optIn()` method
4. Enter the desired network's address
5. Sign and send the transaction

### Verify via Etherscan

1. Open the "Read Contract" tab in the `OperatorNetworkOptInService` contract
2. Open the `isOptedIn()` method
3. Enter your `OPERATOR_ADDRESS` in the `who` parameter and `NETWORK_ADDRESS` in the `where` parameter
4. Click "Query" — it should return `True`

![Opt-in to vault verification](/guides/img/opt-in/opt-in-network.png)

## Opt-in to Vault

### Using [Safe](https://app.safe.global/)

1. Open "Transaction builder"
2. Enter `OperatorVaultOptInService` as the contract address
3. Select the `optIn()` method
4. Enter the desired vault's address
5. Sign and send the transaction

### Verify via Etherscan

1. Open the "Read Contract" tab in the `OperatorVaultOptInService` contract
2. Open the `isOptedIn()` method
3. Enter your `OPERATOR_ADDRESS` in the `who` parameter and `VAULT_ADDRESS` in the `where` parameter
4. Click "Query" — it should return `True`

![Opt-in to vault verification](/guides/img/opt-in/opt-in-vault.png)

# Claim Rewards

Operators claim fees from `Rewards.sol` using the `claimOperatorFees` entrypoint for Vault Snapshot rewards. Find the up-to-date Rewards contract address on the [Addresses page](/get-started/resources/addresses#rewards).

## Check claimable rewards

Use the view functions on `Rewards.sol` to determine the range of rewards to claim:

* `rewardsLength(vault, network, token)` returns the total number of reward distributions.
* `lastUnclaimedOperatorReward(account, vault, network, token)` returns the index of your last unclaimed reward.

## Claim operator fees (spec)

```solidity
function claimOperatorFees(
    address recipient,
    address network,
    address token,
    address vault,
    uint256 lastUnclaimedRewards,
    uint256 firstRewardToClaim,
    uint256 rewardsToClaim,
    bytes calldata extraData
) public
```

| Parameter              | Description                                                                   |
| ---------------------- | ----------------------------------------------------------------------------- |
| `recipient`            | Address that receives the claimed tokens                                      |
| `network`              | Network whose operator fees are being claimed                                 |
| `token`                | ERC20 reward token                                                            |
| `vault`                | Vault address                                                                 |
| `lastUnclaimedRewards` | Expected current index from storage (reorg protection)                        |
| `firstRewardToClaim`   | Optional starting index for claiming                                          |
| `rewardsToClaim`       | Max number of rewards to process                                              |
| `extraData`            | ABI-encoded hints for NetworkRestakeDelegator; pass empty bytes if not needed |

### Example: calculate unclaimed reward and execute claim function

```solidity
uint256 totalRewards = rewards.rewardsLength(vault, network, token);
uint256 lastClaimed = rewards.lastUnclaimedOperatorReward(operator, vault, network, token);
uint256 unclaimedCount = totalRewards - lastClaimed;

bytes memory extraData = abi.encode(operatorNetworkSharesHints, totalOperatorNetworkSharesHint);
rewards.claimOperatorFees(
    recipient,
    network,
    token,
    vault,
    lastClaimed,
    0,
    unclaimedCount,
    ""
);
```

# Helpful Core Contracts' Endpoints

This page lists useful functions for operators across Symbiotic Core contracts.

| Function                                                                                                                                                                              | Use-case                 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
| [`OperatorRegistry.registerOperator()`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/IOperatorRegistry.sol#L12)                   | Register operator        |
| [`OperatorNetworkOptInService.optIn(address where)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/service/IOptInService.sol#L76)  | Opt into the network     |
| [`OperatorNetworkOptInService.optOut(address where)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/service/IOptInService.sol#L91) | Opt out from the network |
| [`OperatorVaultOptInService.optIn(address where)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/service/IOptInService.sol#L76)    | Opt into the vault       |
| [`OperatorVaultOptInService.optOut(address where)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/service/IOptInService.sol#L91)   | Opt out from the vault   |

# Get Started

This guide walks you through the curator lifecycle in Symbiotic. You'll deploy a vault, manage allocations, and earn fees from managing depositors' funds.

::::steps

## Deploy Vault

Deploy a vault that matches your curation needs.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Deploy a vault configured for your curation strategy."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/curators/deploy-vault"
  />
</div>

## Configure Curator & Operator Fees

Register the curator in `CuratorRegistry` and configure curator and operator fees.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Register the curator and configure fee settings."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/curators/registry-and-fees"
  />
</div>

## Submit Metadata

Make your curator and vault visible on the Symbiotic UI.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Submit a PR with your curator's and vault's metadata to make them visible on the Symbiotic UI."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/curators/submit-metadata"
  />
</div>

## Manage Allocations

Configure how your vault allocates stake to networks and operators.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Configure stake allocations to networks and operators based on your risk and allocation policy."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/curators/manage-allocations"
  />
</div>

## Claim Curator Fees

Claim curator fees from the Rewards contract when distributions are available.

<div
  style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
      gap: "24px",
      marginBottom: "48px",
  }}
>
  <Card1
    title=""
    description="Claim curator fees from the Rewards contract."
    icon={
      <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
          <rect
              x="8"
              y="8"
              width="32"
              height="32"
              rx="2"
              stroke="currentColor"
              strokeWidth="2"
              fill="none"
          />
          <rect x="12" y="12" width="24" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="18" width="20" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="24" width="16" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
          <rect x="12" y="30" width="18" height="3" rx="1.5" fill="currentColor" opacity="0.3" />
      </svg>
  }
    href="/integrate/curators/registry-and-fees#claim-process"
  />
</div>

::::

# Deploy Vault

Symbiotic is a highly modular protocol with many separate parts and more coming in the future. This guide describes possible vault deployment configurations.

## General-purpose deployment

To deploy a ready-to-go vault, first determine how it will be used:

1. As a very specific configuration inside some complex system of contracts that you design and create
2. As a very pure configuration with most parameters non-updatable that is difficult to manage in practice
3. **As some common configuration that may cover most of the use cases**

We choose the 3rd option. Follow these steps to get a production-ready configuration:

1. Deploy a **Burner Router** (a specific implementation of the Burner module)

2. Deploy **core modules such as Vault, Delegator, Slasher** using the deployed Burner Router address

3. Deploy **staker rewards** with the use of the Vault’s address got during the previous step

### 1. Burner Router

A burner is a contract that receives slashed collateral tokens. Symbiotic doesn't specify how funds are processed after slashing. Possible approaches include:

* Fully burn the funds (unwrap the underlying assets if needed)
* Redistribute to good operators
* Compensate the victims (in case of using the stake as a security deposit)

From our side, we provide:

* **DefaultBurners** - pure burner contracts for several ETH LSTs
* **BurnerRouter** - a router contract that allows redirection of the slashed funds to different addresses depending on the slashing networks and the slashed operators

Our pure burners have one advantage and disadvantage: they are fully immutable, removing trust assumptions, but if the underlying LST's contracts upgrade, their flow may break. We recommend using **BurnerRouter**, which includes receiver update functionality, paired with a **DefaultBurner** as a global receiver.

![burner](/guides/img/deployment/burner.png)

<Details summary="Burner Router deployment">
  1. Clone the burners repository by running the following command:

  ```bash [bash]
  git clone --recurse-submodules https://github.com/symbioticfi/burners.git
  ```

  2. Navigate into the cloned repository folder:

  ```bash [bash]
  cd burners
  ```

  3. Deploy a burner router contract using [a simple script](https://github.com/symbioticfi/burners/blob/main/script/deploy/BurnerRouter.s.sol):

  :::note
  This is an **example** command. Replace the given values with your own.

  ***

  In addition, you need to [choose a preferred wallet option](https://book.getfoundry.sh/reference/forge/forge-script?highlight=forge%20script#wallet-options---raw) and adjust the command accordingly.
  :::

  <Tabs groupId="chains" defaultValue="mainnet">
    <TabItem value="mainnet" label="Mainnet">
      ```bash [bash]
      OWNER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7                 # address of the router’s owner
      COLLATERAL=0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0            # address of the collateral - wstETH (MUST be the same as for the Vault to connect)
      DELAY=1814400                                                    # duration of the receivers’ update delay (= 21 days)
      GLOBAL_RECEIVER=0xdCaC890b14121FD5D925E2589017Be68C2B5B324       # address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
      NETWORK_RECEIVERS=[]                                             # array with elements like "\(network_address,receiver_address\)" meaning network-specific receivers
      OPERATOR_NETWORK_RECEIVERS=[]                                    # array with elements like "\(network_address,operator_address,receiver_address\)" meaning operator-network-specific receivers

      forge script script/deploy/BurnerRouter.s.sol:BurnerRouterScript \
        $OWNER \
        $COLLATERAL \
        $DELAY \
        $GLOBAL_RECEIVER \
        $NETWORK_RECEIVERS \
        $OPERATOR_NETWORK_RECEIVERS \
      --sig "run(address,address,uint48,address,(address,address)[],(address,address,address)[])" \
      --rpc-url=https://ethereum-rpc.publicnode.com \
      --chain mainnet \
      --broadcast
      ```
    </TabItem>

    <TabItem value="hoodi" label="Hoodi">
      ```bash [bash]
      OWNER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7                 # address of the router’s owner
      COLLATERAL=0x8d09a4502Cc8Cf1547aD300E066060D043f6982D            # address of the collateral - wstETH (MUST be the same as for the Vault to connect)
      DELAY=1814400                                                    # duration of the receivers’ update delay (= 21 days)
      GLOBAL_RECEIVER=0x25133c2c49A343F8312bb6e896C1ea0Ad8CD0EBd       # address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
      NETWORK_RECEIVERS=[]                                             # array with elements like "\(network_address,receiver_address\)" meaning network-specific receivers
      OPERATOR_NETWORK_RECEIVERS=[]                                    # array with elements like "\(network_address,operator_address,receiver_address\)" meaning operator-network-specific receivers

      forge script script/deploy/BurnerRouter.s.sol:BurnerRouterScript \
        $OWNER \
        $COLLATERAL \
        $DELAY \
        $GLOBAL_RECEIVER \
        $NETWORK_RECEIVERS \
        $OPERATOR_NETWORK_RECEIVERS \
      --sig "run(address,address,uint48,address,(address,address)[],(address,address,address)[])" \
      --rpc-url=https://ethereum-hoodi.gateway.tatum.io \
      --chain hoodi \
      --broadcast
      ```
    </TabItem>

    <TabItem value="sepolia" label="Sepolia">
      ```bash [bash]
      OWNER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7                 # address of the router’s owner
      COLLATERAL=0xB82381A3fBD3FaFA77B3a7bE693342618240067b            # address of the collateral - wstETH (MUST be the same as for the Vault to connect)
      DELAY=1814400                                                    # duration of the receivers’ update delay (= 21 days)
      GLOBAL_RECEIVER=0x58D347334A5E6bDE7279696abE59a11873294FA4       # address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
      NETWORK_RECEIVERS=[]                                             # array with elements like "\(network_address,receiver_address\)" meaning network-specific receivers
      OPERATOR_NETWORK_RECEIVERS=[]                                    # array with elements like "\(network_address,operator_address,receiver_address\)" meaning operator-network-specific receivers

      forge script script/deploy/BurnerRouter.s.sol:BurnerRouterScript \
        $OWNER \
        $COLLATERAL \
        $DELAY \
        $GLOBAL_RECEIVER \
        $NETWORK_RECEIVERS \
        $OPERATOR_NETWORK_RECEIVERS \
      --sig "run(address,address,uint48,address,(address,address)[],(address,address,address)[])" \
      --rpc-url=https://ethereum-sepolia-rpc.publicnode.com \
      --chain sepolia \
      --broadcast
      ```
    </TabItem>
  </Tabs>
</Details>

<Details summary="Burner Router deployment - technical (Solidity)">
  The following instruction assumes you have an already initialized Foundry repository ([read more here](https://book.getfoundry.sh/getting-started/first-steps)).

  1. Install the burners repository by running the following command:

  ```bash [bash]
  forge install symbioticfi/burners
  ```

  2. Update (or create if not yet) a `remappings.txt` file inside your repository accordingly:

  ```txt title="remappings.txt"
  ...
  @symbioticfi/burners/=lib/burners/
  ```

  3. Create a burner router contract using [a BurnerRouterFactory contract](https://github.com/symbioticfi/burners/blob/main/src/contracts/router/BurnerRouterFactory.sol):

  :::note
  This is an **example** code snippet. Replace the given values with your own.
  :::

  <Tabs groupId="chains" defaultValue="mainnet">
    <TabItem value="mainnet" label="Mainnet">
      ```solidity [DeployBurnerRouter.s.sol]
      import {IBurnerRouterFactory} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouterFactory.sol";
      import {IBurnerRouter} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouter.sol";

      // ...

         address BURNER_ROUTER_FACTORY = 0x99F2B89fB3C363fBafD8d826E5AA77b28bAB70a0;          // address of the BurnerRouterFactory (see Deployments page)

      // ...

            address burnerRouter = IBurnerRouterFactory(BURNER_ROUTER_FACTORY).create(
               IBurnerRouter.InitParams({
                     owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                       // address of the router’s owner
                     collateral: 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0,                  // address of the collateral - wstETH (MUST be the same as for the Vault to connect)
                     delay: 1814400,                                                          // duration of the receivers’ update delay (= 21 days)
                     globalReceiver: 0xdCaC890b14121FD5D925E2589017Be68C2B5B324,              // address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
                     networkReceivers: new IBurnerRouter.NetworkReceiver[](0),                // array with IBurnerRouter.NetworkReceiver elements meaning network-specific receivers
                     operatorNetworkReceivers: new IBurnerRouter.OperatorNetworkReceiver[](0) // array with IBurnerRouter.OperatorNetworkReceiver elements meaning network-specific receivers
               })
            );

      // ...
      ```
    </TabItem>

    <TabItem value="hoodi" label="Hoodi">
      ```solidity [DeployBurnerRouter.s.sol]
      import {IBurnerRouterFactory} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouterFactory.sol";
      import {IBurnerRouter} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouter.sol";

      // ...

         address BURNER_ROUTER_FACTORY = 0xF619c99D166224B4AC008b14Cc67ac72C2E91D8a;          // address of the BurnerRouterFactory (see Deployments page)

      // ...

            address burnerRouter = IBurnerRouterFactory(BURNER_ROUTER_FACTORY).create(
               IBurnerRouter.InitParams({
                     owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                       // address of the router’s owner
                     collateral: 0x8d09a4502Cc8Cf1547aD300E066060D043f6982D,                  // address of the collateral - wstETH (MUST be the same as for the Vault to connect)
                     delay: 1814400,                                                          // duration of the receivers’ update delay (= 21 days)
                     globalReceiver: 0x25133c2c49A343F8312bb6e896C1ea0Ad8CD0EBd,              // address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
                     networkReceivers: new IBurnerRouter.NetworkReceiver[](0),                // array with IBurnerRouter.NetworkReceiver elements meaning network-specific receivers
                     operatorNetworkReceivers: new IBurnerRouter.OperatorNetworkReceiver[](0) // array with IBurnerRouter.OperatorNetworkReceiver elements meaning network-specific receivers
               })
            );

      // ...
      ```
    </TabItem>

    <TabItem value="sepolia" label="Sepolia">
      ```solidity [DeployBurnerRouter.s.sol]
      import {IBurnerRouterFactory} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouterFactory.sol";
      import {IBurnerRouter} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouter.sol";

      // ...

         address BURNER_ROUTER_FACTORY = 0x32e2AfbdAffB1e675898ABA75868d92eE1E68f3b;          // address of the BurnerRouterFactory (see Deployments page)

      // ...

            address burnerRouter = IBurnerRouterFactory(BURNER_ROUTER_FACTORY).create(
               IBurnerRouter.InitParams({
                     owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                       // address of the router’s owner
                     collateral: 0xB82381A3fBD3FaFA77B3a7bE693342618240067b,                  // address of the collateral - wstETH (MUST be the same as for the Vault to connect)
                     delay: 1814400,                                                          // duration of the receivers’ update delay (= 21 days)
                     globalReceiver: 0x58D347334A5E6bDE7279696abE59a11873294FA4,              // address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
                     networkReceivers: new IBurnerRouter.NetworkReceiver[](0),                // array with IBurnerRouter.NetworkReceiver elements meaning network-specific receivers
                     operatorNetworkReceivers: new IBurnerRouter.OperatorNetworkReceiver[](0) // array with IBurnerRouter.OperatorNetworkReceiver elements meaning network-specific receivers
               })
            );

      // ...
      ```
    </TabItem>
  </Tabs>
</Details>

### 2. Core modules

#### Vault

Vault is a contract that:

* storages the collateral
* performs accounting in the sense of deposits and withdrawals
* processes slashing events by transferring the collateral to the burner
* allows deposit whitelisting and deposit limiting

We provide two types of vaults:

1. **Vault (version 1)** - a standard version responsible for all the functions mentioned above
2. **Tokenized Vault (version 2)** - an extended version that represents stake shares as ERC-20 tokens

We don't need tokenization of the stake as LRTs provide it. Therefore, we'll use the common **Vault**.

![vault](/guides/img/deployment/vault.png)

:::info
You can also deploy a vault using our [form](https://app.symbiotic.fi/create).
:::

#### Delegator

A delegator is a contract that allows vault curators to allocate stake to networks and operators.

Currently, we have four types:

1. **NetworkRestakeDelegator (type 0)** - accounts for allocations in absolute numbers for networks and in shares for operator-network pairs, enabling staking and restaking across networks (depending on delegated amounts)
2. **FullRestakeDelegator (type 1)** - accounts for allocations in absolute numbers for both networks and operator-network pairs, enabling everything NetworkRestakeDelegator allows plus restaking across operators within networks
3. **OperatorSpecificDelegator (type 2)** - a simplified version of NetworkRestakeDelegator where only one specific operator has allocations
4. **OperatorNetworkSpecificDelegator (type 3)** - the simplest version where only one specific operator at one specific network has an allocation

FullRestakeDelegator covers all delegation use cases but can create highly risky configurations that need proper handling. OperatorSpecificDelegator limits use cases for LRTs with multiple operators, and OperatorNetworkSpecificDelegator has more limitations by design. We'll choose **NetworkRestakeDelegator** for our needs.

:::info
You can achieve a multi-operator single-network vault by using a Network-Restake delegator with a disabled NetworkLimitSet role
:::

![delegator](/guides/img/deployment/delegator.png)

#### Slasher

A Slasher is a contract responsible for proper penalty execution, preserving networks' rights to slash captured stake and stakers' rights not to be slashed more than deserved.

There are two types of slasher:

1. **Slasher (type 0)** - a common slasher that receives slashing requests and instantly executes them
2. **VetoSlasher (type 1)** - allows vetoing received slashing requests using resolvers

For VetoSlasher, networks may propose resolvers that can veto slashing requests. **Networks can also choose not to set a resolver, enabling an instant slashing mechanic similar to Slasher's.** If a vault curator isn't ready to provide stake without a resolver, the curator may simply not allocate any stake to such networks. Since **VetoSlasher** extends Slasher, we'll choose it.

![slasher](/guides/img/deployment/slasher.png)

<Details summary="Core modules deployment">
  1. Clone the core contracts repository by running the following command:

     ```bash [bash]
     git clone --recurse-submodules https://github.com/symbioticfi/core.git
     ```

  2. Navigate into the cloned repository folder:

     ```bash [bash]
     cd core
     ```

  3. Deploy core modules contracts using a simple script:
     Open [DeployVault.s.sol](https://github.com/symbioticfi/core/blob/main/script/DeployVault.s.sol) and configure these settings:

     ```bash [bash]
       // Address of the owner of the vault who can migrate the vault to new versions whitelisted by Symbiotic
       address OWNER = 0x0000000000000000000000000000000000000000;
       // Address of the collateral token
       address COLLATERAL = 0x0000000000000000000000000000000000000000;
       // Vault's burner to send slashed funds to (e.g., 0xdEaD or some unwrapper contract; not used in case of no slasher)
       address BURNER = 0x000000000000000000000000000000000000dEaD;
       // Duration of the vault epoch (the withdrawal delay for staker varies from EPOCH_DURATION to 2 * EPOCH_DURATION depending on when the withdrawal is requested)
       uint48 EPOCH_DURATION = 7 days;
       // Type of the delegator:
       //  0. NetworkRestakeDelegator (allows restaking across multiple networks and having multiple operators per network)
       //  1. FullRestakeDelegator (do not use without knowing what you are doing)
       //  2. OperatorSpecificDelegator (allows restaking across multiple networks with only a single operator)
       //  3. OperatorNetworkSpecificDelegator (allocates the stake to a specific operator and network)
       uint64 DELEGATOR_INDEX = 0;
       // Setting depending on the delegator type:
       // 0. NetworkLimitSetRoleHolders (adjust allocations for networks)
       // 1. NetworkLimitSetRoleHolders (adjust allocations for networks)
       // 2. NetworkLimitSetRoleHolders (adjust allocations for networks)
       // 3. network (the only network that will receive the stake; should be an array with a single element)
       address[] NETWORK_ALLOCATION_SETTERS_OR_NETWORK = [0x0000000000000000000000000000000000000000];
       // Setting depending on the delegator type:
       // 0. OperatorNetworkSharesSetRoleHolders (adjust allocations for operators inside networks; in shares, resulting percentage is operatorShares / totalOperatorShares)
       // 1. OperatorNetworkLimitSetRoleHolders (adjust allocations for operators inside networks; in shares, resulting percentage is operatorShares / totalOperatorShares)
       // 2. operator (the only operator that will receive the stake; should be an array with a single element)
       // 3. operator (the only operator that will receive the stake; should be an array with a single element)
       address[] OPERATOR_ALLOCATION_SETTERS_OR_OPERATOR = [0x0000000000000000000000000000000000000000];
       // Whether to deploy a slasher
       bool WITH_SLASHER = true;
       // Type of the slasher:
       //  0. Slasher (allows instant slashing)
       //  1. VetoSlasher (allows having a veto period if the resolver is set)
       uint64 SLASHER_INDEX = 1;
       // Duration of a veto period (should be less than EPOCH_DURATION)
       uint48 VETO_DURATION = 1 days;

       // Optional

       // Deposit limit (maximum amount of the active stake allowed in the vault)
       uint256 DEPOSIT_LIMIT = 0;
       // Addresses of the whitelisted depositors
       address[] WHITELISTED_DEPOSITORS = new address[](0);
       // Address of the hook contract which, e.g., can automatically adjust the allocations on slashing events (not used in case of no slasher)
       address HOOK = 0x0000000000000000000000000000000000000000;
       // Delay in epochs for a network to update a resolver
       uint48 RESOLVER_SET_EPOCHS_DELAY = 3;
     ```

  Edit the configuration fields, then run:

  <Tabs groupId="chains" defaultValue="mainnet">
    <TabItem value="mainnet" label="Mainnet">
      ```bash [bash]
      forge script script/DeployVault.s.sol:DeployVaultScript \
         --rpc-url=https://ethereum-rpc.publicnode.com \
         --chain mainnet \
         --broadcast
      ```
    </TabItem>

    <TabItem value="hoodi" label="Hoodi">
      ```bash [bash]
      forge script script/DeployVault.s.sol:DeployVaultScript \
         --rpc-url=https://0xrpc.io/hoodi \
         --chain hoodi \
         --broadcast
      ```
    </TabItem>

    <TabItem value="sepolia" label="Sepolia">
      ```bash [bash]
      forge script script/DeployVault.s.sol:DeployVaultScript \
         --rpc-url=https://ethereum-sepolia-rpc.publicnode.com \
         --chain sepolia \
         --broadcast
      ```
    </TabItem>
  </Tabs>

  :::note
  This is an **example** command. Replace the given values with your own.

  ***

  In addition, you need to [choose a preferred wallet option](https://book.getfoundry.sh/reference/forge/forge-script?highlight=forge%20script#wallet-options---raw) and adjust the command accordingly.
  :::
</Details>

<Details summary="Core modules deployment - technical (Solidity)">
  The following instruction assumes you have an already initialized Foundry repository ([read more here](https://book.getfoundry.sh/getting-started/first-steps)).

  1. Install the core contracts repository by running the following command:

  ```bash [bash]
  forge install symbioticfi/core
  ```

  2. Update (or create if not yet) a `remappings.txt` file inside your repository accordingly:

  ```txt title="remappings.txt"
  ...
  @symbioticfi/core/=lib/core/
  ```

  3. Create core modules using [a VaultConfigurator contract](https://github.com/symbioticfi/core/blob/main/src/contracts/VaultConfigurator.sol):

  :::note
  This is an **example** code snippet. Replace the given values with your own.
  :::

  <Tabs groupId="chains" defaultValue="mainnet">
    <TabItem value="mainnet" label="Mainnet">
      ```solidity [DeployVault.s.sol]
      import {IVaultConfigurator} from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol";
      import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
      import {IBaseDelegator} from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol";
      import {INetworkRestakeDelegator} from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol";
      import {IBaseSlasher} from "@symbioticfi/core/src/interfaces/slasher/IBaseSlasher.sol";
      import {IVetoSlasher} from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol";

      // ...

         address VAULT_CONFIGURATOR = 0x29300b1d3150B4E2b12fE80BE72f365E200441EC;                  // address of the VaultConfigurator (see Deployments page)

      // ...

            address[] memory networkLimitSetRoleHolders = new address[](1);
            networkLimitSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
            address[] memory operatorNetworkSharesSetRoleHolders = new address[](1);
            operatorNetworkSharesSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
            (address vault, address networkRestakeDelegator, address vetoSlasher) = IVaultConfigurator(VAULT_CONFIGURATOR).create(
               IVaultConfigurator.InitParams({
                     version: 1,                                                                   // Vault’s version (= common one)
                     owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                            // address of the Vault’s owner (can migrate the Vault to new versions in the future)
                     vaultParams: abi.encode(IVault.InitParams({
                        collateral: 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0,                    // address of the collateral - wstETH
                        burner: <BURNER_ROUTER>,                                                   // address of the deployed burner router
                        epochDuration: 604800,                                                     // duration of the Vault epoch in seconds (= 7 days)
                        depositWhitelist: false,                                                   // if enable deposit whitelisting
                        isDepositLimit: false,                                                     // if enable deposit limit
                        depositLimit: 0,                                                           // deposit limit
                        defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,        // address of the Vault’s admin (can manage all roles)
                        depositWhitelistSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7, // address of the enabler/disabler of the deposit whitelisting
                        depositorWhitelistRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,  // address of the depositors whitelister
                        isDepositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,   // address of the enabler/disabler of the deposit limit
                        depositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7      // address of the deposit limit setter
                     })),
                     delegatorIndex: 0,                                                            // Delegator’s type (= NetworkRestakeDelegator)
                     delegatorParams: abi.encode(INetworkRestakeDelegator.InitParams({
                        baseParams: IBaseDelegator.BaseParams({
                           defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,     // address of the Delegator’s admin (can manage all roles)
                           hook: 0x0000000000000000000000000000000000000000,                       // address of the hook (if not zero, receives onSlash() call on each slashing)
                           hookSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7           // address of the hook setter
                        }),
                        networkLimitSetRoleHolders: networkLimitSetRoleHolders,                    // array of addresses of the network limit setters
                        operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders   // array of addresses of the operator-network shares setters
                     })),
                     withSlasher: true,                                                            // if enable Slasher module
                     slasherIndex: 1,                                                              // Slasher’s type (= VetoSlasher)
                     slasherParams: abi.encode(IVetoSlasher.InitParams({
                        baseParams: IBaseSlasher.BaseParams({
                           isBurnerHook: true                                                      // if enable the `burner` to receive onSlash() call after each slashing (is needed for the burner router workflow)
                        }),
                        vetoDuration: 86400,                                                       // veto duration (= 1 day)
                        resolverSetEpochsDelay: 3                                                  // number of Vault epochs needed for the resolver to be changed
                     }))
               })
            );

      // ...
      ```
    </TabItem>

    <TabItem value="hoodi" label="Hoodi">
      ```solidity [DeployVault.s.sol]
      import {IVaultConfigurator} from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol";
      import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
      import {IBaseDelegator} from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol";
      import {INetworkRestakeDelegator} from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol";
      import {IBaseSlasher} from "@symbioticfi/core/src/interfaces/slasher/IBaseSlasher.sol";
      import {IVetoSlasher} from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol";

      // ...

         address VAULT_CONFIGURATOR = 0x94c344E816A53D07fC4c7F4a18f82b6Da87CFc8f;                  // address of the VaultConfigurator (see Deployments page)

      // ...

            address[] memory networkLimitSetRoleHolders = new address[](1);
            networkLimitSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
            address[] memory operatorNetworkSharesSetRoleHolders = new address[](1);
            operatorNetworkSharesSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
            (address vault, address networkRestakeDelegator, address vetoSlasher) = IVaultConfigurator(VAULT_CONFIGURATOR).create(
               IVaultConfigurator.InitParams({
                     version: 1,                                                                   // Vault’s version (= common one)
                     owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                            // address of the Vault’s owner (can migrate the Vault to new versions in the future)
                     vaultParams: abi.encode(IVault.InitParams({
                        collateral: 0x8d09a4502Cc8Cf1547aD300E066060D043f6982D,                    // address of the collateral - wstETH
                        burner: <BURNER_ROUTER>,                                                   // address of the deployed burner router
                        epochDuration: 604800,                                                     // duration of the Vault epoch in seconds (= 7 days)
                        depositWhitelist: false,                                                   // if enable deposit whitelisting
                        isDepositLimit: false,                                                     // if enable deposit limit
                        depositLimit: 0,                                                           // deposit limit
                        defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,        // address of the Vault’s admin (can manage all roles)
                        depositWhitelistSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7, // address of the enabler/disabler of the deposit whitelisting
                        depositorWhitelistRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,  // address of the depositors whitelister
                        isDepositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,   // address of the enabler/disabler of the deposit limit
                        depositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7      // address of the deposit limit setter
                     })),
                     delegatorIndex: 0,                                                            // Delegator’s type (= NetworkRestakeDelegator)
                     delegatorParams: abi.encode(INetworkRestakeDelegator.InitParams({
                        baseParams: IBaseDelegator.BaseParams({
                           defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,     // address of the Delegator’s admin (can manage all roles)
                           hook: 0x0000000000000000000000000000000000000000,                       // address of the hook (if not zero, receives onSlash() call on each slashing)
                           hookSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7           // address of the hook setter
                        }),
                        networkLimitSetRoleHolders: networkLimitSetRoleHolders,                    // array of addresses of the network limit setters
                        operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders   // array of addresses of the operator-network shares setters
                     })),
                     withSlasher: true,                                                            // if enable Slasher module
                     slasherIndex: 1,                                                              // Slasher’s type (= VetoSlasher)
                     slasherParams: abi.encode(IVetoSlasher.InitParams({
                        baseParams: IBaseSlasher.BaseParams({
                           isBurnerHook: true                                                      // if enable the `burner` to receive onSlash() call after each slashing (is needed for the burner router workflow)
                        }),
                        vetoDuration: 86400,                                                       // veto duration (= 1 day)
                        resolverSetEpochsDelay: 3                                                  // number of Vault epochs needed for the resolver to be changed
                     }))
               })
            );

      // ...
      ```
    </TabItem>

    <TabItem value="sepolia" label="Sepolia">
      ```solidity [DeployVault.s.sol]
      import {IVaultConfigurator} from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol";
      import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
      import {IBaseDelegator} from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol";
      import {INetworkRestakeDelegator} from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol";
      import {IBaseSlasher} from "@symbioticfi/core/src/interfaces/slasher/IBaseSlasher.sol";
      import {IVetoSlasher} from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol";

      // ...

         address VAULT_CONFIGURATOR = 0xD2191FE92987171691d552C219b8caEf186eb9cA;                  // address of the VaultConfigurator (see Deployments page)

      // ...

            address[] memory networkLimitSetRoleHolders = new address[](1);
            networkLimitSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
            address[] memory operatorNetworkSharesSetRoleHolders = new address[](1);
            operatorNetworkSharesSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
            (address vault, address networkRestakeDelegator, address vetoSlasher) = IVaultConfigurator(VAULT_CONFIGURATOR).create(
               IVaultConfigurator.InitParams({
                     version: 1,                                                                   // Vault’s version (= common one)
                     owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                            // address of the Vault’s owner (can migrate the Vault to new versions in the future)
                     vaultParams: abi.encode(IVault.InitParams({
                        collateral: 0xB82381A3fBD3FaFA77B3a7bE693342618240067b,                    // address of the collateral - wstETH
                        burner: <BURNER_ROUTER>,                                                   // address of the deployed burner router
                        epochDuration: 604800,                                                     // duration of the Vault epoch in seconds (= 7 days)
                        depositWhitelist: false,                                                   // if enable deposit whitelisting
                        isDepositLimit: false,                                                     // if enable deposit limit
                        depositLimit: 0,                                                           // deposit limit
                        defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,        // address of the Vault’s admin (can manage all roles)
                        depositWhitelistSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7, // address of the enabler/disabler of the deposit whitelisting
                        depositorWhitelistRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,  // address of the depositors whitelister
                        isDepositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,   // address of the enabler/disabler of the deposit limit
                        depositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7      // address of the deposit limit setter
                     })),
                     delegatorIndex: 0,                                                            // Delegator’s type (= NetworkRestakeDelegator)
                     delegatorParams: abi.encode(INetworkRestakeDelegator.InitParams({
                        baseParams: IBaseDelegator.BaseParams({
                           defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,     // address of the Delegator’s admin (can manage all roles)
                           hook: 0x0000000000000000000000000000000000000000,                       // address of the hook (if not zero, receives onSlash() call on each slashing)
                           hookSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7           // address of the hook setter
                        }),
                        networkLimitSetRoleHolders: networkLimitSetRoleHolders,                    // array of addresses of the network limit setters
                        operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders   // array of addresses of the operator-network shares setters
                     })),
                     withSlasher: true,                                                            // if enable Slasher module
                     slasherIndex: 1,                                                              // Slasher’s type (= VetoSlasher)
                     slasherParams: abi.encode(IVetoSlasher.InitParams({
                        baseParams: IBaseSlasher.BaseParams({
                           isBurnerHook: true                                                      // if enable the `burner` to receive onSlash() call after each slashing (is needed for the burner router workflow)
                        }),
                        vetoDuration: 86400,                                                       // veto duration (= 1 day)
                        resolverSetEpochsDelay: 3                                                  // number of Vault epochs needed for the resolver to be changed
                     }))
               })
            );

      // ...
      ```
    </TabItem>
  </Tabs>
</Details>

### 3. Staker rewards

Rewards logic is not enshrined in the core contract, and we allow anyone to create their own implementations if needed. However, it requires resources like time, knowledge, and money. Therefore, we provide a default implementation of the staker rewards named **DefaultStakerRewards**. Its main goals are:

* allow networks to distribute rewards for the stakers of the certain Vault
* allow stakers to claim these rewards
* allow Vault curators to receive fees from the distributed rewards

This is the only staker rewards implementation we provide, so let's add it to our deployment configuration.

![staker\_rewards](/guides/img/deployment/staker-rewards.png)

<Details summary="Staker rewards deployment">
  1. Clone the rewards contracts repository by running the following command:

     ```bash [bash]
     git clone --recurse-submodules https://github.com/symbioticfi/rewards.git
     ```

  2. Navigate into the cloned repository folder:

     ```bash [bash]
     cd rewards
     ```

  3. Deploy a staker rewards contract using [a simple script](https://github.com/symbioticfi/rewards/blob/main/script/deploy/DefaultStakerRewards.s.sol):

  :::note
  This is an **example** command. Replace the given values with your own.

  ***

  In addition, you need to [choose a preferred wallet option](https://book.getfoundry.sh/reference/forge/forge-script?highlight=forge%20script#wallet-options---raw) and adjust the command accordingly.
  :::

  <Tabs groupId="chains" defaultValue="mainnet">
    <TabItem value="mainnet" label="Mainnet">
      ```bash [bash]
      VAULT=<VAULT>                                                             # address of the deployed Vault
      ADMIN_FEE=1000                                                            # admin fee percent to get from all the rewards distributions (10% = 1_000 | 100% = 10_000)
      ADMIN=0xe8616DEcea16b5216e805B0b8caf7784de7570E7                          # address of the main admin (can manage all roles)
      ADMIN_FEE_CLAIMER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7              # address of the admin fee claimer
      ADMIN_FEE_SETTER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7               # address of the admin fee setter

      forge script script/deploy/DefaultStakerRewards.s.sol:DefaultStakerRewardsScript \
         $VAULT \
         $ADMIN_FEE \
         $ADMIN \
         $ADMIN_FEE_CLAIMER \
         $ADMIN_FEE_SETTER \
      --sig "run(address,uint256,address,address,address)" \
      --rpc-url=https://ethereum-rpc.publicnode.com \
      --chain mainnet \
      --broadcast
      ```
    </TabItem>

    <TabItem value="hoodi" label="Hoodi">
      ```bash [bash]
      VAULT=<VAULT>                                                             # address of the deployed Vault
      ADMIN_FEE=1000                                                            # admin fee percent to get from all the rewards distributions (10% = 1_000 | 100% = 10_000)
      ADMIN=0xe8616DEcea16b5216e805B0b8caf7784de7570E7                          # address of the main admin (can manage all roles)
      ADMIN_FEE_CLAIMER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7              # address of the admin fee claimer
      ADMIN_FEE_SETTER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7               # address of the admin fee setter

      forge script script/deploy/DefaultStakerRewards.s.sol:DefaultStakerRewardsScript \
         $VAULT \
         $ADMIN_FEE \
         $ADMIN \
         $ADMIN_FEE_CLAIMER \
         $ADMIN_FEE_SETTER \
      --sig "run(address,uint256,address,address,address)" \
      --rpc-url=https://ethereum-hoodi.gateway.tatum.io \
      --chain hoodi \
      --broadcast
      ```
    </TabItem>

    <TabItem value="sepolia" label="Sepolia">
      ```bash [bash]
      VAULT=<VAULT>                                                             # address of the deployed Vault
      ADMIN_FEE=1000                                                            # admin fee percent to get from all the rewards distributions (10% = 1_000 | 100% = 10_000)
      ADMIN=0xe8616DEcea16b5216e805B0b8caf7784de7570E7                          # address of the main admin (can manage all roles)
      ADMIN_FEE_CLAIMER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7              # address of the admin fee claimer
      ADMIN_FEE_SETTER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7               # address of the admin fee setter

      forge script script/deploy/DefaultStakerRewards.s.sol:DefaultStakerRewardsScript \
         $VAULT \
         $ADMIN_FEE \
         $ADMIN \
         $ADMIN_FEE_CLAIMER \
         $ADMIN_FEE_SETTER \
      --sig "run(address,uint256,address,address,address)" \
      --rpc-url=https://ethereum-sepolia-rpc.publicnode.com \
      --chain sepolia \
      --broadcast
      ```
    </TabItem>
  </Tabs>
</Details>

<Details summary="Staker rewards deployment - technical (Solidity)">
  The following instruction assumes you have an already initialized Foundry repository ([read more here](https://book.getfoundry.sh/getting-started/first-steps)).

  1. Install the rewards contracts repository by running the following command:

  ```bash [bash]
  forge install symbioticfi/rewards
  ```

  2. Update (or create if not yet) a `remappings.txt` file inside your repository accordingly:

  ```txt title="remappings.txt"
  ...
  @symbioticfi/rewards/=lib/rewards/
  ```

  3. Create a staker rewards contract using [a DefaultStakerRewardsFactory contract](https://github.com/symbioticfi/rewards/blob/main/src/contracts/defaultStakerRewards/DefaultStakerRewardsFactory.sol):

  :::note
  It is an **example** code snippet, meaning you need to replace the given values with necessary ones.
  :::

  <Tabs groupId="chains" defaultValue="mainnet">
    <TabItem value="mainnet" label="Mainnet">
      ```solidity [DefaultStakerRewards.s.sol]
      import {IDefaultStakerRewardsFactory} from "@symbioticfi/rewards/src/interfaces/defaultStakerRewards/IDefaultStakerRewardsFactory.sol";
      import {IDefaultStakerRewards} from "@symbioticfi/rewards/src/interfaces/defaultStakerRewards/IDefaultStakerRewards.sol";

      // ...

         address DEFAULT_STAKER_REWARDS_FACTORY = 0x290CAB97a312164Ccf095d75D6175dF1C4A0a25F; // address of the DefaultStakerRewardsFactory (see Deployments page)

      // ...

            address defaultStakerRewards = IDefaultStakerRewardsFactory(DEFAULT_STAKER_REWARDS_FACTORY).create(IDefaultStakerRewards.InitParams({
               vault: <VAULT>,                                                                // address of the deployed Vault
               adminFee: 1000,                                                                // admin fee percent to get from all the rewards distributions (10% = 1_000 | 100% = 10_000)
               defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,            // address of the main admin (can manage all roles)
               adminFeeClaimRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,           // address of the admin fee claimer
               adminFeeSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7              // address of the admin fee setter
            }));

      // ...
      ```
    </TabItem>

    <TabItem value="hoodi" label="Hoodi">
      ```solidity [DefaultStakerRewards.s.sol]
      import {IDefaultStakerRewardsFactory} from "@symbioticfi/rewards/src/interfaces/defaultStakerRewards/IDefaultStakerRewardsFactory.sol";
      import {IDefaultStakerRewards} from "@symbioticfi/rewards/src/interfaces/defaultStakerRewards/IDefaultStakerRewards.sol";

      // ...

         address DEFAULT_STAKER_REWARDS_FACTORY = 0x698C36DE44D73AEfa3F0Ce3c0255A8667bdE7cFD; // address of the DefaultStakerRewardsFactory (see Deployments page)

      // ...

            address defaultStakerRewards = IDefaultStakerRewardsFactory(DEFAULT_STAKER_REWARDS_FACTORY).create(IDefaultStakerRewards.InitParams({
               vault: <VAULT>,                                                                // address of the deployed Vault
               adminFee: 1000,                                                                // admin fee percent to get from all the rewards distributions (10% = 1_000 | 100% = 10_000)
               defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,            // address of the main admin (can manage all roles)
               adminFeeClaimRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,           // address of the admin fee claimer
               adminFeeSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7              // address of the admin fee setter
            }));

      // ...
      ```
    </TabItem>

    <TabItem value="sepolia" label="Sepolia">
      ```solidity [DefaultStakerRewards.s.sol]
      import {IDefaultStakerRewardsFactory} from "@symbioticfi/rewards/src/interfaces/defaultStakerRewards/IDefaultStakerRewardsFactory.sol";
      import {IDefaultStakerRewards} from "@symbioticfi/rewards/src/interfaces/defaultStakerRewards/IDefaultStakerRewards.sol";

      // ...

         address DEFAULT_STAKER_REWARDS_FACTORY = 0x70C618a13D1A57f7234c0b893b9e28C5cA8E7f37; // address of the DefaultStakerRewardsFactory (see Deployments page)

      // ...

            address defaultStakerRewards = IDefaultStakerRewardsFactory(DEFAULT_STAKER_REWARDS_FACTORY).create(IDefaultStakerRewards.InitParams({
               vault: <VAULT>,                                                                // address of the deployed Vault
               adminFee: 1000,                                                                // admin fee percent to get from all the rewards distributions (10% = 1_000 | 100% = 10_000)
               defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,            // address of the main admin (can manage all roles)
               adminFeeClaimRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,           // address of the admin fee claimer
               adminFeeSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7              // address of the admin fee setter
            }));

      // ...
      ```
    </TabItem>
  </Tabs>
</Details>

## Advanced

### Network-specific burners

The further text describes extended configurations that may bring risk reductions, wider support of the networks, and more capital efficiency for users.

Such a case is possible:

* A vault typically wants slashed funds to be burnt.
* Alternatively, a highly reputable network wants its slashings redistributed to users who could suffer losses due to operators' malicious activity.
* The vault decides to integrate such a network to increase its capital efficiency.

Currently, our configuration doesn't contain such logic, but it already supports it. [As mentioned earlier](#1-burner-router), **BurnerRouter** allows splitting slashed funds across any number of receivers depending on the slashing networks and slashed operators. Given the network address that needs this functionality and the burner address to send funds to, you can either configure this behavior using an existing burner router or handle it during deployment.

:::warning
Burning slashed funds is one of the safest approaches. Any other methodology for processing slashed funds may create incentives for different parties to trigger slashing, depending on many factors.
:::

![network-burner](/guides/img/deployment/network-burner.png)

<Details summary="Burner Router with preconfigured network-specific burner deployment">
  1. Clone the burners repository by running the following command:

     ```bash [bash]
     git clone --recurse-submodules https://github.com/symbioticfi/burners.git
     ```

  2. Navigate into the cloned repository folder:

     ```bash [bash]
     cd burners
     ```

  3. Deploy a burner router contract with a preconfigured network-specific burner using [a simple script](https://github.com/symbioticfi/burners/blob/main/script/deploy/BurnerRouter.s.sol):

  :::note
  This is an **example** command. Replace the given values with your own.

  ***

  In addition, you need to [choose a preferred wallet option](https://book.getfoundry.sh/reference/forge/forge-script?highlight=forge%20script#wallet-options---raw) and adjust the command accordingly.
  :::

  <Tabs groupId="chains" defaultValue="mainnet">
    <TabItem value="mainnet" label="Mainnet">
      ```bash [bash]
      OWNER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7                 # address of the router’s owner
      COLLATERAL=0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0            # address of the collateral - wstETH (MUST be the same as for the Vault to connect)
      DELAY=1814400                                                    # duration of the receivers’ update delay (= 21 days)
      GLOBAL_RECEIVER=0xdCaC890b14121FD5D925E2589017Be68C2B5B324       # address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
      NETWORK_RECEIVERS=[\(<NETWORK_ADDRESS>,<RECEIVER_ADDRESS>\)]                                             # array with elements like "\(network_address,receiver_address\)" meaning network-specific receivers
      OPERATOR_NETWORK_RECEIVERS=[]                                    # array with elements like "\(network_address,operator_address,receiver_address\)" meaning operator-network-specific receivers

      forge script script/deploy/BurnerRouter.s.sol:BurnerRouterScript \
         $OWNER \
         $COLLATERAL \
         $DELAY \
         $GLOBAL_RECEIVER \
         $NETWORK_RECEIVERS \
         $OPERATOR_NETWORK_RECEIVERS \
      --sig "run(address,address,uint48,address,(address,address)[],(address,address,address)[])" \
      --rpc-url=https://ethereum-rpc.publicnode.com \
      --chain mainnet \
      --broadcast
      ```
    </TabItem>

    <TabItem value="hoodi" label="Hoodi">
      ```bash [bash]
      OWNER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7                 # address of the router’s owner
      COLLATERAL=0x8d09a4502Cc8Cf1547aD300E066060D043f6982D            # address of the collateral - wstETH (MUST be the same as for the Vault to connect)
      DELAY=1814400                                                    # duration of the receivers’ update delay (= 21 days)
      GLOBAL_RECEIVER=0x25133c2c49A343F8312bb6e896C1ea0Ad8CD0EBd       # address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
      NETWORK_RECEIVERS=[\(<NETWORK_ADDRESS>,<RECEIVER_ADDRESS>\)]                                             # array with elements like "\(network_address,receiver_address\)" meaning network-specific receivers
      OPERATOR_NETWORK_RECEIVERS=[]                                    # array with elements like "\(network_address,operator_address,receiver_address\)" meaning operator-network-specific receivers

      forge script script/deploy/BurnerRouter.s.sol:BurnerRouterScript \
         $OWNER \
         $COLLATERAL \
         $DELAY \
         $GLOBAL_RECEIVER \
         $NETWORK_RECEIVERS \
         $OPERATOR_NETWORK_RECEIVERS \
      --sig "run(address,address,uint48,address,(address,address)[],(address,address,address)[])" \
      --rpc-url=https://ethereum-hoodi.gateway.tatum.io \
      --chain hoodi \
      --broadcast
      ```
    </TabItem>

    <TabItem value="sepolia" label="Sepolia">
      ```bash [bash]
      OWNER=0xe8616DEcea16b5216e805B0b8caf7784de7570E7                 # address of the router’s owner
      COLLATERAL=0xB82381A3fBD3FaFA77B3a7bE693342618240067b            # address of the collateral - wstETH (MUST be the same as for the Vault to connect)
      DELAY=1814400                                                    # duration of the receivers’ update delay (= 21 days)
      GLOBAL_RECEIVER=0x58D347334A5E6bDE7279696abE59a11873294FA4       # address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
      NETWORK_RECEIVERS=[\(<NETWORK_ADDRESS>,<RECEIVER_ADDRESS>\)]                                             # array with elements like "\(network_address,receiver_address\)" meaning network-specific receivers
      OPERATOR_NETWORK_RECEIVERS=[]                                    # array with elements like "\(network_address,operator_address,receiver_address\)" meaning operator-network-specific receivers

      forge script script/deploy/BurnerRouter.s.sol:BurnerRouterScript \
         $OWNER \
         $COLLATERAL \
         $DELAY \
         $GLOBAL_RECEIVER \
         $NETWORK_RECEIVERS \
         $OPERATOR_NETWORK_RECEIVERS \
      --sig "run(address,address,uint48,address,(address,address)[],(address,address,address)[])" \
      --rpc-url=https://ethereum-sepolia-rpc.publicnode.com \
      --chain sepolia \
      --broadcast
      ```
    </TabItem>
  </Tabs>
</Details>

<Details summary="Burner Router with preconfigured network-specific burner deployment - technical (Solidity)">
  The following instruction assumes you have an already initialized Foundry repository ([read more here](https://book.getfoundry.sh/getting-started/first-steps)).

  1. Install the burners repository by running the following command:

     ```bash [bash]
     forge install symbioticfi/burners
     ```

  2. Update (or create if not yet) a `remappings.txt` file inside your repository accordingly:

     ```txt title="remappings.txt"
     ...
     @symbioticfi/burners/=lib/burners/
     ```

  3. Create a burner router contract using [a BurnerRouterFactory contract](https://github.com/symbioticfi/burners/blob/main/src/contracts/router/BurnerRouterFactory.sol):

     :::note
     This is an **example** code snippet. Replace the given values with your own.
     :::

     <Tabs groupId="chains" defaultValue="mainnet">
       <TabItem value="mainnet" label="Mainnet">
         ```solidity [DeployBurnerRouter.s.sol]
         import {IBurnerRouterFactory} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouterFactory.sol";
         import {IBurnerRouter} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouter.sol";

         // ...

            address BURNER_ROUTER_FACTORY = 0x99F2B89fB3C363fBafD8d826E5AA77b28bAB70a0;          // address of the BurnerRouterFactory (see Deployments page)

         // ...

               IBurnerRouter.NetworkReceiver[] memory networkReceivers = new IBurnerRouter.NetworkReceiver[](1);
               networkReceivers[0] = IBurnerRouter.NetworkReceiver({
                  network: <NETWORK_ADDRESS>,
                  receiver: <RECEIVER_ADDRESS>
               });
               address burnerRouter = IBurnerRouterFactory(BURNER_ROUTER_FACTORY).create(
                  IBurnerRouter.InitParams({
                        owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                       // address of the router’s owner
                        collateral: 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0,                  // address of the collateral - wstETH (MUST be the same as for the Vault to connect)
                        delay: 1814400,                                                          // duration of the receivers’ update delay (= 21 days)
                        globalReceiver: 0xdCaC890b14121FD5D925E2589017Be68C2B5B324,              // address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
                        networkReceivers: networkReceivers,                                      // array with IBurnerRouter.NetworkReceiver elements meaning network-specific receivers
                        operatorNetworkReceivers: new IBurnerRouter.OperatorNetworkReceiver[](0) // array with IBurnerRouter.OperatorNetworkReceiver elements meaning network-specific receivers
                  })
               );

         // ...
         ```
       </TabItem>

       <TabItem value="hoodi" label="Hoodi">
         ```solidity [DeployBurnerRouter.s.sol]
         import {IBurnerRouterFactory} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouterFactory.sol";
         import {IBurnerRouter} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouter.sol";

         // ...

            address BURNER_ROUTER_FACTORY = 0xF619c99D166224B4AC008b14Cc67ac72C2E91D8a;          // address of the BurnerRouterFactory (see Deployments page)

         // ...

               IBurnerRouter.NetworkReceiver[] memory networkReceivers = new IBurnerRouter.NetworkReceiver[](1);
               networkReceivers[0] = IBurnerRouter.NetworkReceiver({
                  network: <NETWORK_ADDRESS>,
                  receiver: <RECEIVER_ADDRESS>
               });
               address burnerRouter = IBurnerRouterFactory(BURNER_ROUTER_FACTORY).create(
                  IBurnerRouter.InitParams({
                        owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                       // address of the router’s owner
                        collateral: 0x8d09a4502Cc8Cf1547aD300E066060D043f6982D,                  // address of the collateral - wstETH (MUST be the same as for the Vault to connect)
                        delay: 1814400,                                                          // duration of the receivers’ update delay (= 21 days)
                        globalReceiver: 0x25133c2c49A343F8312bb6e896C1ea0Ad8CD0EBd,              // address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
                        networkReceivers: networkReceivers,                                      // array with IBurnerRouter.NetworkReceiver elements meaning network-specific receivers
                        operatorNetworkReceivers: new IBurnerRouter.OperatorNetworkReceiver[](0) // array with IBurnerRouter.OperatorNetworkReceiver elements meaning network-specific receivers
                  })
               );

         // ...
         ```
       </TabItem>

       <TabItem value="sepolia" label="Sepolia">
         ```solidity [DeployBurnerRouter.s.sol]
         import {IBurnerRouterFactory} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouterFactory.sol";
         import {IBurnerRouter} from "@symbioticfi/burners/src/interfaces/router/IBurnerRouter.sol";

         // ...

            address BURNER_ROUTER_FACTORY = 0x32e2AfbdAffB1e675898ABA75868d92eE1E68f3b;          // address of the BurnerRouterFactory (see Deployments page)

         // ...

               IBurnerRouter.NetworkReceiver[] memory networkReceivers = new IBurnerRouter.NetworkReceiver[](1);
               networkReceivers[0] = IBurnerRouter.NetworkReceiver({
                  network: <NETWORK_ADDRESS>,
                  receiver: <RECEIVER_ADDRESS>
               });
               address burnerRouter = IBurnerRouterFactory(BURNER_ROUTER_FACTORY).create(
                  IBurnerRouter.InitParams({
                        owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                       // address of the router’s owner
                        collateral: 0xB82381A3fBD3FaFA77B3a7bE693342618240067b,                  // address of the collateral - wstETH (MUST be the same as for the Vault to connect)
                        delay: 1814400,                                                          // duration of the receivers’ update delay (= 21 days)
                        globalReceiver: 0x58D347334A5E6bDE7279696abE59a11873294FA4,              // address of the pure burner corresponding to the collateral - wstETH_Burner (some collaterals are covered by us; see Deployments page)
                        networkReceivers: networkReceivers,                                      // array with IBurnerRouter.NetworkReceiver elements meaning network-specific receivers
                        operatorNetworkReceivers: new IBurnerRouter.OperatorNetworkReceiver[](0) // array with IBurnerRouter.OperatorNetworkReceiver elements meaning network-specific receivers
                  })
               );

         // ...
         ```
       </TabItem>
     </Tabs>
</Details>

<Details summary="Configure Burner Router with network-specific burner after deployment">
  Generally, all the changes inside the burner router can be performed in 2 steps:

  1. Create a pending request to change some value
  2. Accept the request after waiting for a configured `delay`

  Therefore, to set a new receiver (which can be a network-specific burner or treasury or any address) for a particular network the further steps are needed:

  1. Owner calls `setNetworkReceiver(network, receiver)`
  2. Wait for `delay`
  3. Anyone commits the change via `acceptNetworkReceiver(network)`

  To set a new receiver for some exact operator inside a particular network:

  1. Owner calls `setOperatorNetworkReceiver(network, operator, receiver)`
  2. Wait for `delay`
  3. Anyone commits the change via `acceptOperatorNetworkReceiver(network, operator)`

  To set a new global receiver that gets funds if no specific receivers for a network-operator pair are configured:

  1. Owner calls `setGlobalReceiver(receiver)`
  2. Wait for `delay`
  3. Anyone commits the change via `acceptGlobalReceiver(network)`

  To change a `delay`:

  1. Owner calls `setDelay(newDelay)`
  2. Wait for an old `delay`
  3. Anyone commits the change via `acceptDelay()`
</Details>

### Hook

Hook is a contract that the Vault curator can set to receive `onSlash()` call on each slashing event. Symbiotic doesn’t specify any logic behind it. However, the basic idea of the hook is to allow the creation of any delegation adjustment mechanic during the slashing.

:::warning
Symbiotic Delegator contracts don’t update allocations on the slashing events in any way. This means that a malicious network or an operator may need only several blocks (depending on their allocated stake) to slash all of Vault’s funds.
:::

We provide pure **example** implementations of some standard adjustment mechanics for each Delegator type - [here](https://github.com/symbioticfi/hooks).

![hook](/guides/img/deployment/hook.png)

<Details summary="Core modules deployment with hook">
  1. Clone the core contracts repository by running the following command:

     ```bash [bash]
     git clone --recurse-submodules https://github.com/symbioticfi/core.git
     ```

  2. Navigate into the cloned repository folder:

     ```bash [bash]
     cd core
     ```

  3. Deploy core modules contracts using a simple script:
     Open [DeployVault.s.sol](https://github.com/symbioticfi/core/blob/main/script/DeployVault.s.sol) and configure these settings:

     ```bash [bash]
       // Address of the owner of the vault who can migrate the vault to new versions whitelisted by Symbiotic
       address OWNER = 0x0000000000000000000000000000000000000000;
       // Address of the collateral token
       address COLLATERAL = 0x0000000000000000000000000000000000000000;
       // Vault's burner to send slashed funds to (e.g., 0xdEaD or some unwrapper contract; not used in case of no slasher)
       address BURNER = 0x000000000000000000000000000000000000dEaD;
       // Duration of the vault epoch (the withdrawal delay for staker varies from EPOCH_DURATION to 2 * EPOCH_DURATION depending on when the withdrawal is requested)
       uint48 EPOCH_DURATION = 7 days;
       // Type of the delegator:
       //  0. NetworkRestakeDelegator (allows restaking across multiple networks and having multiple operators per network)
       //  1. FullRestakeDelegator (do not use without knowing what you are doing)
       //  2. OperatorSpecificDelegator (allows restaking across multiple networks with only a single operator)
       //  3. OperatorNetworkSpecificDelegator (allocates the stake to a specific operator and network)
       uint64 DELEGATOR_INDEX = 0;
       // Setting depending on the delegator type:
       // 0. NetworkLimitSetRoleHolders (adjust allocations for networks)
       // 1. NetworkLimitSetRoleHolders (adjust allocations for networks)
       // 2. NetworkLimitSetRoleHolders (adjust allocations for networks)
       // 3. network (the only network that will receive the stake; should be an array with a single element)
       address[] NETWORK_ALLOCATION_SETTERS_OR_NETWORK = [0x0000000000000000000000000000000000000000];
       // Setting depending on the delegator type:
       // 0. OperatorNetworkSharesSetRoleHolders (adjust allocations for operators inside networks; in shares, resulting percentage is operatorShares / totalOperatorShares)
       // 1. OperatorNetworkLimitSetRoleHolders (adjust allocations for operators inside networks; in shares, resulting percentage is operatorShares / totalOperatorShares)
       // 2. operator (the only operator that will receive the stake; should be an array with a single element)
       // 3. operator (the only operator that will receive the stake; should be an array with a single element)
       address[] OPERATOR_ALLOCATION_SETTERS_OR_OPERATOR = [0x0000000000000000000000000000000000000000];
       // Whether to deploy a slasher
       bool WITH_SLASHER = true;
       // Type of the slasher:
       //  0. Slasher (allows instant slashing)
       //  1. VetoSlasher (allows having a veto period if the resolver is set)
       uint64 SLASHER_INDEX = 1;
       // Duration of a veto period (should be less than EPOCH_DURATION)
       uint48 VETO_DURATION = 1 days;

       // Optional

       // Deposit limit (maximum amount of the active stake allowed in the vault)
       uint256 DEPOSIT_LIMIT = 0;
       // Addresses of the whitelisted depositors
       address[] WHITELISTED_DEPOSITORS = new address[](0);
       // Address of the hook contract which, e.g., can automatically adjust the allocations on slashing events (not used in case of no slasher)
       address HOOK = <HOOK>;
       // Delay in epochs for a network to update a resolver
       uint48 RESOLVER_SET_EPOCHS_DELAY = 3;
     ```

  Edit the configuration fields, then run:

  <Tabs groupId="chains" defaultValue="mainnet">
    <TabItem value="mainnet" label="Mainnet">
      ```bash [bash]
      forge script script/DeployVault.s.sol:DeployVaultScript \
         --rpc-url=https://ethereum-rpc.publicnode.com \
         --chain mainnet \
         --broadcast
      ```
    </TabItem>

    <TabItem value="hoodi" label="Hoodi">
      ```bash [bash]
      forge script script/DeployVault.s.sol:DeployVaultScript \
         --rpc-url=https://0xrpc.io/hoodi \
         --chain hoodi \
         --broadcast
      ```
    </TabItem>

    <TabItem value="sepolia" label="Sepolia">
      ```bash [bash]
      forge script script/DeployVault.s.sol:DeployVaultScript \
         --rpc-url=https://ethereum-sepolia-rpc.publicnode.com \
         --chain sepolia \
         --broadcast
      ```
    </TabItem>
  </Tabs>

  :::note
  This is an **example** command. Replace the given values with your own.

  ***

  In addition, you need to [choose a preferred wallet option](https://book.getfoundry.sh/reference/forge/forge-script?highlight=forge%20script#wallet-options---raw) and adjust the command accordingly.
  :::
</Details>

<Details summary="Core modules deployment with hook - technical (Solidity)">
  The following instruction assumes you have an already initialized Foundry repository ([read more here](https://book.getfoundry.sh/getting-started/first-steps)).

  1. Install the core contracts repository by running the following command:

     ```bash [bash]
     forge install symbioticfi/core
     ```

  2. Update (or create if not yet) a `remappings.txt` file inside your repository accordingly:

  ```txt title="remappings.txt"
  ...
  @symbioticfi/core/=lib/core/
  ```

  3. Create core modules with hook using [a VaultConfigurator contract](https://github.com/symbioticfi/core/blob/main/src/contracts/VaultConfigurator.sol):

     :::note
     This is an **example** code snippet. Replace the given values with your own.
     :::

     <Tabs groupId="chains" defaultValue="mainnet">
       <TabItem value="mainnet" label="Mainnet">
         ```solidity [DeployVaultWithHook.s.sol]
         import {IVaultConfigurator} from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol";
         import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
         import {IBaseDelegator} from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol";
         import {INetworkRestakeDelegator} from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol";
         import {IBaseSlasher} from "@symbioticfi/core/src/interfaces/slasher/IBaseSlasher.sol";
         import {IVetoSlasher} from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol";

         // ...

            address VAULT_CONFIGURATOR = 0x29300b1d3150B4E2b12fE80BE72f365E200441EC;                  // address of the VaultConfigurator (see Deployments page)

         // ...

               address hook = <HOOK>;
               address[] memory networkLimitSetRoleHolders = new address[](2);
               networkLimitSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
               networkLimitSetRoleHolders[1] = hook;
               address[] memory operatorNetworkSharesSetRoleHolders = new address[](2);
               operatorNetworkSharesSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
               operatorNetworkSharesSetRoleHolders[1] = hook;

               (address vault, address networkRestakeDelegator, address vetoSlasher) = IVaultConfigurator(VAULT_CONFIGURATOR).create(
                  IVaultConfigurator.InitParams({
                        version: 1,                                                                   // Vault’s version (= common one)
                        owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                            // address of the Vault’s owner (can migrate the Vault to new versions in the future)
                        vaultParams: abi.encode(IVault.InitParams({
                           collateral: 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0,                    // address of the collateral - wstETH
                           burner: <BURNER_ROUTER>,                                                   // address of the deployed burner router
                           epochDuration: 604800,                                                     // duration of the Vault epoch in seconds (= 7 days)
                           depositWhitelist: false,                                                   // if enable deposit whitelisting
                           isDepositLimit: false,                                                     // if enable deposit limit
                           depositLimit: 0,                                                           // deposit limit
                           defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,        // address of the Vault’s admin (can manage all roles)
                           depositWhitelistSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7, // address of the enabler/disabler of the deposit whitelisting
                           depositorWhitelistRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,  // address of the depositors whitelister
                           isDepositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,   // address of the enabler/disabler of the deposit limit
                           depositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7      // address of the deposit limit setter
                        })),
                        delegatorIndex: 0,                                                            // Delegator’s type (= NetworkRestakeDelegator)
                        delegatorParams: abi.encode(INetworkRestakeDelegator.InitParams({
                           baseParams: IBaseDelegator.BaseParams({
                              defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,     // address of the Delegator’s admin (can manage all roles)
                              hook: hook,                                                             // address of the hook (if not zero, receives onSlash() call on each slashing)
                              hookSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7           // address of the hook setter
                           }),
                           networkLimitSetRoleHolders: networkLimitSetRoleHolders,                    // array of addresses of the network limit setters
                           operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders   // array of addresses of the operator-network shares setters
                        })),
                        withSlasher: true,                                                            // if enable Slasher module
                        slasherIndex: 1,                                                              // Slasher’s type (= VetoSlasher)
                        slasherParams: abi.encode(IVetoSlasher.InitParams({
                           baseParams: IBaseSlasher.BaseParams({
                              isBurnerHook: true                                                      // if enable the `burner` to receive onSlash() call after each slashing (is needed for the burner router workflow)
                           }),
                           vetoDuration: 86400,                                                       // veto duration (= 1 day)
                           resolverSetEpochsDelay: 3                                                  // number of Vault epochs needed for the resolver to be changed
                        }))
                  })
               );

         // ...
         ```
       </TabItem>

       <TabItem value="hoodi" label="Hoodi">
         ```solidity [DeployVaultWithHook.s.sol]
         import {IVaultConfigurator} from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol";
         import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
         import {IBaseDelegator} from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol";
         import {INetworkRestakeDelegator} from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol";
         import {IBaseSlasher} from "@symbioticfi/core/src/interfaces/slasher/IBaseSlasher.sol";
         import {IVetoSlasher} from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol";

         // ...

            address VAULT_CONFIGURATOR = 0x94c344E816A53D07fC4c7F4a18f82b6Da87CFc8f;                  // address of the VaultConfigurator (see Deployments page)

         // ...

               address hook = <HOOK>;
               address[] memory networkLimitSetRoleHolders = new address[](2);
               networkLimitSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
               networkLimitSetRoleHolders[1] = hook;
               address[] memory operatorNetworkSharesSetRoleHolders = new address[](2);
               operatorNetworkSharesSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
               operatorNetworkSharesSetRoleHolders[1] = hook;

               (address vault, address networkRestakeDelegator, address vetoSlasher) = IVaultConfigurator(VAULT_CONFIGURATOR).create(
                  IVaultConfigurator.InitParams({
                        version: 1,                                                                   // Vault’s version (= common one)
                        owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                            // address of the Vault’s owner (can migrate the Vault to new versions in the future)
                        vaultParams: abi.encode(IVault.InitParams({
                           collateral: 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0,                    // address of the collateral - wstETH
                           burner: <BURNER_ROUTER>,                                                   // address of the deployed burner router
                           epochDuration: 604800,                                                     // duration of the Vault epoch in seconds (= 7 days)
                           depositWhitelist: false,                                                   // if enable deposit whitelisting
                           isDepositLimit: false,                                                     // if enable deposit limit
                           depositLimit: 0,                                                           // deposit limit
                           defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,        // address of the Vault’s admin (can manage all roles)
                           depositWhitelistSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7, // address of the enabler/disabler of the deposit whitelisting
                           depositorWhitelistRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,  // address of the depositors whitelister
                           isDepositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,   // address of the enabler/disabler of the deposit limit
                           depositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7      // address of the deposit limit setter
                        })),
                        delegatorIndex: 0,                                                            // Delegator’s type (= NetworkRestakeDelegator)
                        delegatorParams: abi.encode(INetworkRestakeDelegator.InitParams({
                           baseParams: IBaseDelegator.BaseParams({
                              defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,     // address of the Delegator’s admin (can manage all roles)
                              hook: hook,                                                             // address of the hook (if not zero, receives onSlash() call on each slashing)
                              hookSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7           // address of the hook setter
                           }),
                           networkLimitSetRoleHolders: networkLimitSetRoleHolders,                    // array of addresses of the network limit setters
                           operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders   // array of addresses of the operator-network shares setters
                        })),
                        withSlasher: true,                                                            // if enable Slasher module
                        slasherIndex: 1,                                                              // Slasher’s type (= VetoSlasher)
                        slasherParams: abi.encode(IVetoSlasher.InitParams({
                           baseParams: IBaseSlasher.BaseParams({
                              isBurnerHook: true                                                      // if enable the `burner` to receive onSlash() call after each slashing (is needed for the burner router workflow)
                           }),
                           vetoDuration: 86400,                                                       // veto duration (= 1 day)
                           resolverSetEpochsDelay: 3                                                  // number of Vault epochs needed for the resolver to be changed
                        }))
                  })
               );

         // ...
         ```
       </TabItem>

       <TabItem value="sepolia" label="Sepolia">
         ```solidity [DeployVaultWithHook.s.sol]
         import {IVaultConfigurator} from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol";
         import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
         import {IBaseDelegator} from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol";
         import {INetworkRestakeDelegator} from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol";
         import {IBaseSlasher} from "@symbioticfi/core/src/interfaces/slasher/IBaseSlasher.sol";
         import {IVetoSlasher} from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol";

         // ...

            address VAULT_CONFIGURATOR = 0xD2191FE92987171691d552C219b8caEf186eb9cA;                  // address of the VaultConfigurator (see Deployments page)

         // ...

               address hook = <HOOK>;
               address[] memory networkLimitSetRoleHolders = new address[](2);
               networkLimitSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
               networkLimitSetRoleHolders[1] = hook;
               address[] memory operatorNetworkSharesSetRoleHolders = new address[](2);
               operatorNetworkSharesSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
               operatorNetworkSharesSetRoleHolders[1] = hook;

               (address vault, address networkRestakeDelegator, address vetoSlasher) = IVaultConfigurator(VAULT_CONFIGURATOR).create(
                  IVaultConfigurator.InitParams({
                        version: 1,                                                                   // Vault’s version (= common one)
                        owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                            // address of the Vault’s owner (can migrate the Vault to new versions in the future)
                        vaultParams: abi.encode(IVault.InitParams({
                           collateral: 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0,                    // address of the collateral - wstETH
                           burner: <BURNER_ROUTER>,                                                   // address of the deployed burner router
                           epochDuration: 604800,                                                     // duration of the Vault epoch in seconds (= 7 days)
                           depositWhitelist: false,                                                   // if enable deposit whitelisting
                           isDepositLimit: false,                                                     // if enable deposit limit
                           depositLimit: 0,                                                           // deposit limit
                           defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,        // address of the Vault’s admin (can manage all roles)
                           depositWhitelistSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7, // address of the enabler/disabler of the deposit whitelisting
                           depositorWhitelistRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,  // address of the depositors whitelister
                           isDepositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,   // address of the enabler/disabler of the deposit limit
                           depositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7      // address of the deposit limit setter
                        })),
                        delegatorIndex: 0,                                                            // Delegator’s type (= NetworkRestakeDelegator)
                        delegatorParams: abi.encode(INetworkRestakeDelegator.InitParams({
                           baseParams: IBaseDelegator.BaseParams({
                              defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,     // address of the Delegator’s admin (can manage all roles)
                              hook: hook,                                                             // address of the hook (if not zero, receives onSlash() call on each slashing)
                              hookSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7           // address of the hook setter
                           }),
                           networkLimitSetRoleHolders: networkLimitSetRoleHolders,                    // array of addresses of the network limit setters
                           operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders   // array of addresses of the operator-network shares setters
                        })),
                        withSlasher: true,                                                            // if enable Slasher module
                        slasherIndex: 1,                                                              // Slasher’s type (= VetoSlasher)
                        slasherParams: abi.encode(IVetoSlasher.InitParams({
                           baseParams: IBaseSlasher.BaseParams({
                              isBurnerHook: true                                                      // if enable the `burner` to receive onSlash() call after each slashing (is needed for the burner router workflow)
                           }),
                           vetoDuration: 86400,                                                       // veto duration (= 1 day)
                           resolverSetEpochsDelay: 3                                                  // number of Vault epochs needed for the resolver to be changed
                        }))
                  })
               );

         // ...
         ```
       </TabItem>
     </Tabs>
</Details>

<Details summary="Configure core modules with hook after deployment">
  1. We need the address of the Vault’s Delegator contract. It can be obtained via `Vault.delegator()`
  2. Make sure the caller has a `Delegator.HOOK_SET_ROLE()` role via [the OpenZeppelin’s `AccessControl` contract](https://docs.openzeppelin.com/contracts/5.x/access-control#using-access-control)
  3. Call `Delegator.setHook(hook)`
</Details>

### Deposit whitelist

Symbiotic Vaults contain a feature called - deposit whitelist. It allows the restriction of making deposits to the Vault only by the whitelisted depositors. Several parties may need such functionality, e.g.:

1. LRTs that want to fully isolate their Vaults from the external users to have a strict logic flow depending only on them
2. Institutional entities that want to reduce the risks maximally and respect the legal side
3. Some third-party entities that want to integrate the Vaults with some specific logic on top of them

![whitelist](/guides/img/deployment/whitelist.png)

<Details summary="Core modules deployment with deposit whitelist">
  1. Clone the core contracts repository by running the following command:

     ```bash [bash]
     git clone --recurse-submodules https://github.com/symbioticfi/core.git
     ```

  2. Navigate into the cloned repository folder:

     ```bash [bash]
     cd core
     ```

  3. Deploy core modules contracts using a simple script:
     Open [DeployVault.s.sol](https://github.com/symbioticfi/core/blob/main/script/DeployVault.s.sol) and configure these settings:

     ```bash [bash]
       // Address of the owner of the vault who can migrate the vault to new versions whitelisted by Symbiotic
       address OWNER = 0x0000000000000000000000000000000000000000;
       // Address of the collateral token
       address COLLATERAL = 0x0000000000000000000000000000000000000000;
       // Vault's burner to send slashed funds to (e.g., 0xdEaD or some unwrapper contract; not used in case of no slasher)
       address BURNER = 0x000000000000000000000000000000000000dEaD;
       // Duration of the vault epoch (the withdrawal delay for staker varies from EPOCH_DURATION to 2 * EPOCH_DURATION depending on when the withdrawal is requested)
       uint48 EPOCH_DURATION = 7 days;
       // Type of the delegator:
       //  0. NetworkRestakeDelegator (allows restaking across multiple networks and having multiple operators per network)
       //  1. FullRestakeDelegator (do not use without knowing what you are doing)
       //  2. OperatorSpecificDelegator (allows restaking across multiple networks with only a single operator)
       //  3. OperatorNetworkSpecificDelegator (allocates the stake to a specific operator and network)
       uint64 DELEGATOR_INDEX = 0;
       // Setting depending on the delegator type:
       // 0. NetworkLimitSetRoleHolders (adjust allocations for networks)
       // 1. NetworkLimitSetRoleHolders (adjust allocations for networks)
       // 2. NetworkLimitSetRoleHolders (adjust allocations for networks)
       // 3. network (the only network that will receive the stake; should be an array with a single element)
       address[] NETWORK_ALLOCATION_SETTERS_OR_NETWORK = [0x0000000000000000000000000000000000000000];
       // Setting depending on the delegator type:
       // 0. OperatorNetworkSharesSetRoleHolders (adjust allocations for operators inside networks; in shares, resulting percentage is operatorShares / totalOperatorShares)
       // 1. OperatorNetworkLimitSetRoleHolders (adjust allocations for operators inside networks; in shares, resulting percentage is operatorShares / totalOperatorShares)
       // 2. operator (the only operator that will receive the stake; should be an array with a single element)
       // 3. operator (the only operator that will receive the stake; should be an array with a single element)
       address[] OPERATOR_ALLOCATION_SETTERS_OR_OPERATOR = [0x0000000000000000000000000000000000000000];
       // Whether to deploy a slasher
       bool WITH_SLASHER = true;
       // Type of the slasher:
       //  0. Slasher (allows instant slashing)
       //  1. VetoSlasher (allows having a veto period if the resolver is set)
       uint64 SLASHER_INDEX = 1;
       // Duration of a veto period (should be less than EPOCH_DURATION)
       uint48 VETO_DURATION = 1 days;

       // Optional

       // Deposit limit (maximum amount of the active stake allowed in the vault)
       uint256 DEPOSIT_LIMIT = 0;
       // Addresses of the whitelisted depositors
       address[] WHITELISTED_DEPOSITORS = <DEPOSITORS_TO_WHITELIST>;
       // Address of the hook contract which, e.g., can automatically adjust the allocations on slashing events (not used in case of no slasher)
       address HOOK = 0x0000000000000000000000000000000000000000;
       // Delay in epochs for a network to update a resolver
       uint48 RESOLVER_SET_EPOCHS_DELAY = 3;
     ```

  Edit the configuration fields, then run:

  <Tabs groupId="chains" defaultValue="mainnet">
    <TabItem value="mainnet" label="Mainnet">
      ```bash [bash]
      forge script script/DeployVault.s.sol:DeployVaultScript \
         --rpc-url=https://ethereum-rpc.publicnode.com \
         --chain mainnet \
         --broadcast
      ```
    </TabItem>

    <TabItem value="hoodi" label="Hoodi">
      ```bash [bash]
      forge script script/DeployVault.s.sol:DeployVaultScript \
         --rpc-url=https://0xrpc.io/hoodi \
         --chain hoodi \
         --broadcast
      ```
    </TabItem>

    <TabItem value="sepolia" label="Sepolia">
      ```bash [bash]
      forge script script/DeployVault.s.sol:DeployVaultScript \
      --rpc-url=https://ethereum-sepolia-rpc.publicnode.com \
      --chain sepolia \
      --broadcast
      ```
    </TabItem>
  </Tabs>

  :::note
  This is an **example** command. Replace the given values with your own.

  ***

  In addition, you need to [choose a preferred wallet option](https://book.getfoundry.sh/reference/forge/forge-script?highlight=forge%20script#wallet-options---raw) and adjust the command accordingly.
  :::
</Details>

<Details summary="Core modules deployment with deposit whitelist - technical (Solidity)">
  The following instruction assumes you have an already initialized Foundry repository ([read more here](https://book.getfoundry.sh/getting-started/first-steps)).

  1. Install the core contracts repository by running the following command:

     ```bash [bash]
     forge install symbioticfi/core
     ```

  2. Update (or create if not yet) a `remappings.txt` file inside your repository accordingly:

     ```txt title="remappings.txt"
     ...
     @symbioticfi/core/=lib/core/
     ```

  3. Create core modules with deposit whitelist using [a VaultConfigurator contract](https://github.com/symbioticfi/core/blob/main/src/contracts/VaultConfigurator.sol):

     :::note
     This is an **example** code snippet. Replace the given values with your own.
     :::

     <Tabs groupId="chains" defaultValue="mainnet">
       <TabItem value="mainnet" label="Mainnet">
         ```solidity [DeployVaultWithWhitelist.s.sol]
         import {Vault} from "@symbioticfi/core/src/contracts/vault/Vault.sol";
         import {IVaultConfigurator} from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol";
         import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
         import {IBaseDelegator} from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol";
         import {INetworkRestakeDelegator} from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol";
         import {IBaseSlasher} from "@symbioticfi/core/src/interfaces/slasher/IBaseSlasher.sol";
         import {IVetoSlasher} from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol";

         // ...

            address VAULT_CONFIGURATOR = 0x29300b1d3150B4E2b12fE80BE72f365E200441EC;                  // address of the VaultConfigurator (see Deployments page)

         // ...

               address[] memory networkLimitSetRoleHolders = new address[](1);
               networkLimitSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
               address[] memory operatorNetworkSharesSetRoleHolders = new address[](1);
               operatorNetworkSharesSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;

               (address vault, address networkRestakeDelegator, address vetoSlasher) = IVaultConfigurator(VAULT_CONFIGURATOR).create(
                  IVaultConfigurator.InitParams({
                        version: 1,                                                                   // Vault’s version (= common one)
                        owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                            // address of the Vault’s owner (can migrate the Vault to new versions in the future)
                        vaultParams: abi.encode(IVault.InitParams({
                           collateral: 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0,                    // address of the collateral - wstETH
                           burner: <BURNER_ROUTER>,                                                   // address of the deployed burner router
                           epochDuration: 604800,                                                     // duration of the Vault epoch in seconds (= 7 days)
                           depositWhitelist: true,                                                    // if enable deposit whitelisting
                           isDepositLimit: false,                                                     // if enable deposit limit
                           depositLimit: 0,                                                           // deposit limit
                           defaultAdminRoleHolder: address(this),                                     // address of the Vault’s admin (can manage all roles)
                           depositWhitelistSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7, // address of the enabler/disabler of the deposit whitelisting
                           depositorWhitelistRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,  // address of the depositors whitelister
                           isDepositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,   // address of the enabler/disabler of the deposit limit
                           depositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7      // address of the deposit limit setter
                        })),
                        delegatorIndex: 0,                                                            // Delegator’s type (= NetworkRestakeDelegator)
                        delegatorParams: abi.encode(INetworkRestakeDelegator.InitParams({
                           baseParams: IBaseDelegator.BaseParams({
                              defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,     // address of the Delegator’s admin (can manage all roles)
                              hook: 0x0000000000000000000000000000000000000000,                       // address of the hook (if not zero, receives onSlash() call on each slashing)
                              hookSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7           // address of the hook setter
                           }),
                           networkLimitSetRoleHolders: networkLimitSetRoleHolders,                    // array of addresses of the network limit setters
                           operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders   // array of addresses of the operator-network shares setters
                        })),
                        withSlasher: true,                                                            // if enable Slasher module
                        slasherIndex: 1,                                                              // Slasher’s type (= VetoSlasher)
                        slasherParams: abi.encode(IVetoSlasher.InitParams({
                           baseParams: IBaseSlasher.BaseParams({
                              isBurnerHook: true                                                      // if enable the `burner` to receive onSlash() call after each slashing (is needed for the burner router workflow)
                           }),
                           vetoDuration: 86400,                                                       // veto duration (= 1 day)
                           resolverSetEpochsDelay: 3                                                  // number of Vault epochs needed for the resolver to be changed
                        }))
                  })
               );

               Vault(vault).grantRole(Vault(vault).DEFAULT_ADMIN_ROLE(), 0xe8616DEcea16b5216e805B0b8caf7784de7570E7);
               Vault(vault).grantRole(Vault(vault).DEPOSITOR_WHITELIST_ROLE(), address(this));

               IVault(vault).setDepositorWhitelistStatus(<DEPOSITOR_TO_WHITELIST>, true);

               Vault(vault).renounceRole(Vault(vault).DEPOSITOR_WHITELIST_ROLE(), address(this));
               Vault(vault).renounceRole(Vault(vault).DEFAULT_ADMIN_ROLE(), address(this));

         // ...
         ```
       </TabItem>

       <TabItem value="hoodi" label="Hoodi">
         ```solidity [DeployVaultWithWhitelist.s.sol]
         import {Vault} from "@symbioticfi/core/src/contracts/vault/Vault.sol";
         import {IVaultConfigurator} from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol";
         import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
         import {IBaseDelegator} from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol";
         import {INetworkRestakeDelegator} from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol";
         import {IBaseSlasher} from "@symbioticfi/core/src/interfaces/slasher/IBaseSlasher.sol";
         import {IVetoSlasher} from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol";

         // ...

            address VAULT_CONFIGURATOR = 0x94c344E816A53D07fC4c7F4a18f82b6Da87CFc8f;                  // address of the VaultConfigurator (see Deployments page)

         // ...

               address[] memory networkLimitSetRoleHolders = new address[](1);
               networkLimitSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
               address[] memory operatorNetworkSharesSetRoleHolders = new address[](1);
               operatorNetworkSharesSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;

               (address vault, address networkRestakeDelegator, address vetoSlasher) = IVaultConfigurator(VAULT_CONFIGURATOR).create(
                  IVaultConfigurator.InitParams({
                        version: 1,                                                                   // Vault’s version (= common one)
                        owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                            // address of the Vault’s owner (can migrate the Vault to new versions in the future)
                        vaultParams: abi.encode(IVault.InitParams({
                           collateral: 0x8d09a4502Cc8Cf1547aD300E066060D043f6982D,                    // address of the collateral - wstETH
                           burner: <BURNER_ROUTER>,                                                   // address of the deployed burner router
                           epochDuration: 604800,                                                     // duration of the Vault epoch in seconds (= 7 days)
                           depositWhitelist: true,                                                    // if enable deposit whitelisting
                           isDepositLimit: false,                                                     // if enable deposit limit
                           depositLimit: 0,                                                           // deposit limit
                           defaultAdminRoleHolder: address(this),                                     // address of the Vault’s admin (can manage all roles)
                           depositWhitelistSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7, // address of the enabler/disabler of the deposit whitelisting
                           depositorWhitelistRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,  // address of the depositors whitelister
                           isDepositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,   // address of the enabler/disabler of the deposit limit
                           depositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7      // address of the deposit limit setter
                        })),
                        delegatorIndex: 0,                                                            // Delegator’s type (= NetworkRestakeDelegator)
                        delegatorParams: abi.encode(INetworkRestakeDelegator.InitParams({
                           baseParams: IBaseDelegator.BaseParams({
                              defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,     // address of the Delegator’s admin (can manage all roles)
                              hook: 0x0000000000000000000000000000000000000000,                       // address of the hook (if not zero, receives onSlash() call on each slashing)
                              hookSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7           // address of the hook setter
                           }),
                           networkLimitSetRoleHolders: networkLimitSetRoleHolders,                    // array of addresses of the network limit setters
                           operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders   // array of addresses of the operator-network shares setters
                        })),
                        withSlasher: true,                                                            // if enable Slasher module
                        slasherIndex: 1,                                                              // Slasher’s type (= VetoSlasher)
                        slasherParams: abi.encode(IVetoSlasher.InitParams({
                           baseParams: IBaseSlasher.BaseParams({
                              isBurnerHook: true                                                      // if enable the `burner` to receive onSlash() call after each slashing (is needed for the burner router workflow)
                           }),
                           vetoDuration: 86400,                                                       // veto duration (= 1 day)
                           resolverSetEpochsDelay: 3                                                  // number of Vault epochs needed for the resolver to be changed
                        }))
                  })
               );

               Vault(vault).grantRole(Vault(vault).DEFAULT_ADMIN_ROLE(), 0xe8616DEcea16b5216e805B0b8caf7784de7570E7);
               Vault(vault).grantRole(Vault(vault).DEPOSITOR_WHITELIST_ROLE(), address(this));

               IVault(vault).setDepositorWhitelistStatus(<DEPOSITOR_TO_WHITELIST>, true);

               Vault(vault).renounceRole(Vault(vault).DEPOSITOR_WHITELIST_ROLE(), address(this));
               Vault(vault).renounceRole(Vault(vault).DEFAULT_ADMIN_ROLE(), address(this));

         // ...
         ```
       </TabItem>

       <TabItem value="sepolia" label="Sepolia">
         ```solidity [DeployVaultWithWhitelist.s.sol]
         import {Vault} from "@symbioticfi/core/src/contracts/vault/Vault.sol";
         import {IVaultConfigurator} from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol";
         import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
         import {IBaseDelegator} from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol";
         import {INetworkRestakeDelegator} from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol";
         import {IBaseSlasher} from "@symbioticfi/core/src/interfaces/slasher/IBaseSlasher.sol";
         import {IVetoSlasher} from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol";

         // ...

            address VAULT_CONFIGURATOR = 0xD2191FE92987171691d552C219b8caEf186eb9cA;                  // address of the VaultConfigurator (see Deployments page)

         // ...

               address[] memory networkLimitSetRoleHolders = new address[](1);
               networkLimitSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;
               address[] memory operatorNetworkSharesSetRoleHolders = new address[](1);
               operatorNetworkSharesSetRoleHolders[0] = 0xe8616DEcea16b5216e805B0b8caf7784de7570E7;

               (address vault, address networkRestakeDelegator, address vetoSlasher) = IVaultConfigurator(VAULT_CONFIGURATOR).create(
                  IVaultConfigurator.InitParams({
                        version: 1,                                                                   // Vault’s version (= common one)
                        owner: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,                            // address of the Vault’s owner (can migrate the Vault to new versions in the future)
                        vaultParams: abi.encode(IVault.InitParams({
                           collateral: 0xB82381A3fBD3FaFA77B3a7bE693342618240067b,                    // address of the collateral - wstETH
                           burner: <BURNER_ROUTER>,                                                   // address of the deployed burner router
                           epochDuration: 604800,                                                     // duration of the Vault epoch in seconds (= 7 days)
                           depositWhitelist: true,                                                    // if enable deposit whitelisting
                           isDepositLimit: false,                                                     // if enable deposit limit
                           depositLimit: 0,                                                           // deposit limit
                           defaultAdminRoleHolder: address(this),                                     // address of the Vault’s admin (can manage all roles)
                           depositWhitelistSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7, // address of the enabler/disabler of the deposit whitelisting
                           depositorWhitelistRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,  // address of the depositors whitelister
                           isDepositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,   // address of the enabler/disabler of the deposit limit
                           depositLimitSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7      // address of the deposit limit setter
                        })),
                        delegatorIndex: 0,                                                            // Delegator’s type (= NetworkRestakeDelegator)
                        delegatorParams: abi.encode(INetworkRestakeDelegator.InitParams({
                           baseParams: IBaseDelegator.BaseParams({
                              defaultAdminRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7,     // address of the Delegator’s admin (can manage all roles)
                              hook: 0x0000000000000000000000000000000000000000,                       // address of the hook (if not zero, receives onSlash() call on each slashing)
                              hookSetRoleHolder: 0xe8616DEcea16b5216e805B0b8caf7784de7570E7           // address of the hook setter
                           }),
                           networkLimitSetRoleHolders: networkLimitSetRoleHolders,                    // array of addresses of the network limit setters
                           operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders   // array of addresses of the operator-network shares setters
                        })),
                        withSlasher: true,                                                            // if enable Slasher module
                        slasherIndex: 1,                                                              // Slasher’s type (= VetoSlasher)
                        slasherParams: abi.encode(IVetoSlasher.InitParams({
                           baseParams: IBaseSlasher.BaseParams({
                              isBurnerHook: true                                                      // if enable the `burner` to receive onSlash() call after each slashing (is needed for the burner router workflow)
                           }),
                           vetoDuration: 86400,                                                       // veto duration (= 1 day)
                           resolverSetEpochsDelay: 3                                                  // number of Vault epochs needed for the resolver to be changed
                        }))
                  })
               );

               Vault(vault).grantRole(Vault(vault).DEFAULT_ADMIN_ROLE(), 0xe8616DEcea16b5216e805B0b8caf7784de7570E7);
               Vault(vault).grantRole(Vault(vault).DEPOSITOR_WHITELIST_ROLE(), address(this));

               IVault(vault).setDepositorWhitelistStatus(<DEPOSITOR_TO_WHITELIST>, true);

               Vault(vault).renounceRole(Vault(vault).DEPOSITOR_WHITELIST_ROLE(), address(this));
               Vault(vault).renounceRole(Vault(vault).DEFAULT_ADMIN_ROLE(), address(this));

         // ...
         ```
       </TabItem>
     </Tabs>
</Details>

<Details summary="Configure core modules with deposit whitelist after deployment">
  1. Make sure the caller has a `Vault.DEPOSIT_WHITELIST_SET_ROLE()` role via [the OpenZeppelin’s `AccessControl` contract](https://docs.openzeppelin.com/contracts/5.x/access-control#using-access-control)
  2. Call `Vault.setDepositWhitelist(true)`
  3. Make sure the caller has a `Vault.DEPOSITOR_WHITELIST_ROLE()` role via [the OpenZeppelin’s `AccessControl` contract](https://docs.openzeppelin.com/contracts/5.x/access-control#using-access-control)
  4. Call `Vault.setDepositorWhitelistStatus(account, true)`
</Details>

# Submit Metadata

The [Symbiotic UI](https://app.symbiotic.fi/deposit) displays TVL, allocations, and relationships between curators, vaults, operators, and networks. To make your entity visible on the UI, submit its metadata to the corresponding repository.

After you submit metadata, the Symbiotic team reviews and merges it. Once merged, your data appears on the UI.

## Add a New Entity Template

### Choose a Repository

| Chain   | URL                                             |
| ------- | ----------------------------------------------- |
| Mainnet | https://github.com/symbioticfi/metadata-mainnet |
| Hoodi   | https://github.com/symbioticfi/metadata-hoodi   |

### Repository Structure

The repository is organized as follows:

```
repository/
├── vaults/
│   ├── 0x<address>/
│   │   ├── info.json
│   │   └── logo.png (optional)
├── networks/
├── operators/
├── tokens/
```

Each entity is identified by its Ethereum address (`0x...`), and its data is stored in a folder named after the address. Inside this folder, include a file `info.json` containing metadata, and optionally, an icon file `logo.png`.

***

### Steps to Add a New Entity

**Note: After your PR is submitted, email your PR link to verify@symbiotic.fi from your official business email (domain must match that of your entity website) to allow us to confirm your identity ahead of merging your PR.**

1. **Determine the entity type**:
   * Decide whether the entity belongs to `vaults`, `networks`, `operators`, `tokens` or `points`.
   * If the entity is a `vault`, ensure its collateral token entity is registered in the `tokens` folder before adding the vault metadata. If not, add the token first.
2. **Register the entity in the registry**:
   * Before adding metadata for vaults, networks, or operators, ensure that they are registered in their respective registries. You can find the current registry contract addresses in the [Addresses page](/get-started/resources/addresses). Unregistered entities will not be accepted.
3. **Create a new folder**:
   * Navigate to the appropriate directory for the entity type.
   * Create a folder named after the Ethereum address (e.g., `0x1234567890abcdef1234567890abcdef12345678`).
4. **Add the `info.json` file**:
   * Include metadata in the specified format (see below).
5. **(Optional) Add an icon file**:
   * If available, include a `logo.png` file with the entity’s logo.

The Symbiotic team reviews your PR after automated checks pass. If approved, it will be merged into the repository.

***

### File Format: `info.json`

The `info.json` file must follow this structure:

#### Required Fields

* `name` (string): The name of the entity.
* `description` (string): A brief description of the entity.
* `tags` (array of strings): Tags categorizing the entity.
* `links` (array of objects): External links related to the entity.

#### Fields for Tokens

* `cmcId` (string): The CoinMarketCap ID for the token. Used to fetch price of the token in USD.
* `permitName` (string): The `name` field for EIP-2612 support.
* `permitVersion` (string): The `version` field for EIP-2612 support.

#### Fields for Vaults

* `curatorId` (string): The ID of the curator of the vault.
* `vaultType` (string): The type of the vault. Can be one of:
  * `eth-restaking`: Vaults with ETH-flavored collateral restaked across multiple networks
  * `btc-restaking`: Vaults with BTC-flavored collateral restaked across multiple networks
  * `network-exclusive`: Vaults exclusive to a single network

#### Supported `links` Types

Each link should include:

* `type`: The type of the link. Supported values are:
  * `website`: The official website of the entity.
  * `explorer`: A blockchain explorer link for the entity's Ethereum address or contract.
  * `docs`: Documentation related to the entity.
  * `example`: Example use cases or tutorials.
  * `externalLink`: A link to be shown below the entity's name.
* `name`: A user-friendly name for the link.
* `url`: The URL of the resource.

### Icon File: `logo.png` (Optional)

If you want to include an icon for the entity, follow these guidelines:

* **File Name**: `logo.png`
* **Dimensions**: 256x256 pixels
* **Format**: PNG

Place the `logo.png` file in the same folder as the `info.json` file.

***

### Validation

Before submitting your PR, ensure the following:

1. The Ethereum address is valid:
   * It must start with `0x` and be exactly 42 characters long.
2. The `info.json` file is valid:
   * Use a JSON validator, such as [https://jsonlint.com/](https://jsonlint.com/).
3. The `logo.png` file (if included) meets the size requirement of **256x256 pixels**.

***

### Submitting the Pull Request

Once your files are added to the repository, create a Pull Request with the following details:

1. **Entity Type**: Specify the type (vault, network, operator, token).
2. **Ethereum Address**: Provide the address of the entity.
3. **Description**: Summarize the entity’s purpose and data.

#### Example PR Description

```
Added new token entity: 0x1234567890abcdef1234567890abcdef12345678

- **Name**: USDT
- **Description**: USDT is a stablecoin pegged to the US Dollar, widely used for trading and liquidity in cryptocurrency markets.
- **Tags**: stablecoin, usdt
- **Links**:
  - [Website](https://tether.to/)
  - [Etherscan](https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7)
  - [Tether Documentation](https://docs.tether.to/)
- **CMC ID**: 825
- **Permit Name**: USDT Permit Token
- **Permit Version**: 1
- **Icon**: Included (256x256 px)
```

***

### Review and Approval

Your PR will be reviewed to ensure:

* The `info.json` file has all required fields and valid data.
* The `logo.png` file (if included) meets the requirements.
* The metadata is accurate and well-structured.
* The submitter of the PR is from the entity in question (verified via an email with your PR link to verify@symbiotic.fi from your official business email)

After approval, your changes will be merged into the repository.

## Add a Curator

:::steps

##### Create a new folder in the `/curators` directory

##### Create a new json file in the folder with the following structure:

```json [info.json]
{
    "name": "My Curator",
    "description": "My Curator is a curator that allows you to manage your vaults.",
    "tags": ["curator", "staking"],
    "links": [
        { "type": "website", "name": "Website", "url": "https://mycurator.com" },
        { "type": "twitter", "name": "Twitter", "url": "https://x.com/mycurator" },
        {
            "type": "explorer",
            "name": "Explorer",
            "url": "https://etherscan.io/address/0x1234567890abcdef1234567890abcdef12345678"
        }
    ]
}
```

##### Save a logo of the Curator to `logo.png` of 256x256 pixels size

:::

## Add a Token

::::steps

##### Create a new folder in the `/tokens` directory

##### Create a new json file in the folder with the following structure:

```json [info.json]
{
    "name": "My Token",
    "description": "My Token is a token that allows you to earn rewards.",
    "tags": ["token", "staking"],
    "cmcId": "1234567890",
    "links": [{ "type": "website", "name": "Website", "url": "https://mytoken.com" }]
}
```

:::warning
If the CMC ID is missing:

* The token’s price cannot be displayed
* TVL (Total Value Locked) in USD won’t be calculated
* Symbiotic Points cannot be calculated or distributed
* Points will be calculated from the date the CMC ID is added; retrospective recalculation for points accrued before this date will not occur.
  :::

##### Save a logo of the Token to `logo.png` of 256x256 pixels size

::::

## Add a Vault

:::warning
If the Vault's collateral is not yet supported by Symbiotic, a separate **Token PR** must be submitted before the **Vault PR**.
:::

::::steps

##### Create a new folder in the `/vaults` directory

##### Create a new json file in the folder with the following structure:

```json [info.json]
{
    "name": "DeFi Vault",
    "description": "A secure vault for decentralized finance.",
    "tags": ["vault", "DeFi"],
    "curatorName": "My Curator",
    "links": [
        {
            "type": "website",
            "name": "Website",
            "url": "https://example-vault.com/"
        },
        {
            "type": "docs",
            "name": "Vault Documentation",
            "url": "https://example-vault.com/docs"
        }
    ]
}
```

:::warning
If the CMC ID is missing:

* The token’s price cannot be displayed
* TVL (Total Value Locked) in USD won’t be calculated
* Symbiotic Points cannot be calculated or distributed
* Points will be calculated from the date the CMC ID is added; retrospective recalculation for points accrued before this date will not occur.
  :::

##### Save a logo of the Vault to `logo.png` of 256x256 pixels size

::::

# Manage Allocations

As a curator, you perform two actions:

* Set network allocation — determine how much funds to delegate to each network
* Set operator shares within each network — specify how the network's allocation is distributed among operators

## Set Initial Network Delegation

### Using [Safe](https://app.safe.global/)

1. Open "Transaction builder"
2. Get the delegator contract address of your vault (using UI, CLI, or Etherscan)
3. Enter the delegator's address as the contract address
4. Click "Use Implementation ABI"
5. Choose the `setNetworkLimit()` method
6. Enter the desired subnetwork (network address concatenated with the uint96 identifier)
7. Enter the maximum amount of collateral to allocate to the subnetwork
8. Sign and send the transaction

### Verify via Etherscan

1. Open the "Read Contract" tab in the delegator contract you used
2. Open the `networkLimit()` method
3. Enter `SUBNETWORK` (network address concatenated with the uint96 identifier) in the `subnetwork` parameter
4. Click "Query" — it should return the set amount
   ![Set network limit using Etherscan](/guides/img/opt-in/curator-network-limit.png)

## Set Initial Operator Delegation

### Using [Safe](https://app.safe.global/)

1. Open "Transaction builder"
2. Get the delegator contract address of your vault (using UI, CLI, or Etherscan)
3. Enter the delegator's address as the contract address
4. Click "Use Implementation ABI"
5. Choose the `setOperatorNetworkShares()` method
6. Enter the desired subnetwork (network address concatenated with the uint96 identifier)
7. Enter the operator address
8. Enter the amount of shares to allocate to the operator (e.g., 100 shares out of 1000 total shares means 10% of the stake allocated to the subnetwork)
9. Sign and send the transaction

### Verify via Etherscan

1. Open the "Read Contract" tab in the delegator you used
2. Open the `operatorNetworkShares()` method (you may also need `totalOperatorNetworkShares`)
3. Enter `SUBNETWORK` (network address concatenated with the uint96 identifier) in the `subnetwork` parameter and `OPERATOR_ADDRESS` in the `operator` parameter
4. Click "Query" — it should return the set amount

![Set operator network shares using Etherscan](/guides/img/opt-in/curator-operator-network-shares.png)

# Manage & Claim Fees

## Register the curator

The `vault.owner()` sets the curator in `CuratorRegistry`. This links a vault to the curator address that will manage fee settings and claim curator fees.

Find the up-to-date `CuratorRegistry` address on the [Addresses page](/get-started/resources/addresses#rewards).

### Register curator example

Curators are set via `setCurator` on `CuratorRegistry` ([Contract](https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/CuratorRegistry.sol) | [Interface](https://github.com/symbioticfi/rewards-v2/blob/main/src/interfaces/ICuratorRegistry.sol)).

```solidity
curatorRegistry.setCurator(vaultAddress, curatorAddress)
```

Authorization rules:

* First-time curator: the caller must be the `vault.owner()`.
* Updating curator: the caller must be the current curator.

```solidity
// Owner sets first curator
vm.prank(vaultOwner);
curatorRegistry.setCurator(vaultAddress, curatorAddress);

// Current curator changes to new curator
vm.prank(currentCurator);
curatorRegistry.setCurator(vaultAddress, newCuratorAddress);
```

## Fees

The system supports three categories of fees, each with default and network-specific settings:

* Curator fee
* Operator fee
* Protocol fee

Curators configure fee settings in `FeeRegistry` ([Contract](https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/FeeRegistry.sol) | [Interface](https://github.com/symbioticfi/rewards-v2/blob/main/src/interfaces/IFeeRegistry.sol)). These fees are applied when rewards are distributed.

Only the vault’s curator can set fees for that vault:

* `setCuratorFee(vault, fee)` sets the default curator fee.
* `setCuratorNetworkFee(vault, network, enable, fee)` sets a network-specific curator fee.
* `setOperatorsFee(vault, fee)` sets the default operator fee.
* `setOperatorsNetworkFee(vault, network, enable, fee)` sets a network-specific operator fee.

The fees cen be obtained via:

* `getOperatorsFee(vault, network)` - operator fee
* `getCuratorFee(vault, network)` - curator fee
* `protocolFee(rewardsType, network)` - protocol fee

:::info

* 100% fee is 1,000,000 bps
* the maximum allowed fee for curator and operator fees each is 50% (500,000 bps)
* network-specific fees override defaults when enabled
  :::
  :::warning
  Operators cannot set fees directly; curators set operator fees on behalf of the vault.
  :::

## Fee Related Calculations

The protocol fees can be taken either from the distribution amount or on top of. To convert distribution amounts between before/after protocol fee deduction ([Rewards Contract](https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/Rewards.sol) | [Rewards Interface](https://github.com/symbioticfi/rewards-v2/blob/main/src/interfaces/IRewards.sol)):

* **Distribution to Total**:
  `Rewards.distributionToTotalAmount(uint64 rewardsType, address network, uint256 distributionAmount)` converts a distribution amount (after fees) to a total amount.
* **Total to Distribution**:
  `Rewards.totalToDistributionAmount(uint64 rewardsType, address network, uint256 totalDistributionAmount)` converts a total amount (before protocol fees) to a distribution amount.

:::note
For example, in Vault Snapshot Rewards the protocol fees are taken from the distribution amount, so that the curator and operators fees are taken after the deduction.
:::

## Claim process

Curators claim fees from `Rewards.sol` ([Contract](https://github.com/symbioticfi/rewards-v2/blob/main/src/contracts/Rewards.sol) | [Interface](https://github.com/symbioticfi/rewards-v2/blob/main/src/interfaces/IRewards.sol)) using `claimCuratorFees`.

```solidity
function claimCuratorFees(address recipient, address vault, address token) public
```

:::warning
If the curator is changed in the registry, any unclaimed fees are claimable by the new curator.
:::

# Vault Wrapping

Sometimes, due to design choices for security guarantees or interaction flow optimization, you can't implement your ideas in a standard way. In these cases, you can wrap the Symbiotic Vault for deposits, slashing, opt-ins, etc. This page presents example cases:

## Mortgage-backed Security Example

A **mortgage-backed security (MBS)** is a financial instrument created by pooling together many individual home loans (mortgages) and selling them as a single tradable security. Instead of a bank holding a mortgage and collecting monthly payments, the cash flows (interest and principal) from thousands of mortgages are bundled, then redistributed to investors in the MBS.

* **Tranching**: To cater to different investor risk appetites, the pool is divided into **tranches**.
  * Senior tranches: Get paid first, lower risk, lower yield.
  * Junior tranches: Get paid later and absorb defaults first, higher risk, higher yield.
* **Risk distribution**: This structure spreads default risk across different investor groups and creates a market for varying levels of risk exposure.

<figure>
  <img src="/guides/img/vault-wrap/vault-wrap-mbs.png" alt="Mortgage Backed Securities Structuring and Value Chain" />

  <figcaption>Mortgage Backed Securities Structuring and Value Chain</figcaption>
</figure>

### Slashing Tranche-Based Vault Wrapper

In Symbiotic, **slashing vaults** are pools where collateral is staked to secure external networks or services. Just like mortgages carry **default risk**, staking carries **slashing risk** (collateral may be cut if operators misbehave).

Here’s how the analogy works:

* **Mortgages = Operator Collateral Positions**
  Each mortgage in an MBS corresponds to an individual operator’s staked collateral in Symbiotic. Just as homeowners may default, operators may be slashed.
* **MBS Pool = Slashing Vault**
  The pooled mortgages in an MBS map to the **vault of collateral** in Symbiotic. Both aggregate risk into a collective structure.
* **Tranches = Vault Risk Segmentation**
  Symbiotic vaults could be designed with **tranches** similar to MBS:
  * Senior tranche: Investors who want safer exposure get priority in withdrawals and protection against small slashes (absorbed by junior tranches first).
  * Mezzanine tranche: Medium-risk exposure, takes losses only after juniors are hit.
  * Junior tranche: Risk-seeking investors absorb slashing losses first but get higher yield (greater share of staking rewards).
* **Cash Flows = Staking Rewards**
  Just as mortgages generate interest payments, collateral in slashing vaults generates staking rewards or fees. These flows are redistributed to participants, depending on their tranche.
* **Risk Transformation**
  MBS transform mortgage default risk into tiered securities with different profiles. Symbiotic vaults could similarly transform **slashing risk** into structured exposure, letting risk-averse and risk-seeking participants coexist in the same vault.

<figure>
  <img src="/guides/img/vault-wrap/vault-wrap-risk.png" alt="Tranche-Based (or Slashing Insurance) Vault Segmentation + Redistribution" />

  <figcaption>
    Tranche-Based (or Slashing Insurance) Vault Segmentation + Redistribution
  </figcaption>
</figure>

### Implementation

A user (staker) would have 3 choices to deposit a single ERC20 asset (collateral) into a Symbiotic vault. They can either deposit into the junior, mezzanine or senior tranche, according to their risk-profile or portfolio fit. The vault wrapper contract would then deposit the collateral to the Symbiotic vault, and the user would receive (or not, depending on the curator choice) an LST.

From our understanding, there may be 2 possibilities to issue the receipt token:

**Model A — 3 Separate ERC20s (most common in structured products)**

* When a user deposits, they **choose the tranche** (junior, mezzanine, senior).
* The wrapper mints them **only that tranche token (LST)**.
* Example:
  * Alice deposits 100 USDC → gets **100 tJNR**.
  * Bob deposits 100 USDC → gets **100 tSNR**.

**Model B — 1 ERC20 + internal “tranche shares” accounting**

* Users deposit into the wrapper without selecting a tranche.
* The wrapper automatically allocates the deposit across junior, mezz, and senior according to some fixed ratio (e.g., 20/30/50).
* The user receives **one unified wrapper-LST** (e.g., `tWRAP`).

<figure>
  <img src="/guides/img/vault-wrap/vault-wrap-impl.png" alt="Tranche-Based Vault Proposed Implementation" />

  <figcaption>Tranche-Based Vault Proposed Implementation</figcaption>
</figure>

The entire paper, co-authored with ReSquared can be found here: https://github.com/dias-henrique/Slashing-Insurance-Vaults/blob/main/CESIV.pdf

# Helpful Core Contracts' Endpoints

This page lists useful functions for curators across Symbiotic Core contracts.

| Function                                                                                                                                                                                                                                                  | Use-case                                                             |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| [`create(InitParams params) -> address, address, address`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/IVaultConfigurator.sol#L52)                                                                   | Create a new Vault                                                   |
| [`Vault.delegator() → address`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/vault/IVaultStorage.sol#L60)                                                                                             | Get the Vault's delegator                                            |
| [`Vault.slasher() → address`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/vault/IVaultStorage.sol#L72)                                                                                               | Get the Vault's slasher                                              |
| [`BaseDelegator.TYPE() → uint64`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/common/IEntity.sol#L17)                                                                                                | Get the delegator's type (0 - NetworkRestake, 1 - FullRestake, etc.) |
| [`BaseDelegator.stake(bytes32 subnetwork, address operator) → uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IBaseDelegator.sol#L150)                                               | Get the operator-network's stake                                     |
| [`NetworkRestakeDelegator.setNetworkLimit(bytes32 subnetwork, uint256 amount)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/INetworkRestakeDelegator.sol#L136)                             | Set a amount of collateral to allocate to the network                |
| [`NetworkRestakeDelegator.networkLimit(bytes32 subnetwork) -> uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/INetworkRestakeDelegator.sol#L84)                                      | Check the network's allocation                                       |
| [`NetworkRestakeDelegator.setOperatorNetworkShares(bytes32 subnetwork, address operator, uint256 shares) `](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/INetworkRestakeDelegator.sol#L147) | Set the operator's share from the network's allocation               |
| [`NetworkRestakeDelegator.operatorNetworkShares(bytes32 subnetwork, address operator) -> uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/INetworkRestakeDelegator.sol#L128)          | Check the operator-network's shares                                  |
| [`FullRestakeDelegator.setNetworkLimit(bytes32 subnetwork, uint256 amount)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IFullRestakeDelegator.sol#L112)                                   | Set a amount of collateral to allocate to the network                |
| [`FullRestakeDelegator.networkLimit(bytes32 subnetwork) -> uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IFullRestakeDelegator.sol#L81)                                            | Check the network's allocation                                       |
| [`NetworkRestakeDelegator.setOperatorNetworkLimit(bytes32 subnetwork, address operator, uint256 amount)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IFullRestakeDelegator.sol#L122)      | Set the operator's limit over the network's allocation               |
| [`NetworkRestakeDelegator.operatorNetworkLimit(bytes32 subnetwork, address operator) -> uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IFullRestakeDelegator.sol#L104)              | Check the operator-network's limit                                   |
| [`OperatorSpecificDelegator.setNetworkLimit(bytes32 subnetwork, uint256 amount)`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IOperatorSpecificDelegator.sol#L85)                          | Set a amount of collateral to allocate to the network                |
| [`OperatorSpecificDelegator.networkLimit(bytes32 subnetwork) -> uint256`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IOperatorSpecificDelegator.sol#L77)                                  | Check the network's allocation                                       |
| [`OperatorSpecificDelegator.operator() -> address`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IOperatorSpecificDelegator.sol#L60)                                                        | Check the operator who receive all the allocations                   |
| [`OperatorSpecificDelegator.network() -> address`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IOperatorNetworkSpecificDelegator.sol#L44)                                                  | Check the network who receive all the allocations                    |
| [`OperatorSpecificDelegator.operator() -> address`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/delegator/IOperatorNetworkSpecificDelegator.sol#L50)                                                 | Check the operator who receive all the allocations                   |
| [`BaseSlasher.TYPE() → uint64`](https://github.com/symbioticfi/core/blob/7cb06639c5cd656d1d212dafa2c270b5fde39306/src/interfaces/common/IEntity.sol#L17)                                                                                                  | Get the slasher's type (0 - Slasher, 1 - VetoSlasher)                |

# CLI

Symbiotic CLI (`symb`) is a command-line tool for reading on-chain data and interacting with Symbiotic Core smart contracts.

It covers common workflows for:

* Networks (registration, limits, resolvers)
* Operators (registration, opt-ins, signature generation)
* Vault curators (delegation limits and shares)
* Stakers (withdraw and claim)
* Rewards (fee settings and claims)

## Install

### Prerequisites

* Node.js **20+** (Node 20/22 LTS recommended)

### Quick install (macOS / Linux)

```bash
curl -fsSL https://raw.githubusercontent.com/symbioticfi/cli/main/install.sh | bash
symb --help
```

By default, this installs into `~/.symb/cli`, puts `symb` into `~/.symb/bin`, and adds `~/.symb/bin` to your `PATH` (shell profile).

If `symb` is not found, open a new terminal and try again.

### Update

Rerun the installer command:

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

## Quickstart

```bash
# Help
symb --help
symb op --help

# List operators and networks
symb op list
symb net list

# Include more fields when available
symb net list --full
symb vault list --full

# JSON output for scripts
symb op list --json
```

## Configuration

### Chain selection

Use `--chain <chain>` (default: `mainnet`).

* `mainnet` (chainId `1`)
* `hoodi` (chainId `560048`)
* `sepolia` (chainId `11155111`)

You can also pass the numeric chainId.

### RPC selection

* `--rpc <url>`: RPC URL override for the current command.
* `SYMB_RPC_URL`: default RPC URL.

If neither is provided, `symb` uses a built-in fallback list of public RPC endpoints for the selected chain.

:::note
For reliability (latency, rate limits), prefer your own RPC for production or heavy usage.
:::

### Environment variables

| Variable           | Description                                                |
| ------------------ | ---------------------------------------------------------- |
| `SYMB_RPC_URL`     | Default RPC URL (can be overridden by `--rpc`).            |
| `SYMB_PRIVATE_KEY` | Private key used for signing (discouraged; prefer Ledger). |

## Signing, simulation, and safety

Read commands don’t require a signer. Write commands and signature commands require one.

### Signer options

* Ledger (recommended): `--ledger` (optional `--ledger-address`)
* Private key: `SYMB_PRIVATE_KEY` or `--private-key <hex>` (discouraged)

`--ledger-address` let you select which Ledger account to use.

:::warning
Avoid passing private keys via command-line flags: they may end up in shell history and process lists.
:::

### Write-only flags

| Flag        | Description                              |
| ----------- | ---------------------------------------- |
| `--yes`     | Bypass confirmation prompts.             |
| `--dry-run` | Simulate only (do not send transaction). |

In this doc:

* `[write options]` = signer options + `--yes` / `--dry-run`
* `[sign options]` = signer options only

## Global flags

All commands support:

| Flag                | Description                                |
| ------------------- | ------------------------------------------ |
| `--chain <chain>`   | Chain key or chainId (default: `mainnet`). |
| `--rpc <url>`       | RPC URL override.                          |
| `--timeout-ms <n>`  | RPC request timeout (ms).                  |
| `--retries <n>`     | RPC retry count.                           |
| `--batch-size <n>`  | Multicall batch size.                      |
| `--concurrency <n>` | Multicall concurrency.                     |
| `--json`            | Machine-readable JSON output.              |
| `--quiet`           | Minimal output.                            |

## Commands

Commands are grouped by area. For the complete list, run `symb --help` and `symb <group> --help`.

### `net`

| Command                                                                              | Description                                                 |
| ------------------------------------------------------------------------------------ | ----------------------------------------------------------- |
| `symb net is <address>`                                                              | Check if an address is a network.                           |
| `symb net middleware <network_address>`                                              | Get the network middleware address.                         |
| `symb net list [--full]`                                                             | List all networks.                                          |
| `symb net ops <network_address>`                                                     | List all operators opted into the network.                  |
| `symb net stakes <network_address>`                                                  | Show stakes for all operators in the network.               |
| `symb net max-network-limit <vault_address> <network_address>`                       | Get the maximum network limit at the vault’s delegator.     |
| `symb net resolver <vault_address> <network_address>`                                | Get the current resolver for a vault’s subnetwork.          |
| `symb net pending-resolver <vault_address> <network_address>`                        | Get the pending resolver for a vault’s subnetwork.          |
| `symb net register [write options]`                                                  | Register the signer as a network.                           |
| `symb net set-max-limit [write options] <vault_address> <max_limit> [subnetwork_id]` | Set the maximum network limit at the vault’s delegator.     |
| `symb net set-resolver [write options] <vault_address> <resolver> [subnetwork_id]`   | Set the resolver for a vault’s subnetwork at `VetoSlasher`. |

### `op`

| Command                                                               | Description                                                                                  |
| --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| `symb op is <address>`                                                | Check if an address is an operator.                                                          |
| `symb op list`                                                        | List all operators.                                                                          |
| `symb op nets <operator_address>`                                     | List all networks the operator is opted into.                                                |
| `symb op stakes <operator_address>`                                   | Show operator stakes across all networks.                                                    |
| `symb op stake <operator_address> <vault_address> <network_address>`  | Get operator stake in a vault for a network (includes shares for `NetworkRestakeDelegator`). |
| `symb op opted-in-vault <operator_address> <vault_address>`           | Check if the operator is opted into a vault.                                                 |
| `symb op opted-in-net <operator_address> <network_address>`           | Check if the operator is opted into a network.                                               |
| `symb op register [write options]`                                    | Register the signer as an operator.                                                          |
| `symb op opt-in-vault [write options] <vault_address>`                | Opt into a vault.                                                                            |
| `symb op opt-out-vault [write options] <vault_address>`               | Opt out from a vault.                                                                        |
| `symb op opt-in-net [write options] <network_address>`                | Opt into a network.                                                                          |
| `symb op opt-out-net [write options] <network_address>`               | Opt out from a network.                                                                      |
| `symb op opt-in-vault-sig [sign options] <vault_address> [duration]`  | Get a signature for opting into a vault.                                                     |
| `symb op opt-out-vault-sig [sign options] <vault_address> [duration]` | Get a signature for opting out from a vault.                                                 |
| `symb op opt-in-net-sig [sign options] <network_address> [duration]`  | Get a signature for opting into a network.                                                   |
| `symb op opt-out-net-sig [sign options] <network_address> [duration]` | Get a signature for opting out from a network.                                               |

### `vault`

| Command                                                                                                                                | Description                                                     |
| -------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| `symb vault is <address>`                                                                                                              | Check if an address is a vault.                                 |
| `symb vault list [--full]`                                                                                                             | List all vaults.                                                |
| `symb vault ops <vault_address>`                                                                                                       | List all operators opted into the vault.                        |
| `symb vault nets <vault_address>`                                                                                                      | List all networks associated with the vault.                    |
| `symb vault netsops <vault_address>`                                                                                                   | List all operators and their associated networks for the vault. |
| `symb vault network-limit <vault_address> <network_address>`                                                                           | Get the network limit at the vault’s delegator.                 |
| `symb vault operator-network-limit <vault_address> <network_address> <operator_address>`                                               | Get the operator-network limit at the vault’s delegator.        |
| `symb vault operator-network-shares <vault_address> <network_address> <operator_address>`                                              | Get operator-network shares at the vault’s delegator.           |
| `symb vault total-operator-network-shares <vault_address> <network_address>`                                                           | Get total operator-network shares at the vault’s delegator.     |
| `symb vault set-network-limit [write options] <vault_address> <network_address> <limit> [subnetwork_id]`                               | Set the network limit at the vault’s delegator.                 |
| `symb vault set-operator-network-limit [write options] <vault_address> <network_address> <operator_address> <limit> [subnetwork_id]`   | Set the operator-network limit at the vault’s delegator.        |
| `symb vault set-operator-network-shares [write options] <vault_address> <network_address> <operator_address> <shares> [subnetwork_id]` | Set operator-network shares at the vault’s delegator.           |

### `staker`

| Command                                                                   | Description                                                 |
| ------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `symb staker active-balance <vault_address> <address>`                    | Get the active balance of an account in a vault.            |
| `symb staker withdrawals <vault_address> <epoch> <address>`               | Get withdrawals for an account in a vault at a given epoch. |
| `symb staker withdrawals-claimed <vault_address> <epoch> <address>`       | Check whether an epoch withdrawal has been claimed.         |
| `symb staker withdraw [write options] <vault_address> <amount> [claimer]` | Withdraw from a vault.                                      |
| `symb staker claim [write options] <vault_address> <epoch> [recipient]`   | Claim a withdrawal for an epoch in a vault.                 |

### `rewards`

| Command                                                                                                                                                 | Description                                                 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `symb rewards curator <vault_address>`                                                                                                                  | Get the curator address for a vault.                        |
| `symb rewards operators-fee <vault_address> <network_address>`                                                                                          | Get effective operators fee (ppm) for a vault + network.    |
| `symb rewards curator-fee <vault_address> <network_address>`                                                                                            | Get effective curator fee (ppm) for a vault + network.      |
| `symb rewards protocol-fee <rewards_type> <network_address>`                                                                                            | Get protocol fee (ppm) for a rewards type and network.      |
| `symb rewards curator-fees <vault_address> <token>`                                                                                                     | Get claimable curator fees (amount) for a vault + token.    |
| `symb rewards vault-snapshot-rewards <staker_address> <vault_address> <network_address> <token> [first_reward_to_claim] [max_rewards]`                  | Get claimable vault snapshot rewards (amount) for a staker. |
| `symb rewards operator-fees <operator_address> <vault_address> <network_address> <token> [first_reward_to_claim] [max_rewards]`                         | Get claimable operator fees (amount) for an operator.       |
| `symb rewards set-curator [write options] <vault_address> <curator>`                                                                                    | Set the curator for a vault.                                |
| `symb rewards set-operators-fee [write options] <vault_address> <fee>`                                                                                  | Set default operators fee (ppm) for a vault.                |
| `symb rewards set-operators-network-fee [write options] <vault_address> <network_address> <fee>`                                                        | Set network-specific operators fee (ppm) for a vault.       |
| `symb rewards set-curator-fee [write options] <vault_address> <fee>`                                                                                    | Set default curator fee (ppm) for a vault.                  |
| `symb rewards set-curator-network-fee [write options] <vault_address> <network_address> <fee>`                                                          | Set network-specific curator fee (ppm) for a vault.         |
| `symb rewards claim-vault-snapshot-rewards [write options] <vault_address> <network_address> <token> [recipient] [first_reward_to_claim] [max_rewards]` | Claim vault snapshot rewards for the signer.                |
| `symb rewards claim-operator-fees [write options] <vault_address> <network_address> <token> [recipient] [first_reward_to_claim] [max_rewards]`          | Claim vault snapshot operator fees for the signer.          |
| `symb rewards claim-curator-fees [write options] <vault_address> <token> [recipient]`                                                                   | Claim vault snapshot curator fees for the signer (curator). |

## Examples

### Register as an operator using Ledger

```bash
symb op register --ledger
```

### Opt in to a vault and network

```bash
symb op opt-in-vault 0xVault... --ledger
symb op opt-in-net 0xNetwork... --ledger
```

### Set a network limit (curator)

```bash
# 1 ETH (wei) limit example
symb vault set-network-limit 0xVault... 0xNetwork... 1000000000000000000 --ledger
```

## Troubleshooting

* Use `--rpc`/`SYMB_RPC_URL` if public RPCs rate-limit you.
* For Ledger signing, make sure the Ethereum app is open and try a different cable/USB port if transport fails.

# Events

This page provides a complete overview of event handling and math across the Symbiotic system.

## Vault Stake

Consider the following events monitoring only a single vault.

### Deposit

* `event Deposit(address indexed depositor, address indexed onBehalfOf, uint256 amount, uint256 shares)`
  * `depositor` - *irrelevant in the current context*
  * `onBehalfOf` - an address of the user that receives the deposited funds
  * `amount` - a number of `collateral` tokens deposited
  * `shares` - a number of shares `onBehalfOf` user received

#### Bucket accounting (why `amount` and `shares` coexist)

1. Alice deposits 12 → `userShares(alice)=12`, `totalAssets=12`, `totalShares=12` → balance = 12.
2. Bob deposits 8 → `userShares(bob)=8`, `totalAssets=20`, `totalShares=20` → balance = 8.
3. Slash 10 → `totalAssets=10` → balances: Alice 6, Bob 4.
4. Jack deposits 10 → minted shares = `depositAmount * totalShares / totalAssets` = `10 * 20 / 10 = 20` → `userShares(jack)=20`, `totalAssets=20`, `totalShares=40` → balances: Alice 6, Bob 4, Jack 10.

#### Off-chain updates per `Deposit`

* `activeStakeBucket.userShares(onBehalfOf) += shares`
* `activeStakeBucket.totalAssets += amount`
* `activeStakeBucket.totalShares += shares`

### Withdraw

* `event Withdraw(address indexed withdrawer, address indexed claimer, uint256 amount, uint256 burnedShares, uint256 mintedShares)`
  * `withdrawer` - an address that loses the withdrawn funds
  * `claimer` - an address that receives withdrawn funds to be claimed
  * `amount` - a number of `collateral` tokens withdrawn
  * `burnedShares` - a number of shares `withdrawer` lost at the `activeStakeBucket`
  * `mintedShares` - a number of shares `claimer` received

Symbiotic Vault works using the epochs mechanic. What does it mean in the context of withdrawals:

Let’s assume the epoch duration of the Vault is 7 days, and the 0th epoch started at timestamp = 0. Right now, it is a timestamp = 0.

1. Alice deposited 10 (`activeStakeBucket`'s state has changed following the logic mentioned above)

Timestamp = 3 days (the 0th epoch)

1. Alice withdraws 3, which means:
   * Decrease `activeStakeBucket.userShares(alice)` by 3 (withdrawal logic from the bucket is similar to a deposit).
   * Decrease `activeStakeBucket.totalAssets` by 3 (withdrawal logic from the bucket is similar to a deposit).
   * Decrease `activeStakeBucket.totalShares` by 3 (withdrawal logic from the bucket is similar to a deposit).
   * Deposit 3 into `withdrawalsBucket_1` (`1` means it is a bucket related to the 1st epoch; “the 1st epoch” because it is the next one)

Timestamp = 10 days (the 1st epoch)

1. Alice withdraws 4, which means:
   * Withdraw 4 from `activeStakeBucket`
   * Deposit 4 to `withdrawalsBucket_2`

#### Off-chain updates per `Withdraw`

* `activeStakeBucket.userShares(withdrawer) -= burnedShares`
* `activeStakeBucket.totalAssets -= amount`
* `activeStakeBucket.totalShares -= burnedShares`
* `withdrawalsBucket_i.userShares(claimer) += mintedShares`
* `withdrawalsBucket_i.totalAssets += amount`
* `withdrawalsBucket_i.totalShares += mintedShares`

### Slash

* `event OnSlash(uint256 amount, uint48 captureTimestamp, uint256 slashedAmount)`
  * `amount` - a number of `collateral` tokens that were requested to be slashed
  * `captureTimestamp` - a capture timestamp the slash was requested for
  * `slashedAmount` - a number of `collateral` tokens that were actually slashed

Basically, the logic behind the slashing is the following:

* A network receives the stake amount only depending on the active stake at the given time point.
* Also, we know that the withdrawals from the current epoch are marked as `withdrawalsBucket_i`, where `i`is the next epoch.
* Therefore, omitting some details, the slashing can be divided into 2 cases:
  1. If `eventTimestamp` and `captureTimestamp` are in different epochs (it can be simply checked via `Vault.epochAt(timestamp)` function).
     * Let’s say `eventEpoch` = `Vault.epochAt(eventTimestamp)`
     * Then the whole slashable amount for this slashing `slashableAmount` = `activeStakeBucket.totalAssets` + `withdrawalsBucket_{eventEpoch}.totalAssets` + `withdrawalsBucket_{eventEpoch + 1}.totalAssets`
     * The `slashedAmount` is proportionally decreased from each bucket, e.g., `activeStakeSlashed` = `slashedAmount` \* `activeStakeBucket.totalAssets` / `slashableAmount`
  2. If `eventTimestamp` and `captureTimestamp` are in the same epoch (it can be simply checked via `Vault.epochAt(timestamp)` function).
     * Let’s say `eventEpoch` = `Vault.epochAt(eventTimestamp)`
     * Then the whole slashable amount for this slashing `slashableAmount` = `activeStakeBucket.totalAssets` + `withdrawalsBucket_{eventEpoch + 1}.totalAssets`
     * The `slashedAmount` is proportionally decreased from each bucket, e.g., `activeStakeSlashed` = `slashedAmount` \* `activeStakeBucket.totalAssets` / `slashableAmount`

<figure>
  <img src="/img/slashing-logic.png" alt="Slashing Logic" />

  <figcaption>
    Slashing Logic - [click to get more
    details](https://github.com/symbioticfi/core/blob/629b9faac2377a9eb9cfdc6362b30d1dc1ef48f2/src/contracts/vault/Vault.sol#L222-L258)
  </figcaption>
</figure>

#### Off-chain updates per `OnSlash`

Let `eventEpoch = Vault.epochAt(eventTimestamp)`.

* If `eventTimestamp` and `captureTimestamp` are in different epochs:
  * `slashableAmount = activeStakeBucket.totalAssets + withdrawalsBucket_{eventEpoch}.totalAssets + withdrawalsBucket_{eventEpoch + 1}.totalAssets`
  * `activeSlashed = slashedAmount * activeStakeBucket.totalAssets / slashableAmount`
  * `nextWithdrawalsSlashed = slashedAmount * withdrawalsBucket_{eventEpoch + 1}.totalAssets / slashableAmount`
  * `withdrawalsSlashed = slashedAmount - activeStakeSlash - withdrawalsNext`
  * If `withdrawalsBucket_{eventEpoch}.totalAssets < withdrawalsSlashed`:
    * `nextWithdrawalsSlashed += withdrawalsSlashed - withdrawalsBucket_{eventEpoch}.totalAssets`
    * `withdrawalsSlashed = withdrawalsBucket_{eventEpoch}.totalAssets`
  * `activeStakeBucket.totalAssets -= activeSlashed`
  * `withdrawalsBucket_{eventEpoch + 1}.totalAssets -= nextWithdrawalsSlashed`
  * `withdrawalsBucket_{eventEpoch}.totalAssets -= withdrawalsSlashed`

* If `eventTimestamp` and `captureTimestamp` are in the same epoch:
  * `slashableAmount = activeStakeBucket.totalAssets + withdrawalsBucket_{eventEpoch + 1}.totalAssets`
  * `activeSlashed = slashedAmount * activeStakeBucket.totalAssets / slashableAmount`
  * `nextWithdrawalsSlashed = slashedAmount - activeSlashed`
  * `activeStakeBucket.totalAssets -= activeSlashed`
  * `withdrawalsBucket_{eventEpoch + 1}.totalAssets -= nextWithdrawalsSlashed`

### Transfer

* `event Transfer(address indexed from, address indexed to, uint256 value)`
  * `from` - an address of the sender
  * `to` - an address of the recipient
  * `value` - a number of tokens transferred
    From the start, we provide two versions of the Vault:
  1. A common Vault that contains only events described above
  2. A tokenized Vault, which represents active stake shares as ERC20 tokens and, therefore, adds a `Transfer` event
     There are 3 possible cases in the sense of the `Transfer` event:
  3. `from` is zero, and `to` is not zero - it means minting the token
  4. `from` is not zero, and `to` is zero - it means burning the token
  5. `from` is not zero, and `to` is not zero - it means a transfer of the token
     In our case, the token's minting and burning are already calculated via `Deposit` and `Withdraw` events. Therefore, only transfers need off-chain handling:
  * If `from` ≠ `0x0000000000000000000000000000000000000000` and `to` ≠ `0x0000000000000000000000000000000000000000`
    * `activeStakeBucket.userShares(from) -= value`
    * `activeStakeBucket.userShares(to) += value`

### Formulas

Now, given we have all the data across all the stakers in the vault, we can get some Vault stake-related data:

<div className="formula-scroll">
  <FormulaGroup>
    {String.raw`
      activeStake(\text{vault}) = \text{vault}.activeStakeBucket.totalAssets

      withdrawals(\text{vault}) = \text{vault}.withdrawalsBucket\_{currentEpoch}.totalAssets

      nextWithdrawals(\text{vault}) = \text{vault}.withdrawalsBucket\_{currentEpoch + 1}.totalAssets

      TVL(\text{vault}) = activeStake(\text{vault}) + withdrawals(\text{vault}) + nextWithdrawals(\text{vault})

      activeSharesOf(\text{vault}, \text{user}) = \text{vault}.activeStakeBucket.userShares(\text{user})

      activeShares(\text{vault}) = \text{vault}.activeStakeBucket.totalShares

      activeStakeOf(\text{vault}, \text{user}) = \frac{activeSharesOf(\text{vault},\text{user}) \times activeStake(\text{vault})}{activeShares(vault)}

      withdrawalsOf(\text{vault}, \text{user}) = \frac{\text{vault}.withdrawalsBucket*{currentEpoch}.userShares(\text{user}) \times withdrawals(\text{vault})}{\text{vault}.withdrawalsBucket*{currentEpoch}.totalShares}

      nextWithdrawalsOf(\text{vault}, \text{user}) = \frac{\text{vault}.withdrawalsBucket*{currentEpoch + 1}.userShares(\text{user}) \times withdrawals(\text{vault})}{\text{vault}.withdrawalsBucket*{currentEpoch + 1}.totalShares}

      slashableBalanceOf(\text{vault}, \text{user}) = activeStakeOf(\text{vault}, \text{user}) + withdrawalsOf(\text{vault}, \text{user}) + nextWithdrawalsOf(\text{vault}, \text{user})
      `}
  </FormulaGroup>
</div>

## Registries

### OperatorRegistry

Monitor events using OperatorRegistry address

* `event AddEntity(address indexed entity)`
  * `entity` - an address of the registered operator

Add `entity` to the `allOperators` list

### NetworkRegistry

Monitor events using NetworkRegistry address

* `event AddEntity(address indexed entity)`
  * `entity` - an address of the registered network

Add `entity` to the `allNetworks` list

### VaultFactory

Monitor events using VaultFactory address

* `event AddEntity(address indexed entity)`
  * `entity` - an address of the created Vault

Add `entity` to the `allVaults` list

## Delegations

### Operator-Network Opt-in

Monitor events using NetworkOptinService address

* `event OptIn(address indexed who, address indexed where)`
  * `who` - an address of the operator who opted into
  * `where` - an address of the network where the operator opted into
* `event OptOut(address indexed who, address indexed where)`
  * `who` - an address of the operator who opted out
  * `where` - an address of the network where the operator opted out from

On each of these events, it is needed to save if the operator is opted into the network like:

* If `OptIn`
  * `operatorNetworkOptIn(operator, network) = true`
* if `OptOut`
  * `operatorNetworkOptIn(operator, network) = false`

### Operator-Vault Opt-in

Monitor events using VaultOptinService address

* `event OptIn(address indexed who, address indexed where)`
  * `who` - an address of the operator who opted into
  * `where` - an address of the vault where the operator opted into
* `event OptOut(address indexed who, address indexed where)`
  * `who` - an address of the operator who opted out
  * `where` - an address of the vault where the operator opted out from

On each of these events, it is needed to save if the operator is opted into the vault like:

* If `OptIn`
  * `operatorVaultOptIn(operator, network) = true`
* if `OptOut`
  * `operatorVaultOptIn(operator, network) = false`

### MaxNetworkLimit

Monitor events using Vault’s Delegator address

* `event SetMaxNetworkLimit(bytes32 indexed subnetwork, uint256 amount)`
  * `subnetwork` - a full identifier of the subnetwork (the first 40 bytes is an address of the `network`, the last 24 bytes are the `identifier`)
  * `amount` - a maximum network limit

Limits’ setting may perform differently depending on the Delegator’s type:

* if `NetworkRestakeDelegator` (type 0)
  * `maxNetworkLimit(network, identifier) = amount`
  * `networkLimit(network, identifier) = min(networkLimit(network, identifier), amount)`
* if `FullRestakeDelegator` (type 1)
  * `maxNetworkLimit(network, identifier) = amount`
  * `networkLimit(network, identifier) = min(networkLimit(network, identifier), amount)`
* if `FullRestakeDelegator` (type 2)
  * `maxNetworkLimit(network, identifier) = amount`
  * `networkLimit(network, identifier) = min(networkLimit(network, identifier), amount)`

### NetworkLimit (if Delegator’s type in \[0, 1, 2])

Monitor events using Vault’s Delegator address

* `event SetNetworkLimit(bytes32 indexed subnetwork, uint256 amount)`
  * `subnetwork` - a full identifier of the subnetwork (the first 40 bytes is an address of the `network`, the last 24 bytes are the `identifier`)
  * `amount` - a network limit

Limits’ setting may perform differently depending on the Delegator’s type:

* if `NetworkRestakeDelegator` (type 0)
  * `networkLimit(network, identifier) = amount`
* if `FullRestakeDelegator` (type 1)
  * `networkLimit(network, identifier) = amount`
* if `FullRestakeDelegator` (type 2)
  * `networkLimit(network, identifier) = amount`

### OperatorNetworkShares (if Delegator’s type in \[0])

Monitor events using Vault’s Delegator address

* `event SetOperatorNetworkShares(bytes32 indexed subnetwork, address indexed operator, uint256 shares)`
  * `subnetwork` - a full identifier of the subnetwork (the first 40 bytes is an address of the `network`, the last 24 bytes are the `identifier`)
  * `operator` - an address of the operator to set shares for
  * `shares` - a number of shares to set

Limits’ setting may perform differently depending on the Delegator’s type:

* if `NetworkRestakeDelegator` (type 0)
  * `totalOperatorNetworkShares(network, identifier) = totalOperatorNetworkShares(network, identifier) - operatorNetworkShares(network, identifier, operator) + shares`
  * `operatorNetworkShares(network, identifier, operator) = shares`

### OperatorNetworkLimit (if Delegator’s type in \[1])

Monitor events using Vault’s Delegator address

* `event SetOperatorNetworkLimit(bytes32 indexed subnetwork, address indexed operator, uint256 amount)`
  * `subnetwork` - a full identifier of the subnetwork (the first 40 bytes is an address of the `network`, the last 24 bytes are the `identifier`)
  * `operator` - an address of the operator to set limit for
  * `amount` - a limit to set

Limits’ setting may perform differently depending on the Delegator’s type:

* if `FullRestakeDelegator` (type 1)
  * `operatorNetworkLimit(network, identifier, operator) = amount`

### Formulas

#### Useful lists for UI

<div className="formula-scroll">
  <FormulaGroup>
    {String.raw`
      unconfirmedVaultSubnetworks(\text{vault}, \text{network}) = \{\text{identifier} \;|\; maxNetworkLimit(\text{network}, \text{identifier}) \neq 0,   \text{where identifier is obtained from SetMaxNetworkLimit}\}

      confirmedVaultSubnetworks(\text{vault}, \text{network}) =\{\text{identifier} ∈ unconfirmedVaultSubnetworks(\text{vault}) \;|\; networkLimit(\text{network}, \text{identifier}) \neq 0, \text{where identifier is obtained from SetMaxNetworkLimit}\}

      unconfirmedVaultNetworks(\text{vault}) = \{\text{network} ∈ allNetworks \;|\; maxNetworkLimit(\text{network}, \text{identifier}) \neq 0 \; \text{for at least one identifier that obtained from SetMaxNetworkLimit}\}

      confirmedVaultNetworks(\text{vault}) = \{\text{network} ∈ unconfirmedVaultNetworks(\text{vault}) \;|\; networkLimit(\text{network}, \text{identifier}) \neq 0 \; \text{for at least one identifier that can be obtained via SetMaxNetworkLimit}\}

      unconfirmedVaultOperators(\text{vault}) = \{\text{operator} ∈ allOperators \;|\; operatorVaultOptIn(\text{operator}, \text{vault}) == true\}

      confirmedVaultOperators(\text{vault}) = \{\text{operator} ∈ unconfirmedVaultOperators(\text{vault}) \;|\; \begin{cases}
      operatorNetworkShares(\text{network}, \text{identifier}, \text{operator}) \neq 0 \; \text{for at least one (network, identifier) pair}, & delegatorType = 0 \\
      operatorNetworkLimit(\text{network}, \text{identifier}, \text{operator}) \neq 0 \; \text{for at least one (network, identifier) pair}, & delegatorType = 1 \\
      operator == Delegator.operator(), & delegatorType = 2
      \end{cases}\}
      `}
  </FormulaGroup>
</div>

#### List of operators for validator set

<div className="formula-scroll">
  <FormulaGroup>
    {String.raw`
      subnetworkVaultOperators(\text{vault}, \text{network}, \text{identifier}) = \{\text{operator}  ∈ allOperators \;|\; operatorVaultOptIn(\text{operator}, \text{vault}) == true \land operatorNetworkOptIn(\text{operator}, \text{network}) == true \land \begin{cases}
      networkLimit(\text{vault}, \text{network}, \text{identifier}) \neq 0 \land operatorNetworkShares(\text{vault}, \text{network}, \text{identifier}, \text{operator}) \neq 0, & delegatorType = 0 \\
      networkLimit(\text{vault}, \text{network}, \text{identifier}) \neq 0 \land operatorNetworkLimit(\text{vault}, \text{network}, \text{identifier}, \text{operator}) \neq 0, & delegatorType = 1 \\
      networkLimit(\text{vault}, \text{network}, \text{identifier}) \neq 0, & delegatorType = 2
      \end{cases}\}
      `}
  </FormulaGroup>
</div>

#### Network-related stake data

# Hints

Symbiotic core contracts simplify integration for networks and products with different stake utilization goals. One key simplification is flexibility to operate in a time flow independent of Symbiotic contract mechanics. This is achieved by enabling retrieval of any stake calculation data at any point.

From a technical perspective, this is implemented using a mechanism called "Checkpoints". Checkpoints are implemented as an ordered-by-timestamp array of values, representing anything from operator opt-in statuses to vault active stakes.

This allows efficient gathering of historical data by performing a binary search over timestamps and returning the last value before the needed time point. However, with 1000 deposits and withdrawals, the algorithm may take up to 10 operations to retrieve the active stake at a given timestamp. This results in gradually increasing gas costs for operations requiring historical data retrievals (e.g., slashing).

![default-checkpoints](/img/default-checkpoints.png)

Fortunately, there's a solution: "hints". These are values calculated off-chain that provide a pointer to the exact checkpoint you need. The result is verified by comparing the initial needed time point, the one determined by the provided value, and the next one. This makes historical retrieval cheap and produces constant gas costs.

![checkpoints-with-hints](/img/checkpoints-with-hints.png)

## How to Construct Hints

:::info
The Hints SDK is under development. Meanwhile, you can check the [deployed hints provision contracts on testnets](/get-started/resources/addresses#hints), which simplifies obtaining them.
:::

# AI Resources

## Assistant

<AskChatGPTButton />

## Materials

### Documentation

| Description                  | Actions                                                                                              |
| ---------------------------- | ---------------------------------------------------------------------------------------------------- |
| Navigation index             | <ActionButtons path="/llms.txt" label="Navigation index" />                                          |
| Full documentation           | <ActionButtons path="/llms-full.txt" label="Full documentation" />                                   |
| Full documentation with Code | <ActionButtons path="/ai/llms-full-full.zip" label="Full documentation with Code" copyMode="link" /> |
| Network Integrate Context    | <ActionButtons path="/ai/network-integrate.txt" label="Network Integrate Context" />                 |
| Curator Integrate Context    | <ActionButtons path="/ai/curator-integrate.txt" label="Curator Integrate Context" />                 |
| Operator Integrate Context   | <ActionButtons path="/ai/operator-integrate.txt" label="Operator Integrate Context" />               |

### Contracts

| Description | Actions                                                              | DeepWiki                                                                                            |
| ----------- | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| Core        | <ActionButtons path="/ai/03_core-contracts.md" label="Core" />       | <OpenActionButton path="https://deepwiki.com/symbioticfi/core" label="Core DeepWiki" />             |
| Relay       | <ActionButtons path="/ai/04_relay-contracts.md" label="Relay" />     | <OpenActionButton path="https://deepwiki.com/symbioticfi/relay-contracts" label="Relay DeepWiki" /> |
| Network     | <ActionButtons path="/ai/05_network-contracts.md" label="Network" /> | <OpenActionButton path="https://deepwiki.com/symbioticfi/network" label="Network DeepWiki" />       |
| Rewards     | <ActionButtons path="/ai/06_rewards-contracts.md" label="Rewards" /> | <OpenActionButton path="https://deepwiki.com/symbioticfi/rewards" label="Rewards DeepWiki" />       |
| Burners     | <ActionButtons path="/ai/07_burners-contracts.md" label="Burners" /> | <OpenActionButton path="https://deepwiki.com/symbioticfi/burners" label="Burners DeepWiki" />       |
| Hooks       | <ActionButtons path="/ai/08_hooks-contracts.md" label="Hooks" />     | <OpenActionButton path="https://deepwiki.com/symbioticfi/hooks" label="Hooks DeepWiki" />           |

### Relay

| Description             | Actions                                                                            | DeepWiki                                                                                                 |
| ----------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Relay (+ Go Client)     | <ActionButtons path="/ai/09_relay-client-go.md" label="Relay (+ Go Client)" />     | <OpenActionButton path="https://deepwiki.com/symbioticfi/relay" label="Relay DeepWiki" />                |
| Relay TypeScript Client | <ActionButtons path="/ai/10_relay-client-ts.md" label="Relay TypeScript Client" /> | <OpenActionButton path="https://deepwiki.com/symbioticfi/relay-client-ts" label="Relay TS DeepWiki" />   |
| Relay Rust Client       | <ActionButtons path="/ai/11_relay-client-rs.md" label="Relay Rust Client" />       | <OpenActionButton path="https://deepwiki.com/symbioticfi/relay-client-rs" label="Relay Rust DeepWiki" /> |

### Examples

| Description             | Actions                                                                                            | DeepWiki                                                                                                            |
| ----------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Symbiotic Super Sum     | <ActionButtons path="/ai/12_symbiotic-super-sum-example.md" label="Symbiotic Super Sum" />         | <OpenActionButton path="https://deepwiki.com/symbioticfi/symbiotic-super-sum" label="Super Sum DeepWiki" />         |
| Symbiotic Flight Delays | <ActionButtons path="/ai/13_symbiotic-flight-delays-example.md" label="Symbiotic Flight Delays" /> | <OpenActionButton path="https://deepwiki.com/symbioticfi/symbiotic-flight-delays" label="Flight Delays DeepWiki" /> |

### CLI

| Description | Actions                                                   | DeepWiki                                                                              |
| ----------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| Python CLI  | <ActionButtons path="/ai/14_cli-python.md" label="CLI" /> | <OpenActionButton path="https://deepwiki.com/symbioticfi/cli" label="CLI DeepWiki" /> |

# Get Started

Build applications on top of Symbiotic and access protocol data. Use these resources to integrate Symbiotic into your project.

# Relay

Symbiotic Relay is the verification layer for stake-backed attestations. It connects validator sets, voting power, secure attestations, and settlement so networks can coordinate off-chain work and verify outcomes on-chain.

## Core Topics

* [Voting Power](/learn/relay/voting-power)
* [Valset (Validator Set)](/learn/relay/valset)
* [Secure Attestations](/learn/relay/secure-attestations)
* [Settlement](/learn/relay/settlement)

# ABIs And Bindings

# APIs

# Relay Quickstart

This quickstart walks through the developer workflow that the repo enables: spinning up Symbiotic Core locally, preparing vaults and operators, wiring middleware, and bringing a relay-powered network online.

After completing this guide, you will learn how to:

1. Spin up Symbiotic Core locally
2. Set up test Vaults and Operators
3. Configure Your Relay-backed Network's Smart Contracts
4. Bring Your Network Online

<Details summary="Symbiotic Super Sum project structure">
  ```
  symbiotic-super-sum
  ├─ network-scripts
  │  ├─ deploy.sh
  │  ├─ genesis-generator.sh
  │  ├─ sidecar-start.sh
  │  └─ sum-node-start.sh
  ├─ off-chain
  │  ├─ abis/
  │  ├─ cmd/
  │  │  ├─ benchmark/
  │  │  └─ node/
  │  │     └─ main.go
  │  └─ internal/
  │     ├─ contracts/
  │     │  └─ sumTask.go
  │     └─ utils/
  ├─ script
  │  ├─ MyRelayDeploy.sol
  │  ├─ mocks/
  │  ├─ my-relay-deploy.toml
  │  └─ utils/
  ├─ src
  │  ├─ SumTask.sol
  │  └─ symbiotic
  │     ├─ Driver.sol
  │     ├─ KeyRegistry.sol
  │     ├─ Settlement.sol
  │     └─ VotingPowers.sol
  ├─ generate_network.sh
  ├─ package.json
  └─ …
  ```
</Details>

## Prerequisites

Make sure to have all the tools listed below installed before you start.

1. **Git** ([Installation Guide](https://git-scm.com/downloads))
2. **Foundry** - Ethereum development toolchain ([Installation Guide](https://book.getfoundry.sh/getting-started/installation))
3. **Node.js** (v18 or later) and **npm** ([Installation Guide](https://nodejs.org/en/download/))
4. **Docker** ([Installation Guide](https://docs.docker.com/get-docker/))
5. **Go** (v1.21 or later) ([Installation Guide](https://golang.org/doc/install))
6. Python (v3.11 or later) ([Installation Guide](https://www.python.org/downloads/))

## **1. Deploy Symbiotic Core and Setup Your First Vault**

![core-and-vault.png](/img/core-and-vault.png)

### **Deploy Symbiotic Core to your local chain**

Symbiotic Core comprises the foundational contracts that govern the Symbiotic ecosystem, offering a comprehensive suite for its administration and interaction. The repository provides pre-configured scripts to facilitate deployment to a local chain, as well as additional utilities designed to streamline ongoing workflows with the core contracts.

<Details summary="Core deployment">
  `SymbioticCoreInit.sol` is the integration script that spins up fresh factories, registries, vaults, and helper services, then exposes utilities for building test scenarios. `SymbioticCoreConstants.sol` is the address book library that returns the canonical contract set and supported collateral tokens for mainnet, Holešky, Sepolia, and Hoodi. `SymbioticCoreBindings.sol` contains the Foundry broadcast helpers used to create vaults, register operators/networks, manage opt-ins, and exercise slashing flows against those core contracts.

  Core contracts can be deployed using `_initCore_SymbioticCore` function ([script details](https://github.com/symbioticfi/relay-contracts/blob/deploy-script-updates/script/RelayDeploy.sol#L101)):

  ```solidity [@symbioticfi/relay-contracts/script/deploy/RelayDeploy.sol#101]
  function getCore() public withoutBroadcast loadConfig returns (SymbioticCoreConstants.Core memory) {
      if (!SymbioticCoreConstants.coreSupported()) {
          if (config.get("vault_factory").data.length == 0) {
              SymbioticCoreConstants.Core memory core = _initCore_SymbioticCore(false); // [!code focus]
  ```

  The console output lists every deployed Symbiotic Core contract (vault factory, registries, opt-in services, etc.). Persist these addresses—you’ll feed them into the rest of the quickstart.
</Details>

### **Deploy a vault**

Vaults are the delegation and restaking management layer of Symbiotic. They handle three crucial parts of the Symbiotic economy: accounting, delegation strategies and slashing processing

<Details summary="Vault deployment">
  The vault is created during operator registration by VotingPowers contract ([see contract details](https://github.com/symbioticfi/relay-contracts/blob/main/src/modules/voting-power/extensions/logic/OpNetVaultAutoDeployLogic.sol#L289)).

  ```solidity [@symbioticfi/relay-contracts/src/modules/voting-power/extensions/logic/OpNetVaultAutoDeployLogic.sol#289]
   function createVault(
       uint64 version,
       address owner,
       bytes memory vaultParams,
       uint64 delegatorIndex,
       bytes memory delegatorParams,
       bool withSlasher,
       uint64 slasherIndex,
       bytes memory slasherParams
   ) public returns (address, address, address) {
       return IVaultConfigurator(IOpNetVaultAutoDeploy(address(this)).VAULT_CONFIGURATOR())
           .create(
               IVaultConfigurator.InitParams({
                   version: version,
                   owner: owner,
                   vaultParams: vaultParams,
                   delegatorIndex: delegatorIndex,
                   delegatorParams: delegatorParams,
                   withSlasher: withSlasher,
                   slasherIndex: slasherIndex,
                   slasherParams: slasherParams
               })
           );
   }

  ```

  For testnet or mainnet vaults you can skip this step and create one directly via the Vault Factory UI at [https://app.symbiotic.fi/create](https://app.symbiotic.fi/create)
</Details>

## **2. Opt-Ins and Stake Allocation**

![operator-opt-in.png](/img/operator-opt-in.png)

### **Required On-Chain Actions**

<Details summary="Deploy network">
  In Symbiotic, networks are represented through a network address (either an EOA or a contract) and a middleware contract. Deploy the network contract using the DeployNetworkBase script. During initialization, the network is also registered within NetworkRegistry ([script details](https://github.com/symbioticfi/symbiotic-super-sum/blob/5e7625c8fb16acdd30a7695050f2f7b5c8f44d32/script/MyRelayDeploy.sol#L101)).

  ```solidity [script/MyRelayDeploy.sol#101]
  function getNetwork() public withoutBroadcast loadConfig returns (address) {
      if (config.get("network").data.length == 0) {
          address[] memory proposersAndExecutors = new address[](1);
          proposersAndExecutors[0] = getDeployerAddress();
          SymbioticCoreConstants.Core memory core = getCore();
          vm.broadcast();
          address networkImpl =
              address(new Network(address(core.networkRegistry), address(core.networkMiddlewareService)));
          config.set(
              "network",
              _deployContract(
                  NETWORK_SALT,
                  networkImpl,
                      abi.encodeCall(
                          INetwork.initialize,
                          (INetwork.NetworkInitParams({
                                  globalMinDelay: 0,
                                  delayParams: new INetwork.DelayParams[](0),
                                  proposers: proposersAndExecutors,
                                  executors: proposersAndExecutors,
                                  name: "Example Network",
                                  metadataURI: "https://example.network",
                                  defaultAdminRoleHolder: getDeployerAddress(),
                                  nameUpdateRoleHolder: getDeployerAddress(),
                                  metadataURIUpdateRoleHolder: getDeployerAddress()
                              }))
                      ),
                      getDeployerAddress(),
                      false
                  )
              );
          }
          return config.get("network").toAddress();
      }

  ```
</Details>

<Details summary="Register operator">
  The OperatorRegistry maintains a record of all registered operators.
  Operators must register here before they can participate in network activities or receive stake allocations ([script details](https://github.com/symbioticfi/symbiotic-super-sum/blob/5e7625c8fb16acdd30a7695050f2f7b5c8f44d32/script/MyRelayDeploy.sol#L371)).

  ```solidity [script/MyRelayDeploy.sol#371]
  getCore().operatorRegistry.registerOperator();
  ```
</Details>

<Details summary="Operators opt into both the network and the vault">
  Opt-ins are crucial for establishing connections between different entities in the Symbiotic ecosystem. Through the OperatorNetworkOptInService, operators can opt into networks they wish to work with. This signifies their willingness to provide services to these networks.
  Operators use the OperatorVaultOptInService to opt into specific vaults. This allows them to receive stake allocations from these vaults ([script details](https://github.com/symbioticfi/symbiotic-super-sum/blob/5e7625c8fb16acdd30a7695050f2f7b5c8f44d32/script/MyRelayDeploy.sol#L372)).

  ```solidity [script/MyRelayDeploy.sol#372]
  getCore().operatorNetworkOptInService.optIn(address(getNetwork())); // [!code focus]
  votingPowers.registerOperator();
  IVault vault = IVault(votingPowers.getAutoDeployedVault(operator.addr));
  getCore().operatorVaultOptInService.optIn(address(vault)); // [!code focus]
  ```
</Details>

<Details summary="Curator configures network limits and allocations">
  Network opt into desired vaults by calling `setMaxNetworkLimit()` on each vault’s delegator contract ([script details](https://github.com/symbioticfi/relay-contracts/blob/70dc1ae21bdebf08e2f01246a42e31aee6a1c39d/src/modules/voting-power/extensions/OpNetVaultAutoDeploy.sol#L69)).

  ```solidity [@symbioticfi/relay-contracts/src/modules/voting-power/extensions/OpNetVaultAutoDeploy.sol#69]
  (address vault, address delegator,) = OpNetVaultAutoDeployLogic.createVault(operator);
  _registerOperatorVault(operator, vault);
  if (isSetMaxNetworkLimitHookEnabled()) {
      ISetMaxNetworkLimitHook(NETWORK())
          .setMaxNetworkLimit(delegator, SUBNETWORK_IDENTIFIER(), type(uint256).max); // [!code focus]
    }
  ```
</Details>

## **3. Network Middleware**

![middleware-flow.png](/img/middleware-flow.png)

### **Overview**

Relay Contracts use a modular architecture with five core modules that together manage validator networks, ensuring flexibility and clear separation of concerns.

* **Network** integrates Relay Contracts into the Symbiotic ecosystem, providing verifiable delays, standardized lifecycle management, and serving as the network address across the system.
* **VotingPowerProvider** connects to Symbiotic Core to calculate operator and vault voting power based on stake and rules. It supports extensible strategies for onboarding, slashing, rewards, and key management.
* **KeyRegistry** manages and verifies operators’ cryptographic keys (BLS BN254, ECDSA SECP256K1), supporting registration, verification, and lifecycle management.
* **ValSetDriver** derives and maintains validator sets for off-chain components, managing epoch transitions and linking on-chain voting power with off-chain consensus.
* **Settlement** commits compressed validator sets each epoch, verifies signatures, and supports multi-chain deployments for cross-chain validation.

<Details summary="Middleware deployment">
  ### **Deployment tooling**

  The deployment tooling is in the `@symbioticfi/relay-contracts/script/deploy/` folder. It consists of `RelayDeploy.sol` Foundry script template and `relay-deploy.sh` bash script (Relay smart contracts use external libraries, so it's not currently possible to use solely Foundry script for multi-chain deployment).

  * `RelayDeploy.sol` - abstract base that wires common Symbiotic Core helpers and exposes the four deployment hooks: KeyRegistry, VotingPowerProvider, Settlement, and ValVetDriver
  * `relay-deploy.sh` - orchestrates per-contract multi-chain deployments

  The script deploys Relay modules under [OpenZeppelin's TransparentUpgradeableProxy](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/transparent/TransparentUpgradeableProxy.sol) using [CreateX](https://github.com/pcaversaccio/createx) (it provides better control for production deployments and more simplified approaches for development).

  ### **Deployment**

  1. Implement your `MyRelayDeploy.sol` Foundry script with the deployment configuration of your Relay modules:
     * Implement all virtual functions of `RelayDeploy.sol`
     * In the constructor, take the path of the `toml` file
     * Use additional helpers such as `getCore()`, `getKeyRegistry()`, `getVotingPowerProvider()`, etc. (see full list in [RelayDeploy.sol](https://github.com/symbioticfi/relay-contracts/blob/deploy-script-updates/script/RelayDeploy.sol))
  2. Implement your `my-relay-deploy.toml` configuration file with RPC URLs needed for deployment and specify which modules to deploy on which chains
  3. Execute the deployment script, e.g.:

     ```bash
     ./lib/relay-contracts-new/script/deploy/relay-deploy.sh ./script/MyRelayDeploy.sol "$DEPLOY_CONFIG_PATH" --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
     ```

  At the end, your `toml` file will contain the addresses of the deployed Relay modules.

  ### Middleware contract

  Networks need a middleware contract that incorporates custom logic and must include slashing logic.
  The script sets middleware for the network in the following way ([script details](https://github.com/symbioticfi/symbiotic-super-sum/blob/5e7625c8fb16acdd30a7695050f2f7b5c8f44d32/script/MyRelayDeploy.sol#L291))

  ```solidity [script/MyRelayDeploy.sol#291]
   Network(payable(network))
      .execute(
          address(core.networkMiddlewareService),
          0,
          abi.encodeWithSelector(INetworkMiddlewareService.setMiddleware.selector, votingPowerProvider),
          bytes32(0),
          bytes32(0)
      );
  ```
</Details>

## **4. Network Go Live**

![relay-sidecar.png](/img/relay-sidecar.png)

The Symbiotic Relay is a peer-to-peer sidecar network that runs alongside main blockchain nodes using a stateless design based entirely on on-chain state. A built-in HTTP API allows querying validator data, tracking epochs, and managing quorum signature aggregation.

Symbiotic-super-sum spins up a mini Symbiotic relay network on your laptop: two local blockchains, a contract deployer, and as many operator nodes as you request. Once the contracts are live, a small genesis job hands every relay node the same starting snapshot so they agree on history. Each operator runs a relay sidecar that keeps them chatting over libp2p, watches both blockchains, and exposes a simple API. A matching sum node sits beside each relay, grabs the contract addresses, and handles the actual task submissions or aggregation work. Together, these containers mimic the full relay network

### **Running network**

`generate_network.sh` generates Docker configuration. Start the network by running `docker compose --project-directory temp-network up -d`

<Details summary="Integration to sidecar example">
  There are several implementations of relay client - [ts](https://github.com/symbioticfi/relay-client-ts), [rust](https://github.com/symbioticfi/relay-client-rs) and [go](https://github.com/symbioticfi/relay).
  Here is Go example of integration to sidecar network ([script details](https://github.com/symbioticfi/symbiotic-super-sum/blob/5e7625c8fb16acdd30a7695050f2f7b5c8f44d32/off-chain/cmd/node/main.go#L315)):

  ```go [off-chain/cmd/node/main.go#315]
  relayClient = v1.NewSymbioticClient(conn)
  ...
  suggestedEpoch := uint64(0)
  epochInfos, err := relayClient.GetLastAllCommitted(ctx, &v1.GetLastAllCommittedRequest{}) // [!code focus]
  if err != nil {
    return err
  } else {
    for _, info := range epochInfos.EpochInfos {
      if suggestedEpoch == 0 || info.GetLastCommittedEpoch() < suggestedEpoch {
        suggestedEpoch = info.GetLastCommittedEpoch()
      }
    }
  }

  resp, err := relayClient.SignMessage(ctx, &v1.SignMessageRequest{  // [!code focus]
    KeyTag:        15,
    Message:       msg,
    RequiredEpoch: &suggestedEpoch,
  })
  if err != nil {
    return err
  }
  ```

  Another example for cosmos-sdk can be found [here](https://github.com/symbioticfi/cosmos-relay-sdk).
</Details>
