Commit graph

13 commits

Author SHA1 Message Date
Ahmad Kaouk
4a16de1061
fix: resolve forge build warnings (#398)
## 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
2026-01-22 09:48:27 -03:00
Ahmad Kaouk
5313089659
refactor(contracts): Harden DataHavenServiceManager with input validation and code cleanup (#395)
## 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>
2026-01-20 10:32:32 +00:00
Ahmad Kaouk
a0ab11afec
refactor: Remove eigenlayer-middleware and flatten ServiceManagerBase (#389)
## Summary

- Flatten `ServiceManagerBase` middleware layer directly into
`DataHavenServiceManager`
- Remove all unused EigenLayer integration code to keep the contract
minimal
- Fix access control on `deregisterOperatorFromOperatorSets` (was
missing `onlyOwner`)

  ## Motivation

The `ServiceManagerBase` from eigenlayer-middleware was designed for the
old `AVSDirectory` model and included many generic functions DataHaven
doesn't use. This refactor:

  - Reduces code complexity and contract size
  - Removes ~200 lines of unused code
  - Makes the codebase easier to audit and maintain
  - Keeps only what DataHaven actually needs

  ## Changes

  ### Architecture
Before: DataHavenServiceManager → ServiceManagerBase →
ServiceManagerBaseStorage → OwnableUpgradeable
After: DataHavenServiceManager → OwnableUpgradeable, IAVSRegistrar,
IDataHavenServiceManager

  ### Removed (unused)
- `IServiceManager` and `IServiceManagerUI` interfaces (old AVSDirectory
model)
  - `ServiceManagerBase` and `ServiceManagerBaseStorage` middleware
  - `PermissionController` integration (5 proxy functions)
  - `createOperatorSets()` - only needed at initialization
  - `avs()` - never called

  ### Kept (with fixes)
- `deregisterOperatorFromOperatorSets()` - added `onlyOwner` modifier
(security fix)
  - `updateAVSMetadataURI()` - needed for EigenLayer registration

  ### Files Deleted
  - `src/interfaces/IServiceManager.sol`
  - `src/interfaces/IServiceManagerUI.sol`
  - `src/middleware/ServiceManagerBase.sol`
  - `src/middleware/ServiceManagerBaseStorage.sol`
  - `test/mocks/ServiceManagerMock.sol`
  - `test/ServiceManagerBase.t.sol`

  ## Test Plan

  - [x] `forge build` passes
  - [x] `forge test` - all 10 tests pass
  - [x] Contract bindings regenerated
  - [x] State diff regenerated
2026-01-13 15:03:10 +01:00
Ahmad Kaouk
9be1acc97e
refactor: cleanup old rewards model (#383)
## Summary

This PR removes the old merkle root-based rewards model and completes
the migration to EigenLayer Rewards V2 distribution. The old model
required operators to claim rewards by providing merkle proofs, while
the new model uses `submitRewards` to send rewards directly to
EigenLayer's `RewardsCoordinator`.

### Key Changes

- **Smart Contracts**: Removed `RewardsRegistry`,
`RewardsRegistryStorage`, `IRewardsRegistry`, and `SortedMerkleProof`
contracts along with all merkle claim functions from
`ServiceManagerBase`
- **Substrate Pallets**: Removed merkle proof generation from
`external-validators-rewards` pallet and deleted the entire
`runtime-api` crate (no longer needed)
- **Test Framework**: Removed all RewardsRegistry-related code from
deployment scripts, CLI handlers, and TypeScript bindings
- **Runtimes**: Cleaned up all three runtimes (testnet, stagenet,
mainnet) to remove runtime API implementations and unused imports

### Files Removed

**Contracts:**
- `contracts/src/middleware/RewardsRegistry.sol`
- `contracts/src/middleware/RewardsRegistryStorage.sol`
- `contracts/src/interfaces/IRewardsRegistry.sol`
- `contracts/src/libraries/SortedMerkleProof.sol`
- `contracts/test/RewardsRegistry.t.sol`
- `contracts/test/ServiceManagerRewardsRegistry.t.sol`

**Substrate:**
- `operator/pallets/external-validators-rewards/runtime-api/` (entire
crate)

**Test Framework:**
- `test/suites/rewards-message.test.ts`

### Files Modified

**Contracts:**
- `ServiceManagerBase.sol` - Removed merkle claim functions
- `ServiceManagerBaseStorage.sol` - Removed
`operatorSetToRewardsRegistry` mapping
- `IServiceManager.sol` - Removed interface members

**Substrate:**
- `external-validators-rewards` pallet - Removed merkle proof
generation, simplified `EraRewardsUtils` struct
- All runtime configs - Removed `ExternalValidatorsRewardsApi`
implementations

**Test Framework:**
- Updated deployment scripts, CLI handlers, relayer configs, and
TypeScript bindings

### Stats

```
50 files changed, 966 insertions(+), 4453 deletions(-)
```

## Test plan

- [x] All Rust tests pass (`cargo test`)
- [x] All contract tests pass (`forge test`)
- [x] TypeScript type checking passes (`bun typecheck`)
- [x] Contracts build successfully (`forge build`)
- [x] Operator builds successfully (`cargo build --release --features
fast-runtime`)
- [ ] E2E tests pass (`bun test:e2e`)
2026-01-09 15:25:49 +01:00
undercover-cactus
863250d555
misc: remove slasher middleware solidity contracts (#366)
## Summary

This PR remove the middlewares contracts from eigen layer. Instead we
are planning to use the eigne layer contract directly. It also removes
the tests related to the middleware slasher code and the mock contract
used in it.

## Motivation

When slashing an operator in the Dathaven we are going through the
substrate slashing pallet already implemented. It already allow to
configure a slashing window and/or to cancel a slashing. In the future
it will also be compatible with a government pallet. This part of code
is therefore redundant. For the same reason we remove the tests because
we are not using the slashing middleware contracts.

## What changed

* Remove the slasher middleware files
* Remove the tests related to the middleware slasher file
2025-12-29 14:55:21 +01:00
Ahmad Kaouk
470f5fc916
feat: update eigenlayer contracts to v1.8.0 (#270)
## Summary
- sync `contracts/lib/eigenlayer-contracts` to tag
`v1.8.0-testnet-final` and refresh `EIGENLAYER.md` with the new commit
reference
- update local/test deployment flows to deploy the upstream
`EigenStrategy`, feed it into `AllocationManager`/`StrategyManager`, and
adopt the revised `EigenPod` constructor
- drop the obsolete `AllocationManagerMock` stub and replace its usage
with targeted `vm.mockCall` stubs that return `slashOperator` share data
- adjust slasher unit tests to match the new ABI so DataHaven stays
aligned with EigenLayer 1.8 semantics

## Testing
- forge build
- forge test
2025-11-04 16:30:18 +01:00
Steve Degosserie
387c056912
fix: Resolve Foundry build errors and apply code formatting (#241)
## Summary

Fixes the CI build failure in the `task-ts-build` workflow caused by
Foundry v1.4.2's Solar linter not being able to resolve Snowbridge's
context-specific import remappings.

## Problem

The Snowbridge submodule uses context-specific remappings (prefixed with
`:`) for its dependencies:
- `lib/snowbridge/contracts/:openzeppelin/` → OpenZeppelin contracts
- `lib/snowbridge/contracts/:prb/math/` → PRB Math library

Foundry v1.4.2's Solar linter doesn't understand these context-specific
remappings and fails with errors like:
```
error: file openzeppelin/utils/cryptography/MerkleProof.sol not found
error: file prb/math/src/UD60x18.sol not found
```

## Solution

Added global remappings that the linter can understand:
```toml
"openzeppelin/=lib/snowbridge/contracts/lib/openzeppelin-contracts/contracts/",
"prb/math/=lib/snowbridge/contracts/lib/prb-math/",
```

### Why This Works
- The linter can now resolve `openzeppelin/` and `prb/math/` imports
globally
- These global remappings take **lower precedence** than
context-specific ones during compilation
- The compiler still uses the context-specific remappings (with `:`)
when compiling Snowbridge contracts
- The linter uses the global remappings when checking all files

## Changes

### Commit 1: Add global remappings
- `contracts/foundry.toml`: Added 2 global remapping entries

### Commit 2: Apply forge fmt
- Applied automatic formatting via `forge fmt` to ensure code style
consistency
- Multi-line formatting for long import statements and function
signatures
- No functional changes - purely formatting updates

## Testing

 Local build succeeds with `forge build`
 No Snowbridge import resolution errors
 `forge fmt --check` passes with no formatting issues
 Only linting notes/warnings remain (not errors)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-20 11:20:59 +03:00
Facundo Farall
3fa11e8f91
chore: ⬆️ Update contract dependencies as submodules (#48) 2025-04-21 17:46:58 -03:00
Facundo Farall
5baa789f52
feat: Relay Validators operator set through Snowbridge (#39)
In this PR:
1. Implement application-specific functionalities in the
`DataHavenServiceManager` contract:
    1. Registering of 3 operator sets: Validators, BSPs and MSPs.
    2. Allowlisted sign up of operators.
    3. Integration with Snowbridge to send message of new validator set.
2. Basic testing of the above functionalities.
3. Tests now use less mocked contracts (especially from EigenLayer).
4. Refactor of `SignUpOperator` script, which now supports the three
kinds of Operator sets.
2025-04-16 15:49:35 +00:00
Facundo Farall
75e39ff98f
feat(contracts): 🚀 Implement deployment scripts for all contracts (#28)
In this PR:
1. Implement deployment script for all contracts involved. This includes
    1. EigenLayer core contracts.
    2. Snowbridge contracts.
    3. Our custom contracts to interact with both protocols.
4. Update README to document functionalities of `contracts` directory.

Future work:
1. Deployment of EigenLayer contracts should be conditional, as we
wouldn't deploy them in testnet or mainnet, but we would do it in an
internal stagenet.
5. Cleaning up unused smart contracts.
2025-04-03 14:06:32 -03:00
Tobi Demeco
13fafcf2b7
feat: initial rewards registry (#17)
This PR adds an initial implementation for a rewards registry, which
will be the contract in charge of allowing DataHaven validators to claim
the rewards they earned for being validators in the previous epoch. The
logic behind it is as follows:
- Whenever an epoch finishes, the corresponding BEEFY block gets relayed
to Ethereum through Snowbridge. This BEEFY block contains, in its
`extra` field, the merkle root of the tree that contains as leafs all
the message commitments of the messages of corresponding block, one of
which is the rewards distribution message.
- The rewards distribution message commitment is the root of the merkle
tree where each leaf is a tuple of the operator ID and the obtained era
points in the finished epoch. In this case, the operator ID is the
corresponding validator's Ethereum address.
- When the rewards distribution message is received, Snowbridge
validates it using the aforementioned BEEFY block and then dispatches
it. The dispatch invokes the `callContract` function of the
`RewardsAgent` agent, with the corresponding parameters so that this
agent calls the `updateRewardsMerkleRoot` function of the
`RewardsRegistry` contract with the new rewards distribution message
commitment.
- After this root is updated, any validator/operator can submit a proof
that it is in a leaf of the merkle tree that produced that root, which
means it has pending rewards to claim, through the
`ServiceManagerBase`'s `claimOperatorRewards` function.
- Each operator set of the AVS can have an assigned `RewardsRegistry`
contract. Operator sets that do not have an assigned `RewardsRegistry`
contract won't be able to received rewards.

This PR also adds two separate unit-test suites: one for the added
functionality to the `ServiceManagerBase` contract and one specific to
the new `RewardsRegistry` contract.

> [!CAUTION]
The `RewardsAgent` agent is the only one allowed to update the rewards'
merkle root, which means if a malicious user could get access to it it
could set the pending rewards to be claimed to an arbitrary tree that
benefits it. Extreme caution must be taken in the Substrate side so only
validated messages are sent to the Ethereum side, as to not allow any
users to impersonate being this agent.

### TODO:
Ideally, we would use the `RewardsCoordinator` contract from the
EigenLayer core to distribute the rewards, but currently that adds a
huge overhead for Operators since they'd have to wait for EigenLayer's
SideCar to snapshot state and update the distribution root (which
happens once a day), generate a proof that they belong to the tree of
that distribution root, store it while waiting for the `activationDelay`
(currently a week) to pass, and just then they would be able to claim
their earned rewards.

---------

Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-03-31 19:54:23 +00:00
Tobi Demeco
d8d792874c
feat: initial slasher implementation (#10)
This PR:
- Sets up the slasher infrastructure with the base functionality
required (in `ISlasher.sol`, `SlasherBase.sol` and
`SlasherBaseStorage.sol`) and adds the tests for it (in
`SlasherBase.t.sol`).
- Adds an implementation of a more complex slasher (in
`IVetoableSlasher.sol` and `VetoableSlasher.sol`) and tests for it (in
`VetoableSlasher.t.sol`).
- Modifies the `ServiceManagerBase` contract to use the new
`VetoableSlasher` contract to manage slashing.
- Updates mocks and tests to reflect the newly added functionality.

---------

Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-03-27 15:20:15 +00:00
Facundo Farall
a78cb3ce41
feat: 🏗️ Setup basic AVS contract (#4)
* forge install: eigenlayer-contracts

v1.1.1

* fix: 🗑️ Cleanup dependencies from init

* forge install: forge-std

v1.9.6

* forge install: openzeppelin-contracts

v5.2.0

* forge install: openzeppelin-contracts-upgradeable

v5.2.0

* chore: 🙈 Ignore IDE directories

* chore: 🏗️ Modify config in `foundry.toml` based on EigenLayer's example

* feat: 🚧 Add `ServiceManagerBase` contract and dependencies based on eigenlayer-middleware

* feat: 🚧 Naive implementation of missing functions replacing AVSDirectory for AllocationManager

* docs: 📝 Add first draft of contracts diagram

* refactor: 🔥 Remove unnecessary functions and refactor most important ones to the top

* docs: 📝 Update contracts diagram

* docs: 📝 Update contracts diagram

* feat:  Implement basic mocked Service Manager

* test: 🚧 Cleanup and start testing setup for mock ServiceManagerBase

* test: 🤡 Add mocks to setup tests

* test: 🤡 Add deployment of RewardsCoordinator

* test:  Deploy EigenLayer mocked contracts in test

* revert:  Remove proglematic submodules

* revert:  Remove forge-std dependency

* forge install: forge-std

v1.9.6

* forge install: openzeppelin-contracts

v5.2.0

* forge install: openzeppelin-contracts-upgradeable

v5.2.0

* forge install: eigenlayer-contracts

v1.3.0

* revert:  Remove faulty dependency

* forge install: eigenlayer-contracts

v1.3.0

* revert:  remove added dependency

* forge install: eigenlayer-contracts

v1.3.0

* revert:  Remove openzeppelin dependencies from root project

* test: 🚧 Make test run after dependency mayhem

* test:  Add passing createOperatorSets test with empty params

* style: 🎨 Apply forge fmt
2025-03-11 17:16:16 -03:00