> ## Documentation Index
> Fetch the complete documentation index at: https://dittonetwork.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Symbiotic — Vault Deployment Guide

> Deploy all required Symbiotic modules and configure your Vault

## Common Addresses

**Sepolia Testnet**

* **BurnerRouterFactory:** `0x32e2AfbdAffB1e675898ABA75868d92eE1E68f3b`
* **wstETH:** `0xB82381A3fBD3FaFA77B3a7bE693342618240067b`
* **wstETH global burner:** `0x58D347334A5E6bDE7279696abE59a11873294FA4`
* **VaultConfigurator:** `0xD2191FE92987171691d552C219b8caEf186eb9cA`
* **Network:** `0x683Ed12e213a6D78C338D4e18440C42bb936085A`
* **NetworkMiddleware:** `0x9403942D5B9EbC1D2cF9Ff0960b688d64588B094`
* **DefaultStakerRewardsFactory:** `0xE6381EDA7444672da17Cd859e442aFFcE7e170F0`
* **NetworkOptInService:** `0x58973d16FFA900D11fC22e5e2B6840d9f7e13401`
* **VaultOptInService:** `0x95CC0a052ae33941877c9619835A233D21D57351`
* **OperatorRegistry:** `0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548`

**Mainnet**

* **BurnerRouterFactory:** `0x99F2B89fB3C363fBafD8d826E5AA77b28bAB70a0`
* **wstETH:** `0xC329400492c6ff2438472D4651Ad17389fCb843a`
* **wstETH global burner:** `0xdCaC890b14121FD5D925E2589017Be68C2B5B324`
* **VaultConfigurator:** `0x29300b1d3150B4E2b12fE80BE72f365E200441EC`
* **Network:** `0x8560C667Ae72F28D09465B342A480daB28821f6b`
* **NetworkMiddleware:** \`\`
* **DefaultStakerRewardsFactory:** `0xFEB871581C2ab2e1EEe6f7dDC7e6246cFa087A23`
* **NetworkOptInService:** `0x7133415b33B438843D581013f98A08704316633c`
* **VaultOptInService:** `0xb361894bC06cbBA7Ea8098BF0e32EB1906A5F891`
* **OperatorRegistry:** `0xAd817a6Bc954F678451A71363f04150FDD81Af9F`

## Setup

The following setup steps will reference various Symbiotic core contracts. Refer to their [deployments page](https://docs.symbiotic.fi/guides/deployments)
and [core source code](https://github.com/dittonetwork/symbiotic-core).

### Prerequisites

> [!NOTE]
>
> For technical users who're comfortable running Foundry scripts, we've provided example code for every step in the setup process.
> → [Setup Scripts](https://github.com/dittonetwork/ditto-contracts/tree/25_add_OperatorMiddlewareScript/script/operator)\
> Alternatively the Symbiotic CLI can assist in many of these steps. Refer to their [docs](https://docs.symbiotic.fi/guides/cli/).

**Docs:**

* [Symbiotic Docs](https://docs.symbiotic.fi)
* [Foundry Docs](https://book.getfoundry.sh/)

**Tooling:**

* `git clone` - **Git** — [install](https://github.com/git-guides/install-git)
* `forge script, cast` - **Foundry** — [install](https://github.com/foundry-rs/foundry#installation)
* `python3 symb.py` - **Symbiotic CLI** — [install](https://docs.symbiotic.fi/guides/cli)

***

### Vault Configuration

The Vault configuration process consists of the following substeps:

**1. Deploy Burner Router**

> [!NOTE]
>
> The **Burner Router** defines *where* slashed collateral is sent (burn address, treasury, etc.).\
> Every Vault must point to a Burner Router, so we deploy this first.
>
> For the official Symbiotic approach, see: [Symbiotic Burner Router Deployment Guide](https://docs.symbiotic.fi/guides/vault-deployment#1-burner-router)

```bash theme={null}
# Clone ditto-contracts repository
git clone https://github.com/dittonetwork/ditto-contracts
cd ditto-contracts
```

**Sepolia**

```bash theme={null}
# Define parameters
OWNER=<owner address>
BURNER_ROUTER_FACTORY=0x32e2AfbdAffB1e675898ABA75868d92eE1E68f3b
COLLATERAL=0xB82381A3fBD3FaFA77B3a7bE693342618240067b  # wstETH
DELAY=$((2*24*60*60))  # 2 days
GLOBAL_RECEIVER=<treasury address>
# For the array parameters, format exactly as shown
NETWORK_RECEIVERS="[(<network address>,<receiver address>)]"
OPERATOR_NETWORK_RECEIVERS="[(<network address>,<operator address>,<receiver address>)]"

# Execute the script
forge script script/operator/01_BurnerRouterSetup.s.sol:BurnerRouterSetup \
  --sig "run(address,address,address,uint48,address,(address,address)[],(address,address,address)[])" \
  $OWNER $BURNER_ROUTER_FACTORY $COLLATERAL $DELAY $GLOBAL_RECEIVER \
  "$NETWORK_RECEIVERS" "$OPERATOR_NETWORK_RECEIVERS" \
  --rpc-url https://ethereum-sepolia-rpc.publicnode.com \
  --chain sepolia \
  --private-key <your-private-key> \
  --etherscan-api-key <etherscan api key> \
  --verify --broadcast
```

**Mainnet**

```bash theme={null}
# Define parameters
OWNER=<owner address>
BURNER_ROUTER_FACTORY=0x99F2B89fB3C363fBafD8d826E5AA77b28bAB70a0
COLLATERAL=0xC329400492c6ff2438472D4651Ad17389fCb843a  # wstETH
DELAY=$((2*24*60*60))  # 2 days
GLOBAL_RECEIVER=<treasury address>
# For the array parameters, format exactly as shown
NETWORK_RECEIVERS="[(<network address>,<receiver address>)]"
OPERATOR_NETWORK_RECEIVERS="[(<network address>,<operator address>,<receiver address>)]"

# Execute the script
forge script script/operator/01_BurnerRouterSetup.s.sol:BurnerRouterSetup \
  --sig "run(address,address,address,uint48,address,(address,address)[],(address,address,address)[])" \
  $OWNER $BURNER_ROUTER_FACTORY $COLLATERAL $DELAY $GLOBAL_RECEIVER \
  "$NETWORK_RECEIVERS" "$OPERATOR_NETWORK_RECEIVERS" \
  --rpc-url https://ethereum-rpc.publicnode.com \
  --chain mainnet \
  --private-key <your-private-key> \
  --etherscan-api-key <etherscan api key> \
  --verify --broadcast
```

**2. Deploy Vault Delegator + Slasher**

> [!NOTE]
>
> A **Vault** is the core Symbiotic primitive—an ERC-20 pool that can be restaked across networks and operators.\
> We use **NetworkRestakeDelegator (type 0)** for Ditto.\
> The **Veto Slasher** lets a resolver veto or approve each slash event.
>
> For the official Symbiotic approach, see: [Symbiotic Core Modules Deployment Guide](https://docs.symbiotic.fi/guides/vault-deployment#2-core-modules)

**Sepolia**

```bash theme={null}
# Define parameters
VAULT_CONFIGURATOR=0xD2191FE92987171691d552C219b8caEf186eb9cA
OWNER=<owner address>
COLLATERAL=0xB82381A3fBD3FaFA77B3a7bE693342618240067b  # wstETH
BURNER=<burner router address from previous step>
EPOCH_DURATION=$((7*24*60*60))  # 7 days
WHITELISTED_DEPOSITORS="[]"  # Empty array or specific addresses
DEPOSIT_LIMIT=0  # No limit, or set a specific limit
DELEGATOR_INDEX=0  # 0=NetworkRestakeDelegator, 1=FullRestakeDelegator, 2=OperatorSpecificDelegator, 3=OperatorNetworkSpecificDelegator
HOOK=0x0000000000000000000000000000000000000000  # Contract with onSlash() or zero address
NETWORK=0x683Ed12e213a6D78C338D4e18440C42bb936085A  # Network address
WITH_SLASHER=true  # Enable slasher
SLASHER_INDEX=1  # 0=Slasher, 1=VetoSlasher
VETO_DURATION=$((24*60*60))  # 1 day

# Execute the script
forge script script/operator/02_CoreSetup.s.sol:CoreSetup \
  --sig "run(address,address,address,address,uint48,address[],uint256,uint64,address,address,bool,uint64,uint48)" \
  $VAULT_CONFIGURATOR $OWNER $COLLATERAL $BURNER $EPOCH_DURATION \
  "$WHITELISTED_DEPOSITORS" $DEPOSIT_LIMIT $DELEGATOR_INDEX \
  $HOOK $NETWORK $WITH_SLASHER $SLASHER_INDEX $VETO_DURATION \
  --rpc-url https://ethereum-sepolia-rpc.publicnode.com \
  --chain sepolia \
  --private-key <your-private-key> \
  --etherscan-api-key <etherscan api key> \
  --verify --broadcast
```

**Mainnet**

```bash theme={null}
# Define parameters
VAULT_CONFIGURATOR=0x29300b1d3150B4E2b12fE80BE72f365E200441EC
OWNER=<owner address>
COLLATERAL=0xC329400492c6ff2438472D4651Ad17389fCb843a  # wstETH
BURNER=<burner router address from previous step>
EPOCH_DURATION=$((7*24*60*60))  # 7 days
WHITELISTED_DEPOSITORS="[]"  # Empty array or specific addresses
DEPOSIT_LIMIT=0  # No limit, or set a specific limit
DELEGATOR_INDEX=0  # 0=NetworkRestakeDelegator, 1=FullRestakeDelegator, 2=OperatorSpecificDelegator, 3=OperatorNetworkSpecificDelegator
HOOK=0x0000000000000000000000000000000000000000  # Contract with onSlash() or zero address
NETWORK=0x8560C667Ae72F28D09465B342A480daB28821f6b  # Network address
WITH_SLASHER=true  # Enable slasher
SLASHER_INDEX=1  # 0=Slasher, 1=VetoSlasher
VETO_DURATION=$((24*60*60))  # 1 day

# Execute the script
forge script script/operator/02_CoreSetup.s.sol:CoreSetup \
  --sig "run(address,address,address,address,uint48,address[],uint256,uint64,address,address,bool,uint64,uint48)" \
  $VAULT_CONFIGURATOR $OWNER $COLLATERAL $BURNER $EPOCH_DURATION \
  "$WHITELISTED_DEPOSITORS" $DEPOSIT_LIMIT $DELEGATOR_INDEX \
  $HOOK $NETWORK $WITH_SLASHER $SLASHER_INDEX $VETO_DURATION \
  --rpc-url https://ethereum-rpc.publicnode.com \
  --chain mainnet \
  --private-key <your-private-key> \
  --etherscan-api-key <etherscan api key> \
  --verify --broadcast
```

***

### Deploy Default Staker Rewards

`DefaultStakerRewards` harvests rewards earned by the Vault and redistributes
them to depositors, taking an optional admin fee.

For the official Symbiotic approach, see: [Symbiotic Staker Rewards Deployment Guide](https://docs.symbiotic.fi/guides/vault-deployment#3-staker-rewards)

**Sepolia**

```bash theme={null}
# Define parameters
VAULT=<vault address from previous step>
ADMIN_FEE=1000  # 10% (basis points, 10000 = 100%)
DEFAULT_ADMIN_ROLE_HOLDER=<admin address>
ADMIN_FEE_CLAIM_ROLE_HOLDER=<admin address>
ADMIN_FEE_SET_ROLE_HOLDER=<admin address>
DEFAULT_STAKER_REWARDS_FACTORY=0xE6381EDA7444672da17Cd859e442aFFcE7e170F0

# Execute the script
forge script script/operator/03_DefaultStakerRewardsSetup.s.sol:DefaultStakerRewardsSetup \
  --sig "run(address,uint256,address,address,address,address)" \
  $VAULT $ADMIN_FEE $DEFAULT_ADMIN_ROLE_HOLDER $ADMIN_FEE_CLAIM_ROLE_HOLDER \
  $ADMIN_FEE_SET_ROLE_HOLDER $DEFAULT_STAKER_REWARDS_FACTORY \
  --rpc-url https://ethereum-sepolia-rpc.publicnode.com \
  --chain sepolia \
  --private-key <your-private-key> \
  --etherscan-api-key <etherscan api key> \
  --broadcast
```

**Mainnet**

```bash theme={null}
# Define parameters
VAULT=<vault address from previous step>
ADMIN_FEE=1000  # 10% (basis points, 10000 = 100%)
DEFAULT_ADMIN_ROLE_HOLDER=<admin address>
ADMIN_FEE_CLAIM_ROLE_HOLDER=<admin address>
ADMIN_FEE_SET_ROLE_HOLDER=<admin address>
DEFAULT_STAKER_REWARDS_FACTORY=0xFEB871581C2ab2e1EEe6f7dDC7e6246cFa087A23

# Execute the script
forge script script/operator/03_DefaultStakerRewardsSetup.s.sol:DefaultStakerRewardsSetup \
  --sig "run(address,uint256,address,address,address,address)" \
  $VAULT $ADMIN_FEE $DEFAULT_ADMIN_ROLE_HOLDER $ADMIN_FEE_CLAIM_ROLE_HOLDER \
  $ADMIN_FEE_SET_ROLE_HOLDER $DEFAULT_STAKER_REWARDS_FACTORY \
  --rpc-url https://ethereum-rpc.publicnode.com \
  --chain mainnet \
  --private-key <your-private-key> \
  --etherscan-api-key <etherscan api key> \
  --broadcast
```

***

### Deposit Collateral

After the vault, burner router, delegator, and slasher are deployed in the previous step, the vault must obtain deposits of the appropriate ERC20 collateral type. These deposits can come from a variety of sources depending on the vault.
For the official Symbiotic approach, refer to the [Symbiotic CLI Guide](https://docs.symbiotic.fi/guides/cli#deposit)

> [!NOTE]
>
> Before depositing, ensure you have approved the vault to spend your tokens:
>
> ```bash theme={null}
> # Approve tokens using cast (replace with your addresses)
> cast send <COLLATERAL_TOKEN> "approve(address,uint256)" <VAULT_ADDRESS> <AMOUNT> \
>   --rpc-url <your-rpc-url> \
>   --private-key <your-private-key>
> ```

***

### Vault Actions

Finally, the vault curator address must make some calls to allocate collateral to the Ditto network and operators.

> [!NOTE]
>
> For Ditto, the subnetwork ID is always 0. The subnetwork bytes32 value is computed by concatenating the network address with the subnetwork ID.
>
> For Mainnet, the subnetwork bytes32 value is:
>
> ```
> 0x8560C667Ae72F28D09465B342A480daB28821f6b000000000000000000000000
> ```
>
> For Sepolia:
>
> ```
> 0x683Ed12e213a6D78C338D4e18440C42bb936085A000000000000000000000000
> ```

**1. Set Network Limit**

First, call `setNetworkLimit(bytes32 subnetwork, uint256 amount)` on the delegator module of the vault. This sets the total amount of collateral the vault would like to restake to the Ditto network.

```bash theme={null}
# Using cast (replace with your addresses and values)
DELEGATOR=<delegator address>  # The delegator module of your vault
SUBNETWORK=0x8560C667Ae72F28D09465B342A480daB28821f6b000000000000000000000000  # For mainnet
LIMIT=<amount>  # Amount in wei (e.g., 1000000000000000000000 for 1000 tokens)

cast send $DELEGATOR "setNetworkLimit(bytes32,uint256)" $SUBNETWORK $LIMIT \
  --rpc-url https://ethereum-rpc.publicnode.com \
  --private-key <your-private-key>
```

**2. Set Operator Network Shares (for NetworkRestakeDelegator)**

> [!NOTE]
>
> **NetworkRestakeDelegator (type 0)**
>
> You must also call `setOperatorNetworkShares(subnetwork, operator, shares)` to allocate stake to specific operators.

> [!NOTE]
>
> **OperatorSpecificDelegator (type 2)**
>
> This step is not required as 100% of shares are automatically allocated to the single operator.

```bash theme={null}
# Using cast (replace with your addresses and values)
DELEGATOR=<delegator address>  # The delegator module of your vault
SUBNETWORK=0x8560C667Ae72F28D09465B342A480daB28821f6b000000000000000000000000  # For mainnet
OPERATOR=<operator address>  # Your operator address
SHARES=<shares>  # Amount in basis points (e.g., 10000 for 100%)

cast send $DELEGATOR "setOperatorNetworkShares(bytes32,address,uint256)" $SUBNETWORK $OPERATOR $SHARES \
  --rpc-url https://ethereum-rpc.publicnode.com \
  --private-key <your-private-key>
```

> [!NOTE]
>
> Here is an example of how the vault curator would complete this step using a Foundry script:
>
> ```solidity theme={null}
> // SaveToFile: VaultActions.s.sol
> // SPDX-License-Identifier: MIT
> pragma solidity 0.8.19;
>
> import {Script} from "forge-std/Script.sol";
> import {console2} from "forge-std/console2.sol";
> import {IOperatorSpecificDelegator} from "symbiotic-core/src/interfaces/delegator/IOperatorSpecificDelegator.sol";
>
> contract VaultActions is Script {
>   function run() external {
>     vm.startBroadcast();
>
>     // Replace with your delegator address
>     IOperatorSpecificDelegator delegator = IOperatorSpecificDelegator(0x75b131De299A5D343b9408081DD6A9891b8c);
>
>     // Set network limit (1,000,000 tokens with 18 decimals)
>     delegator.setNetworkLimit(0x8560C667Ae72F28D09465B342A480daB28821f6b000000000000000000000000, 1000000 ether);
>
>     // Check stake allocation for the operator
>     uint256 stake = delegator.stake(0x8560C667Ae72F28D09465B342A480daB28821f6b000000000000000000000000, msg.sender);
>     console2.log("Stake toward operator:", stake);
>
>     vm.stopBroadcast();
>   }
> }
> ```
>
> To run this script:
>
> ```bash theme={null}
> # Create the script file and paste the content above
>
> # Execute the script
> forge script VaultActions.s.sol:VaultActions \
>   --rpc-url https://ethereum-rpc.publicnode.com \
>   --private-key <your-private-key> \
>   --etherscan-api-key <etherscan api key> \
>   --broadcast
> ```

***

## Troubleshooting

If you encounter any issues during the setup process, check our common troubleshooting solutions:

> **Transaction Errors**
>
> * Verify all addresses are correct
> * Ensure you have sufficient ETH for gas
> * Check that array parameters are properly formatted

> **Contract Errors**
>
> * Confirm dependencies are properly installed (`forge install`)
> * Ensure you're using compatible versions of contracts

> **Deployment Verification**
>
> * Verify all contracts are properly deployed using a block explorer
> * Test contract interactions before proceeding to the next step

For further assistance, contact Ditto support.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.