Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ Use "charon exit [command] --help" for more information about a command.
:::warning
This command requires Charon to access the distributed validator's private keys, please use caution and keep these private keys securely backed up and secret.

The default `publish-address` for this command sends signed exit messages to Obol's [API](../../api/) for aggregation and distribution. Exit signatures are stored in line with Obol's [terms and contiditions](https://obol.tech/terms.pdf).
The default `publish-address` for this command sends signed exit messages to Obol's [API](../../../api/) for aggregation and distribution. Exit signatures are stored in line with Obol's [terms and contiditions](https://obol.tech/terms.pdf).
:::

This command submits partial exit signatures to the remote API for aggregation. The required flags are `--beacon-node-url` and `--validator-public-key` of the validator you wish to exit. An exit message can only be signed for a validator that is fully deposited and assigned a validator index.
Expand Down
28 changes: 28 additions & 0 deletions versioned_docs/version-v1.11/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
title: "Introduction"
description: "Documentation, integration guides, and protocol specifications"
sidebar_label: "Introduction"
slug: /learn/readme
---

## Welcome to Obol!

Obol builds Distributed Validator Technology (DVT), which empowers node operators, staking protocols, and institutions run Ethereum validators that are more secure, fault-tolerant, and performant. DVT benefits both operators and capital allocators while strengthening the network itself by reducing centralization risk and protecting against supermajority failures. Obol DVs are the staking endgame.

Whether you’re here to learn about DVT, integrate it into your staking stack, or want to stake your ETH on DVs, these docs will help you get started.

---

## Quick start

<div class="gb-cards">
<a class="gb-card" href="https://obol.org"><img class="gb-card-img" src="../../img/gitbook/cards/stake.png" alt="" loading="lazy" /><h3>Stake ETH on Obol DVs</h3><p>Stake on existing DVT products and explore available options.</p></a>
<a class="gb-card" href="readme/learn-about-obol"><img class="gb-card-img" src="../../img/gitbook/cards/open_book.png" alt="" loading="lazy" /><h3>Learn About Obol</h3><p>Start here to understand DVT, how Charon (our middleware) works, and why distributed validators are fundamental to Ethereums future.</p></a>
</div>

<div class="gb-cards">
<a class="gb-card" href="../run-a-dv/start/quickstart_overview"><img class="gb-card-img" src="../../img/gitbook/cards/integrate.png" alt="" loading="lazy" /><h3>Integrate Obol DVs</h3><p>Deploy DVs on mainnet or testnet and follow the quickstart path for operators and allocators.</p></a>
<a class="gb-card" href="mailto:business@obol.tech"><img class="gb-card-img" src="../../img/gitbook/cards/contact_us.png" alt="" loading="lazy" /><h3>Get In Touch</h3><p>Partnerships, integration support, allocator onboarding, or general questions.</p></a>
</div>

> **Browsing as an AI agent?** Start with [obol.org/llms.txt](https://obol.org/llms.txt) for a terse index of the ecosystem, or [obol.org/llms-full.txt](https://obol.org/llms-full.txt) for a self-contained briefing. The [`ObolNetwork/skills`](https://github.com/ObolNetwork/skills) repo publishes Claude Code skills for running DVs and the Obol Stack.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
sidebar_label: "Advanced Guides"
slug: /advanced-and-troubleshooting/advanced
---

# advanced

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
description: "Use advanced docker-compose features to have more flexibility and power to change the default configuration."
sidebar_label: "Advanced Docker Configs"
slug: /advanced-and-troubleshooting/advanced/adv-docker-configs
---

# Advanced Docker Configs

:::info
This section is intended for _docker power users_, i.e.: for those who are familiar with working with `docker compose` and want to have more flexibility and power to change the default configuration.
:::

We use the "Multiple Compose File" feature which provides a very powerful way to override any configuration in `docker-compose.yml` without needing to modify version-controlled files since that results in conflicts when upgrading this repo. See [this](https://docs.docker.com/compose/extends/#multiple-compose-files) for more details.

There are some additional compose files in [this repository](https://github.com/ObolNetwork/charon-distributed-validator-node/), `compose-debug.yml` and `docker-compose.override.yml.sample`, along with the default `docker-compose.yml` file that you can use for this purpose.

* `compose-debug.yml` contains some additional containers that developers can use for debugging, like `tempo`. To achieve this, you can run:

```shell
docker compose -f docker-compose.yml -f compose-debug.yml up
```

* `docker-compose.override.yml.sample` is intended to override the default configuration provided in `docker-compose.yml`. This is useful when, for example, you wish to add port mappings or want to disable a container.
* To use it, just copy the sample file to `docker-compose.override.yml` and customize it to your liking. Please create this file ONLY when you want to tweak something. This is because the default override file is empty and docker errors if you provide an empty compose file.

```shell
cp docker-compose.override.yml.sample docker-compose.override.yml

# Tweak docker-compose.override.yml and then run docker compose up
docker compose up
```

* You can also run all these compose files together. This is desirable when you want to use both the features. For example, you may want to have some debugging containers AND also want to override some defaults. To achieve this, you can run:

```shell
docker compose -f docker-compose.yml -f docker-compose.override.yml -f compose-debug.yml up
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
description: "Prepare an alternative deposit for an unused validator"
sidebar_label: "Alter Withdrawal Addresses"
slug: /advanced-and-troubleshooting/advanced/alter-withdrawal-addresses
---

# Altering a Withdrawal Address for an unused validator

:::warning
Please take care when changing a withdrawal address for an inactivated validator. Activating a validator that exits to a withdrawal address you don't control likely means your funds are lost.

A signed deposit message is a public bearer artifact: anyone who has the bytes can submit it to the canonical Ethereum deposit contract. If a previous valid deposit message exists for the same validator pubkey — for instance the original one signed by the operators at cluster creation time — it [could be used to front-run](https://medium.com/immunefi/rocketpool-lido-frontrunning-bug-fix-postmortem-e701f26d7971) the alternative deposit, and the validator would activate with the original withdrawal credentials instead of the new ones.

Once a deposit has been processed for a validator pubkey, its withdrawal credentials are fixed — every subsequent deposit ignores the `withdrawal_credentials` field and follows the originally activated ones. A re-signed deposit message for a pubkey that has already been deposited is therefore wasted: the funds sent with it will land at the original withdrawal address, not the new one. Before using a re-signed deposit, verify on-chain that no `DepositEvent` for the validator pubkey exists on the canonical deposit contract (`0x00000000219ab540356cBB839Cbe05303d7705Fa`).
:::

On occasion it can be useful to be able to change the withdrawal address specified for an already created but unused distributed validator. For example if they are unneeded extra capacity, or if the withdrawal address to be used was not known at cluster creation time and a trusted placeholder address was used instead. The `charon deposit` commands allow you to sign alternative deposit messages for **inactive validators** with the help of the Obol [API](../../api/what-is-this-api.md).

:::info
If you want to change the withdrawal address of a running validator, consider a validator [consolidation](../../run-a-dv/editing/replace-operator.md#method-2-validator-consolidation) instead.
:::

## Sign an alternative deposit message

A threshold of operators must decide which public keys they are changing the withdrawal address for, and what the new withdrawal address will be. Then each run the `charon deposit sign` command with their partial private keys and the appropriate (identical) flags.

**Single public key**

```sh
docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.11.0 deposit sign \
--validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \
--withdrawal-addresses="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
```

:::info
`validator-public-keys` are the distributed validator public keys for which the alternative deposit data should be signed (find them in your cluster_lock.json file in the `distributed_validator_public_keys` mapping or on the DV Launchpad). `withdrawal-addresses` are the new withdrawal address(es) for which the new deposit data should be signed. There should either be the same amount as `validator-public-keys` specified, or a single address that will be used for all public keys specified.

Optionally, users can also specify multiple different `deposit-amounts` (defaults to only `32`) to be prepared.
:::

**Multiple public keys, multiple withdrawal addresses**

```sh
docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.11.0 deposit sign \
--validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da,0xc9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \
--withdrawal-addresses="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045,0x1db3439a222c519ab44bb1144fc28167b4fa6ee6"
```

**Multiple public keys, single withdrawal address**

```sh
docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.11.0 deposit sign \
--validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da,0xc9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \
--withdrawal-addresses="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
```

## Fetch full deposit data

After a threshold of operators have submitted partial alternative deposits, a full aggregated deposit message can be fetched from Obol API.

```sh
docker run -u $(id -u):$(id -g) --rm -v "$(pwd)/:/opt/charon" obolnetwork/charon:v1.11.0 deposit fetch \
--validator-public-keys="0xb9171b84a09da7ff983a36e1c6e873e1537e97ad31aa868185d62c68e255baad8c1cfb83f508460ed96572d2a8e9e9da" \
```

:::info
`validator-public-keys` are the validator public keys for which the new deposit data should be fetched.
:::

After a successful fetch the new deposit data files are saved in `.charon/deposit-data-<TIMESTAMP>.json`.

If there are not enough partial signatures, an error message will be returned.

```sh
17:18:40.771 ERRO cmd Application failed to start: fetch full deposit data from Obol API: not enough partial signatures to meet threshold {"submitted_public_keys": "[0x8677e2014a173f72b3d4528893cb01881549631c2a39d90d7c19c230299a57440e73c82c7daf1d72713b1e26e42bae99]", "submitted_public_keys_length": 1, "required_threshold": 3}
```

This deposit message file can be used with a deposit interface, to activate the validator on the Ethereum deposit contract.

:::danger
Please take care not to mistakenly activate the old `deposit-data.json` file when the cluster was originally created, containing the withdrawal address you hope to replace. If you activate a validator with a withdrawal address you don't control, your funds are likely lost.
:::
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
description: "Learn how to assign permissions within the Obol Vault Manager (OVM) smart contract using the efficient bitwise role system."
sidebar_label: "Assign OVM Roles"
slug: /advanced-and-troubleshooting/advanced/assign-ovm-roles
---

# How to Assign Roles to Addresses in OVM

This guide explains how to assign permissions within the Obol Vault Manager (OVM) smart contract using its bitwise role system and outlines key security recommendations.

---

## 1. Understanding the Bitwise Role System

The OVM contract manages permissions by assigning each role a unique power-of-two value (a single binary bit). To grant multiple roles, you simply add (or bitwise OR) their values together to produce a single, final integer that the smart contract reads.

### Contract Role Definitions

| Role Name | Decimal Value | Hex Value | Primary Purpose |
| --- | --- | --- | --- |
| **`WITHDRAWAL_ROLE`** | 1 | `0x01` | Initiate validator withdrawals/claims. |
| **`CONSOLIDATION_ROLE`** | 2 | `0x02` | Initiate validator consolidation (migration). |
| **`SET_BENEFICIARY_ROLE`** | 4 | `0x04` | Set/change the principal/withdrawal address. |
| **`RECOVER_FUNDS_ROLE`** | 8 | `0x08` | Emergency recovery of stuck assets. |
| **`SET_REWARD_ROLE`** | 16 | `0x10` | Set/change the reward fee recipient address. |
| **`DEPOSIT_ROLE`** | 32 | `0x20` | Submit validator deposit data. |

## 2. Guide to Assigning and Managing Roles

The easiest way to generate the required hex code is by using the dedicated calculator tool.

### Step 1: Find the hex code (Using the Calculator)

Use the following interactive tool to instantly find the code for your required role combination:

- **[OVM Roles Calculator](https://dazzling-genie-4aaac7.netlify.app/)**

1. **Select Roles:** Go to the calculator and click the **Checkboxes** for all the roles you need to grant.
2. **Retrieve Code:** The calculator will automatically calculate and display the final **Total hex code** (e.g., `0x11`) and **Total Decimal Code** (e.g., 17). Use the **Total hex code** in the next stage.

### Step 2: Assign the Roles On-Chain

Roles are assigned using the **`grantRoles`** function on the OVM smart contract.

1. **Go to Etherscan:** Navigate to the Block Explorer page for your deployed OVM smart contract.
2. **Access Write Contract:** Click the **"Contract"** tab, and then the **"Write Contract"** sub-tab.
3. **Connect Wallet:** Click **"Connect to Web3"** and connect the wallet that currently holds **ownership** of the OVM contract.
4. **Execute `grantRoles`:**
- Find the function **`grantRoles`**.
- **`user (address)`:** Enter the wallet address you want to grant permissions to (this is the target operator's address).
- **`roles (uint256)`:** Input the **Decimal Value** (e.g., `17`) or **Hex Value** (e.g., `0x11`) copied from the calculator.
- Click **"Write"** and approve the transaction.

![Screenshot of the OVM contract on a block explorer with the role-assignment transaction prepared.](/img/gitbook/AssignOVMRoles1.png)

## 3. Review the Roles

1. Assigned roles will show up in the Launchpad to the designated address.

![Screenshot of the DV Launchpad showing newly assigned OVM roles.](/img/gitbook/AssignOVMRoles2.png)

2. Sometimes the Launchpad may take a short time to reflect role updates due to RPC issues.. Try refreshing if this occurs. You can also use Etherscan directly to confirm roles.

![Screenshot of the DV Launchpad reflecting updated OVM role assignments.](/img/gitbook/AssignOVMRoles3.png)

## 4. Security and Recommendations 🔒

The security of the cluster relies entirely on the assignment and control of these roles. Follow these best practices:

### A. Principle of Least Privilege

- **Avoid `0x3F` (All Roles):** Never grant the full combination code (`0x3F` or 63) to any address that doesn't absolutely require it (like the primary owner/governance multi-sig).
- **Role Separation:** Grant only the specific roles an operator needs for their job. For example:
- A technical operator managing deposits/withdrawals needs `WITHDRAWAL_ROLE` (1), `CONSOLIDATION_ROLE` (2), and `DEPOSIT_ROLE` (32).
- A separate, highly-trusted governance multi-sig should hold **high-privilege roles** like `SET_BENEFICIARY_ROLE` (4), `SET_REWARD_ROLE` (16), and `RECOVER_FUNDS_ROLE` (8).

### B. Ownership & Trust

- **Secure the Owner:** The address that can call `grantRoles` and `revokeRoles` is the most powerful. This address **must be a hardware wallet or, ideally, a Gnosis SAFE multi-sig wallet.**
- **Cluster Creation Timing:** It is recommended to **grant final roles before sharing cluster invites** with external invitees. This ensures the security model is locked down before the cluster scales.
- **Renounce Ownership (Conditional):** If the cluster's roles are intended to be fixed forever (e.g., in a fully immutable system), you can **renounce ownership** after setting the final roles. However, if any role needs to be modifiable later (like changing the fee recipient), the owner must retain the ability to execute `grantRoles`.

![Screenshot of the DV Launchpad showing the OVM ownership and role-renouncement options.](/img/gitbook/AssignOVMRoles4.png)

## 5. Miscellaneous: How does Bitwise Logic Work?

The final hex code is generated by the **Bitwise OR** operation. Since every role value is a unique power of two, the code for any combination is simply the sum of the desired decimal values.

| Role Combination Requested | Decimal Addition | Bitwise OR (Binary) | Final hex code |
| --- | --- | --- | --- |
| **WITHDRAWAL** and **DEPOSIT** | 1+32=33 | `000001` \| `100000` = `100001` | **`0x21`** |
| **CONSOLIDATION** and **SET_REWARD** | 2+16=18 | `000010` \| `010000` = `010010` | **`0x12`** |
| **All 4 Basic Roles** | 1+2+4+8=15 | `000001` \| `000010` \| `000100` \| `001000` = `001111` | **`0x0F`** |
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
description: "Send authenticated requests to a beacon node protected by HTTP Basic, or header-based access control."
sidebar_label: "Beacon node authentication"
slug: /advanced-and-troubleshooting/advanced/beacon-node-authentication
---

# Beacon node authentication

## HTTP Basic Access Authentication

If you want to use Charon with an [HTTP basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) protected beacon node, then you can supply `charon run` with the `--beacon-node-headers` flag. The flag's value should be set like: `Authorization=Basic <credentials>` where `Authorization` will be the header key and `Basic <credentials>` will be the header value. The `<credentials>` are a [Base64](https://en.wikipedia.org/wiki/Base64) encoding of the username and password joined by a single colon `:`.

:::warning
These headers will be sent in every request to every beacon node. This could leak your credentials to the other beacon nodes. Make sure you trust every listed beacon node.
:::

## Usage example

Suppose we have an HTTP Basic access protected beacon node with username `john` and password `doe`. To access it we would construct the credentials by running the following command:

```
echo -n "john:doe" | base64
```

Then you could pass the flag to your Charon instance like this:

```
charon run --beacon-node-headers="Authorization=Basic am9objpkb2U="
```

Or you could specify it as an environment variable like this:

```
CHARON_BEACON_NODE_HEADERS="Authorization=Basic am9objpkb2U="
```

:::info
Note that 'Authorization' is followed with an `=` rather than the usual `:`.
:::
Loading
Loading