Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
ff67c6f
feat: multi chain interfaces (#1423)
ypatil12 Jun 2, 2025
cd29b99
chore: update multichain interfaces (#1433)
ypatil12 Jun 2, 2025
e9ea812
chore: bindings + interface update (#1438)
ypatil12 Jun 3, 2025
054b311
feat: bn254 certificate verifier (#1431)
eigenmikem Jun 4, 2025
c1d774b
feat: operator table updater (#1436)
ypatil12 Jun 4, 2025
8e9183f
feat: KeyRegistrar (#1421)
eigenmikem Jun 5, 2025
74cd67a
feat: bn254 operator table contracts (#1429)
8sunyuan Jun 6, 2025
a95b11e
chore: update BN254CertificateVerifier (#1447)
ypatil12 Jun 6, 2025
d27af9e
feat: cross chain registry (#1439)
0xrajath Jun 6, 2025
11c1858
chore: multichain deploy scripts (#1449)
ypatil12 Jun 9, 2025
694467e
feat: add operator table updater to CCR (#1451)
ypatil12 Jun 9, 2025
9bebd92
chore: bindings (#1452)
ypatil12 Jun 9, 2025
d702cff
chore: add latest `referenceTimestamp` to OTC interface (#1454)
ypatil12 Jun 10, 2025
ec504dd
fix: `OperatorTableUpdater` encoding (#1456)
ypatil12 Jun 10, 2025
047dc2d
refactor: sig verification into library (#1455)
eigenmikem Jun 10, 2025
13ee634
fix: global table update message hash (#1460)
ypatil12 Jun 10, 2025
b51f81f
refactor: `CrossChainRegistry` (#1457)
ypatil12 Jun 11, 2025
1001149
chore: add sig digest functions to interface (#1464)
ypatil12 Jun 11, 2025
ba7f08f
chore: add helper view function (#1465)
ypatil12 Jun 11, 2025
0780d9c
feat: add view function for `getGlobalConfirmerSetReferenceTimestamp`…
ypatil12 Jun 16, 2025
4b87179
feat: ecdsa cert verifier (#1470)
eigenmikem Jun 17, 2025
66b6b20
feat: release manager (#1469)
0xClandestine Jun 17, 2025
8824436
feat: add `referenceBlockNumber` (#1472)
ypatil12 Jun 17, 2025
11c4357
refactor: `BN254OperatorTableCalculator` (#1463)
ypatil12 Jun 17, 2025
ff466c6
feat: ecdsacv views (#1475)
eigenmikem Jun 20, 2025
065e5a6
feat: ecdsa table calculator (#1473)
eigenmikem Jun 23, 2025
344334b
refactor: `Bn254CertificateVerifierUnitTests` (#1476)
ypatil12 Jun 23, 2025
7e2801b
refactor: `ECDSACertificateVerifier` testing (#1478)
ypatil12 Jun 23, 2025
cee4a48
refactor: operators can deregister keys if not slashable (#1480)
eigenmikem Jun 24, 2025
f4be753
refactor: `ECDSATableCalculator` testing (#1479)
ypatil12 Jun 24, 2025
15674c1
feat: disable root (#1481)
ypatil12 Jun 27, 2025
4ade403
refactor: `KeyRegistry` unit testing (#1482)
ypatil12 Jun 27, 2025
4bbb3c8
refactor: remove table calculators (#1493)
ypatil12 Jun 27, 2025
8ddcb60
docs: multichain docs (#1488)
ypatil12 Jun 28, 2025
5749e5d
fix: zero length (#1490)
ypatil12 Jun 28, 2025
4ca155e
chore: remove stale bindings (#1498)
ypatil12 Jun 30, 2025
cb7bb1a
fix: circular dependency for initial global root update (#1499)
eigenmikem Jun 30, 2025
3f6fd49
refactor: `globalRootConfirmerSet` -> `generator` (#1500)
ypatil12 Jun 30, 2025
7d736a5
feat: add `publishMetadataURI` (#1492)
0xClandestine Jul 1, 2025
d37c98f
feat: operator table updater pauser (#1501)
ypatil12 Jul 1, 2025
d04ebf5
feat: multichain deploy scripts (#1487)
ypatil12 Jul 1, 2025
592f311
docs: changelog (#1504)
ypatil12 Jul 1, 2025
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
3 changes: 2 additions & 1 deletion .github/workflows/foundry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ jobs:
esac
env:
FOUNDRY_PROFILE: ${{ matrix.suite == 'Fork' && 'forktest' || 'medium' }}
RPC_MAINNET: https://billowing-capable-sound.quiknode.pro/
RPC_MAINNET: ${{ secrets.RPC_MAINNET }}
RPC_HOLESKY: ${{ secrets.RPC_HOLESKY }}

# -----------------------------------------------------------------------
# Forge Storage Diff
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/validate-deployment-scripts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
fail-fast: true
matrix:
env: [preprod, testnet, mainnet, testnet-sepolia, testnet-hoodi]
env: [preprod, testnet, mainnet, testnet-sepolia, testnet-hoodi, testnet-base-sepolia]

steps:
# Check out repository with all submodules for complete codebase access.
Expand Down Expand Up @@ -67,7 +67,7 @@ jobs:
- name: Validate Solidity Scripts
run: |
# Find all .sol files under /script/releases
RELEASE_FILES=$(find script/releases -type f -name "*.sol" ! -name "Env.sol" 2>/dev/null || echo "")
RELEASE_FILES=$(find script/releases -type f -name "*.sol" ! -name "Env.sol" ! -name "CrosschainDeployLib.sol" 2>/dev/null || echo "")

# Combine file lists
FILES="$RELEASE_FILES"
Expand All @@ -88,6 +88,8 @@ jobs:
RPC_URL="${{ secrets.RPC_SEPOLIA }}"
elif [ "${{ matrix.env }}" = "testnet-hoodi" ]; then
RPC_URL="${{ secrets.RPC_HOODI }}"
elif [ "${{ matrix.env }}" = "testnet-base-sepolia" ]; then
RPC_URL="${{ secrets.RPC_BASE_SEPOLIA }}"
elif [ "${{ matrix.env }}" = "mainnet" ]; then
RPC_URL="${{ secrets.RPC_MAINNET }}"
fi
Expand Down
91 changes: 64 additions & 27 deletions CHANGELOG/CHANGELOG-1.7.0.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,82 @@
# v1.7.0 Multi Chain

**Use this template to draft changelog and submit PR to review by the team**
The multichain release enables AVSs to launch their services and make verified Operator outputs available on any EVM chain, meeting their customers where they are. AVSs can specify custom operator weights to be transported to any destination chain. The release has 3 components:

1. Core Contracts
2. AVS Contracts
3. Offchain Infrastructure

## Release Manager
The below release notes cover Core Contracts. For more information on the end to end protocol, see our [docs](../docs/multichain/README.md) and [ELIP-008](https://github.com/eigenfoundation/ELIPs/blob/main/ELIPs/ELIP-008.md).

@ypatil12
## Release Manager

@ypatil12 @eigenmikem

## Highlights

🚀 New Features – Highlight major new functionality
- ...
- ...
This multichain release only introduces new standards and contracts. As a result, there are no breaking changes or deprecations.

⛔ Breaking Changes – Call out backward-incompatible changes.
- ...
- ...
🚀 New Features – Highlight major new functionality

📌 Deprecations – Mention features that are being phased out.
- ...
- ...
Source-Chain Contracts
- `KeyRegistrar`: Manages cryptographic keys for operators across different operator sets. It supports both ECDSA and BN254 key types and ensures global uniqueness of keys across all operator sets
- `CrossChainRegistry`: Enables AVSs to register to have their operator stakes transported to supported destination chains
- `ReleaseManager`: Provides a standardized way for AVSs to publish software artifacts (binaries, docker images, etc.) that operators in their operator sets should upgrade to by specified deadlines

🛠️ Security Fixes – Specify patched vulnerabilities.
- ...
- ...
Destination Chain Contracts
- `CertificateVerifier`: Proves the offchain execution of a task, via a Certificate, by the operators of an operatorSet. Two types of key material are supported: ECDSA and BN254
- `OperatorTableUpdater`: Updates operator tables in the `CertificateVerifier` to have tasks validated against up-to-date operator stake weights

🔧 Improvements – Enhancements to existing features.
- ...
- ...

🐛 Bug Fixes – List resolved issues.
- ...
- ...

- The multichain protocol has protocol-ized several AVS-deployed contracts, enabling an simpler AVS developer experience. These include:
- `KeyRegistrar`: Manages BLS and ECDSA signing keys. AVSs no longer have to deploy a `BLSAPKRegistry`
- `CertificateVerifier`: Handles signature verification for BLS and ECDSA keys. AVSs no longer have to deploy a `BLSSignatureChecker`
- Offchain Multichain Transport: AVSs no longer have to maintain [avs-sync](https://github.com/Layr-Labs/avs-sync) to keep operator stakes fresh

## Changelog

Copy the one that's auto generated from github by default to here, and submit PR for review


- merged PRs in diff from last release
- contributors
- etc
- feat: multichain deploy scripts [PR #1487](https://github.com/layr-labs/eigenlayer-contracts/pull/1487)
- feat: operator table updater pauser [PR #1501](https://github.com/layr-labs/eigenlayer-contracts/pull/1501)
- feat: add `publishMetadataURI` [PR #1492](https://github.com/layr-labs/eigenlayer-contracts/pull/1492)
- refactor: `globalRootConfirmerSet` -> `generator` [PR #1500](https://github.com/layr-labs/eigenlayer-contracts/pull/1500)
- fix: circular dependency for initial global root update [PR #1499](https://github.com/layr-labs/eigenlayer-contracts/pull/1499)
- chore: remove stale bindings [PR #1498](https://github.com/layr-labs/eigenlayer-contracts/pull/1498)
- fix: zero length [PR #1490](https://github.com/layr-labs/eigenlayer-contracts/pull/1490)
- docs: multichain docs [PR #1488](https://github.com/layr-labs/eigenlayer-contracts/pull/1488)
- refactor: remove table calculators [PR #1493](https://github.com/layr-labs/eigenlayer-contracts/pull/1493)
- refactor: `KeyRegistry` unit testing [PR #1482](https://github.com/layr-labs/eigenlayer-contracts/pull/1482)
- feat: disable root [PR #1481](https://github.com/layr-labs/eigenlayer-contracts/pull/1481)
- refactor: `ECDSATableCalculator` testing [PR #1479](https://github.com/layr-labs/eigenlayer-contracts/pull/1479)
- refactor: operators can deregister keys if not slashable [PR #1480](https://github.com/layr-labs/eigenlayer-contracts/pull/1480)
- refactor: `ECDSACertificateVerifier` testing [PR #1478](https://github.com/layr-labs/eigenlayer-contracts/pull/1478)
- refactor: `Bn254CertificateVerifierUnitTests` [PR #1476](https://github.com/layr-labs/eigenlayer-contracts/pull/1476)
- feat: ecdsa table calculator [PR #1473](https://github.com/layr-labs/eigenlayer-contracts/pull/1473)
- feat: ecdsacv views [PR #1475](https://github.com/layr-labs/eigenlayer-contracts/pull/1475)
- refactor: `BN254OperatorTableCalculator` [PR #1463](https://github.com/layr-labs/eigenlayer-contracts/pull/1463)
- feat: add `referenceBlockNumber` [PR #1472](https://github.com/layr-labs/eigenlayer-contracts/pull/1472)
- feat: release manager [PR #1469](https://github.com/layr-labs/eigenlayer-contracts/pull/1469)
- feat: ecdsa cert verifier [PR #1470](https://github.com/layr-labs/eigenlayer-contracts/pull/1470)
- feat: add view function for `getGlobalConfirmerSetReferenceTimestamp` [PR #1471](https://github.com/layr-labs/eigenlayer-contracts/pull/1471)
- chore: add helper view function [PR #1465](https://github.com/layr-labs/eigenlayer-contracts/pull/1465)
- chore: add sig digest functions to interface [PR #1464](https://github.com/layr-labs/eigenlayer-contracts/pull/1464)
- refactor: `CrossChainRegistry` [PR #1457](https://github.com/layr-labs/eigenlayer-contracts/pull/1457)
- fix: global table update message hash [PR #1460](https://github.com/layr-labs/eigenlayer-contracts/pull/1460)
- refactor: sig verification into library [PR #1455](https://github.com/layr-labs/eigenlayer-contracts/pull/1455)
- fix: `OperatorTableUpdater` encoding [PR #1456](https://github.com/layr-labs/eigenlayer-contracts/pull/1456)
- chore: add latest `referenceTimestamp` to OTC interface [PR #1454](https://github.com/layr-labs/eigenlayer-contracts/pull/1454)
- chore: bindings [PR #1452](https://github.com/layr-labs/eigenlayer-contracts/pull/1452)
- feat: add operator table updater to CCR [PR #1451](https://github.com/layr-labs/eigenlayer-contracts/pull/1451)
- chore: multichain deploy scripts [PR #1449](https://github.com/layr-labs/eigenlayer-contracts/pull/1449)
- feat: cross chain registry [PR #1439](https://github.com/layr-labs/eigenlayer-contracts/pull/1439)
- chore: update BN254CertificateVerifier [PR #1447](https://github.com/layr-labs/eigenlayer-contracts/pull/1447)
- feat: bn254 operator table contracts [PR #1429](https://github.com/layr-labs/eigenlayer-contracts/pull/1429)
- feat: KeyRegistrar [PR #1421](https://github.com/layr-labs/eigenlayer-contracts/pull/1421)
- feat: operator table updater [PR #1436](https://github.com/layr-labs/eigenlayer-contracts/pull/1436)
- feat: bn254 certificate verifier [PR #1431](https://github.com/layr-labs/eigenlayer-contracts/pull/1431)
- chore: bindings + interface update [PR #1438](https://github.com/layr-labs/eigenlayer-contracts/pull/1438)
- chore: update multichain interfaces [PR #1433](https://github.com/layr-labs/eigenlayer-contracts/pull/1433)
- feat: multi chain interfaces [PR #1423](https://github.com/layr-labs/eigenlayer-contracts/pull/1423)
- docs: update version matrix [PR #1491](https://github.com/layr-labs/eigenlayer-contracts/pull/1491)
- chore: add multisend parser to scripts directory [PR #1486](https://github.com/layr-labs/eigenlayer-contracts/pull/1486)
- chore: update eigenpod and eigen impls addresses in holesky and hoodi [PR #1448](https://github.com/layr-labs/eigenlayer-contracts/pull/1448)
243 changes: 243 additions & 0 deletions docs/core/ReleaseManager.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
# ReleaseManager

| File | Notes |
| -------- | -------- |
| [`ReleaseManager.sol`](../../src/contracts/core/ReleaseManager.sol) | |
| [`ReleaseManagerStorage.sol`](../../src/contracts/core/ReleaseManagerStorage.sol) | state variables |
| [`IReleaseManager.sol`](../../src/contracts/interfaces/IReleaseManager.sol) | interface |

Libraries and Mixins:

| File | Notes |
| -------- | -------- |
| [`PermissionControllerMixin.sol`](../../src/contracts/mixins/PermissionControllerMixin.sol) | account delegation |
| [`SemVerMixin.sol`](../../src/contracts/mixins/SemVerMixin.sol) | semantic versioning |
| [`OperatorSetLib.sol`](../../src/contracts/libraries/OperatorSetLib.sol) | encode/decode operator sets |

## Overview

The `ReleaseManager` manages software releases for AVS operator sets. It provides a standardized way for AVSs to publish software artifacts (binaries, docker images, etc.) that operators in their operator sets should upgrade to by specified deadlines. This ensures operators run compatible and up-to-date software versions required by the AVS.

The `ReleaseManager's` responsibilities include:

* **Release Publishing**: AVSs can publish new releases containing one or more software artifacts for their operator sets.
* **Upgrade Deadlines**: Each release specifies a deadline by which operators must upgrade.
* **Release Tracking**: Maintains a history of all releases for each operator set.
* **Release Queries**: Provides view functions to query release information.

An AVS in the context of `ReleaseManager` is defined as the `address` of the contract that implements the AVS logic. For `PermissionController` purposes, this AVS address is also the AVS [account](https://github.com/Layr-Labs/eigenlayer-contracts/blob/dev/docs/permissions/PermissionController.md#accounts).

### Important Notes on Release Management

* **Latest Release Validity**: Only the latest release for an operator set is considered valid. Previous releases become obsolete as soon as a new release is published.
* **Upgrade Deadlines**: The `upgradeByTime` timestamp (in Unix time) is a suggested deadline and is not enforced on-chain or off-chain. It serves as a communication mechanism for AVSs to indicate when operators should complete their upgrades.
* **Multiple Releases in Same Block**: If multiple releases are published in the same block with the same `upgradeByTime`, the last transaction processed in that block will determine the latest valid release.

---

## Releases

A release represents a collection of software artifacts that operators in an operator set must run. Each release is associated with a specific operator set and contains:

* **Artifacts**: An array of software artifacts, each with a digest (hash) and registry URL
* **Upgrade By Time**: A Unix timestamp by which operators should complete the upgrade

The release structure is defined as:

```solidity
/**
* @notice Represents a software artifact with its digest and registry URL.
* @param digest The hash digest of the artifact.
* @param registryUrl The URL where the artifact can be found.
*/
struct Artifact {
bytes32 digest;
string registryUrl;
}

/**
* @notice Represents a release containing multiple artifacts and an upgrade deadline.
* @param artifacts Array of artifacts included in this release.
* @param upgradeByTime Timestamp by which operators must upgrade to this release.
*/
struct Release {
Artifact[] artifacts;
uint32 upgradeByTime;
}
```

**State Management:**

```solidity
/// @dev Mapping from operator set key to array of releases for that operator set
mapping(bytes32 operatorSetKey => Release[]) internal _operatorSetReleases;
```

**Methods:**
* [`publishRelease`](#publishrelease)
* [`getTotalReleases`](#gettotalreleases)
* [`getRelease`](#getrelease)
* [`getLatestRelease`](#getlatestrelease)
* [`getLatestUpgradeByTime`](#getlatestupgradebytime)
* [`isValidRelease`](#isValidRelease)

---

### Write Functions

#### `publishRelease`

```solidity
/**
* @notice Publishes a new release for an operator set.
* @param operatorSet The operator set this release is for.
* @param release The release that was published.
* @return releaseId The index of the newly published release.
*/
function publishRelease(
OperatorSet calldata operatorSet,
Release calldata release
)
external
checkCanCall(operatorSet.avs)
returns (uint256 releaseId)
```

_Note: this method can be called directly by an AVS, or by a caller authorized by the AVS. See [`PermissionController.md`](../permissions/PermissionController.md) for details._

AVSs use this method to publish new software releases for their operator sets. Each release contains one or more artifacts that represent the software components operators must run (e.g., validator clients, network monitors, etc.). The AVS specifies a deadline (`upgradeByTime`) by which all operators in the operator set must upgrade to the new release.

The `releaseId` returned is the zero-based index of the release in the operator set's release array. This ID can be used to query the release later using [`getRelease`](#getrelease).

*Effects*:
* Appends the release to `_operatorSetReleases[operatorSet.key()]`
* The new release is assigned a `releaseId` equal to the previous array length
* All artifact information (digest and registryUrl) is copied to storage
* Emits a `ReleasePublished` event with the operator set, release ID, and release details

*Requirements*:
* Caller MUST be authorized, either as the AVS itself or an admin/appointee (see [`PermissionController.md`](../permissions/PermissionController.md))
* `release.upgradeByTime` MUST be greater than or equal to the current block timestamp
---

### View Functions

#### `getTotalReleases`

```solidity
/**
* @notice Returns the total number of releases for an operator set.
* @param operatorSet The operator set to query.
* @return The number of releases.
*/
function getTotalReleases(
OperatorSet memory operatorSet
)
public
view
returns (uint256)
```

Returns the total number of releases that have been published for the specified operator set. This can be used to iterate through all releases or to determine if any releases exist.

*Returns*:
* The length of the releases array for the given operator set
* Returns 0 if no releases have been published

#### `getRelease`

```solidity
/**
* @notice Returns a specific release by index.
* @param operatorSet The operator set to query.
* @param releaseId The id of the release to get.
* @return The release at the specified index.
*/
function getRelease(
OperatorSet memory operatorSet,
uint256 releaseId
)
external
view
returns (Release memory)
```

Retrieves a specific release by its ID for a given operator set. The `releaseId` is the zero-based index of the release in the operator set's release history.

*Returns*:
* The complete `Release` struct including all artifacts and the upgrade deadline
* Reverts if `releaseId` is out of bounds

#### `getLatestRelease`

```solidity
/**
* @notice Returns the latest release for an operator set.
* @param operatorSet The operator set to query.
* @return The id of the latest release.
* @return The latest release.
*/
function getLatestRelease(
OperatorSet memory operatorSet
)
public
view
returns (uint256, Release memory)
```

Retrieves the most recently published release for an operator set. This is typically the release that operators should be running or upgrading to.

*Returns*:
* The latest `Release` struct from the operator set's release array
* Reverts if no releases have been published for the operator set

#### `getLatestUpgradeByTime`

```solidity
/**
* @notice Returns the upgrade by time for the latest release.
* @param operatorSet The operator set to query.
* @return The upgrade by time for the latest release.
*/
function getLatestUpgradeByTime(
OperatorSet memory operatorSet
)
external
view
returns (uint256)
```

A convenience function that returns just the upgrade deadline from the latest release. This can be useful for quickly checking when operators must complete their upgrades.

*Returns*:
* The `upgradeByTime` timestamp from the latest release
* Reverts if no releases have been published for the operator set

#### `isValidRelease`

```solidity
/**
* @notice Returns true if the release is the latest release, false otherwise.
* @param operatorSet The operator set to query.
* @param releaseId The id of the release to check.
* @return True if the release is the latest release, false otherwise.
*/
function isValidRelease(
OperatorSet memory operatorSet,
uint256 releaseId
)
external
view
returns (bool)
```

Checks whether a given release ID corresponds to the latest release for an operator set. This can be useful for operators to verify they are running the most current software version.

**Note**: Only the latest release is considered valid. All previous releases are considered obsolete and should not be used by operators.

*Returns*:
* `true` if the `releaseId` matches the latest release index
* `false` if the `releaseId` refers to an older release
* Reverts if the operator set has no releases

---
Binary file added docs/images/multichain-registration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading