datahaven/contracts/test/mocks/ServiceManagerMock.sol

62 lines
2.1 KiB
Solidity
Raw Permalink Normal View History

feat: 🏗️ Setup basic AVS contract (#4) * forge install: eigenlayer-contracts v1.1.1 * fix: :wastebasket: 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: :see_no_evil: Ignore IDE directories * chore: :building_construction: Modify config in `foundry.toml` based on EigenLayer's example * feat: :construction: Add `ServiceManagerBase` contract and dependencies based on eigenlayer-middleware * feat: :construction: Naive implementation of missing functions replacing AVSDirectory for AllocationManager * docs: :memo: Add first draft of contracts diagram * refactor: :fire: Remove unnecessary functions and refactor most important ones to the top * docs: :memo: Update contracts diagram * docs: :memo: Update contracts diagram * feat: :sparkles: Implement basic mocked Service Manager * test: :construction: Cleanup and start testing setup for mock ServiceManagerBase * test: :clown_face: Add mocks to setup tests * test: :clown_face: Add deployment of RewardsCoordinator * test: :white_check_mark: Deploy EigenLayer mocked contracts in test * revert: :heavy_minus_sign: Remove proglematic submodules * revert: :heavy_minus_sign: 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: :heavy_minus_sign: Remove faulty dependency * forge install: eigenlayer-contracts v1.3.0 * revert: :heavy_minus_sign: remove added dependency * forge install: eigenlayer-contracts v1.3.0 * revert: :heavy_minus_sign: Remove openzeppelin dependencies from root project * test: :construction: Make test run after dependency mayhem * test: :white_check_mark: Add passing createOperatorSets test with empty params * style: :art: Apply forge fmt
2025-03-11 20:16:16 +00:00
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
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 08:20:59 +00:00
import {
IRewardsCoordinator
} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
import {
IPermissionController
} from "eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol";
import {
IAllocationManager
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
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
import {IRewardsRegistry} from "../../src/interfaces/IRewardsRegistry.sol";
feat: 🏗️ Setup basic AVS contract (#4) * forge install: eigenlayer-contracts v1.1.1 * fix: :wastebasket: 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: :see_no_evil: Ignore IDE directories * chore: :building_construction: Modify config in `foundry.toml` based on EigenLayer's example * feat: :construction: Add `ServiceManagerBase` contract and dependencies based on eigenlayer-middleware * feat: :construction: Naive implementation of missing functions replacing AVSDirectory for AllocationManager * docs: :memo: Add first draft of contracts diagram * refactor: :fire: Remove unnecessary functions and refactor most important ones to the top * docs: :memo: Update contracts diagram * docs: :memo: Update contracts diagram * feat: :sparkles: Implement basic mocked Service Manager * test: :construction: Cleanup and start testing setup for mock ServiceManagerBase * test: :clown_face: Add mocks to setup tests * test: :clown_face: Add deployment of RewardsCoordinator * test: :white_check_mark: Deploy EigenLayer mocked contracts in test * revert: :heavy_minus_sign: Remove proglematic submodules * revert: :heavy_minus_sign: 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: :heavy_minus_sign: Remove faulty dependency * forge install: eigenlayer-contracts v1.3.0 * revert: :heavy_minus_sign: remove added dependency * forge install: eigenlayer-contracts v1.3.0 * revert: :heavy_minus_sign: Remove openzeppelin dependencies from root project * test: :construction: Make test run after dependency mayhem * test: :white_check_mark: Add passing createOperatorSets test with empty params * style: :art: Apply forge fmt
2025-03-11 20:16:16 +00:00
import {ServiceManagerBase} from "../../src/middleware/ServiceManagerBase.sol";
/**
* @title Minimal implementation of a ServiceManager-type contract.
* Uses the ServiceManagerBase contract as is.
*/
contract ServiceManagerMock is ServiceManagerBase {
uint256 public number;
/// @notice Sets the (immutable) `_registryCoordinator` address
constructor(
IRewardsCoordinator __rewardsCoordinator,
IPermissionController __permissionController,
IAllocationManager __allocationManager
) ServiceManagerBase(__rewardsCoordinator, __permissionController, __allocationManager) {}
function initialise(
feat: 🏗️ Setup basic AVS contract (#4) * forge install: eigenlayer-contracts v1.1.1 * fix: :wastebasket: 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: :see_no_evil: Ignore IDE directories * chore: :building_construction: Modify config in `foundry.toml` based on EigenLayer's example * feat: :construction: Add `ServiceManagerBase` contract and dependencies based on eigenlayer-middleware * feat: :construction: Naive implementation of missing functions replacing AVSDirectory for AllocationManager * docs: :memo: Add first draft of contracts diagram * refactor: :fire: Remove unnecessary functions and refactor most important ones to the top * docs: :memo: Update contracts diagram * docs: :memo: Update contracts diagram * feat: :sparkles: Implement basic mocked Service Manager * test: :construction: Cleanup and start testing setup for mock ServiceManagerBase * test: :clown_face: Add mocks to setup tests * test: :clown_face: Add deployment of RewardsCoordinator * test: :white_check_mark: Deploy EigenLayer mocked contracts in test * revert: :heavy_minus_sign: Remove proglematic submodules * revert: :heavy_minus_sign: 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: :heavy_minus_sign: Remove faulty dependency * forge install: eigenlayer-contracts v1.3.0 * revert: :heavy_minus_sign: remove added dependency * forge install: eigenlayer-contracts v1.3.0 * revert: :heavy_minus_sign: Remove openzeppelin dependencies from root project * test: :construction: Make test run after dependency mayhem * test: :white_check_mark: Add passing createOperatorSets test with empty params * style: :art: Apply forge fmt
2025-03-11 20:16:16 +00:00
address initialOwner,
address rewardsInitiator
) public virtual initializer {
__ServiceManagerBase_init(initialOwner, rewardsInitiator);
}
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
/**
* @notice Get the rewards registry for an operator set (exposing for testing)
* @param operatorSetId The ID of the operator set
* @return The rewards registry for the operator set
*/
function getOperatorSetRewardsRegistry(
uint32 operatorSetId
) external view returns (IRewardsRegistry) {
return operatorSetToRewardsRegistry[operatorSetId];
}
/**
* @notice Override the internal _ensureOperatorIsPartOfOperatorSet function to simplify testing
* @param operator The operator address
* @param operatorSetId The operator set ID
* @dev This should be removed once the AllocationManagerMock is updated to be able to handle operator sets
*/
function _ensureOperatorIsPartOfOperatorSet(
address operator,
uint32 operatorSetId
) internal view override {
// No-op for testing
}
feat: 🏗️ Setup basic AVS contract (#4) * forge install: eigenlayer-contracts v1.1.1 * fix: :wastebasket: 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: :see_no_evil: Ignore IDE directories * chore: :building_construction: Modify config in `foundry.toml` based on EigenLayer's example * feat: :construction: Add `ServiceManagerBase` contract and dependencies based on eigenlayer-middleware * feat: :construction: Naive implementation of missing functions replacing AVSDirectory for AllocationManager * docs: :memo: Add first draft of contracts diagram * refactor: :fire: Remove unnecessary functions and refactor most important ones to the top * docs: :memo: Update contracts diagram * docs: :memo: Update contracts diagram * feat: :sparkles: Implement basic mocked Service Manager * test: :construction: Cleanup and start testing setup for mock ServiceManagerBase * test: :clown_face: Add mocks to setup tests * test: :clown_face: Add deployment of RewardsCoordinator * test: :white_check_mark: Deploy EigenLayer mocked contracts in test * revert: :heavy_minus_sign: Remove proglematic submodules * revert: :heavy_minus_sign: 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: :heavy_minus_sign: Remove faulty dependency * forge install: eigenlayer-contracts v1.3.0 * revert: :heavy_minus_sign: remove added dependency * forge install: eigenlayer-contracts v1.3.0 * revert: :heavy_minus_sign: Remove openzeppelin dependencies from root project * test: :construction: Make test run after dependency mayhem * test: :white_check_mark: Add passing createOperatorSets test with empty params * style: :art: Apply forge fmt
2025-03-11 20:16:16 +00:00
}