## Summary
- Add stagenet-hoodi deployment artifacts (contract addresses, rewards
info) and update Snowbridge config with latest validator set
- Fix the `bun cli contracts verify` command to correctly verify all
deployed contracts, including proxy contracts and Snowbridge
dependencies
- Fix the `bun cli contracts update-metadata` command to use the correct
config file when `--environment` is specified
## Contract verification fixes
The verification CLI hardcoded all contract source paths as
`src/<Name>.sol`, which failed for:
- **Snowbridge contracts** (Gateway, BeefyClient, AgentExecutor) — these
live in `lib/snowbridge/contracts/src/`
- **Gateway proxy** — the `Gateway` deployment address is actually a
`GatewayProxy`, not the Gateway implementation. The implementation
address needs to be resolved from the ERC1967 storage slot
- **ServiceManager proxy** — was not being verified at all
Changes:
- Added `contractPath` field to `ContractToVerify` so each contract
specifies its source location relative to the contracts directory
- Added `guessConstructorArgs` option for proxy contracts with complex
encoded init data (uses forge's `--guess-constructor-args`)
- Gateway is now verified as two separate contracts: Gateway
Implementation (address resolved from ERC1967 proxy slot) and
GatewayProxy
- ServiceManager proxy is now verified as `TransparentUpgradeableProxy`
## Update-metadata fix
The `update-metadata` command was ignoring the `--environment` flag when
selecting the deployments file:
1. The handler received a pre-built networkId (`"stagenet-hoodi"`) as
the chain parameter, which `getChainDeploymentParams` couldn't resolve
(falling back to anvil). Now chain and environment are passed
separately.
2. Commander.js routed `--environment` to the parent contracts command,
leaving `options.environment` undefined on the subcommand. Added the
same parent-fallback logic already used for `--chain`.
## Test plan
- [x] `bun typecheck` passes
- [x] Ran `bun cli contracts verify --chain hoodi --environment
stagenet` — all contracts verified successfully on Etherscan
- [x] `bun cli contracts update-metadata --chain hoodi --environment
stagenet` now reads the correct `stagenet-hoodi.json` deployments file
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
- Wire the Frontier `EthPubSub` module into the node's RPC layer,
enabling WebSocket-based `eth_subscribe`/`eth_unsubscribe` support for
`newHeads`, `logs`, and `newPendingTransactions`
- Use Ethereum-style hex (`0x`-prefixed) subscription IDs via
`EthereumSubIdProvider` for client compatibility
- Add Moonwall test suites (adapted from Moonbeam) covering block header
subscriptions, log filtering (by address, topics, wildcards, conditional
parameters), and pending transaction notifications
## Changes
### `operator/node/src/rpc.rs`
- Import and merge `EthPubSub` / `EthPubSubApiServer` into the RPC
module
- Accept `subscription_task_executor` and `pubsub_notification_sinks`
parameters in `create_full()`
- Remove stale commented-out boilerplate
### `operator/node/src/service.rs`
- Clone `pubsub_notification_sinks` and forward it (along with
`subscription_executor`) into the RPC factory closure
- Set `config.rpc.id_provider` to `EthereumSubIdProvider` for
Ethereum-compatible subscription IDs
### `test/moonwall/suites/dev/stagenet/subscription/`
- `test-subscription.ts` — `newHeads`: subscription ID format, block
header field validation
- `test-subscription-logs.ts` — `logs`: basic log notification on
contract deployment
- `test-subscription-logs2.ts` — `logs`: filtering by single/multiple
addresses, topics, wildcards, conditional and combined parameters (8
cases)
- `test-subscription-pending.ts` — `newPendingTransactions`: pending tx
hash notification
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
Summary
- drop the Foundry library and build artifact cache restores from the
e2e workflow
- also remove the Foundry build cache from the dedicated Foundry tests
workflow since it wasn’t providing value
Testing
- Not run (not requested)
## Summary
We are now launching the MSP backend when starting stpragehub services.
In this PR, we also fix the MSP and BSP node configuration and register
it with the correct keys.
## What changed
* Added a launch Backend MSP function that is called when launching
storage hub services
* Fix the wrong genesis error message in storagehub node by removing the
`--chain dev` flags (so it can be launch of the same network as our
local datahaven nodes).
* Use the correct keys to register MSP and BSP. We were injecting
different keys that the one we used for MSP and BSP registration leading
to the MSP and BSP node to never fully register as storage providers.
---------
Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
## Summary
- Add the `mmr-gadget` to the DataHaven client for proper MMR leaf
indexing in offchain storage
- Gate the gadget on `offchain_worker.indexing_enabled` to avoid running
when indexing is disabled
- Enable efficient MMR proof queries by block number via the MMR RPC
## Problem
The DataHaven client was missing the `mmr-gadget`, which prevented MMR
leaves from being correctly indexed in the offchain database. Without
it:
- MMR proofs could only be queried by block hash, not block number
- Light clients and bridge relayers could not efficiently verify
finality
- The `mmr_generateProof` RPC had degraded functionality
## Changes
| File | Change |
|------|--------|
| `operator/Cargo.toml` | Add workspace deps for `mmr-gadget`,
`sp-mmr-primitives` |
| `operator/node/Cargo.toml` | Add node deps for `mmr-gadget`,
`sp-mmr-primitives` |
| `operator/node/src/service.rs` | Add import and spawn `MmrGadget`
after BEEFY gadget |
## Test plan
- [x] Build passes: `cd operator && cargo build --release --features
fast-runtime`
- [x] Run node with debug logging: `--log mmr-gadget=debug`
- [x] Verify `mmr-gadget` task starts in logs
- [x] Test MMR RPC by block number works:
```bash
curl -H "Content-Type: application/json" \
-d '{"id":1,"jsonrpc":"2.0","method":"mmr_generateProof","params":[[1],
null, null]}' \
http://localhost:9944
```
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Add missing weights
The aim of this PR is to complete our weights by enabling more runtime
benchmarks from the pallets used in DataHaven. I will start this effort
with Storage Hub pallets.
## What's included
- [x] `pallet_nfts`
- [x] Added signing helper for pallet nfts
- [x] Add pallet to benchmarks
- [x] Run benches and generate weights
- [x] Wire up weights to runtimes
- [x] `pallet_session`
- [x] Added a `pallet_session_benchmarking` crate
- [x] Added signing helpers
- [x] Add pallet to benchmarks
- [x] Run benches and generate weights
- [x] Wire up weights to runtimes
- [x] `pallet_payment_streams`
- [x] Add `TreasuryAccount` helper and configure properly
- [x] Add pallet to benchmarks
- [x] Run benches and generate weights
- [x] Wire up weights to runtimes
- [x] `pallet_storage_providers`
- [x] Add `TreasuryAccount` helper and configure properly
- [x] Add pallet to benchmarks
- [x] Run benches and generate weights
- [x] Wire up weights to runtimes
- [x] `pallet_file_system`
- [x] Add pallet to benchmarks and configure properly
- [ ] Run benches and generate weights
- [x] Wire up weights to runtimes
- [x] `pallet_proofs_dealer`
- [x] Add pallet to benchmarks and configure properly
- [x] Run benches and generate weights
- [x] Wire up weights to runtimes
## What's not included
- `pallet_identity` - We'll enable it once we update to `2506`, that
will allow us to have a BenchmarkHelper in the config on the pallet (see
[here](ac28323e7d/operator/runtime/mainnet/src/configs/mod.rs (L632-L643)))
- `pallet_grandpa` - the upstream pallet defines
[benchmarks](bbc435c766/substrate/frame/grandpa/src/benchmarking.rs (L25))
for `check_equivocation_proof` and `note_stalled`, but the required
weights to be wired are actually `report_equivocation`,
`report_equivocation_unsigned` and `note_stalled`. That means including
`pallet_grandpa` in the benchmarks results in an inconsistent
`WeightInfo` implementation, so further understanding in the pallet's
approach to benchmarking is needed.
- `pallet_file_system` -> Run benches and generate weights. Weights will
fail because of a hardcoded `AccountId32` on the
[benchmarks](57d2a195d5/pallets/file-system/src/benchmark_proofs.rs (L69-L71)).
I'll create a PR for SH soon.
These two are left for a follow up PR.
## Summary
- Add multi-environment deployment support (stagenet, testnet, mainnet)
to CLI and contracts
- Configure stagenet and testnet runtimes with correct genesis hashes
and Snowbridge Agent IDs
- Add CLI commands for BEEFY checkpoint updates and rewards origin
computation
- Add ETH validator strategies (native beacon chain ETH + LSTs) to all
config files
## Changes
### Runtime Configuration
**Stagenet Runtime:**
- Set `StagenetGenesisHash` to DataHaven stagenet genesis hash
- Configure `RewardsAgentOrigin` with computed Snowbridge Agent ID
- Add tests verifying rewards account derivation and agent ID
computation
**Testnet Runtime:**
- Set `TestnetGenesisHash` to DataHaven testnet genesis hash
- Configure `RewardsAgentOrigin` with computed Snowbridge Agent ID
- Add tests verifying rewards account derivation and agent ID
computation
The Rewards Agent ID is computed following Snowbridge's location
description pattern:
```
blake2_256(SCALE_ENCODE("GlobalConsensus", ByGenesis(genesis), "AccountKey20", rewards_account))
```
### CLI Enhancements
- All contracts subcommands (`status`, `deploy`, `verify`,
`update-metadata`) now accept `--environment` option
- Config and deployment files use environment-prefixed naming (e.g.,
`stagenet-hoodi.json`, `testnet-hoodi.json`)
- New `update-beefy-checkpoint` command that:
- Connects to a live DataHaven chain via WebSocket RPC
- Fetches all BEEFY data at the same finalized block for consistency
- Uses parallel queries with `Promise.all` for better performance
- Computes authority hashes (keccak256 of Ethereum addresses derived
from BEEFY public keys)
- Uses Snowbridge's quorum formula `n - floor((n-1)/3)` for strictly >
2/3 majority
- New `update-rewards-origin` command that computes the Snowbridge Agent
ID for the rewards pallet
- Centralized validation via `contractsPreActionHook` for all contract
commands
- Environment validation against allowlist (`stagenet`, `testnet`,
`mainnet`)
### Contract Changes
- Network validation uses explicit allowlist instead of suffix matching
- Added `initialValidatorSetId` and `nextValidatorSetId` fields to
`SnowbridgeConfig` struct
- `DeployBase.s.sol` now uses config values for validator set IDs
instead of hardcoded 0/1
- `DeployParams.s.sol` loads validator set IDs from config with
backwards compatibility
### Validator Strategies
Added ETH-equivalent strategies to allow validators to stake using
native ETH or LSTs:
**All Networks:**
- `0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0` - Native beacon chain ETH
(virtual strategy)
**Hoodi Testnet:**
- `0xf8a1a66130d614c7360e868576d5e59203475fe0` - stETH
- `0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d` - WETH
**Ethereum Mainnet:**
- `0x93c4b944D05dfe6df7645A86cd2206016c51564D` - stETH
- `0x1BeE69b7dFFfA4E2d53C2a2Df135C388AD25dCD2` - rETH
- `0x54945180dB7943c0ed0FEE7EdaB2Bd24620256bc` - cbETH
### Config Files
- `stagenet-hoodi.json` - Hoodi testnet with stagenet EigenLayer
addresses
- `testnet-hoodi.json` - Hoodi testnet with testnet EigenLayer addresses
- `mainnet-ethereum.json` - Ethereum mainnet with mainnet EigenLayer
addresses
- Removed `hoodi.json` (replaced by environment-prefixed files)
## Usage
```bash
# Deploy to stagenet on Hoodi
bun cli contracts deploy --chain hoodi --environment stagenet
# Update BEEFY checkpoint from live chain
bun cli contracts update-beefy-checkpoint \
--chain hoodi \
--environment stagenet \
--rpc-url wss://services.datahaven-dev.network/stagenet
# Compute rewards origin for a chain
bun cli contracts update-rewards-origin \
--chain hoodi \
--environment stagenet \
--rpc-url wss://services.datahaven-dev.network/stagenet
# Check deployment status
bun cli contracts status --chain hoodi --environment stagenet
```
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Import `pallet-proxy-genesis-companion` from Moonbeam to enable proxy
account configuration at genesis time
- Configure the pallet in all runtimes (mainnet, stagenet, testnet) with
pallet index 106
- Add `Serialize`/`Deserialize` derives to `ProxyType` enum to satisfy
`MaybeSerializeDeserialize` bounds
- Include mock runtime and unit tests adapted for polkadot-stable2412-6
This pallet extends `pallet-proxy` with genesis configuration support,
allowing proxy relationships to be established at chain genesis rather
than requiring extrinsic calls after launch.
### Key adaptations from Moonbeam
The pallet was modified to work with the DataHaven SDK version
(polkadot-stable2412-6):
- Removed `BlockNumberProvider` associated type constraint (not present
in this version of pallet-proxy)
- Uses `frame_system::pallet_prelude::BlockNumberFor<T>` directly for
delay parameter
- Uses `MaybeSerializeDeserialize` trait bound for `ProxyType`
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
Co-authored-by: Ahmad Kaouk <ahmadkaouk.93@gmail.com>
Upgrades StorageHub dependencies from v0.3.3 to v0.3.5. This requires a
client upgrade.
## ⚠️ Breaking Changes ⚠️
Fisherman CLI options have been added to support specifying filtering
and ordering strategies for pending file deletions with reasonable
defaults:
- `--fisherman-filtering`: The filtering strategy [**`none` (default)**,
`ttl`]
- `--fisherman-ordering`: The ordering strategy [**`chronological`
(default)**, `randomized`]
- `--fisherman-ttl-threshold-seconds`: TTL for a file to be ignored for
deletion in seconds
MSP and BSP CLI options have been added to support specifying a specific
batch response and confirm size for MSP and BSP nodes with reasonable
defaults.
- `--bsp-confirm-file-batch-size`: How many storage requests to respond
to (confirming) in a single extrinsic call **(default: 20)**
- `--msp-respond-storage-batch-size`: How many storage requests to
respond to (accepting or rejecting) in a single extrinsic call
**(default: 20)**
### Summary
Set username deletion to use a 30‑day grace period (in blocks) and added
a non‑zero username deposit, both based on the Moonbeam's runtimes. This
makes username unbinding wait before deletion and makes authority‑issued
usernames non‑free, mitigating the sybil vector while aligning with
existing identity config patterns.
### Changes
- Configures for `pallet_identity`
- `UsernameGracePeriod = 30 * DAYS`
- `UsernameGracePeriod = deposit(0, MaxUsernameLength::get())`
Use the latest v0.15.2 release of Kurtosis, that includes improved
compatibility with rootless Podman (wrt. socket detection and bind
mounting) following the merge of
https://github.com/kurtosis-tech/kurtosis/pull/2803.
Up to now, the e2e CI job was using a custom (patched) version of
Kurtosis CLI, Engine & Core images.
## Summary
- Fixed `ProxyType` enum in the Solidity Proxy precompile interface to
match the runtime definition
- Removed non-existent `AuthorMapping` variant
- Added missing `SudoOnly` variant
## Problem
The Solidity interface in `Proxy.sol` had incorrect `ProxyType` enum
values that didn't match the runtime definition:
| Index | Runtime (Correct) | Solidity (Was) |
|-------|------------------|----------------|
| 0 | Any | Any |
| 1 | NonTransfer | NonTransfer |
| 2 | Governance | Governance |
| 3 | Staking | Staking |
| 4 | CancelProxy | CancelProxy |
| 5 | Balances | Balances |
| 6 | **IdentityJudgement** | **AuthorMapping** ❌ |
| 7 | **SudoOnly** | **IdentityJudgement** ❌ |
This mismatch would cause EVM users calling the Proxy precompile with
`IdentityJudgement` (index 7 in Solidity) to actually get `SudoOnly`
behavior, and `AuthorMapping` (index 6) would fail to decode entirely
since it doesn't exist in the runtime.
## Solution
Updated the Solidity enum to match the runtime:
```solidity
enum ProxyType {
Any,
NonTransfer,
Governance,
Staking,
CancelProxy,
Balances,
IdentityJudgement,
SudoOnly
}
```
## ⚠️ Breaking Changes ⚠️
- **`ProxyType.AuthorMapping` removed**: This variant never existed in
the runtime and would fail to decode.
- **`ProxyType.IdentityJudgement` index changed**: Moved from index 7 to
index 6. Solidity code using `ProxyType.IdentityJudgement` will now work
correctly (previously it mapped to `SudoOnly` in the runtime)
- **`ProxyType.SudoOnly` added**: New variant at index 7 for proxies
that can only execute Sudo pallet calls
## Test plan
- [x] Proxy precompile tests pass (32/32)
- [x] Mainnet runtime proxy tests pass (22/22)
- [x] Governance proxy tests pass (6/6)
- [x] Verified `InstanceFilter<RuntimeCall>` implementation handles all
8 variants correctly
- [x] Verified `EvmProxyCallFilter` implementation handles all 8
variants correctly
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Upgrades to StorageHub version v0.3.3. This upgrade requires both a
runtime and client upgrade.
---------
Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
## Summary
### Configuration
- Remove deprecated `deny_warnings` config key from foundry.toml
- Add global `[lint]` config to suppress naming convention warnings for
AVS/EL/ERC patterns (`mixed-case-function`, `mixed-case-variable`)
### DataHavenServiceManager Refactoring
- Rename immutable variables to SCREAMING_SNAKE_CASE
(`_allocationManager` → `_ALLOCATION_MANAGER`, `_rewardsCoordinator` →
`_REWARDS_COORDINATOR`)
- Wrap modifier logic in internal functions (`_checkRewardsInitiator`,
`_checkValidator`, `_checkAllocationManager`) to reduce contract size
- Add `_toAddress` helper with assembly for safe bytes-to-address
conversion
### Safe Typecasting
- Replace direct typecasts with OpenZeppelin's SafeCast library in
deploy scripts and test utilities
- Use `.toUint32()`, `.toUint64()`, `.toUint160()` for
overflow-protected conversions
- Replace `bytes32("wrong origin")` string cast with hex literal in test
deployer
### Code Cleanup
- Remove 25+ unused imports across script and test files
- Convert plain imports to named imports for better clarity
- Use `SafeERC20.safeTransfer()` for token transfers in tests
- Change `view` to `pure` where appropriate
## Test plan
- [x] `forge build` completes with no warnings
- [x] `forge test` passes all 10 tests
## Summary
ERC20 balances precompile `withdraw()` was failing to account for gas
costs associated with storage reads. In fact the function was calling
`usable_balance` without accounting for `record_db_read`.
## Changes
- Added `116 bytes` of storage read computed like this: `Blake2128(16) +
AccountId(20) + AccountInfo ((4 * 4) + AccountData(16 * 4))`, to cover
for `usable_balance`, following the same that `balance_of` does.
## Summary
Reorganizes the test directory structure for better clarity and
maintainability:
- **Rename `test/datahaven/` → `test/moonwall/`**: Clearly identifies
these as Moonwall single-node tests
- **Move `test/framework/` → `test/e2e/framework/`**: Groups e2e test
utilities under a dedicated folder
- **Move `test/suites/` → `test/e2e/suites/`**: Groups e2e test suites
with the framework
- **Add `test/e2e/framework/validators.ts`**: Extracts validator test
helpers from utils into the e2e framework
- **Update documentation**: README.md and E2E_FRAMEWORK_OVERVIEW.md
reflect the new structure
### New Directory Structure
```
test/
├── e2e/
│ ├── suites/ # E2E test suites (Kurtosis-based)
│ └── framework/ # E2E test utilities & helpers
├── moonwall/ # Moonwall single-node tests
├── launcher/ # Network deployment tools
└── ...
```
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Add zero address validation across all functions that accept address
parameters to prevent misconfiguration
- Fix race condition in `buildNewValidatorSetMessage()` that could cause
reverts during validator deregistration
- Refactor contract for improved readability and reduced code
duplication
- Update AVS metadata URL to point to the correct hosted JSON file
## Changes
### Security & Validation
- Add `ZeroAddress` error and validate all address inputs in
`initialize`, `setRewardsInitiator`, `setSnowbridgeGateway`,
`addValidatorToAllowlist`, `registerOperator`, and
`updateSolochainAddressForValidator`
- Fix race condition: filter out zero solochain addresses in
`buildNewValidatorSetMessage()` to prevent reverts when a validator is
mid-deregistration
### Refactoring
- Replace verbose `if/revert` patterns with `require` statements for
consistency
- Inline single-use internal functions (`_createDataHavenOperatorSets`,
`_setRewardsInitiator`)
- Consolidate duplicate error types into single `ZeroAddress` error
- Rename `initialise` → `initialize` to maintain consistency with the
transparent upgradability pattern
- Optimize validator set message encoding by removing redundant wrapper
function
### Observability
- Add `SolochainAddressUpdated` event for tracking validator address
changes
### Cleanup
- Remove unused remappings from `foundry.toml`
- Fix typo in metadata description
---------
Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
## Summary
Remove `compressedPubKeyToEthereumAddress` and the `crypto.ts` because
the function is not being used and it has been already defined in the
file `datahaven.ts`.
## What changed
* Deleted the file `test/launcher/utils/crypto.ts` as the function what
the only function defined in the file
* Update `index.ts` to reflect the change mentioned above
Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
## Summary
- Increase `MaxBatchConfirmStorageRequests` runtime constant from 10 to
100
- Applied across all runtime environments: mainnet, stagenet, and
testnet
## Test plan
- [x] Verify builds pass for all runtime configurations
Bumps [alloy-dyn-abi](https://github.com/alloy-rs/core) from 0.8.25 to
0.8.26.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/alloy-rs/core/releases">alloy-dyn-abi's
releases</a>.</em></p>
<blockquote>
<h2>alloy-core v0.8.26</h2>
<h2>Security</h2>
<h3>Patched: DoS vulnerability on <code>alloy_dyn_abi::TypedData</code>
hashing</h3>
<p>An uncaught panic triggered by malformed input to
<code>alloy_dyn_abi::TypedData</code> could lead to a denial-of-service
(DoS) via <code>eip712_signing_hash()</code>.</p>
<p>Software with high availability requirements such as network services
may be particularly impacted. If in use, external auto-restarting
mechanisms can partially mitigate the availability issues unless
repeated attacks are possible.</p>
<p>The vulnerability was patched by adding a check to ensure the element
is not empty before accessing its first element; an error is returned if
it is empty. The fix is included in version <a
href="https://crates.io/crates/alloy-dyn-abi/1.4.1">v1.4.1</a> and
backported to <a
href="https://crates.io/crates/alloy-dyn-abi/0.8.26">v0.8.26</a>.</p>
<p>See: <a
href="https://github.com/alloy-rs/core/security/advisories/GHSA-pgp9-98jm-wwq2">https://github.com/alloy-rs/core/security/advisories/GHSA-pgp9-98jm-wwq2</a></p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/alloy-rs/core/compare/v0.8.25...v0.8.26">https://github.com/alloy-rs/core/compare/v0.8.25...v0.8.26</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/alloy-rs/core/blob/v0.8.26/CHANGELOG.md">alloy-dyn-abi's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/alloy-rs/core/releases/tag/v0.8.26">0.8.26</a>
- 2025-10-14</h2>
<h3>Bug Fixes</h3>
<ul>
<li>[dyn-abi] Don't panic when linearization is empty</li>
</ul>
<h3>Miscellaneous Tasks</h3>
<ul>
<li>Clippy</li>
<li>Add typos (<a
href="https://redirect.github.com/alloy-rs/core/issues/991">#991</a>)</li>
</ul>
<h3>Testing</h3>
<ul>
<li>Remove invalid name</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="79d0ef6e6a"><code>79d0ef6</code></a>
chore: release 0.8.26</li>
<li><a
href="951758a470"><code>951758a</code></a>
test: remove invalid name</li>
<li><a
href="d1c55e2b81"><code>d1c55e2</code></a>
chore: clippy</li>
<li><a
href="cbf2f9c66c"><code>cbf2f9c</code></a>
chore: add typos (<a
href="https://redirect.github.com/alloy-rs/core/issues/991">#991</a>)</li>
<li><a
href="f8f323f905"><code>f8f323f</code></a>
fix(dyn-abi): don't panic when linearization is empty</li>
<li>See full diff in <a
href="https://github.com/alloy-rs/core/compare/v0.8.25...v0.8.26">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/datahaven-xyz/datahaven/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
## Summary
This PR integrate the slashing feature with EigenLayer. With this PR,
slashing can now be relayed to our Datahaven AVS and then executed
within EigenLayer. In addition some refactoring of the original slashing
pallet has been done.
## Motivation
To avoid misbehaving actor in the network, Datahaven has implemented a
slashing pallet in which offenses can be reported and then if adequate
can lead to a sanction on the misbehaving node. It incentive nodes to
only follow good behavior in addition to the reward incentive. The
rewards flow is managed directly into EigenLayer (see
https://github.com/datahaven-xyz/datahaven/pull/351).
## Slashing flow
<img width="2355" height="946" alt="Slashing Flow"
src="https://github.com/user-attachments/assets/c1ddc3dc-2a7e-429d-94e0-1e02a3f65246"
/>
## What changes
* Implemented `slashValidatorsOperator` in `DataHavenServiceManager`. It
received all the slashing requests batched (every new era the queued
slashing are being relayed from substrate to Ethereum). It handle the
slashing of the operators reported into the Validator set.
* Added a `slashes_adapter.rs` utility file to remove the duplication
for each runtime. In addition, we made use of the `sol!` macro from
alloy to encode the calldata for the Ethereum call. This avoid rewriting
encoding logic and allow to remove the hardcoded selector value used to
call the slashing function.
* Added some tests in solidity to test the registering and slashing of
an operator in Ethereum via Eigen Layer.
* Added e2e tests that test the injection of a slash request, it being
relayed via the snowbridge relayer and executed by our Datahaven AVS.
## What could be better
* We are only deploying one strategy for now so it is hardcoded in the
slashing flow. We should be able to update the pallet in case we are
adding a new strategy. So communication from Ethereum should be relayed.
* We don't have error being return in case the slashing fail. Which
could happen if we don't have the right number of strategy or the
validator is not registered... etc.
* More tests for the unhappy path
This PR upgrades the StorageHub version to
[v0.3.1](https://github.com/Moonsong-Labs/storage-hub/releases/tag/v0.3.1).
The changes applied are the ones suggested in the corresponding release
notes, which in short are:
- Adding the `get_number_of_active_users_of_provider` runtime API to the
`PaymentStreams` pallet runtime APIs.
- Supporting `--max-open-forests` CLI param (has defaults).
- Supporting Prometheus telemetry.
IMPORTANT: This upgrade requires a Runtime upgrade as well as a Client
upgrade.
---------
Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
## Summary
- Split CI workflow to stop re-running validation when PRs are merged to
main
- Create dedicated `release.yml` workflow for Docker Hub releases on
main branch
- Keep full CI validation for PRs and `perm-*` branches
## Motivation
Since the repository is configured to:
1. Require PRs to be up-to-date with main before merging
2. Require all CI checks to pass
Re-running the full CI suite (~12 jobs) on main after merge is redundant
and wastes CI runner time that could be used for other tasks.
## Changes
| Workflow | Before | After |
|----------|--------|-------|
| `CI.yml` | Triggers on push to `main`, `perm-*`, and PRs to `main` |
Triggers on push to `perm-*` and PRs to `main` only |
| `release.yml` | N/A (new) | Triggers on push to `main`, runs only
`docker-build-release` |
## Impact
| Event | Before | After | Savings |
|-------|--------|-------|---------|
| PR to main | 13 jobs | 12 jobs | 1 job |
| Merge to main | 13 jobs | 1 job | 12 jobs |
| Push to perm-* | 13 jobs | 12 jobs | 1 job |
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
Improve CI performance through better caching and simplified workflows:
- Add a new `warm-sccache` job that runs before all Rust CI jobs to
pre-populate the sccache cache
- Cache locally installed tools (`~/.local/bin`, `~/.local/lib`,
`~/.local/include`) with a version-based hash key
- Simplify Rust tests by removing matrix partitioning and switching from
cargo-nextest to cargo test
## Problem
**Poor sccache hit rates:**
- `rust-lint`, `unit-tests`, and `build-operator` ran in parallel with
cold caches
- Each job compiled dependencies independently
- Cache was only saved at job completion (too late for parallel jobs to
benefit)
**Redundant tool downloads:**
- Mold, LLVM/Clang, protoc, and libpq (~500MB+) were downloaded fresh on
each job
- No caching of locally installed tools
**Overcomplicated test setup:**
- 2-partition matrix for tests added complexity without significant
benefit
- cargo-nextest required installation step (~30s overhead)
- Separate result-checker job wasn't necessary
## Solution
### 1. sccache warm-up job (`task-warm-sccache.yml`)
- Runs first (Tier 0) before all Rust jobs
- Compiles with release mode + all features (`fast-runtime`,
`try-runtime`, `runtime-benchmarks`)
- Compiles with debug mode to cover test builds
- Uses `SKIP_WASM_BUILD=1` to minimize warm-up time
### 2. Local tools caching (`setup-env/action.yml`)
- Define tool versions as env vars (`MOLD_VERSION`, `LLVM_VERSION`,
`PROTOC_VERSION`, `LIBPQ_VERSION`)
- Generate SHA256 hash from versions for cache key
- Cache `~/.local/bin`, `~/.local/lib`, `~/.local/include` (not all of
`~/.local` to avoid container storage)
- Set up PATH and env vars immediately after cache restore
### 3. Simplified Rust tests (`task-rust-tests.yml`)
- Remove 2-partition matrix strategy
- Replace cargo-nextest with `cargo test --locked`
- Remove separate tests-result-checker job
## CI Flow
```
┌─ build-operator (warm sccache + cached tools)
│
CI Start → warm-sccache ─┼─ rust-lint (warm sccache + cached tools)
│
└─ unit-tests (warm sccache + cached tools)
```
## Test plan
- [x] CI workflow runs successfully
- [x] Warm-sccache job completes and shows cache stats
- [x] Local tools cache restores correctly (no permission errors)
- [x] Downstream Rust jobs show improved cache hit rates
- [x] Rust tests pass with simplified single-job setup
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
Co-authored-by: undercover-cactus <lola@moonsonglabs.com>
Upgrade to StorageHub version 0.3.0. This is a minor release, including
breaking changes.
## ⚠️ Breaking Changes ⚠️
The changes applied in this PR are according to the suggested changes in
StorageHub's [v0.3.0
release](https://github.com/Moonsong-Labs/storage-hub/releases/tag/v0.3.0)
---------
Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
## Summary
Use block authorship as direct proof of liveness for the 30% liveness
component of validator rewards. Validators who author at least one block
in a session are considered online and receive the full liveness bonus.
## Problem
The rewards pallet was checking validator liveness via ImOnline
**after** the session had rotated - at which point ImOnline had already
cleared its `AuthoredBlocks` storage. This caused all validators to
appear offline, resulting in only ~70% of expected rewards being
allocated (missing the 30% liveness bonus).
## Solution
Use **block authorship as the proxy for liveness**:
- A validator who authored at least one block is definitively online
- Liveness is determined directly in `award_session_performance_points`
via `blocks_authored > 0`
- No dependency on external liveness checks (ImOnline)
### Rewards Formula
- **60%** Block authorship (proportional to blocks produced)
- **30%** Liveness (full bonus if authored ≥1 block, zero otherwise)
- **10%** Base reward (for being in the validator set)
### Files Changed
- `pallets/external-validators-rewards/src/lib.rs` - Core logic changes
- `pallets/external-validators-rewards/src/mock.rs` - Test mock updates
- `pallets/external-validators-rewards/src/tests.rs` - Test updates
- `runtime/{mainnet,testnet,stagenet}/src/configs/mod.rs` - Config
updates
## Testing
- All 76 pallet tests pass
- Local testing should show correct points per session (e.g., 3200
points for 2 validators with 10 blocks)
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
## Summary
- Fix Docker Hub rate limit errors in E2E CI job by adding
authentication
- Pass existing `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` secrets to
the E2E workflow
## Problem
The E2E CI job pulls `datahavenxyz/snowbridge-relay:latest` from Docker
Hub without authentication, causing rate limit errors (10 pulls/hour for
unauthenticated requests):
```
Error: initializing source docker://datahavenxyz/snowbridge-relay:latest: reading manifest latest in docker.io/datahavenxyz/snowbridge-relay: toomanyrequests: You have reached your unauthenticated pull rate limit.
```
## Solution
Reuse the Docker Hub secrets already configured for
`docker-build-release` by:
1. Passing secrets from `CI.yml` to the E2E workflow
2. Adding optional secrets declaration in `task-e2e.yml`
3. Adding Docker Hub login step before pulling `snowbridge-relay`
---------
Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
## Summary
Re-add the static build feature option to bundle postgres dependency
into the binary. It simplify the installation because now to run the
node the operator doesn't need to have postgres dependencies installed
on its system.
## What changed ?
* Added a `static` feature that can be activated to add the extra
dependencies during the build.
* A task that run every time a dependency has been modified so we can
make sure the build with the feature is still working correctly. (we are
assuming simple change in the code won't have an impact on it because
postgres is being used in diesel which is not a direct dependecy to
datahaven).
## Summary
This PR improve the generating state workflow. It will also check for
outdated state-diff.json and add a practical script to easily generate a
new one.
The way we generate state has also been changed to make it work with
macOS M1 system. We don't run the tool in the container anymore but
instead directly on the machine.
## What changes
* A check-generated-state.js script was added to quickly look for
outdated test
* The check was added in the CI
* A generate-contracts.ts script was added to easily generate the new
state with the new instructions to run on MacOS
---------
Co-authored-by: Gonza Montiel <gon.montiel@gmail.com>
Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com>
Co-authored-by: Gonza Montiel <gonzamontiel@users.noreply.github.com>
## Summary
- Revise README to align with DataHaven's **AI-first decentralized
storage** narrative
- Feature **StorageHub** as a core component with link to the repository
- Expand architecture diagram to include StorageHub pallets and the full
storage provider network (MSP, BSP, Indexer, Fisherman)
- Add "How Storage Works" section explaining
upload/replication/retrieval/verification flow
- Add new Key Features sections for verifiable storage and provider
network
- Add Use Cases section (AI/ML, DePIN, RWAs)
- Clarify slashing mechanisms: BSPs use on-chain slashing via StorageHub
pallets, while validators use EigenLayer
- Add links to DataHaven website, documentation, and StorageHub
repository
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>