2025-03-11 20:16:16 +00:00
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
|
pragma solidity ^0.8.27;
|
|
|
|
|
|
2026-01-22 12:48:27 +00:00
|
|
|
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
|
|
|
|
|
import {
|
|
|
|
|
TransparentUpgradeableProxy,
|
|
|
|
|
ITransparentUpgradeableProxy
|
|
|
|
|
} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
|
2025-03-11 20:16:16 +00:00
|
|
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
2026-01-22 12:48:27 +00:00
|
|
|
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
|
2025-03-11 20:16:16 +00:00
|
|
|
|
|
|
|
|
import {PauserRegistry} from "eigenlayer-contracts/src/contracts/permissions/PauserRegistry.sol";
|
|
|
|
|
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
|
|
|
|
|
import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol";
|
|
|
|
|
import {RewardsCoordinator} from "eigenlayer-contracts/src/contracts/core/RewardsCoordinator.sol";
|
|
|
|
|
import {AllocationManager} from "eigenlayer-contracts/src/contracts/core/AllocationManager.sol";
|
|
|
|
|
import {
|
|
|
|
|
IRewardsCoordinator,
|
|
|
|
|
IRewardsCoordinatorTypes
|
|
|
|
|
} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
|
|
|
|
|
import {EmptyContract} from "eigenlayer-contracts/src/test/mocks/EmptyContract.sol";
|
|
|
|
|
import {StrategyBase} from "eigenlayer-contracts/src/contracts/strategies/StrategyBase.sol";
|
2025-11-04 15:30:18 +00:00
|
|
|
import {EigenStrategy} from "eigenlayer-contracts/src/contracts/strategies/EigenStrategy.sol";
|
2025-04-21 20:46:58 +00:00
|
|
|
import {EigenPodManagerMock} from "eigenlayer-contracts/src/test/mocks/EigenPodManagerMock.sol";
|
|
|
|
|
import {StrategyManager} from "eigenlayer-contracts/src/contracts/core/StrategyManager.sol";
|
|
|
|
|
import {IEigenPodManager} from "eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol";
|
2025-03-11 20:16:16 +00:00
|
|
|
import {ERC20FixedSupply} from "./ERC20FixedSupply.sol";
|
2025-04-16 15:49:35 +00:00
|
|
|
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
|
2025-03-11 20:16:16 +00:00
|
|
|
// Mocks
|
|
|
|
|
import {RewardsCoordinatorMock} from "../mocks/RewardsCoordinatorMock.sol";
|
|
|
|
|
import {PermissionControllerMock} from "../mocks/PermissionControllerMock.sol";
|
2026-01-20 10:32:32 +00:00
|
|
|
import {SnowbridgeGatewayMock} from "../mocks/SnowbridgeGatewayMock.sol";
|
2025-04-16 15:49:35 +00:00
|
|
|
import {DelegationManager} from "eigenlayer-contracts/src/contracts/core/DelegationManager.sol";
|
2025-03-11 20:16:16 +00:00
|
|
|
|
2026-01-22 12:48:27 +00:00
|
|
|
import {Test, console, Vm} from "forge-std/Test.sol";
|
2025-03-11 20:16:16 +00:00
|
|
|
|
2025-04-16 15:49:35 +00:00
|
|
|
contract AVSDeployer is Test {
|
2026-01-22 12:48:27 +00:00
|
|
|
using SafeCast for uint256;
|
|
|
|
|
|
2025-04-11 23:54:20 +00:00
|
|
|
Vm public cheats = Vm(VM_ADDRESS);
|
2025-03-11 20:16:16 +00:00
|
|
|
|
|
|
|
|
ProxyAdmin public proxyAdmin;
|
|
|
|
|
PauserRegistry public pauserRegistry;
|
|
|
|
|
|
|
|
|
|
EmptyContract public emptyContract;
|
|
|
|
|
|
|
|
|
|
// AVS contracts
|
2025-04-16 15:49:35 +00:00
|
|
|
DataHavenServiceManager public serviceManager;
|
|
|
|
|
DataHavenServiceManager public serviceManagerImplementation;
|
2025-03-27 15:20:15 +00:00
|
|
|
|
2025-03-11 20:16:16 +00:00
|
|
|
// EigenLayer contracts
|
2025-04-16 15:49:35 +00:00
|
|
|
StrategyManager public strategyManager;
|
|
|
|
|
StrategyManager public strategyManagerImplementation;
|
|
|
|
|
DelegationManager public delegationManager;
|
|
|
|
|
DelegationManager public delegationManagerImplementation;
|
2025-03-11 20:16:16 +00:00
|
|
|
EigenPodManagerMock public eigenPodManagerMock;
|
|
|
|
|
AllocationManager public allocationManager;
|
|
|
|
|
AllocationManager public allocationManagerImplementation;
|
2025-11-04 15:30:18 +00:00
|
|
|
IStrategy public eigenStrategy;
|
2025-03-11 20:16:16 +00:00
|
|
|
RewardsCoordinator public rewardsCoordinator;
|
|
|
|
|
RewardsCoordinator public rewardsCoordinatorImplementation;
|
|
|
|
|
RewardsCoordinatorMock public rewardsCoordinatorMock;
|
|
|
|
|
PermissionControllerMock public permissionControllerMock;
|
2026-01-20 10:32:32 +00:00
|
|
|
SnowbridgeGatewayMock public snowbridgeGatewayMock;
|
2025-03-11 20:16:16 +00:00
|
|
|
|
|
|
|
|
// Addresses
|
|
|
|
|
address public proxyAdminOwner = address(uint160(uint256(keccak256("proxyAdminOwner"))));
|
|
|
|
|
address public regularDeployer = address(uint160(uint256(keccak256("regularDeployer"))));
|
|
|
|
|
address public avsOwner = address(uint160(uint256(keccak256("avsOwner"))));
|
|
|
|
|
address public rewardsInitiator = address(uint160(uint256(keccak256("rewardsInitiator"))));
|
|
|
|
|
address public pauser = address(uint160(uint256(keccak256("pauser"))));
|
|
|
|
|
address public unpauser = address(uint160(uint256(keccak256("unpauser"))));
|
|
|
|
|
address public rewardsUpdater = address(uint160(uint256(keccak256("rewardsUpdater"))));
|
|
|
|
|
address public strategyOwner = address(uint160(uint256(keccak256("strategyOwner"))));
|
|
|
|
|
|
|
|
|
|
// RewardsCoordinator constants
|
2025-04-11 23:54:20 +00:00
|
|
|
uint32 public constant CALCULATION_INTERVAL_SECONDS = 7 days;
|
|
|
|
|
uint32 public constant MAX_REWARDS_DURATION = 70 days;
|
|
|
|
|
uint32 public constant MAX_RETROACTIVE_LENGTH = 84 days;
|
|
|
|
|
uint32 public constant MAX_FUTURE_LENGTH = 28 days;
|
|
|
|
|
uint32 public constant GENESIS_REWARDS_TIMESTAMP = 1712188800;
|
2025-03-11 20:16:16 +00:00
|
|
|
|
|
|
|
|
/// @notice Delay in timestamp before a posted root can be claimed against
|
2025-04-11 23:54:20 +00:00
|
|
|
uint32 public activationDelay = 7 days;
|
2025-03-11 20:16:16 +00:00
|
|
|
/// @notice the commission for all operators across all AVSs
|
2025-04-11 23:54:20 +00:00
|
|
|
uint16 public globalCommissionBips = 1000;
|
2025-03-11 20:16:16 +00:00
|
|
|
|
|
|
|
|
// Mock strategies
|
2025-04-11 23:54:20 +00:00
|
|
|
IERC20[] public rewardTokens;
|
|
|
|
|
uint256 public mockTokenInitialSupply = 10e50;
|
|
|
|
|
IStrategy[] public deployedStrategies;
|
|
|
|
|
StrategyBase public strategyImplementation;
|
|
|
|
|
IRewardsCoordinator.StrategyAndMultiplier[] public defaultStrategyAndMultipliers;
|
2025-03-11 20:16:16 +00:00
|
|
|
|
|
|
|
|
function _deployMockEigenLayerAndAVS() internal {
|
|
|
|
|
emptyContract = new EmptyContract();
|
|
|
|
|
|
|
|
|
|
// Deploy EigenLayer core contracts.
|
|
|
|
|
cheats.startPrank(proxyAdminOwner);
|
|
|
|
|
proxyAdmin = new ProxyAdmin();
|
|
|
|
|
cheats.stopPrank();
|
|
|
|
|
|
|
|
|
|
console.log("ProxyAdmin deployed");
|
|
|
|
|
|
|
|
|
|
cheats.startPrank(regularDeployer);
|
|
|
|
|
address[] memory pausers = new address[](1);
|
|
|
|
|
pausers[0] = pauser;
|
|
|
|
|
pauserRegistry = new PauserRegistry(pausers, unpauser);
|
|
|
|
|
eigenPodManagerMock = new EigenPodManagerMock(pauserRegistry);
|
|
|
|
|
permissionControllerMock = new PermissionControllerMock();
|
|
|
|
|
rewardsCoordinatorMock = new RewardsCoordinatorMock();
|
2026-01-20 10:32:32 +00:00
|
|
|
snowbridgeGatewayMock = new SnowbridgeGatewayMock();
|
2025-03-11 20:16:16 +00:00
|
|
|
cheats.stopPrank();
|
|
|
|
|
|
2025-04-16 15:49:35 +00:00
|
|
|
console.log("Mock EigenLayer contracts deployed");
|
2025-03-11 20:16:16 +00:00
|
|
|
|
2025-04-16 15:49:35 +00:00
|
|
|
// Deploying proxy contracts for AllocationManager and StrategyManager.
|
2025-03-11 20:16:16 +00:00
|
|
|
// The `proxyAdmin` contract is set as the admin of the proxy contracts,
|
|
|
|
|
// which will be later upgraded to the actual implementation.
|
|
|
|
|
cheats.prank(regularDeployer);
|
|
|
|
|
allocationManager = AllocationManager(
|
|
|
|
|
address(
|
|
|
|
|
new TransparentUpgradeableProxy(address(emptyContract), address(proxyAdmin), "")
|
|
|
|
|
)
|
|
|
|
|
);
|
2025-04-16 15:49:35 +00:00
|
|
|
strategyManager = StrategyManager(
|
|
|
|
|
address(
|
|
|
|
|
new TransparentUpgradeableProxy(address(emptyContract), address(proxyAdmin), "")
|
|
|
|
|
)
|
|
|
|
|
);
|
2025-03-11 20:16:16 +00:00
|
|
|
|
2025-04-16 15:49:35 +00:00
|
|
|
console.log("AllocationManager and StrategyManager proxy contracts deployed");
|
2025-03-11 20:16:16 +00:00
|
|
|
|
2025-11-04 15:30:18 +00:00
|
|
|
cheats.prank(regularDeployer);
|
|
|
|
|
eigenStrategy =
|
|
|
|
|
IStrategy(address(new EigenStrategy(strategyManager, pauserRegistry, "v-mock")));
|
|
|
|
|
|
|
|
|
|
console.log("EigenStrategy deployed");
|
|
|
|
|
|
2025-04-16 15:49:35 +00:00
|
|
|
// Deploying DelegationManager implementation and its proxy.
|
|
|
|
|
cheats.prank(regularDeployer);
|
|
|
|
|
delegationManagerImplementation = new DelegationManager(
|
|
|
|
|
strategyManager,
|
2025-04-21 20:46:58 +00:00
|
|
|
IEigenPodManager(address(eigenPodManagerMock)),
|
2025-04-16 15:49:35 +00:00
|
|
|
allocationManager,
|
|
|
|
|
pauserRegistry,
|
|
|
|
|
permissionControllerMock,
|
|
|
|
|
uint32(10), // MIN_WITHDRAWAL_DELAY_BLOCKS
|
|
|
|
|
"v-mock"
|
|
|
|
|
);
|
|
|
|
|
cheats.prank(regularDeployer);
|
|
|
|
|
delegationManager = DelegationManager(
|
|
|
|
|
address(
|
|
|
|
|
new TransparentUpgradeableProxy(
|
|
|
|
|
address(delegationManagerImplementation), address(proxyAdmin), ""
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
);
|
2025-03-11 20:16:16 +00:00
|
|
|
// Deploying AllocationManager implementation and upgrading the proxy.
|
|
|
|
|
cheats.prank(regularDeployer);
|
|
|
|
|
allocationManagerImplementation = new AllocationManager(
|
2025-04-16 15:49:35 +00:00
|
|
|
delegationManager,
|
2025-11-04 15:30:18 +00:00
|
|
|
eigenStrategy,
|
2025-03-11 20:16:16 +00:00
|
|
|
pauserRegistry,
|
|
|
|
|
permissionControllerMock,
|
|
|
|
|
uint32(7 days), // DEALLOCATION_DELAY
|
|
|
|
|
uint32(1 days), // ALLOCATION_CONFIGURATION_DELAY
|
|
|
|
|
"v-mock"
|
|
|
|
|
);
|
|
|
|
|
cheats.prank(proxyAdminOwner);
|
|
|
|
|
proxyAdmin.upgrade(
|
|
|
|
|
ITransparentUpgradeableProxy(address(allocationManager)),
|
|
|
|
|
address(allocationManagerImplementation)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
console.log("AllocationManager implementation deployed");
|
|
|
|
|
|
2025-04-16 15:49:35 +00:00
|
|
|
// Deploying StrategyManager implementation and its proxy.
|
|
|
|
|
cheats.prank(regularDeployer);
|
|
|
|
|
strategyManagerImplementation =
|
2025-11-04 15:30:18 +00:00
|
|
|
new StrategyManager(allocationManager, delegationManager, pauserRegistry, "v-mock");
|
2025-04-16 15:49:35 +00:00
|
|
|
cheats.prank(proxyAdminOwner);
|
|
|
|
|
uint256 allUnpaused = 0;
|
|
|
|
|
proxyAdmin.upgradeAndCall(
|
|
|
|
|
ITransparentUpgradeableProxy(address(strategyManager)),
|
|
|
|
|
address(strategyManagerImplementation),
|
|
|
|
|
abi.encodeWithSelector(
|
|
|
|
|
StrategyManager.initialize.selector, strategyOwner, strategyOwner, allUnpaused
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
console.log("StrategyManager implementation deployed");
|
|
|
|
|
|
2025-03-11 20:16:16 +00:00
|
|
|
// Deploying RewardsCoordinator implementation and its proxy.
|
|
|
|
|
// When the proxy is deployed, the `initialize` function is called.
|
|
|
|
|
cheats.startPrank(regularDeployer);
|
|
|
|
|
IRewardsCoordinatorTypes.RewardsCoordinatorConstructorParams memory params =
|
2025-10-20 08:20:59 +00:00
|
|
|
IRewardsCoordinatorTypes.RewardsCoordinatorConstructorParams({
|
|
|
|
|
delegationManager: delegationManager,
|
|
|
|
|
strategyManager: IStrategyManager(address(strategyManager)),
|
|
|
|
|
allocationManager: allocationManager,
|
|
|
|
|
pauserRegistry: pauserRegistry,
|
|
|
|
|
permissionController: permissionControllerMock,
|
|
|
|
|
CALCULATION_INTERVAL_SECONDS: CALCULATION_INTERVAL_SECONDS,
|
|
|
|
|
MAX_REWARDS_DURATION: MAX_REWARDS_DURATION,
|
|
|
|
|
MAX_RETROACTIVE_LENGTH: MAX_RETROACTIVE_LENGTH,
|
|
|
|
|
MAX_FUTURE_LENGTH: MAX_FUTURE_LENGTH,
|
|
|
|
|
GENESIS_REWARDS_TIMESTAMP: GENESIS_REWARDS_TIMESTAMP,
|
|
|
|
|
version: "v-mock"
|
|
|
|
|
});
|
2025-03-11 20:16:16 +00:00
|
|
|
rewardsCoordinatorImplementation = new RewardsCoordinator(params);
|
|
|
|
|
rewardsCoordinator = RewardsCoordinator(
|
|
|
|
|
address(
|
|
|
|
|
new TransparentUpgradeableProxy(
|
|
|
|
|
address(rewardsCoordinatorImplementation),
|
|
|
|
|
address(proxyAdmin),
|
|
|
|
|
abi.encodeWithSelector(
|
|
|
|
|
RewardsCoordinator.initialize.selector,
|
|
|
|
|
msg.sender,
|
|
|
|
|
0, /*initialPausedStatus*/
|
|
|
|
|
rewardsUpdater,
|
|
|
|
|
activationDelay,
|
|
|
|
|
globalCommissionBips
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
cheats.stopPrank();
|
|
|
|
|
|
|
|
|
|
console.log("RewardsCoordinator implementation deployed");
|
|
|
|
|
|
2025-04-16 15:49:35 +00:00
|
|
|
// Set up strategies before deploying the ServiceManager
|
|
|
|
|
_setUpDefaultStrategiesAndMultipliers();
|
|
|
|
|
|
2025-03-11 20:16:16 +00:00
|
|
|
// Deploying ServiceManager implementation and its proxy.
|
|
|
|
|
// When the proxy is deployed, the `initialize` function is called.
|
|
|
|
|
cheats.startPrank(regularDeployer);
|
2026-01-13 14:03:10 +00:00
|
|
|
serviceManagerImplementation =
|
|
|
|
|
new DataHavenServiceManager(rewardsCoordinator, allocationManager);
|
2025-04-16 15:49:35 +00:00
|
|
|
|
|
|
|
|
serviceManager = DataHavenServiceManager(
|
2025-03-11 20:16:16 +00:00
|
|
|
address(
|
|
|
|
|
new TransparentUpgradeableProxy(
|
|
|
|
|
address(serviceManagerImplementation),
|
|
|
|
|
address(proxyAdmin),
|
|
|
|
|
abi.encodeWithSelector(
|
2026-01-20 10:32:32 +00:00
|
|
|
DataHavenServiceManager.initialize.selector,
|
2025-04-16 15:49:35 +00:00
|
|
|
avsOwner,
|
|
|
|
|
rewardsInitiator,
|
2026-02-24 08:23:57 +00:00
|
|
|
defaultStrategyAndMultipliers,
|
feat: automated validator set submission with era targeting (#433)
## Era-targeted validator set submission with dedicated submitter role
> **Note:** This PR includes a detailed specification at
[`specs/validator-set-submission/validator-set-submission.md`](https://github.com/datahaven-xyz/datahaven/blob/feat/validator-set-submitter/specs/validator-set-submission/validator-set-submission.md)
that covers the design rationale, submission lifecycle, era-targeting
rules, and failure modes. Reading the spec first will make the contract,
pallet, and daemon changes easier to follow.
### Summary
- Introduce a dedicated `validatorSetSubmitter` role on
`DataHavenServiceManager`, separating validator set submission authority
from the contract owner
- Replace the unscoped `sendNewValidatorSet` with
`sendNewValidatorSetForEra`, which encodes a `targetEra` into the
Snowbridge message payload
- Add server-side era validation in the `external-validators` pallet to
reject stale, duplicate, or out-of-range submissions
- Add a long-running TypeScript daemon that watches session changes and
automatically submits each era's validator set at the right time
### Contract changes (`contracts/`)
- **New `validatorSetSubmitter` storage slot** — set during `initialize`
and rotatable via `setValidatorSetSubmitter` (owner-only). The storage
gap is decremented accordingly.
- **`sendNewValidatorSet` → `sendNewValidatorSetForEra`** — accepts a
`uint64 targetEra` parameter and is restricted to
`onlyValidatorSetSubmitter` instead of `onlyOwner`.
- **`buildNewValidatorSetMessageForEra`** — the
`NewValidatorSetPayload.externalIndex` is now caller-supplied instead of
hardcoded to `0`.
- **New events** — `ValidatorSetSubmitterUpdated`,
`ValidatorSetMessageSubmitted`.
- **New error** — `OnlyValidatorSetSubmitter`.
- **New test suite** — `ValidatorSetSubmitter.t.sol` covering submitter
set/rotate, access control, era encoding, and legacy function removal.
### Pallet changes (`operator/`)
- **`validate_target_era`** in `external-validators` — enforces
`activeEra < targetEra <= activeEra + 1` and `targetEra > ExternalIndex`
(dedup guard).
- **New errors** — `TargetEraTooOld`, `TargetEraTooNew`,
`DuplicateOrStaleTargetEra`.
- **Tests** — five new test cases for era boundary conditions (next-era
acceptance, old-era rejection, too-new rejection, duplicate rejection,
genesis behavior). Existing `era_hooks_with_external_index` test updated
to use valid target eras.
- **Runtime test fixes** — `external_index: 0` → `1` in
mainnet/stagenet/testnet EigenLayer message processor tests to satisfy
the new validation.
### Validator set submitter daemon
(`test/tools/validator-set-submitter/`)
- Event-driven service that subscribes to finalized
`Session.CurrentIndex` via Polkadot-API `watchValue`.
- Submits once per era during the last session, targeting `ActiveEra +
1`.
- Tracks submitted eras to avoid duplicates; skips if `ExternalIndex`
already covers the target.
- Startup self-checks: Ethereum connectivity, DataHaven connectivity,
on-chain submitter authorization.
- Supports `--dry-run` mode and YAML configuration.
- Graceful shutdown on `SIGINT`/`SIGTERM`.
### Test & tooling updates
- **E2E test** (`validator-set-update.test.ts`) — calls
`sendNewValidatorSetForEra` with a computed `targetEra` and filters the
substrate event by `external_index`.
- **`update-validator-set.ts` script** — accepts `--target-era` flag;
defaults to era 1 for fresh networks.
- **CLI launch** — wires validator set update as an interactive step
after relayer launch.
- **`package.json`** — new `submitter` and `submitter:dry-run` scripts.
- Regenerated contract bindings, PAPI metadata, state-diff, and storage
layout snapshots.
### Test plan
- [x] `forge test` — passes, including new `ValidatorSetSubmitter.t.sol`
- [x] `cargo test` — passes, including new era-validation tests in
`external-validators`
- [x] `bun test:e2e` — validator-set-update suite passes with
era-targeted flow
- [x] Manual: run submitter daemon against local network (`bun
submitter`), verify it submits once per era at the correct session
## ⚠️ Breaking Changes ⚠️
- **`sendNewValidatorSet` removed** — replaced by
`sendNewValidatorSetForEra(uint64 targetEra, ...)`. Callers must now
supply a `targetEra` parameter.
- **Access control changed** — validator set submission is now
restricted to the `validatorSetSubmitter` role instead of the contract
`owner`. The submitter address is set during `initialize` and rotatable
via `setValidatorSetSubmitter` (owner-only).
- **`external-validators` pallet now validates `targetEra`** — messages
with a stale, duplicate, or out-of-range `external_index` are rejected
on-chain. Existing integrations sending `external_index: 0` will fail
validation.
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-20 09:31:44 +00:00
|
|
|
address(snowbridgeGatewayMock),
|
|
|
|
|
avsOwner
|
2025-03-11 20:16:16 +00:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
cheats.stopPrank();
|
|
|
|
|
console.log("ServiceManager implementation deployed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _setUpDefaultStrategiesAndMultipliers() internal virtual {
|
|
|
|
|
// Deploy mock tokens to be used for strategies.
|
2025-04-16 15:49:35 +00:00
|
|
|
cheats.startPrank(strategyOwner);
|
2025-03-11 20:16:16 +00:00
|
|
|
IERC20 token1 =
|
|
|
|
|
new ERC20FixedSupply("dog wif hat", "MOCK1", mockTokenInitialSupply, address(this));
|
|
|
|
|
IERC20 token2 =
|
|
|
|
|
new ERC20FixedSupply("jeo boden", "MOCK2", mockTokenInitialSupply, address(this));
|
|
|
|
|
IERC20 token3 =
|
|
|
|
|
new ERC20FixedSupply("pepe wif avs", "MOCK3", mockTokenInitialSupply, address(this));
|
|
|
|
|
|
|
|
|
|
// Deploy mock strategies.
|
2025-04-16 15:49:35 +00:00
|
|
|
strategyImplementation =
|
|
|
|
|
new StrategyBase(IStrategyManager(address(strategyManager)), pauserRegistry, "v-mock");
|
2025-04-11 23:54:20 +00:00
|
|
|
deployedStrategies.push(
|
|
|
|
|
StrategyBase(
|
|
|
|
|
address(
|
|
|
|
|
new TransparentUpgradeableProxy(
|
|
|
|
|
address(strategyImplementation),
|
|
|
|
|
address(proxyAdmin),
|
|
|
|
|
abi.encodeWithSelector(
|
|
|
|
|
StrategyBase.initialize.selector, token1, pauserRegistry
|
|
|
|
|
)
|
|
|
|
|
)
|
2025-03-11 20:16:16 +00:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
);
|
2025-04-11 23:54:20 +00:00
|
|
|
deployedStrategies.push(
|
|
|
|
|
StrategyBase(
|
|
|
|
|
address(
|
|
|
|
|
new TransparentUpgradeableProxy(
|
|
|
|
|
address(strategyImplementation),
|
|
|
|
|
address(proxyAdmin),
|
|
|
|
|
abi.encodeWithSelector(
|
|
|
|
|
StrategyBase.initialize.selector, token2, pauserRegistry
|
|
|
|
|
)
|
|
|
|
|
)
|
2025-03-11 20:16:16 +00:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
);
|
2025-04-11 23:54:20 +00:00
|
|
|
deployedStrategies.push(
|
|
|
|
|
StrategyBase(
|
|
|
|
|
address(
|
|
|
|
|
new TransparentUpgradeableProxy(
|
|
|
|
|
address(strategyImplementation),
|
|
|
|
|
address(proxyAdmin),
|
|
|
|
|
abi.encodeWithSelector(
|
|
|
|
|
StrategyBase.initialize.selector, token3, pauserRegistry
|
|
|
|
|
)
|
|
|
|
|
)
|
2025-03-11 20:16:16 +00:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
);
|
2025-04-16 15:49:35 +00:00
|
|
|
cheats.stopPrank();
|
2025-03-11 20:16:16 +00:00
|
|
|
|
2025-04-11 23:54:20 +00:00
|
|
|
deployedStrategies = _sortArrayAsc(deployedStrategies);
|
2025-03-11 20:16:16 +00:00
|
|
|
|
2025-04-16 15:49:35 +00:00
|
|
|
cheats.startPrank(strategyOwner);
|
|
|
|
|
strategyManager.addStrategiesToDepositWhitelist(deployedStrategies);
|
|
|
|
|
cheats.stopPrank();
|
2025-03-11 20:16:16 +00:00
|
|
|
|
|
|
|
|
defaultStrategyAndMultipliers.push(
|
2025-04-11 23:54:20 +00:00
|
|
|
IRewardsCoordinatorTypes.StrategyAndMultiplier(
|
|
|
|
|
IStrategy(address(deployedStrategies[0])), 1e18
|
|
|
|
|
)
|
2025-03-11 20:16:16 +00:00
|
|
|
);
|
|
|
|
|
defaultStrategyAndMultipliers.push(
|
2025-04-11 23:54:20 +00:00
|
|
|
IRewardsCoordinatorTypes.StrategyAndMultiplier(
|
|
|
|
|
IStrategy(address(deployedStrategies[1])), 2e18
|
|
|
|
|
)
|
2025-03-11 20:16:16 +00:00
|
|
|
);
|
|
|
|
|
defaultStrategyAndMultipliers.push(
|
2025-04-11 23:54:20 +00:00
|
|
|
IRewardsCoordinatorTypes.StrategyAndMultiplier(
|
|
|
|
|
IStrategy(address(deployedStrategies[2])), 3e18
|
|
|
|
|
)
|
2025-03-11 20:16:16 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _labelContracts() internal {
|
2025-04-16 15:49:35 +00:00
|
|
|
cheats.label(address(emptyContract), "EmptyContract");
|
|
|
|
|
cheats.label(address(proxyAdmin), "ProxyAdmin");
|
|
|
|
|
cheats.label(address(pauserRegistry), "PauserRegistry");
|
|
|
|
|
cheats.label(address(delegationManager), "DelegationManager");
|
|
|
|
|
cheats.label(address(eigenPodManagerMock), "EigenPodManagerMock");
|
|
|
|
|
cheats.label(address(strategyManager), "StrategyManager");
|
|
|
|
|
cheats.label(address(rewardsCoordinatorMock), "RewardsCoordinatorMock");
|
|
|
|
|
cheats.label(address(allocationManager), "AllocationManager");
|
|
|
|
|
cheats.label(address(allocationManagerImplementation), "AllocationManagerImplementation");
|
|
|
|
|
cheats.label(address(serviceManager), "ServiceManager");
|
|
|
|
|
cheats.label(address(serviceManagerImplementation), "ServiceManagerImplementation");
|
2025-03-11 20:16:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @dev Sort to ensure that the array is in ascending order for strategies
|
|
|
|
|
function _sortArrayAsc(
|
|
|
|
|
IStrategy[] memory arr
|
|
|
|
|
) internal pure returns (IStrategy[] memory) {
|
|
|
|
|
uint256 l = arr.length;
|
|
|
|
|
for (uint256 i = 0; i < l; i++) {
|
|
|
|
|
for (uint256 j = i + 1; j < l; j++) {
|
|
|
|
|
if (address(arr[i]) > address(arr[j])) {
|
|
|
|
|
IStrategy temp = arr[i];
|
|
|
|
|
arr[i] = arr[j];
|
|
|
|
|
arr[j] = temp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-20 08:20:59 +00:00
|
|
|
function _incrementAddress(
|
|
|
|
|
address start,
|
|
|
|
|
uint256 inc
|
|
|
|
|
) internal pure returns (address) {
|
2026-01-22 12:48:27 +00:00
|
|
|
return address((uint256(uint160(start)) + inc).toUint160());
|
2025-03-11 20:16:16 +00:00
|
|
|
}
|
|
|
|
|
|
2025-10-20 08:20:59 +00:00
|
|
|
function _incrementBytes32(
|
|
|
|
|
bytes32 start,
|
|
|
|
|
uint256 inc
|
|
|
|
|
) internal pure returns (bytes32) {
|
2025-03-11 20:16:16 +00:00
|
|
|
return bytes32(uint256(start) + inc);
|
|
|
|
|
}
|
2025-04-16 15:49:35 +00:00
|
|
|
|
2025-10-20 08:20:59 +00:00
|
|
|
function _setERC20Balance(
|
|
|
|
|
address token,
|
|
|
|
|
address user,
|
|
|
|
|
uint256 amount
|
|
|
|
|
) internal {
|
2025-04-16 15:49:35 +00:00
|
|
|
// Assumes balanceOf is in slot 0 (standard in OpenZeppelin ERC20)
|
|
|
|
|
bytes32 slot = keccak256(abi.encode(user, uint256(0)));
|
|
|
|
|
cheats.store(token, slot, bytes32(amount));
|
|
|
|
|
}
|
2025-03-11 20:16:16 +00:00
|
|
|
}
|