mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 09:50:01 +00:00
Merge branch 'main' into sde/storagehub-docs
This commit is contained in:
commit
948a57832e
55 changed files with 769 additions and 1576 deletions
|
|
@ -6,6 +6,9 @@ inputs:
|
|||
target:
|
||||
description: The CPU target for the binary
|
||||
required: true
|
||||
build:
|
||||
description: If we should statically build it or not
|
||||
required: false
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
|
|
@ -24,6 +27,7 @@ runs:
|
|||
--tag prod --no-cache \
|
||||
--build-arg="COMMIT=${{ github.event.inputs.sha }}" \
|
||||
--build-arg="RUSTFLAGS=-C target-cpu=${{ inputs.target }}" \
|
||||
--build-arg="BUILD=${{ inputs.build }}" \
|
||||
--file ./docker/datahaven-production.Dockerfile \
|
||||
.
|
||||
|
||||
|
|
@ -46,12 +50,29 @@ runs:
|
|||
docker rmi prod
|
||||
|
||||
- name: Save DataHaven node binary
|
||||
if: inputs.build != 'static'
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p build
|
||||
cp datahaven-node build/datahaven-node-${{ inputs.target }}
|
||||
|
||||
- name: Save DataHaven node binary
|
||||
if: inputs.build == 'static'
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p build
|
||||
cp datahaven-node build/datahaven-node-${{ inputs.target }}-static
|
||||
|
||||
- name: Upload binary
|
||||
if: inputs.build != 'static'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: datahaven-binaries-${{inputs.target}}
|
||||
path: build/datahaven-node-${{inputs.target }}
|
||||
|
||||
- name: Upload binary
|
||||
if: inputs.build == 'static'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: datahaven-binaries-${{inputs.target}}-static
|
||||
path: build/datahaven-node-${{inputs.target }}-static
|
||||
|
|
|
|||
3
.github/workflows/CI.yml
vendored
3
.github/workflows/CI.yml
vendored
|
|
@ -51,12 +51,9 @@ jobs:
|
|||
binary-hash: ${{ needs.build-operator.outputs.binary-hash }}
|
||||
|
||||
docker-build-release:
|
||||
needs: [build-operator]
|
||||
if: github.ref == 'refs/heads/main'
|
||||
uses: ./.github/workflows/task-docker-release.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
binary-hash: ${{ needs.build-operator.outputs.binary-hash }}
|
||||
|
||||
moonwall-tests:
|
||||
needs: [build-operator]
|
||||
|
|
|
|||
24
.github/workflows/actions/setup-env/action.yml
vendored
24
.github/workflows/actions/setup-env/action.yml
vendored
|
|
@ -12,6 +12,11 @@ inputs:
|
|||
required: false
|
||||
default: "true"
|
||||
|
||||
skip-libpq:
|
||||
description: "Indicate to skip postgres lib install or not"
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
|
|
@ -68,9 +73,16 @@ runs:
|
|||
shell: bash
|
||||
run: sudo apt-get update && sudo apt-get install -y libpq-dev libclang-dev
|
||||
|
||||
# Auto-install missing dependencies when install-deps is false (for self-hosted runners)
|
||||
# Install protoc only when install-deps is true
|
||||
- name: Install Protoc
|
||||
if: inputs.install-deps == 'true'
|
||||
uses: arduino/setup-protoc@v3
|
||||
with:
|
||||
repo-token: ${{ github.token }}
|
||||
|
||||
# Auto-install missing dependencies when install-deps is false (for self-hosted runners) can be skipped when statically build the node
|
||||
- name: Setup system dependencies (self-hosted)
|
||||
if: inputs.install-deps == 'false'
|
||||
if: inputs.install-deps == 'false' && inputs.skip-libpq == 'false'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Checking and installing system dependencies locally if needed..."
|
||||
|
|
@ -172,13 +184,7 @@ runs:
|
|||
|
||||
echo "All required system dependencies ready!"
|
||||
|
||||
# Install protoc only when install-deps is true
|
||||
- name: Install Protoc
|
||||
if: inputs.install-deps == 'true'
|
||||
uses: arduino/setup-protoc@v3
|
||||
with:
|
||||
repo-token: ${{ github.token }}
|
||||
|
||||
|
||||
# Auto-install protoc when install-deps is false (for self-hosted runners)
|
||||
- name: Setup Protoc (self-hosted)
|
||||
if: inputs.install-deps == 'false'
|
||||
|
|
|
|||
46
.github/workflows/task-build-static-operator.yml
vendored
Normal file
46
.github/workflows/task-build-static-operator.yml
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
name: DataHaven Operator Static Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
# Only check the build if we are adding a dependency to save runner time
|
||||
- 'operator/Cargo.toml'
|
||||
- 'operator/Cargo.lock'
|
||||
|
||||
jobs:
|
||||
build-node:
|
||||
name: Build operator binary
|
||||
runs-on:
|
||||
group: DH-runners
|
||||
env:
|
||||
RUSTC_WRAPPER: "sccache"
|
||||
CARGO_INCREMENTAL: "0"
|
||||
CARGO_TERM_COLOR: always
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./operator
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: ./.github/workflows/actions/setup-env
|
||||
with:
|
||||
cache-key: BUILD-RELEASE
|
||||
install-deps: false
|
||||
skip-libpq: true
|
||||
|
||||
- name: Set build flags
|
||||
run: echo "RUSTFLAGS=${{ env.RUSTFLAGS }} -C linker=clang -C link-arg=-fuse-ld=mold" >> $GITHUB_ENV
|
||||
|
||||
- name: Build node binary
|
||||
run: |
|
||||
cargo build --release --locked --features fast-runtime,static
|
||||
|
||||
- name: Test binary
|
||||
run: |
|
||||
ldd ./target/release/datahaven-node
|
||||
./target/release/datahaven-node --version
|
||||
|
||||
50
.github/workflows/task-docker-release.yml
vendored
50
.github/workflows/task-docker-release.yml
vendored
|
|
@ -17,11 +17,6 @@ on:
|
|||
type: boolean
|
||||
default: false
|
||||
workflow_call:
|
||||
inputs:
|
||||
binary-hash:
|
||||
description: "The hash of the operator binary (for CI builds)"
|
||||
required: true
|
||||
type: string
|
||||
outputs:
|
||||
image-tag:
|
||||
description: "The tag portion of the docker image (without registry)"
|
||||
|
|
@ -48,21 +43,6 @@ jobs:
|
|||
ref: ${{ github.event.inputs.branch || github.ref }}
|
||||
|
||||
- uses: ./.github/workflows/actions/cleanup-runner
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
|
||||
# --- Conditional: Download binary for CI builds ---
|
||||
- name: Download binary artifact (CI build)
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: datahaven-node-${{ inputs.binary-hash }}
|
||||
path: ./build/
|
||||
|
||||
- name: Prepare binary (CI build)
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
run: |
|
||||
chmod +x ./build/datahaven-node
|
||||
ls -la ./build/
|
||||
|
||||
# --- Docker metadata ---
|
||||
- name: Docker meta (dispatch)
|
||||
|
|
@ -100,9 +80,8 @@ jobs:
|
|||
echo "image-tag=$TAG_ONLY" >> $GITHUB_OUTPUT
|
||||
echo "image-name=datahavenxyz/datahaven:$TAG_ONLY" >> $GITHUB_OUTPUT
|
||||
|
||||
# --- Conditional: Cargo cache for full builds ---
|
||||
- name: Set up cargo cache (full build)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
# --- Cargo cache for full builds ---
|
||||
- name: Set up cargo cache
|
||||
uses: actions/cache@v4
|
||||
id: cache
|
||||
with:
|
||||
|
|
@ -115,8 +94,7 @@ jobs:
|
|||
cache-mount-${{ hashFiles('./docker/datahaven-build.Dockerfile') }}
|
||||
cache-mount-
|
||||
|
||||
- name: Inject cache into docker (full build)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
- name: Inject cache into docker
|
||||
uses: reproducible-containers/buildkit-cache-dance@v3.1.0
|
||||
with:
|
||||
cache-map: |
|
||||
|
|
@ -126,9 +104,8 @@ jobs:
|
|||
}
|
||||
skip-extraction: ${{ steps.cache.outputs.cache-hit }}
|
||||
|
||||
# --- Build and push: Full build (workflow_dispatch) ---
|
||||
- name: Build and push Docker image (full build)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
# --- Build and push Docker image ---
|
||||
- name: Build and push Docker image
|
||||
uses: ./.github/workflow-templates/publish-docker
|
||||
with:
|
||||
dockerfile: ./docker/datahaven-build.Dockerfile
|
||||
|
|
@ -136,28 +113,13 @@ jobs:
|
|||
registry: docker.io
|
||||
registry_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
registry_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
image_tags: ${{ steps.meta-dispatch.outputs.tags }}
|
||||
image_tags: ${{ steps.meta-dispatch.outputs.tags || steps.meta-ci.outputs.tags }}
|
||||
image_title: "DataHaven Node - Release"
|
||||
image_description: "Release build of DataHaven blockchain node"
|
||||
cache_scope: datahaven-release-build
|
||||
build_args: |
|
||||
FAST_RUNTIME=${{ github.event.inputs.fast_runtime == 'true' && 'TRUE' || 'FALSE' }}
|
||||
|
||||
# --- Build and push: CI binary reuse (workflow_call) ---
|
||||
- name: Build and push Docker image (CI binary)
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
uses: ./.github/workflow-templates/publish-docker
|
||||
with:
|
||||
dockerfile: ./operator/Dockerfile
|
||||
context: .
|
||||
registry: docker.io
|
||||
registry_username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
registry_password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
image_tags: ${{ steps.meta-ci.outputs.tags }}
|
||||
image_title: "DataHaven Node - Release"
|
||||
image_description: "Release build of DataHaven operator node"
|
||||
cache_scope: datahaven-release-ci
|
||||
|
||||
# --- Smoke tests ---
|
||||
- name: Pull and test node --help
|
||||
run: |
|
||||
|
|
|
|||
7
.github/workflows/task-publish-binary.yml
vendored
7
.github/workflows/task-publish-binary.yml
vendored
|
|
@ -37,6 +37,12 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
cpu: ["x86-64", "skylake", "znver3"]
|
||||
build: ["default", "static"]
|
||||
exclude:
|
||||
- cpu: skylake
|
||||
build: static
|
||||
- cpu: znver3
|
||||
build: static
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
|
@ -46,6 +52,7 @@ jobs:
|
|||
uses: ./.github/workflow-templates/build-prod-binary
|
||||
with:
|
||||
target: ${{ matrix.cpu }}
|
||||
build: ${{ matrix.build }}
|
||||
|
||||
####### Prepare and publish the release draft #######
|
||||
|
||||
|
|
|
|||
6
contracts/.gitignore
vendored
6
contracts/.gitignore
vendored
|
|
@ -2,10 +2,8 @@
|
|||
cache/
|
||||
out/
|
||||
|
||||
# Ignores development broadcast logs
|
||||
!/broadcast
|
||||
/broadcast/*/3*/
|
||||
/broadcast/**/dry-run/
|
||||
# Ignores development broadcast logs (autogenerated by forge script --broadcast)
|
||||
broadcast/
|
||||
|
||||
# Docs
|
||||
docs/
|
||||
|
|
|
|||
|
|
@ -1,145 +1,71 @@
|
|||
# DataHaven AVS Smart Contracts 📜
|
||||
# DataHaven AVS Smart Contracts
|
||||
|
||||
This directory contains the smart contracts for the DataHaven Actively Validated Service (AVS) built on EigenLayer.
|
||||
|
||||
## Overview
|
||||
|
||||
DataHaven is an EVM-compatible Substrate blockchain secured by EigenLayer. These contracts implement the AVS Service Manager, middleware, and associated utilities that integrate with EigenLayer's operator registration, slashing, and rewards infrastructure.
|
||||
Implements the Actively Validated Service (AVS) logic for DataHaven, secured by EigenLayer. These contracts manage operator registration, handle cross-chain rewards via Snowbridge, and enforce slashing with a veto period.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
contracts/
|
||||
├── src/ # Smart contract source code
|
||||
├── src/
|
||||
│ ├── DataHavenServiceManager.sol # Core AVS service manager
|
||||
│ ├── RewardsRegistry.sol # Validator performance & rewards tracking
|
||||
│ ├── VetoableSlasher.sol # Slashing with veto period
|
||||
│ ├── middleware/ # RewardsRegistry, VetoableSlasher, Snowbridge helpers
|
||||
│ ├── interfaces/ # Contract interfaces
|
||||
│ ├── libraries/ # Utility libraries
|
||||
│ └── middleware/ # EigenLayer middleware integration
|
||||
├── script/ # Deployment & setup scripts
|
||||
│ └── deploy/ # Environment-specific deployment
|
||||
├── test/ # Foundry test suites
|
||||
└── foundry.toml # Foundry configuration
|
||||
│ └── libraries/ # Utility libraries
|
||||
├── script/ # Deployment & setup scripts
|
||||
├── lib/ # External dependencies (EigenLayer, Snowbridge, OpenZeppelin)
|
||||
└── test/ # Foundry test suites
|
||||
```
|
||||
|
||||
### Key Contracts
|
||||
## Key Components
|
||||
|
||||
- **DataHavenServiceManager**: Manages operator lifecycle, registration, and deregistration with EigenLayer
|
||||
- **RewardsRegistry**: Tracks validator performance metrics and handles reward distribution via Snowbridge
|
||||
- **VetoableSlasher**: Implements slashing mechanism with dispute resolution veto period
|
||||
- **Middleware**: Integration layer with EigenLayer's core contracts (based on [eigenlayer-middleware](https://github.com/Layr-Labs/eigenlayer-middleware))
|
||||
- **DataHavenServiceManager** (`src/DataHavenServiceManager.sol`): Core contract for operator lifecycle; inherits `ServiceManagerBase`.
|
||||
- **RewardsRegistry** (`src/middleware/RewardsRegistry.sol`): Tracks validator performance and distributes rewards via Snowbridge.
|
||||
- **VetoableSlasher** (`src/middleware/VetoableSlasher.sol`): Handles slashing requests with a dispute resolution veto window.
|
||||
|
||||
## Prerequisites
|
||||
## Development
|
||||
|
||||
- [Foundry](https://book.getfoundry.sh/getting-started/installation)
|
||||
|
||||
## Build
|
||||
|
||||
To build the contracts:
|
||||
Requires [Foundry](https://book.getfoundry.sh).
|
||||
|
||||
```bash
|
||||
cd contracts
|
||||
# Build and Test
|
||||
forge build
|
||||
```
|
||||
|
||||
This will compile all contracts and generate artifacts in the `out` directory.
|
||||
|
||||
## Test
|
||||
|
||||
Run the test suite with:
|
||||
|
||||
```bash
|
||||
forge test
|
||||
```
|
||||
|
||||
For more verbose output including logs:
|
||||
|
||||
```bash
|
||||
forge test -vv
|
||||
```
|
||||
|
||||
For maximum verbosity including stack traces:
|
||||
|
||||
```bash
|
||||
forge test -vvvv
|
||||
```
|
||||
|
||||
Run specific test contracts:
|
||||
|
||||
```bash
|
||||
forge test --match-contract RewardsRegistry
|
||||
```
|
||||
|
||||
Run specific test functions:
|
||||
|
||||
```bash
|
||||
forge test --match-test test_newRewardsMessage
|
||||
```
|
||||
|
||||
Exclude specific tests:
|
||||
|
||||
```bash
|
||||
forge test --no-match-test test_newRewardsMessage_OnlyRewardsAgent
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### Local Deployment
|
||||
|
||||
1. In a separate terminal, start a local Anvil instance:
|
||||
|
||||
```bash
|
||||
anvil
|
||||
```
|
||||
|
||||
2. Deploy to local Anvil:
|
||||
|
||||
```bash
|
||||
forge script script/deploy/DeployLocal.s.sol --rpc-url anvil --broadcast
|
||||
```
|
||||
|
||||
### Network Deployment
|
||||
|
||||
To deploy to a network configured in `foundry.toml`:
|
||||
|
||||
```bash
|
||||
forge script script/deploy/DeployLocal.s.sol --rpc-url $NETWORK_RPC_URL --private-key $PRIVATE_KEY --broadcast
|
||||
```
|
||||
|
||||
Replace `$NETWORK_RPC_URL` with the RPC endpoint and `$PRIVATE_KEY` with your deployer's private key.
|
||||
|
||||
Or using a network from `foundry.toml`:
|
||||
|
||||
```bash
|
||||
forge script script/deploy/DeployLocal.s.sol --rpc-url mainnet --private-key $PRIVATE_KEY --broadcast
|
||||
# Regenerate TS bindings (after contract changes)
|
||||
cd ../test && bun generate:wagmi
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The deployment configuration can be modified in:
|
||||
Deployment parameters (EigenLayer addresses, initial validators, owners) are defined in `contracts/config/<network>.json`.
|
||||
- **Do not edit** `Config.sol` or `DeployParams.s.sol` directly; they only load the JSON.
|
||||
- Ensure `contracts/config/hoodi.json` (or `holesky.json`) matches your target environment before deploying.
|
||||
|
||||
- `script/deploy/Config.sol`: Environment-specific configuration
|
||||
- `script/deploy/DeployParams.s.sol`: Deployment parameters
|
||||
## Deployment
|
||||
|
||||
## Code Generation
|
||||
|
||||
After making changes to contracts, regenerate TypeScript bindings for the test framework:
|
||||
Two deployment paths exist: **Local** (Anvil) and **Testnet** (Hoodi/Holesky). Both install the **DataHaven AVS contracts** (ServiceManager, RewardsRegistry, VetoableSlasher) and **Snowbridge** (BeefyClient, Gateway, Agent). They differ in EigenLayer setup:
|
||||
|
||||
### Local (Anvil)
|
||||
**`DeployLocal.s.sol`** bootstraps a full EigenLayer core deployment (DelegationManager, StrategyManager, AVSDirectory, etc.) alongside DataHaven AVS and Snowbridge.
|
||||
```bash
|
||||
cd ../test
|
||||
bun generate:wagmi
|
||||
anvil
|
||||
forge script script/deploy/DeployLocal.s.sol --rpc-url anvil --broadcast
|
||||
```
|
||||
|
||||
This generates type-safe contract interfaces used by the E2E test suite.
|
||||
### Testnet (Hoodi / Holesky)
|
||||
**`DeployTestnet.s.sol`** references existing EigenLayer contracts (addresses from `contracts/config/<network>.json`) and only deploys DataHaven AVS + Snowbridge.
|
||||
```bash
|
||||
NETWORK=hoodi forge script script/deploy/DeployTestnet.s.sol \
|
||||
--rpc-url hoodi \
|
||||
--private-key $PRIVATE_KEY \
|
||||
--broadcast
|
||||
```
|
||||
Supported networks: `hoodi`, `holesky` (no mainnet config yet). Artifacts → `contracts/deployments/<network>.json`.
|
||||
|
||||
## Integration with DataHaven
|
||||
## How It Works
|
||||
1. **Registration**: Validators register with EigenLayer via `DataHavenServiceManager`.
|
||||
2. **Performance Tracking**: DataHaven computes reward points and sends a Merkle root to `RewardsRegistry` on Ethereum via Snowbridge.
|
||||
3. **Rewards Claims**: Validators claim rewards on Ethereum from `RewardsRegistry` using Merkle proofs.
|
||||
4. **Slashing**: Misbehavior triggers `VetoableSlasher` (subject to veto period).
|
||||
|
||||
These contracts integrate with the DataHaven Substrate node through:
|
||||
|
||||
1. **Operator Registration**: Validators register on-chain via `DataHavenServiceManager`
|
||||
2. **Performance Tracking**: Node submits validator metrics to `RewardsRegistry`
|
||||
3. **Cross-chain Rewards**: Rewards distributed from Ethereum to DataHaven via Snowbridge
|
||||
4. **Slashing**: Misbehavior triggers slashing through `VetoableSlasher` with veto period
|
||||
|
||||
For full network integration testing, see the [test directory](../test/README.md).
|
||||
See `test/README.md` for full network integration tests.
|
||||
|
|
|
|||
|
|
@ -24,15 +24,13 @@
|
|||
"allocationConfigurationDelay": 75,
|
||||
"beaconChainGenesisTimestamp": 1695902400
|
||||
},
|
||||
"avs": {
|
||||
"avsOwner": "0x976EA74026E726554dB657fA54763abd0C3a0aa9",
|
||||
"rewardsInitiator": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955",
|
||||
"vetoCommitteeMember": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f",
|
||||
"vetoWindowBlocks": 100,
|
||||
"validatorsStrategies": [],
|
||||
"bspsStrategies": [],
|
||||
"mspsStrategies": []
|
||||
},
|
||||
"avs": {
|
||||
"avsOwner": "0x976EA74026E726554dB657fA54763abd0C3a0aa9",
|
||||
"rewardsInitiator": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955",
|
||||
"vetoCommitteeMember": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f",
|
||||
"vetoWindowBlocks": 100,
|
||||
"validatorsStrategies": []
|
||||
},
|
||||
"snowbridge": {
|
||||
"randaoCommitDelay": 4,
|
||||
"randaoCommitExpiration": 24,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
"lib/snowbridge/contracts/:prb/math/=lib/snowbridge/contracts/lib/prb-math/",
|
||||
"openzeppelin/=lib/snowbridge/contracts/lib/openzeppelin-contracts/contracts/",
|
||||
"prb/math/=lib/snowbridge/contracts/lib/prb-math/",
|
||||
"src/contracts/=lib/eigenlayer-contracts/src/contracts/",
|
||||
"src/test/=lib/eigenlayer-contracts/src/test/",
|
||||
]
|
||||
# Specifies the exact version of Solidity to use, overriding auto-detection.
|
||||
solc_version = '0.8.28'
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ contract Config {
|
|||
address vetoCommitteeMember;
|
||||
uint32 vetoWindowBlocks;
|
||||
address[] validatorsStrategies;
|
||||
address[] bspsStrategies;
|
||||
address[] mspsStrategies;
|
||||
}
|
||||
|
||||
// EigenLayer parameters
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
|
|||
_logProgress();
|
||||
|
||||
// Deploy Snowbridge (same for both modes)
|
||||
Logging.logHeader("SNOWBRIDGE DEPLOYMENT");
|
||||
(
|
||||
BeefyClient beefyClient,
|
||||
AgentExecutor agentExecutor,
|
||||
|
|
@ -170,6 +169,8 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
|
|||
function _deploySnowbridge(
|
||||
SnowbridgeConfig memory config
|
||||
) internal returns (BeefyClient, AgentExecutor, IGatewayV2, address payable) {
|
||||
Logging.logHeader("SNOWBRIDGE DEPLOYMENT");
|
||||
|
||||
Logging.logSection("Deploying Snowbridge Core Components");
|
||||
|
||||
BeefyClient beefyClient = _deployBeefyClient(config);
|
||||
|
|
|
|||
|
|
@ -194,8 +194,6 @@ contract DeployLocal is DeployBase {
|
|||
params.avsOwner,
|
||||
params.rewardsInitiator,
|
||||
params.validatorsStrategies,
|
||||
new IStrategy[](0), // FIXME remove when BSPs are removed
|
||||
new IStrategy[](0), // FIXME remove when MSPs are removed
|
||||
params.gateway
|
||||
);
|
||||
|
||||
|
|
@ -662,12 +660,8 @@ contract DeployLocal is DeployBase {
|
|||
) internal pure {
|
||||
if (config.validatorsStrategies.length == 0) {
|
||||
config.validatorsStrategies = new address[](strategies.length);
|
||||
config.bspsStrategies = new address[](strategies.length);
|
||||
config.mspsStrategies = new address[](strategies.length);
|
||||
for (uint256 i = 0; i < strategies.length; i++) {
|
||||
config.validatorsStrategies[i] = strategies[i].address_;
|
||||
config.bspsStrategies[i] = strategies[i].address_;
|
||||
config.mspsStrategies[i] = strategies[i].address_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ contract DeployTestnet is DeployBase {
|
|||
);
|
||||
|
||||
currentTestnet = _detectAndValidateNetwork(networkName);
|
||||
totalSteps = 2; // Reduced steps since we're not deploying EigenLayer
|
||||
totalSteps = 4;
|
||||
|
||||
_executeSharedDeployment();
|
||||
}
|
||||
|
|
@ -132,8 +132,6 @@ contract DeployTestnet is DeployBase {
|
|||
params.avsOwner,
|
||||
params.rewardsInitiator,
|
||||
params.validatorsStrategies,
|
||||
new IStrategy[](0), // FIXME remove when BSPs and MSPs are removed
|
||||
new IStrategy[](0), // FIXME remove when BSPs and MSPs are removed
|
||||
params.gateway
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
import {SignUpOperatorBase} from "./SignUpOperatorBase.s.sol";
|
||||
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
|
||||
|
||||
/**
|
||||
* @title SignUpBsp
|
||||
* @notice Script to sign up a backup storage provider (BSP) for the DataHaven network
|
||||
*/
|
||||
contract SignUpBsp is SignUpOperatorBase {
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _getOperatorSetId() internal view override returns (uint32) {
|
||||
return serviceManager.BSPS_SET_ID();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _addToAllowlist() internal override {
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.addBspToAllowlist(_operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _getOperatorTypeName() internal pure override returns (string memory) {
|
||||
return "BSP";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
import {SignUpOperatorBase} from "./SignUpOperatorBase.s.sol";
|
||||
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
|
||||
|
||||
/**
|
||||
* @title SignUpMsp
|
||||
* @notice Script to sign up a main storage provider (MSP) for the DataHaven network
|
||||
*/
|
||||
contract SignUpMsp is SignUpOperatorBase {
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _getOperatorSetId() internal view override returns (uint32) {
|
||||
return serviceManager.MSPS_SET_ID();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _addToAllowlist() internal override {
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.addMspToAllowlist(_operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _getOperatorTypeName() internal pure override returns (string memory) {
|
||||
return "MSP";
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ import {Accounts} from "../utils/Accounts.sol";
|
|||
|
||||
/**
|
||||
* @title SignUpOperatorBase
|
||||
* @notice Base contract for signing up different types of operators (Validators, BSPs, MSPs)
|
||||
* @notice Base contract for signing up validators
|
||||
*/
|
||||
abstract contract SignUpOperatorBase is Script, ELScriptStorage, DHScriptStorage, Accounts {
|
||||
// Progress indicator
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ import {ServiceManagerBase} from "./middleware/ServiceManagerBase.sol";
|
|||
|
||||
/**
|
||||
* @title DataHaven ServiceManager contract
|
||||
* @notice Manages validators, backup storage providers (BSPs), and main storage providers (MSPs)
|
||||
* in the DataHaven network
|
||||
* @notice Manages validators in the DataHaven network
|
||||
*/
|
||||
contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager {
|
||||
/// @notice The metadata for the DataHaven AVS.
|
||||
|
|
@ -36,17 +35,9 @@ contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager
|
|||
|
||||
/// @notice The EigenLayer operator set ID for the Validators securing the DataHaven network.
|
||||
uint32 public constant VALIDATORS_SET_ID = 0;
|
||||
/// @notice The EigenLayer operator set ID for the Backup Storage Providers participating in the DataHaven network.
|
||||
uint32 public constant BSPS_SET_ID = 1;
|
||||
/// @notice The EigenLayer operator set ID for the Main Storage Providers participating in the DataHaven network.
|
||||
uint32 public constant MSPS_SET_ID = 2;
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
mapping(address => bool) public validatorsAllowlist;
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
mapping(address => bool) public bspsAllowlist;
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
mapping(address => bool) public mspsAllowlist;
|
||||
|
||||
IGatewayV2 private _snowbridgeGateway;
|
||||
|
||||
|
|
@ -75,8 +66,6 @@ contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager
|
|||
address initialOwner,
|
||||
address rewardsInitiator,
|
||||
IStrategy[] memory validatorsStrategies,
|
||||
IStrategy[] memory bspsStrategies,
|
||||
IStrategy[] memory mspsStrategies,
|
||||
address _snowbridgeGatewayAddress
|
||||
) public virtual initializer {
|
||||
__ServiceManagerBase_init(initialOwner, rewardsInitiator);
|
||||
|
|
@ -84,8 +73,8 @@ contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager
|
|||
// Register the DataHaven service in the AllocationManager.
|
||||
_allocationManager.updateAVSMetadataURI(address(this), DATAHAVEN_AVS_METADATA);
|
||||
|
||||
// Create the operator sets for the DataHaven service.
|
||||
_createDataHavenOperatorSets(validatorsStrategies, bspsStrategies, mspsStrategies);
|
||||
// Create the operator set for the DataHaven service.
|
||||
_createDataHavenOperatorSets(validatorsStrategies);
|
||||
|
||||
// Set the Snowbridge Gateway address.
|
||||
// This is the contract to which messages are sent, to be relayed to the Solochain network.
|
||||
|
|
@ -159,34 +148,20 @@ contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager
|
|||
revert CantRegisterToMultipleOperatorSets();
|
||||
}
|
||||
|
||||
// Case: Validator
|
||||
if (operatorSetIds[0] == VALIDATORS_SET_ID) {
|
||||
if (!validatorsAllowlist[operator]) {
|
||||
revert OperatorNotInAllowlist();
|
||||
}
|
||||
|
||||
// In the case of the Validators operator set, expect the data to have the Solochain address of the operator.
|
||||
// Require validators to provide 20 bytes addresses.
|
||||
require(data.length == 20, "Invalid solochain address length");
|
||||
validatorEthAddressToSolochainAddress[operator] = address(bytes20(data));
|
||||
}
|
||||
// Case: BSP
|
||||
else if (operatorSetIds[0] == BSPS_SET_ID) {
|
||||
if (!bspsAllowlist[operator]) {
|
||||
revert OperatorNotInAllowlist();
|
||||
}
|
||||
}
|
||||
// Case: MSP
|
||||
else if (operatorSetIds[0] == MSPS_SET_ID) {
|
||||
if (!mspsAllowlist[operator]) {
|
||||
revert OperatorNotInAllowlist();
|
||||
}
|
||||
}
|
||||
// Case: Invalid operator set ID
|
||||
else {
|
||||
// Only validators are supported
|
||||
if (operatorSetIds[0] != VALIDATORS_SET_ID) {
|
||||
revert InvalidOperatorSetId();
|
||||
}
|
||||
|
||||
if (!validatorsAllowlist[operator]) {
|
||||
revert OperatorNotInAllowlist();
|
||||
}
|
||||
|
||||
// In the case of the Validators operator set, expect the data to have the Solochain address of the operator.
|
||||
// Require validators to provide 20 bytes addresses.
|
||||
require(data.length == 20, "Invalid solochain address length");
|
||||
validatorEthAddressToSolochainAddress[operator] = address(bytes20(data));
|
||||
|
||||
emit OperatorRegistered(operator, operatorSetIds[0]);
|
||||
}
|
||||
|
||||
|
|
@ -204,17 +179,12 @@ contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager
|
|||
revert CantDeregisterFromMultipleOperatorSets();
|
||||
}
|
||||
|
||||
if (
|
||||
operatorSetIds[0] != VALIDATORS_SET_ID && operatorSetIds[0] != BSPS_SET_ID
|
||||
&& operatorSetIds[0] != MSPS_SET_ID
|
||||
) {
|
||||
if (operatorSetIds[0] != VALIDATORS_SET_ID) {
|
||||
revert InvalidOperatorSetId();
|
||||
}
|
||||
|
||||
if (operatorSetIds[0] == VALIDATORS_SET_ID) {
|
||||
// Remove validator from the addresses mapping
|
||||
delete validatorEthAddressToSolochainAddress[operator];
|
||||
}
|
||||
// Remove validator from the addresses mapping
|
||||
delete validatorEthAddressToSolochainAddress[operator];
|
||||
|
||||
emit OperatorDeregistered(operator, operatorSetIds[0]);
|
||||
}
|
||||
|
|
@ -227,22 +197,6 @@ contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager
|
|||
emit ValidatorAddedToAllowlist(validator);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function addBspToAllowlist(
|
||||
address bsp
|
||||
) external onlyOwner {
|
||||
bspsAllowlist[bsp] = true;
|
||||
emit BspAddedToAllowlist(bsp);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function addMspToAllowlist(
|
||||
address msp
|
||||
) external onlyOwner {
|
||||
mspsAllowlist[msp] = true;
|
||||
emit MspAddedToAllowlist(msp);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeValidatorFromAllowlist(
|
||||
address validator
|
||||
|
|
@ -251,22 +205,6 @@ contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager
|
|||
emit ValidatorRemovedFromAllowlist(validator);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeBspFromAllowlist(
|
||||
address bsp
|
||||
) external onlyOwner {
|
||||
bspsAllowlist[bsp] = false;
|
||||
emit BspRemovedFromAllowlist(bsp);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeMspFromAllowlist(
|
||||
address msp
|
||||
) external onlyOwner {
|
||||
mspsAllowlist[msp] = false;
|
||||
emit MspRemovedFromAllowlist(msp);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function validatorsSupportedStrategies() external view returns (IStrategy[] memory) {
|
||||
OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: VALIDATORS_SET_ID});
|
||||
|
|
@ -289,71 +227,23 @@ contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager
|
|||
_allocationManager.addStrategiesToOperatorSet(address(this), VALIDATORS_SET_ID, _strategies);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function bspsSupportedStrategies() external view returns (IStrategy[] memory) {
|
||||
OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: BSPS_SET_ID});
|
||||
return _allocationManager.getStrategiesInOperatorSet(operatorSet);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeStrategiesFromBspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external onlyOwner {
|
||||
_allocationManager.removeStrategiesFromOperatorSet(address(this), BSPS_SET_ID, _strategies);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function addStrategiesToBspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external onlyOwner {
|
||||
_allocationManager.addStrategiesToOperatorSet(address(this), BSPS_SET_ID, _strategies);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function mspsSupportedStrategies() external view returns (IStrategy[] memory) {
|
||||
OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: MSPS_SET_ID});
|
||||
return _allocationManager.getStrategiesInOperatorSet(operatorSet);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeStrategiesFromMspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external onlyOwner {
|
||||
_allocationManager.removeStrategiesFromOperatorSet(address(this), MSPS_SET_ID, _strategies);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function addStrategiesToMspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external onlyOwner {
|
||||
_allocationManager.addStrategiesToOperatorSet(address(this), MSPS_SET_ID, _strategies);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function snowbridgeGateway() external view returns (address) {
|
||||
return address(_snowbridgeGateway);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Creates the initial operator sets for DataHaven in the AllocationManager.
|
||||
* @dev This function should be called during initialisation to set up the required operator sets.
|
||||
* @notice Creates the initial operator set for DataHaven in the AllocationManager.
|
||||
* @dev This function should be called during initialisation to set up the required operator set.
|
||||
*/
|
||||
function _createDataHavenOperatorSets(
|
||||
IStrategy[] memory validatorsStrategies,
|
||||
IStrategy[] memory bspsStrategies,
|
||||
IStrategy[] memory mspsStrategies
|
||||
IStrategy[] memory validatorsStrategies
|
||||
) internal {
|
||||
IAllocationManagerTypes.CreateSetParams[] memory operatorSets =
|
||||
new IAllocationManagerTypes.CreateSetParams[](3);
|
||||
new IAllocationManagerTypes.CreateSetParams[](1);
|
||||
operatorSets[0] = IAllocationManagerTypes.CreateSetParams({
|
||||
operatorSetId: VALIDATORS_SET_ID, strategies: validatorsStrategies
|
||||
});
|
||||
operatorSets[1] = IAllocationManagerTypes.CreateSetParams({
|
||||
operatorSetId: BSPS_SET_ID, strategies: bspsStrategies
|
||||
});
|
||||
operatorSets[2] = IAllocationManagerTypes.CreateSetParams({
|
||||
operatorSetId: MSPS_SET_ID, strategies: mspsStrategies
|
||||
});
|
||||
_allocationManager.createOperatorSets(address(this), operatorSets);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,26 +43,10 @@ interface IDataHavenServiceManagerEvents {
|
|||
/// @param validator Address of the validator added to the allowlist
|
||||
event ValidatorAddedToAllowlist(address indexed validator);
|
||||
|
||||
/// @notice Emitted when a Backup Storage Provider is added to the allowlist
|
||||
/// @param bsp Address of the BSP added to the allowlist
|
||||
event BspAddedToAllowlist(address indexed bsp);
|
||||
|
||||
/// @notice Emitted when a Main Storage Provider is added to the allowlist
|
||||
/// @param msp Address of the MSP added to the allowlist
|
||||
event MspAddedToAllowlist(address indexed msp);
|
||||
|
||||
/// @notice Emitted when a validator is removed from the allowlist
|
||||
/// @param validator Address of the validator removed from the allowlist
|
||||
event ValidatorRemovedFromAllowlist(address indexed validator);
|
||||
|
||||
/// @notice Emitted when a Backup Storage Provider is removed from the allowlist
|
||||
/// @param bsp Address of the BSP removed from the allowlist
|
||||
event BspRemovedFromAllowlist(address indexed bsp);
|
||||
|
||||
/// @notice Emitted when a Main Storage Provider is removed from the allowlist
|
||||
/// @param msp Address of the MSP removed from the allowlist
|
||||
event MspRemovedFromAllowlist(address indexed msp);
|
||||
|
||||
/// @notice Emitted when the Snowbridge Gateway address is set
|
||||
/// @param snowbridgeGateway Address of the Snowbridge Gateway
|
||||
event SnowbridgeGatewaySet(address indexed snowbridgeGateway);
|
||||
|
|
@ -70,8 +54,8 @@ interface IDataHavenServiceManagerEvents {
|
|||
|
||||
/**
|
||||
* @title DataHaven Service Manager Interface
|
||||
* @notice Defines the interface for the DataHaven Service Manager, which manages validators,
|
||||
* backup storage providers (BSPs), and main storage providers (MSPs) in the DataHaven network
|
||||
* @notice Defines the interface for the DataHaven Service Manager, which manages validators
|
||||
* in the DataHaven network
|
||||
*/
|
||||
interface IDataHavenServiceManager is
|
||||
IDataHavenServiceManagerErrors,
|
||||
|
|
@ -84,20 +68,6 @@ interface IDataHavenServiceManager is
|
|||
address validator
|
||||
) external view returns (bool);
|
||||
|
||||
/// @notice Checks if a BSP address is in the allowlist
|
||||
/// @param bsp Address to check
|
||||
/// @return True if the BSP is in the allowlist, false otherwise
|
||||
function bspsAllowlist(
|
||||
address bsp
|
||||
) external view returns (bool);
|
||||
|
||||
/// @notice Checks if an MSP address is in the allowlist
|
||||
/// @param msp Address to check
|
||||
/// @return True if the MSP is in the allowlist, false otherwise
|
||||
function mspsAllowlist(
|
||||
address msp
|
||||
) external view returns (bool);
|
||||
|
||||
/// @notice Returns the Snowbridge Gateway address
|
||||
/// @return The Snowbridge gateway address
|
||||
function snowbridgeGateway() external view returns (address);
|
||||
|
|
@ -116,15 +86,11 @@ interface IDataHavenServiceManager is
|
|||
* @param initialOwner Address of the initial owner
|
||||
* @param rewardsInitiator Address authorized to initiate rewards
|
||||
* @param validatorsStrategies Array of strategies supported by validators
|
||||
* @param bspsStrategies Array of strategies supported by BSPs
|
||||
* @param mspsStrategies Array of strategies supported by MSPs
|
||||
*/
|
||||
function initialise(
|
||||
address initialOwner,
|
||||
address rewardsInitiator,
|
||||
IStrategy[] memory validatorsStrategies,
|
||||
IStrategy[] memory bspsStrategies,
|
||||
IStrategy[] memory mspsStrategies,
|
||||
address _snowbridgeGatewayAddress
|
||||
) external;
|
||||
|
||||
|
|
@ -174,22 +140,6 @@ interface IDataHavenServiceManager is
|
|||
address validator
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Adds a BSP to the allowlist
|
||||
* @param bsp Address of the BSP to add
|
||||
*/
|
||||
function addBspToAllowlist(
|
||||
address bsp
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Adds an MSP to the allowlist
|
||||
* @param msp Address of the MSP to add
|
||||
*/
|
||||
function addMspToAllowlist(
|
||||
address msp
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Removes a validator from the allowlist
|
||||
* @param validator Address of the validator to remove
|
||||
|
|
@ -198,22 +148,6 @@ interface IDataHavenServiceManager is
|
|||
address validator
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Removes a BSP from the allowlist
|
||||
* @param bsp Address of the BSP to remove
|
||||
*/
|
||||
function removeBspFromAllowlist(
|
||||
address bsp
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Removes an MSP from the allowlist
|
||||
* @param msp Address of the MSP to remove
|
||||
*/
|
||||
function removeMspFromAllowlist(
|
||||
address msp
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Returns all strategies supported by the DataHaven Validators operator set
|
||||
* @return An array of strategy contracts that validators can delegate to
|
||||
|
|
@ -235,48 +169,4 @@ interface IDataHavenServiceManager is
|
|||
function addStrategiesToValidatorsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Returns all strategies supported by the Backup Storage Providers (BSPs) operator set
|
||||
* @return An array of strategy contracts that BSPs can delegate to
|
||||
*/
|
||||
function bspsSupportedStrategies() external view returns (IStrategy[] memory);
|
||||
|
||||
/**
|
||||
* @notice Removes strategies from the list of supported strategies for Backup Storage Providers
|
||||
* @param _strategies Array of strategy contracts to remove from BSPs operator set
|
||||
*/
|
||||
function removeStrategiesFromBspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Adds strategies to the list of supported strategies for Backup Storage Providers
|
||||
* @param _strategies Array of strategy contracts to add to BSPs operator set
|
||||
*/
|
||||
function addStrategiesToBspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Returns all strategies supported by the Main Storage Providers (MSPs) operator set
|
||||
* @return An array of strategy contracts that MSPs can delegate to
|
||||
*/
|
||||
function mspsSupportedStrategies() external view returns (IStrategy[] memory);
|
||||
|
||||
/**
|
||||
* @notice Removes strategies from the list of supported strategies for Main Storage Providers
|
||||
* @param _strategies Array of strategy contracts to remove from MSPs operator set
|
||||
*/
|
||||
function removeStrategiesFromMspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Adds strategies to the list of supported strategies for Main Storage Providers
|
||||
* @param _strategies Array of strategy contracts to add to MSPs operator set
|
||||
*/
|
||||
function addStrategiesToMspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,16 +252,12 @@ contract AVSDeployer is Test {
|
|||
rewardsCoordinator, permissionControllerMock, allocationManager
|
||||
);
|
||||
|
||||
// Create arrays for the three sets of strategies required by DataHavenServiceManager
|
||||
// Create array for validators strategies required by DataHavenServiceManager
|
||||
IStrategy[] memory validatorsStrategies = new IStrategy[](deployedStrategies.length);
|
||||
IStrategy[] memory bspsStrategies = new IStrategy[](deployedStrategies.length);
|
||||
IStrategy[] memory mspsStrategies = new IStrategy[](deployedStrategies.length);
|
||||
|
||||
// For testing purposes, we'll use the same strategies for all three sets
|
||||
// For testing purposes, we'll use the deployed strategies for validators
|
||||
for (uint256 i = 0; i < deployedStrategies.length; i++) {
|
||||
validatorsStrategies[i] = deployedStrategies[i];
|
||||
bspsStrategies[i] = deployedStrategies[i];
|
||||
mspsStrategies[i] = deployedStrategies[i];
|
||||
}
|
||||
|
||||
serviceManager = DataHavenServiceManager(
|
||||
|
|
@ -274,8 +270,6 @@ contract AVSDeployer is Test {
|
|||
avsOwner,
|
||||
rewardsInitiator,
|
||||
validatorsStrategies,
|
||||
bspsStrategies,
|
||||
mspsStrategies,
|
||||
address(0) // This deployment does not use Snowbridge
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -43,10 +43,6 @@ contract SnowbridgeAndAVSDeployer is AVSDeployer {
|
|||
0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f, // Ninth pre-funded address in anvil
|
||||
0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 // Tenth pre-funded address in anvil
|
||||
];
|
||||
// The addresses of the Backup Storage Providers that are allowed to register to the DataHaven service.
|
||||
address[] public bspsAllowlist;
|
||||
// The addresses of the Main Storage Providers that are allowed to register to the DataHaven service.
|
||||
address[] public mspsAllowlist;
|
||||
|
||||
// Snowbridge contracts params
|
||||
// The hashes of the initial (current) Validators in the DataHaven solochain.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ FROM docker.io/library/ubuntu:22.04 AS builder
|
|||
# Branch or tag to build DataHaven from
|
||||
ARG COMMIT="main"
|
||||
ARG RUSTFLAGS=""
|
||||
ARG BUILD=""
|
||||
ENV RUSTFLAGS=$RUSTFLAGS
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV PROTOC_VER=21.12
|
||||
|
|
@ -37,7 +38,11 @@ WORKDIR /datahaven
|
|||
RUN rustc --print target-cpus
|
||||
|
||||
RUN echo "*** Building DataHaven ***"
|
||||
RUN cargo build --profile=production --all
|
||||
RUN if [ "$BUILD" = "static" ]; then \
|
||||
cargo build --profile=production --all --features static
|
||||
else \
|
||||
cargo build --profile=production --all
|
||||
fi
|
||||
|
||||
FROM debian:stable-slim
|
||||
LABEL maintainer="steve@moonsonglabs.com"
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@ lto = "thin"
|
|||
opt-level = 2
|
||||
|
||||
[registries.crates-io]
|
||||
protocol = "sparse"
|
||||
protocol = "sparse"
|
||||
|
|
|
|||
12
operator/Cargo.lock
generated
12
operator/Cargo.lock
generated
|
|
@ -3100,6 +3100,7 @@ dependencies = [
|
|||
"pallet-transaction-payment-rpc",
|
||||
"pallet-transaction-payment-rpc-runtime-api",
|
||||
"parity-scale-codec",
|
||||
"pq-sys",
|
||||
"sc-basic-authorship",
|
||||
"sc-cli",
|
||||
"sc-client-api",
|
||||
|
|
@ -11921,6 +11922,16 @@ dependencies = [
|
|||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pq-src"
|
||||
version = "0.3.10+libpq-18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56ef39ce621f4993d6084fdcd4cbf1e01c84bdba53109cfad095d2cf441b85b9"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pq-sys"
|
||||
version = "0.7.4"
|
||||
|
|
@ -11929,6 +11940,7 @@ checksum = "089d5dc8f44104b719912ad4478fd558b59a431ce19ef9101f637be8c656b90a"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"pq-src",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -304,6 +304,10 @@ shp-types = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v
|
|||
## Precompiles
|
||||
pallet-evm-precompile-file-system = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.1.4", default-features = false }
|
||||
|
||||
# Static linking
|
||||
#### Needed to build static binaries ####
|
||||
pq-sys = { version = "0.7.4" }
|
||||
|
||||
# The list of dependencies below (which can be both direct and indirect dependencies) are crates
|
||||
# that are suspected to be CPU-intensive, and that are unlikely to require debugging (as some of
|
||||
# their debug info might be missing) or to require to be frequently recompiled. We compile these
|
||||
|
|
|
|||
|
|
@ -132,6 +132,10 @@ serde = { workspace = true, default-features = true }
|
|||
cumulus-client-service = { workspace = true }
|
||||
toml = { workspace = true }
|
||||
|
||||
# Static linking
|
||||
#### Needed to build static binaries ####
|
||||
pq-sys = { workspace = true, optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
substrate-build-script-utils = { workspace = true, default-features = true }
|
||||
|
||||
|
|
@ -144,6 +148,7 @@ std = [
|
|||
"datahaven-testnet-runtime/std",
|
||||
"shp-opaque/std"
|
||||
]
|
||||
static = ["pq-sys", "pq-sys/bundled"]
|
||||
|
||||
# Dependencies that are only required if runtime benchmarking should be build.
|
||||
runtime-benchmarks = [
|
||||
|
|
|
|||
|
|
@ -123,7 +123,6 @@ pub type PCall = BatchPrecompileCall<Runtime>;
|
|||
mock_account!(Batch, |_| MockAccount::from_u64(1));
|
||||
mock_account!(Revert, |_| MockAccount::from_u64(2));
|
||||
|
||||
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
|
||||
/// Block storage limit in bytes. Set to 40 KB.
|
||||
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;
|
||||
|
||||
|
|
@ -131,10 +130,7 @@ parameter_types! {
|
|||
pub BlockGasLimit: U256 = U256::from(u64::MAX);
|
||||
pub PrecompilesValue: Precompiles<Runtime> = Precompiles::new();
|
||||
pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
|
||||
pub GasLimitPovSizeRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(MAX_POV_SIZE)
|
||||
};
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
pub GasLimitStorageGrowthRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
|
||||
|
|
|
|||
|
|
@ -124,7 +124,6 @@ pub type Precompiles<R> = PrecompileSetBuilder<
|
|||
|
||||
pub type PCall = CollectivePrecompileCall<Runtime, pallet_collective::Instance1>;
|
||||
|
||||
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
|
||||
/// Block storage limit in bytes. Set to 40 KB.
|
||||
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;
|
||||
|
||||
|
|
@ -132,10 +131,7 @@ parameter_types! {
|
|||
pub BlockGasLimit: U256 = U256::from(u64::MAX);
|
||||
pub PrecompilesValue: Precompiles<Runtime> = Precompiles::new();
|
||||
pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
|
||||
pub GasLimitPovSizeRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(MAX_POV_SIZE)
|
||||
};
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
pub GasLimitStorageGrowthRatio : u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ impl pallet_balances::Config for Runtime {
|
|||
type DoneSlashHandler = ();
|
||||
}
|
||||
|
||||
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
|
||||
/// Block storage limit in bytes. Set to 40 KB.
|
||||
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;
|
||||
|
||||
|
|
@ -117,10 +116,7 @@ parameter_types! {
|
|||
pub BlockGasLimit: U256 = U256::from(u64::MAX);
|
||||
pub PrecompilesValue: Precompiles<Runtime> = Precompiles::new();
|
||||
pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
|
||||
pub GasLimitPovSizeRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(MAX_POV_SIZE)
|
||||
};
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
pub GasLimitStorageGrowthRatio : u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
|
||||
|
|
|
|||
|
|
@ -108,7 +108,6 @@ pub type Precompiles<R> = PrecompileSetBuilder<
|
|||
|
||||
pub type PCall = Erc20BalancesPrecompileCall<Runtime, NativeErc20Metadata, ()>;
|
||||
|
||||
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
|
||||
/// Block storage limit in bytes. Set to 40 KB.
|
||||
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;
|
||||
|
||||
|
|
@ -116,10 +115,7 @@ parameter_types! {
|
|||
pub BlockGasLimit: U256 = U256::from(u64::MAX);
|
||||
pub PrecompilesValue: Precompiles<Runtime> = Precompiles::new();
|
||||
pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
|
||||
pub GasLimitPovSizeRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(MAX_POV_SIZE)
|
||||
};
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
pub GasLimitStorageGrowthRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
|
||||
|
|
|
|||
|
|
@ -110,7 +110,6 @@ impl pallet_balances::Config for Runtime {
|
|||
type DoneSlashHandler = ();
|
||||
}
|
||||
|
||||
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
|
||||
/// Block storage limit in bytes. Set to 40 KB.
|
||||
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;
|
||||
|
||||
|
|
@ -118,10 +117,7 @@ parameter_types! {
|
|||
pub BlockGasLimit: U256 = U256::from(u64::MAX);
|
||||
pub PrecompilesValue: Precompiles<Runtime> = Precompiles::new();
|
||||
pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
|
||||
pub GasLimitPovSizeRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(MAX_POV_SIZE)
|
||||
};
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
pub GasLimitStorageGrowthRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ impl pallet_balances::Config for Runtime {
|
|||
type DoneSlashHandler = ();
|
||||
}
|
||||
|
||||
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
|
||||
/// Block storage limit in bytes. Set to 40 KB.
|
||||
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;
|
||||
|
||||
|
|
@ -109,10 +108,7 @@ parameter_types! {
|
|||
pub BlockGasLimit: U256 = U256::from(u64::MAX);
|
||||
pub PrecompilesValue: Precompiles<Runtime> = Precompiles::new();
|
||||
pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
|
||||
pub GasLimitPovSizeRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(MAX_POV_SIZE)
|
||||
};
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
pub GasLimitStorageGrowthRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
|
||||
|
|
|
|||
|
|
@ -150,7 +150,6 @@ impl<OuterOrigin> EnsureAddressOrigin<OuterOrigin> for EnsureAddressAlways {
|
|||
}
|
||||
}
|
||||
|
||||
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
|
||||
/// Block storage limit in bytes. Set to 40 KB.
|
||||
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;
|
||||
|
||||
|
|
@ -158,10 +157,7 @@ parameter_types! {
|
|||
pub BlockGasLimit: U256 = U256::from(u64::MAX);
|
||||
pub PrecompilesValue: Precompiles<Runtime> = Precompiles::new();
|
||||
pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
|
||||
pub GasLimitPovSizeRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(MAX_POV_SIZE)
|
||||
};
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
pub GasLimitStorageGrowthRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
|
||||
|
|
|
|||
|
|
@ -152,10 +152,7 @@ parameter_types! {
|
|||
pub BlockGasLimit: U256 = U256::from(u64::MAX);
|
||||
pub PrecompilesValue: TestPrecompiles<Runtime> = TestPrecompiles::new();
|
||||
pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
|
||||
pub GasLimitPovSizeRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(MAX_POV_SIZE)
|
||||
};
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
pub GasLimitStorageGrowthRatio: u64 = {
|
||||
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
|
||||
block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
|
||||
|
|
|
|||
|
|
@ -26,8 +26,11 @@ pub mod time {
|
|||
const ONE_MINUTE: BlockNumber = MINUTES;
|
||||
|
||||
frame_support::parameter_types! {
|
||||
/// Session/epoch duration:
|
||||
/// - Production: 1 hour (600 blocks)
|
||||
/// - Fast-runtime: 1 minute (10 blocks)
|
||||
pub const EpochDurationInBlocks: BlockNumber = prod_or_fast!(ONE_HOUR, ONE_MINUTE);
|
||||
pub const SessionsPerEra: SessionIndex = prod_or_fast!(6, 3);
|
||||
pub const SessionsPerEra: SessionIndex = prod_or_fast!(6, 1);
|
||||
}
|
||||
|
||||
// These time units are defined in number of blocks.
|
||||
|
|
|
|||
|
|
@ -18,6 +18,42 @@
|
|||
//!
|
||||
//! The types and constants defined here keep the pallet configuration consistent between
|
||||
//! networks while leaving each runtime free to decide which migrations should actually run.
|
||||
//!
|
||||
//! ## Migration History
|
||||
//!
|
||||
//! This section documents migrations that have been executed and subsequently removed from the
|
||||
//! codebase. The migration framework tracks completed migrations on-chain, preventing re-execution.
|
||||
//!
|
||||
//! ### Executed Migrations (Code Removed)
|
||||
//!
|
||||
//! #### 1. EVM Pallet Alias Migration
|
||||
//! - **Migration ID**: `datahaven-evm-mbm` (version 0 → 1)
|
||||
//! - **Type**: Multi-block stepped migration
|
||||
//! - **Original PR**: [#213](https://github.com/datahaven-xyz/datahaven/pull/213)
|
||||
//! - **Intent**: Fixed `eth_getCode` and other Ethereum RPC calls by renaming the pallet_evm
|
||||
//! FRAME alias from `Evm` to `EVM`. Frontier's `StorageOverrideHandler` hardcodes the storage
|
||||
//! prefix as `twox_128("EVM")`, but our runtimes used `Evm`, causing all contract bytecode
|
||||
//! lookups to fail. This migration realigned the storage prefix with Frontier's expectations.
|
||||
//! - **Storage Migrated**:
|
||||
//! - `Evm::AccountCodes` → `EVM::AccountCodes`
|
||||
//! - `Evm::AccountCodesMetadata` → `EVM::AccountCodesMetadata`
|
||||
//! - `Evm::AccountStorages` → `EVM::AccountStorages`
|
||||
//! - **Execution**: Successfully executed on Testnet and Stagenet (39 keys migrated, <0.1% block weight)
|
||||
//! - **Removed**: 2025-01 ([PR #318](https://github.com/datahaven-xyz/datahaven/pull/318))
|
||||
//!
|
||||
//! #### 2. EVM Chain ID Migration
|
||||
//! - **Migration ID**: `dh-evm-chain-id-v1` (version 0 → 1)
|
||||
//! - **Type**: Single-step migration
|
||||
//! - **Original PR**: [#280](https://github.com/datahaven-xyz/datahaven/pull/280)
|
||||
//! - **Intent**: Updated chain IDs for all three DataHaven environments to their final assigned
|
||||
//! values. The stored EVM chain ID in `pallet_evm_chain_id::ChainId` was migrated to match
|
||||
//! the configured constants after chain ID assignments were finalized.
|
||||
//! - **Networks**:
|
||||
//! - Mainnet: Chain ID 55930 (no migration needed, set at genesis)
|
||||
//! - Testnet: Migrated to chain ID 55931
|
||||
//! - Stagenet: Migrated to chain ID 55932
|
||||
//! - **Execution**: Successfully executed on Testnet and Stagenet
|
||||
//! - **Removed**: 2025-01 ([PR #318](https://github.com/datahaven-xyz/datahaven/pull/318))
|
||||
|
||||
use frame_support::pallet_prelude::*;
|
||||
|
||||
|
|
@ -36,7 +72,7 @@ pub type MigrationIdentifierMaxLen = ConstU32<MIGRATION_IDENTIFIER_MAX_LEN>;
|
|||
/// The tuple starts empty and can be extended with concrete migrations over time. Keeping it in a
|
||||
/// shared module reduces duplication once we coordinate migrations across networks.
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
pub type MultiBlockMigrationList<T> = (evm_alias::EvmAliasMigration<T>,);
|
||||
pub type MultiBlockMigrationList = ();
|
||||
|
||||
/// During benchmarking we switch to the pallet-provided mocked migrations to guarantee success.
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
|
|
@ -45,521 +81,16 @@ pub type MultiBlockMigrationList = pallet_migrations::mock_helpers::MockedMigrat
|
|||
/// Placeholder handler for migration status notifications. We do not emit any extra signals yet.
|
||||
pub type MigrationStatusHandler = ();
|
||||
|
||||
/// Default handler triggered on migration failures.
|
||||
pub type FailedMigrationHandler = frame_support::migrations::FreezeChainOnFailedMigration;
|
||||
|
||||
/// Multi-block migration for updating the EVM chain ID to the new value.
|
||||
pub mod evm_chain_id {
|
||||
use core::marker::PhantomData;
|
||||
use frame_support::{
|
||||
migrations::{MigrationId, SteppedMigration, SteppedMigrationError},
|
||||
pallet_prelude::*,
|
||||
weights::WeightMeter,
|
||||
};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use codec::Encode;
|
||||
|
||||
/// Multi-block migration that updates the stored EVM chain ID to match the new configuration.
|
||||
pub struct EvmChainIdMigration<T, const NEW_CHAIN_ID: u64>(PhantomData<T>);
|
||||
|
||||
impl<T, const NEW_CHAIN_ID: u64> SteppedMigration for EvmChainIdMigration<T, NEW_CHAIN_ID>
|
||||
where
|
||||
T: pallet_evm_chain_id::Config,
|
||||
{
|
||||
type Cursor = ();
|
||||
type Identifier = MigrationId<20>;
|
||||
|
||||
fn id() -> Self::Identifier {
|
||||
MigrationId {
|
||||
pallet_id: *b"dh-evm-chain-id-v1 ",
|
||||
version_from: 0,
|
||||
version_to: 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn step(
|
||||
cursor: Option<Self::Cursor>,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<Option<Self::Cursor>, SteppedMigrationError> {
|
||||
// This migration completes in a single step
|
||||
if cursor.is_some() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let required = T::DbWeight::get().reads_writes(1, 1);
|
||||
if meter.try_consume(required).is_err() {
|
||||
return Err(SteppedMigrationError::InsufficientWeight { required });
|
||||
}
|
||||
|
||||
log::info!(
|
||||
"🔄 [EVM Chain ID Migration] Updating chain ID to {}",
|
||||
NEW_CHAIN_ID
|
||||
);
|
||||
|
||||
// Update the chain ID storage
|
||||
pallet_evm_chain_id::ChainId::<T>::put(NEW_CHAIN_ID);
|
||||
|
||||
log::info!(
|
||||
"✅ [EVM Chain ID Migration] Successfully updated chain ID to {}",
|
||||
NEW_CHAIN_ID
|
||||
);
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
let old_chain_id = pallet_evm_chain_id::ChainId::<T>::get();
|
||||
log::info!(
|
||||
"📋 [EVM Chain ID Migration] Current chain ID: {}",
|
||||
old_chain_id
|
||||
);
|
||||
Ok(old_chain_id.encode())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
|
||||
use codec::Decode;
|
||||
|
||||
let old_chain_id =
|
||||
u64::decode(&mut &state[..]).map_err(|_| "Failed to decode old chain ID")?;
|
||||
let new_chain_id = pallet_evm_chain_id::ChainId::<T>::get();
|
||||
|
||||
log::info!(
|
||||
"🔍 [EVM Chain ID Migration] Chain ID updated from {} to {}",
|
||||
old_chain_id,
|
||||
new_chain_id
|
||||
);
|
||||
|
||||
if new_chain_id != NEW_CHAIN_ID {
|
||||
return Err(sp_runtime::TryRuntimeError::Other(
|
||||
"Chain ID was not updated correctly",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Multi-block migration for renaming the EVM pallet alias.
|
||||
pub mod evm_alias {
|
||||
use core::marker::PhantomData;
|
||||
use frame_support::{
|
||||
migrations::{MigrationId, SteppedMigration, SteppedMigrationError},
|
||||
pallet_prelude::*,
|
||||
weights::WeightMeter,
|
||||
BoundedVec, StorageHasher,
|
||||
};
|
||||
use sp_io::storage;
|
||||
use sp_std::{convert::TryFrom, vec::Vec};
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
use sp_std::collections::btree_map::BTreeMap;
|
||||
|
||||
/// Multi-block migration that renames the Frontier EVM pallet alias from `Evm` to `EVM`.
|
||||
pub struct EvmAliasMigration<T>(PhantomData<T>);
|
||||
|
||||
impl<T> SteppedMigration for EvmAliasMigration<T>
|
||||
where
|
||||
T: pallet_evm::Config,
|
||||
{
|
||||
type Cursor = BoundedVec<u8, ConstU32<128>>;
|
||||
type Identifier = MigrationId<17>;
|
||||
|
||||
fn id() -> Self::Identifier {
|
||||
MigrationId {
|
||||
pallet_id: *b"datahaven-evm-mbm",
|
||||
version_from: 0,
|
||||
version_to: 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn step(
|
||||
cursor: Option<Self::Cursor>,
|
||||
meter: &mut WeightMeter,
|
||||
) -> Result<Option<Self::Cursor>, SteppedMigrationError> {
|
||||
if cursor.is_none() {
|
||||
log::info!(
|
||||
"🚀 [EVM Migration] Starting pallet alias migration from 'Evm' to 'EVM'"
|
||||
);
|
||||
}
|
||||
|
||||
let old_prefix = Twox128::hash(b"Evm");
|
||||
let new_prefix = Twox128::hash(b"EVM");
|
||||
let mut current_key: Vec<u8> = cursor
|
||||
.map(Into::into)
|
||||
.unwrap_or_else(|| old_prefix.to_vec());
|
||||
let mut processed = 0u32;
|
||||
let required = T::DbWeight::get().reads_writes(1, 2);
|
||||
|
||||
loop {
|
||||
let next_key = match storage::next_key(¤t_key) {
|
||||
Some(next) if next.starts_with(&old_prefix) => next,
|
||||
_ => {
|
||||
log::info!(
|
||||
"✅ [EVM Migration] Completed! Processed {} keys in this step",
|
||||
processed
|
||||
);
|
||||
return Ok(None);
|
||||
}
|
||||
};
|
||||
|
||||
if meter.try_consume(required).is_err() {
|
||||
if processed == 0 {
|
||||
log::warn!(
|
||||
"⚠️ [EVM Migration] Insufficient weight for even one key migration"
|
||||
);
|
||||
return Err(SteppedMigrationError::InsufficientWeight { required });
|
||||
}
|
||||
log::info!(
|
||||
"⏸️ [EVM Migration] Pausing after migrating {} keys (weight limit reached)",
|
||||
processed
|
||||
);
|
||||
return BoundedVec::try_from(current_key)
|
||||
.map(Some)
|
||||
.map_err(|_| SteppedMigrationError::Failed);
|
||||
}
|
||||
|
||||
if let Some(value) = storage::get(&next_key) {
|
||||
let mut new_key = Vec::with_capacity(next_key.len());
|
||||
new_key.extend_from_slice(&new_prefix);
|
||||
new_key.extend_from_slice(&next_key[16..]);
|
||||
storage::set(&new_key, &value);
|
||||
}
|
||||
storage::clear(&next_key);
|
||||
|
||||
processed = processed.saturating_add(1);
|
||||
current_key = next_key;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
|
||||
use codec::Encode;
|
||||
|
||||
let storage_prefix = |item: &[u8]| {
|
||||
let mut key = [0u8; 32];
|
||||
key[0..16].copy_from_slice(&Twox128::hash(b"Evm"));
|
||||
key[16..32].copy_from_slice(&Twox128::hash(item));
|
||||
key
|
||||
};
|
||||
|
||||
let mut counts = BTreeMap::new();
|
||||
|
||||
for name in [
|
||||
b"AccountCodes" as &[u8],
|
||||
b"AccountCodesMetadata",
|
||||
b"AccountStorages",
|
||||
] {
|
||||
let count = count_keys(&storage_prefix(name));
|
||||
counts.insert(name.to_vec(), count.encode());
|
||||
}
|
||||
|
||||
Ok(counts.encode())
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
|
||||
use codec::Decode;
|
||||
|
||||
let snapshot: BTreeMap<Vec<u8>, Vec<u8>> =
|
||||
Decode::decode(&mut &state[..]).expect("Failed to decode snapshot");
|
||||
|
||||
let old_storage = |item: &[u8]| {
|
||||
let mut key = [0u8; 32];
|
||||
key[0..16].copy_from_slice(&Twox128::hash(b"Evm"));
|
||||
key[16..32].copy_from_slice(&Twox128::hash(item));
|
||||
key
|
||||
};
|
||||
|
||||
let new_storage = |item: &[u8]| {
|
||||
let mut key = [0u8; 32];
|
||||
key[0..16].copy_from_slice(&Twox128::hash(b"EVM"));
|
||||
key[16..32].copy_from_slice(&Twox128::hash(item));
|
||||
key
|
||||
};
|
||||
|
||||
for name in [
|
||||
b"AccountCodes" as &[u8],
|
||||
b"AccountCodesMetadata",
|
||||
b"AccountStorages",
|
||||
] {
|
||||
let old_count = count_keys(&old_storage(name));
|
||||
assert_eq!(old_count, 0, "Old Evm prefix still present after migration");
|
||||
|
||||
let expected = snapshot
|
||||
.get(name)
|
||||
.and_then(|v| u32::decode(&mut &v[..]).ok())
|
||||
.unwrap_or(0);
|
||||
let actual = count_keys(&new_storage(name));
|
||||
|
||||
assert_eq!(expected, actual, "Migrated entry count mismatch");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to count storage keys with a given prefix.
|
||||
#[cfg(any(feature = "try-runtime", test))]
|
||||
pub(crate) fn count_keys(prefix: &[u8]) -> u32 {
|
||||
let mut count = 0u32;
|
||||
let mut cursor = prefix.to_vec();
|
||||
loop {
|
||||
match storage::next_key(&cursor) {
|
||||
Some(next) if next.starts_with(prefix) => {
|
||||
count = count.saturating_add(1);
|
||||
cursor = next;
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
count
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::evm_alias::{count_keys, EvmAliasMigration};
|
||||
use codec::Encode;
|
||||
use frame_support::{
|
||||
derive_impl,
|
||||
migrations::SteppedMigration,
|
||||
parameter_types,
|
||||
weights::{constants::RocksDbWeight, Weight, WeightMeter},
|
||||
StorageHasher, Twox128,
|
||||
};
|
||||
use pallet_evm::AccountCodes;
|
||||
use sp_core::{H160, H256, U256};
|
||||
use sp_io::storage;
|
||||
use sp_runtime::BuildStorage;
|
||||
use sp_std::vec;
|
||||
|
||||
frame_support::construct_runtime!(
|
||||
pub enum TestRuntime {
|
||||
System: frame_system::{Pallet, Call, Config<T>, Storage, Event<T>},
|
||||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
Timestamp: pallet_timestamp::{Pallet, Call, Storage},
|
||||
EVM: pallet_evm::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
EvmChainId: pallet_evm_chain_id::{Pallet, Storage},
|
||||
}
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: u64 = 250;
|
||||
pub BlockWeights: frame_system::limits::BlockWeights =
|
||||
frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1024, 0));
|
||||
}
|
||||
|
||||
#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig as frame_system::DefaultConfig)]
|
||||
impl frame_system::Config for TestRuntime {
|
||||
type Nonce = u64;
|
||||
type Block = frame_system::mocking::MockBlock<Self>;
|
||||
type BlockHashCount = BlockHashCount;
|
||||
type AccountData = pallet_balances::AccountData<u64>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
}
|
||||
|
||||
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
|
||||
impl pallet_balances::Config for TestRuntime {
|
||||
type RuntimeHoldReason = ();
|
||||
type Balance = u64;
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type AccountStore = System;
|
||||
}
|
||||
|
||||
#[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig)]
|
||||
impl pallet_timestamp::Config for TestRuntime {}
|
||||
|
||||
parameter_types! {
|
||||
pub MockPrecompiles: MockPrecompileSet = MockPrecompileSet;
|
||||
}
|
||||
|
||||
#[derive_impl(pallet_evm::config_preludes::TestDefaultConfig)]
|
||||
impl pallet_evm::Config for TestRuntime {
|
||||
type AccountProvider = pallet_evm::FrameSystemAccountProvider<Self>;
|
||||
type FeeCalculator = FixedGasPrice;
|
||||
type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping<Self>;
|
||||
type Currency = Balances;
|
||||
type Runner = pallet_evm::runner::stack::Runner<Self>;
|
||||
type Timestamp = Timestamp;
|
||||
type PrecompilesType = MockPrecompileSet;
|
||||
type PrecompilesValue = MockPrecompiles;
|
||||
}
|
||||
|
||||
impl pallet_evm_chain_id::Config for TestRuntime {}
|
||||
|
||||
pub struct FixedGasPrice;
|
||||
impl pallet_evm::FeeCalculator for FixedGasPrice {
|
||||
fn min_gas_price() -> (U256, Weight) {
|
||||
(1_000_000_000u128.into(), Weight::from_parts(1_000, 0))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MockPrecompileSet;
|
||||
impl pallet_evm::PrecompileSet for MockPrecompileSet {
|
||||
fn execute(
|
||||
&self,
|
||||
_handle: &mut impl pallet_evm::PrecompileHandle,
|
||||
) -> Option<pallet_evm::PrecompileResult> {
|
||||
None
|
||||
}
|
||||
|
||||
fn is_precompile(&self, _address: H160, _gas: u64) -> pallet_evm::IsPrecompileResult {
|
||||
pallet_evm::IsPrecompileResult::Answer {
|
||||
is_precompile: false,
|
||||
extra_cost: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn old_storage_prefix(item: &[u8]) -> [u8; 32] {
|
||||
let mut key = [0u8; 32];
|
||||
key[0..16].copy_from_slice(&Twox128::hash(b"Evm"));
|
||||
key[16..32].copy_from_slice(&Twox128::hash(item));
|
||||
key
|
||||
}
|
||||
|
||||
fn raw_key(storage_name: &[u8], address: H160, index: Option<H256>) -> Vec<u8> {
|
||||
let mut key = old_storage_prefix(storage_name).to_vec();
|
||||
key.extend_from_slice(&sp_io::hashing::blake2_128(&address.encode()));
|
||||
key.extend_from_slice(address.as_bytes());
|
||||
if let Some(idx) = index {
|
||||
key.extend_from_slice(&sp_io::hashing::blake2_128(&idx.encode()));
|
||||
key.extend_from_slice(idx.as_bytes());
|
||||
}
|
||||
key
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_block_evm_alias_migration_moves_all_entries() {
|
||||
let mut storage = frame_system::GenesisConfig::<TestRuntime>::default()
|
||||
.build_storage()
|
||||
.unwrap();
|
||||
pallet_balances::GenesisConfig::<TestRuntime>::default()
|
||||
.assimilate_storage(&mut storage)
|
||||
.unwrap();
|
||||
let mut ext = sp_io::TestExternalities::new(storage);
|
||||
ext.execute_with(|| {
|
||||
let addresses: Vec<H160> = (1u64..=3).map(H160::from_low_u64_be).collect();
|
||||
|
||||
for (idx, &address) in addresses.iter().enumerate() {
|
||||
storage::set(
|
||||
&raw_key(b"AccountCodes", address, None),
|
||||
&vec![idx as u8; 3].encode(),
|
||||
);
|
||||
storage::set(
|
||||
&raw_key(b"AccountCodesMetadata", address, None),
|
||||
&(42u64 + idx as u64, H256::repeat_byte(idx as u8)).encode(),
|
||||
);
|
||||
storage::set(
|
||||
&raw_key(
|
||||
b"AccountStorages",
|
||||
address,
|
||||
Some(H256::repeat_byte(0xAA + idx as u8)),
|
||||
),
|
||||
&H256::repeat_byte(idx as u8).encode(),
|
||||
);
|
||||
}
|
||||
|
||||
let mut cursor = None;
|
||||
loop {
|
||||
let mut meter = WeightMeter::with_limit(RocksDbWeight::get().reads_writes(1, 2));
|
||||
match EvmAliasMigration::<TestRuntime>::step(cursor, &mut meter) {
|
||||
Ok(None) => break,
|
||||
Ok(Some(next)) => cursor = Some(next),
|
||||
Err(err) => panic!("migration failed: {:?}", err),
|
||||
}
|
||||
}
|
||||
|
||||
for address in addresses {
|
||||
assert!(!AccountCodes::<TestRuntime>::get(address).is_empty());
|
||||
}
|
||||
|
||||
assert_eq!(count_keys(&old_storage_prefix(b"AccountCodes")[..]), 0);
|
||||
assert_eq!(
|
||||
count_keys(&old_storage_prefix(b"AccountCodesMetadata")[..]),
|
||||
0
|
||||
);
|
||||
assert_eq!(count_keys(&old_storage_prefix(b"AccountStorages")[..]), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evm_chain_id_migration_updates_storage() {
|
||||
use super::evm_chain_id::EvmChainIdMigration;
|
||||
|
||||
let mut storage = frame_system::GenesisConfig::<TestRuntime>::default()
|
||||
.build_storage()
|
||||
.unwrap();
|
||||
pallet_balances::GenesisConfig::<TestRuntime>::default()
|
||||
.assimilate_storage(&mut storage)
|
||||
.unwrap();
|
||||
let mut ext = sp_io::TestExternalities::new(storage);
|
||||
|
||||
ext.execute_with(|| {
|
||||
// Set an old chain ID value
|
||||
const OLD_CHAIN_ID: u64 = 12345;
|
||||
const NEW_CHAIN_ID: u64 = 55931;
|
||||
|
||||
pallet_evm_chain_id::ChainId::<TestRuntime>::put(OLD_CHAIN_ID);
|
||||
assert_eq!(
|
||||
pallet_evm_chain_id::ChainId::<TestRuntime>::get(),
|
||||
OLD_CHAIN_ID
|
||||
);
|
||||
|
||||
// Run the migration
|
||||
let mut meter = WeightMeter::with_limit(Weight::MAX);
|
||||
let result = EvmChainIdMigration::<TestRuntime, NEW_CHAIN_ID>::step(None, &mut meter);
|
||||
|
||||
// Verify migration succeeded and completed in one step
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), None);
|
||||
|
||||
// Verify the chain ID was updated
|
||||
assert_eq!(
|
||||
pallet_evm_chain_id::ChainId::<TestRuntime>::get(),
|
||||
NEW_CHAIN_ID
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evm_chain_id_migration_is_idempotent() {
|
||||
use super::evm_chain_id::EvmChainIdMigration;
|
||||
|
||||
let mut storage = frame_system::GenesisConfig::<TestRuntime>::default()
|
||||
.build_storage()
|
||||
.unwrap();
|
||||
pallet_balances::GenesisConfig::<TestRuntime>::default()
|
||||
.assimilate_storage(&mut storage)
|
||||
.unwrap();
|
||||
let mut ext = sp_io::TestExternalities::new(storage);
|
||||
|
||||
ext.execute_with(|| {
|
||||
const NEW_CHAIN_ID: u64 = 55932;
|
||||
|
||||
// Run the migration twice
|
||||
let mut meter = WeightMeter::with_limit(Weight::MAX);
|
||||
let result1 = EvmChainIdMigration::<TestRuntime, NEW_CHAIN_ID>::step(None, &mut meter);
|
||||
|
||||
let mut meter = WeightMeter::with_limit(Weight::MAX);
|
||||
let result2 = EvmChainIdMigration::<TestRuntime, NEW_CHAIN_ID>::step(None, &mut meter);
|
||||
|
||||
// Both should succeed
|
||||
assert!(result1.is_ok());
|
||||
assert!(result2.is_ok());
|
||||
|
||||
// Chain ID should be set correctly
|
||||
assert_eq!(
|
||||
pallet_evm_chain_id::ChainId::<TestRuntime>::get(),
|
||||
NEW_CHAIN_ID
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
/// Handler triggered on migration failures.
|
||||
///
|
||||
/// This handler attempts to enter SafeMode when a migration fails, allowing governance to
|
||||
/// intervene and fix the issue while preventing regular user transactions from interacting
|
||||
/// with potentially inconsistent storage state.
|
||||
///
|
||||
/// The handler is parameterized by the SafeMode pallet type from each runtime, with a fallback
|
||||
/// to freezing the chain if SafeMode cannot be entered.
|
||||
pub type FailedMigrationHandler<SafeMode> =
|
||||
frame_support::migrations::EnterSafeModeOnFailedMigration<
|
||||
SafeMode,
|
||||
frame_support::migrations::FreezeChainOnFailedMigration,
|
||||
>;
|
||||
|
|
|
|||
|
|
@ -79,14 +79,14 @@ use datahaven_runtime_common::{
|
|||
},
|
||||
gas::WEIGHT_PER_GAS,
|
||||
migrations::{
|
||||
FailedMigrationHandler as DefaultFailedMigrationHandler, MigrationCursorMaxLen,
|
||||
MigrationIdentifierMaxLen, MigrationStatusHandler,
|
||||
FailedMigrationHandler, MigrationCursorMaxLen, MigrationIdentifierMaxLen,
|
||||
MigrationStatusHandler,
|
||||
},
|
||||
safe_mode::{
|
||||
ReleaseDelayNone, RuntimeCallFilter, SafeModeDuration, SafeModeEnterDeposit,
|
||||
SafeModeExtendDeposit, TxPauseWhitelistedCalls,
|
||||
},
|
||||
time::{EpochDurationInBlocks, DAYS, MILLISECS_PER_BLOCK},
|
||||
time::{EpochDurationInBlocks, SessionsPerEra, DAYS, MILLISECS_PER_BLOCK},
|
||||
};
|
||||
use dhp_bridge::{EigenLayerMessageProcessor, NativeTokenTransferMessageProcessor};
|
||||
use frame_support::{
|
||||
|
|
@ -138,7 +138,7 @@ use sp_runtime::{
|
|||
traits::{Convert, ConvertInto, IdentityLookup, Keccak256, OpaqueKeys, UniqueSaturatedInto},
|
||||
FixedPointNumber, Perbill, Perquintill,
|
||||
};
|
||||
use sp_staking::{EraIndex, SessionIndex};
|
||||
use sp_staking::EraIndex;
|
||||
use sp_std::{
|
||||
convert::{From, Into},
|
||||
prelude::*,
|
||||
|
|
@ -164,7 +164,6 @@ const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
|
|||
parameter_types! {
|
||||
pub const MaxAuthorities: u32 = 32;
|
||||
pub const BondingDuration: EraIndex = polkadot_runtime_common::prod_or_fast!(28, 3);
|
||||
pub const SessionsPerEra: SessionIndex = polkadot_runtime_common::prod_or_fast!(6, 1);
|
||||
pub const AuthorRewardPoints: u32 = 20;
|
||||
}
|
||||
|
||||
|
|
@ -511,7 +510,8 @@ impl pallet_beefy::Config for Runtime {
|
|||
type AncestryHelper = BeefyMmrLeaf;
|
||||
type WeightInfo = ();
|
||||
type KeyOwnerProof = <Historical as KeyOwnerProofSystem<(KeyTypeId, BeefyId)>>::Proof;
|
||||
type EquivocationReportSystem = ();
|
||||
type EquivocationReportSystem =
|
||||
pallet_beefy::EquivocationReportSystem<Self, Offences, Historical, ReportLongevity>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
|
@ -847,14 +847,13 @@ impl pallet_parameters::Config for Runtime {
|
|||
impl pallet_migrations::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList<Runtime>;
|
||||
type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList;
|
||||
type CursorMaxLen = MigrationCursorMaxLen;
|
||||
type IdentifierMaxLen = MigrationIdentifierMaxLen;
|
||||
type MigrationStatusHandler = MigrationStatusHandler;
|
||||
// TODO: Remove this once we have a proper failed migration handler (Safe mode)
|
||||
type FailedMigrationHandler = DefaultFailedMigrationHandler;
|
||||
type FailedMigrationHandler = FailedMigrationHandler<SafeMode>;
|
||||
type MaxServiceWeight = MaxServiceWeight;
|
||||
type WeightInfo = mainnet_weights::pallet_migrations::WeightInfo<Runtime>;
|
||||
}
|
||||
|
|
@ -996,13 +995,10 @@ parameter_types! {
|
|||
pub PrecompilesValue: Precompiles = DataHavenPrecompiles::<Runtime>::new();
|
||||
pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0);
|
||||
pub SuicideQuickClearLimit: u32 = 0;
|
||||
/// The amount of gas per pov. A ratio of 16 if we convert ref_time to gas and we compare
|
||||
/// it with the pov_size for a block. E.g.
|
||||
/// ceil(
|
||||
/// (max_extrinsic.ref_time() / max_extrinsic.proof_size()) / WEIGHT_PER_GAS
|
||||
/// )
|
||||
/// The amount of gas per pov. Set to 0 because DataHaven is a solo chain and we don't
|
||||
/// account for POV (Proof-of-Validity) size constraints like parachains do.
|
||||
/// We should re-check `xcm_config::Erc20XcmBridgeTransferGasLimit` when changing this value
|
||||
pub const GasLimitPovSizeRatio: u64 = 16;
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
/// The amount of gas per storage (in bytes): BLOCK_GAS_LIMIT / BLOCK_STORAGE_LIMIT
|
||||
/// (60_000_000 / 160 kb)
|
||||
pub GasLimitStorageGrowthRatio: u64 = 366;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@
|
|||
mod common;
|
||||
|
||||
use common::*;
|
||||
use datahaven_mainnet_runtime::{Runtime, RuntimeCall, RuntimeOrigin};
|
||||
use datahaven_mainnet_runtime::{
|
||||
Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SafeMode, System,
|
||||
};
|
||||
use frame_support::{assert_noop, assert_ok};
|
||||
use pallet_migrations::{Call as MigrationsCall, HistoricCleanupSelector};
|
||||
use sp_runtime::{traits::Dispatchable, DispatchError};
|
||||
|
|
@ -69,3 +71,76 @@ fn migrations_force_calls_are_root_only() {
|
|||
assert_ok!(clear_historic.dispatch(RuntimeOrigin::root()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failed_migration_enters_safe_mode() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
// Verify SafeMode is not active initially
|
||||
assert!(
|
||||
!SafeMode::is_entered(),
|
||||
"SafeMode should not be active initially"
|
||||
);
|
||||
|
||||
// Simulate a failed migration by directly calling the FailedMigrationHandler
|
||||
// This tests that when migrations fail, the system enters SafeMode
|
||||
use frame_support::migrations::FailedMigrationHandler;
|
||||
type Handler = <Runtime as pallet_migrations::Config>::FailedMigrationHandler;
|
||||
|
||||
// Call the failed handler (simulating a migration failure)
|
||||
let result = Handler::failed(Some(0));
|
||||
|
||||
// The handler should indicate that SafeMode was entered
|
||||
assert_eq!(
|
||||
result,
|
||||
frame_support::migrations::FailedMigrationHandling::KeepStuck,
|
||||
"Handler should keep the chain stuck in SafeMode"
|
||||
);
|
||||
|
||||
// Verify that SafeMode is now active
|
||||
assert!(
|
||||
SafeMode::is_entered(),
|
||||
"SafeMode should be active after migration failure"
|
||||
);
|
||||
|
||||
// Get the block number when SafeMode should expire
|
||||
let entered_until = pallet_safe_mode::EnteredUntil::<Runtime>::get();
|
||||
assert!(
|
||||
entered_until.is_some(),
|
||||
"SafeMode should have an expiry block"
|
||||
);
|
||||
|
||||
// Verify that the SafeMode event was emitted
|
||||
let events = System::events();
|
||||
assert!(
|
||||
events.iter().any(|e| matches!(
|
||||
e.event,
|
||||
RuntimeEvent::SafeMode(pallet_safe_mode::Event::Entered { .. })
|
||||
)),
|
||||
"SafeMode::Entered event should be emitted"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safe_mode_allows_governance_during_migration_failure() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
// Simulate a failed migration
|
||||
use frame_support::migrations::FailedMigrationHandler;
|
||||
type Handler = <Runtime as pallet_migrations::Config>::FailedMigrationHandler;
|
||||
Handler::failed(Some(0));
|
||||
|
||||
// Verify SafeMode is active
|
||||
assert!(SafeMode::is_entered(), "SafeMode should be active");
|
||||
|
||||
// Test that SafeMode management calls are still allowed
|
||||
let force_exit_call = RuntimeCall::SafeMode(pallet_safe_mode::Call::force_exit {});
|
||||
let result = force_exit_call.dispatch(RuntimeOrigin::root());
|
||||
assert_ok!(result);
|
||||
|
||||
// Verify SafeMode is now inactive
|
||||
assert!(
|
||||
!SafeMode::is_entered(),
|
||||
"SafeMode should be inactive after force exit"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,14 +79,14 @@ use datahaven_runtime_common::{
|
|||
},
|
||||
gas::WEIGHT_PER_GAS,
|
||||
migrations::{
|
||||
FailedMigrationHandler as DefaultFailedMigrationHandler, MigrationCursorMaxLen,
|
||||
MigrationIdentifierMaxLen, MigrationStatusHandler,
|
||||
FailedMigrationHandler, MigrationCursorMaxLen, MigrationIdentifierMaxLen,
|
||||
MigrationStatusHandler,
|
||||
},
|
||||
safe_mode::{
|
||||
ReleaseDelayNone, RuntimeCallFilter, SafeModeDuration, SafeModeEnterDeposit,
|
||||
SafeModeExtendDeposit, TxPauseWhitelistedCalls,
|
||||
},
|
||||
time::{EpochDurationInBlocks, DAYS, MILLISECS_PER_BLOCK},
|
||||
time::{EpochDurationInBlocks, SessionsPerEra, DAYS, MILLISECS_PER_BLOCK},
|
||||
};
|
||||
use dhp_bridge::{EigenLayerMessageProcessor, NativeTokenTransferMessageProcessor};
|
||||
use frame_support::{
|
||||
|
|
@ -138,7 +138,7 @@ use sp_runtime::{
|
|||
traits::{Convert, ConvertInto, IdentityLookup, Keccak256, OpaqueKeys, UniqueSaturatedInto},
|
||||
FixedPointNumber, Perbill, Perquintill,
|
||||
};
|
||||
use sp_staking::{EraIndex, SessionIndex};
|
||||
use sp_staking::EraIndex;
|
||||
use sp_std::{
|
||||
convert::{From, Into},
|
||||
prelude::*,
|
||||
|
|
@ -164,7 +164,6 @@ const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
|
|||
parameter_types! {
|
||||
pub const MaxAuthorities: u32 = 32;
|
||||
pub const BondingDuration: EraIndex = polkadot_runtime_common::prod_or_fast!(28, 3);
|
||||
pub const SessionsPerEra: SessionIndex = polkadot_runtime_common::prod_or_fast!(6, 1);
|
||||
pub const AuthorRewardPoints: u32 = 20;
|
||||
}
|
||||
|
||||
|
|
@ -508,7 +507,8 @@ impl pallet_beefy::Config for Runtime {
|
|||
type AncestryHelper = BeefyMmrLeaf;
|
||||
type WeightInfo = ();
|
||||
type KeyOwnerProof = <Historical as KeyOwnerProofSystem<(KeyTypeId, BeefyId)>>::Proof;
|
||||
type EquivocationReportSystem = ();
|
||||
type EquivocationReportSystem =
|
||||
pallet_beefy::EquivocationReportSystem<Self, Offences, Historical, ReportLongevity>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
|
@ -844,20 +844,13 @@ impl pallet_parameters::Config for Runtime {
|
|||
impl pallet_migrations::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
type Migrations = (
|
||||
datahaven_runtime_common::migrations::MultiBlockMigrationList<Runtime>,
|
||||
datahaven_runtime_common::migrations::evm_chain_id::EvmChainIdMigration<
|
||||
Runtime,
|
||||
EVM_CHAIN_ID,
|
||||
>,
|
||||
);
|
||||
type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList;
|
||||
type CursorMaxLen = MigrationCursorMaxLen;
|
||||
type IdentifierMaxLen = MigrationIdentifierMaxLen;
|
||||
type MigrationStatusHandler = MigrationStatusHandler;
|
||||
// TODO: Remove this once we have a proper failed migration handler (Safe mode)
|
||||
type FailedMigrationHandler = DefaultFailedMigrationHandler;
|
||||
type FailedMigrationHandler = FailedMigrationHandler<SafeMode>;
|
||||
type MaxServiceWeight = MaxServiceWeight;
|
||||
type WeightInfo = stagenet_weights::pallet_migrations::WeightInfo<Runtime>;
|
||||
}
|
||||
|
|
@ -999,13 +992,10 @@ parameter_types! {
|
|||
pub PrecompilesValue: Precompiles = DataHavenPrecompiles::<Runtime>::new();
|
||||
pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0);
|
||||
pub SuicideQuickClearLimit: u32 = 0;
|
||||
/// The amount of gas per pov. A ratio of 16 if we convert ref_time to gas and we compare
|
||||
/// it with the pov_size for a block. E.g.
|
||||
/// ceil(
|
||||
/// (max_extrinsic.ref_time() / max_extrinsic.proof_size()) / WEIGHT_PER_GAS
|
||||
/// )
|
||||
/// The amount of gas per pov. Set to 0 because DataHaven is a solo chain and we don't
|
||||
/// account for POV (Proof-of-Validity) size constraints like parachains do.
|
||||
/// We should re-check `xcm_config::Erc20XcmBridgeTransferGasLimit` when changing this value
|
||||
pub const GasLimitPovSizeRatio: u64 = 16;
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
/// The amount of gas per storage (in bytes): BLOCK_GAS_LIMIT / BLOCK_STORAGE_LIMIT
|
||||
/// (60_000_000 / 160 kb)
|
||||
pub GasLimitStorageGrowthRatio: u64 = 366;
|
||||
|
|
|
|||
146
operator/runtime/stagenet/tests/migrations.rs
Normal file
146
operator/runtime/stagenet/tests/migrations.rs
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
// Copyright 2025 DataHaven
|
||||
// This file is part of DataHaven.
|
||||
|
||||
// DataHaven is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// DataHaven is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with DataHaven. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
|
||||
use common::*;
|
||||
use datahaven_stagenet_runtime::{
|
||||
Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SafeMode, System,
|
||||
};
|
||||
use frame_support::{assert_noop, assert_ok};
|
||||
use pallet_migrations::{Call as MigrationsCall, HistoricCleanupSelector};
|
||||
use sp_runtime::{traits::Dispatchable, DispatchError};
|
||||
|
||||
#[test]
|
||||
fn migrations_force_calls_are_root_only() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
let signed_origin = RuntimeOrigin::signed(account_id(ALICE));
|
||||
|
||||
let force_onboard =
|
||||
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::force_onboard_mbms {});
|
||||
assert_noop!(
|
||||
force_onboard.clone().dispatch(signed_origin.clone()),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(force_onboard.dispatch(RuntimeOrigin::root()));
|
||||
|
||||
let force_set_cursor =
|
||||
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::force_set_cursor {
|
||||
cursor: None,
|
||||
});
|
||||
assert_noop!(
|
||||
force_set_cursor.clone().dispatch(signed_origin.clone()),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(force_set_cursor.dispatch(RuntimeOrigin::root()));
|
||||
|
||||
let force_set_active =
|
||||
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::force_set_active_cursor {
|
||||
index: 0,
|
||||
inner_cursor: None,
|
||||
started_at: None,
|
||||
});
|
||||
assert_noop!(
|
||||
force_set_active.clone().dispatch(signed_origin.clone()),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(force_set_active.dispatch(RuntimeOrigin::root()));
|
||||
|
||||
let clear_historic =
|
||||
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::clear_historic {
|
||||
selector: HistoricCleanupSelector::Specific(Vec::new()),
|
||||
});
|
||||
assert_noop!(
|
||||
clear_historic.clone().dispatch(signed_origin),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(clear_historic.dispatch(RuntimeOrigin::root()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failed_migration_enters_safe_mode() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
// Verify SafeMode is not active initially
|
||||
assert!(
|
||||
!SafeMode::is_entered(),
|
||||
"SafeMode should not be active initially"
|
||||
);
|
||||
|
||||
// Simulate a failed migration by directly calling the FailedMigrationHandler
|
||||
// This tests that when migrations fail, the system enters SafeMode
|
||||
use frame_support::migrations::FailedMigrationHandler;
|
||||
type Handler = <Runtime as pallet_migrations::Config>::FailedMigrationHandler;
|
||||
|
||||
// Call the failed handler (simulating a migration failure)
|
||||
let result = Handler::failed(Some(0));
|
||||
|
||||
// The handler should indicate that SafeMode was entered
|
||||
assert_eq!(
|
||||
result,
|
||||
frame_support::migrations::FailedMigrationHandling::KeepStuck,
|
||||
"Handler should keep the chain stuck in SafeMode"
|
||||
);
|
||||
|
||||
// Verify that SafeMode is now active
|
||||
assert!(
|
||||
SafeMode::is_entered(),
|
||||
"SafeMode should be active after migration failure"
|
||||
);
|
||||
|
||||
// Get the block number when SafeMode should expire
|
||||
let entered_until = pallet_safe_mode::EnteredUntil::<Runtime>::get();
|
||||
assert!(
|
||||
entered_until.is_some(),
|
||||
"SafeMode should have an expiry block"
|
||||
);
|
||||
|
||||
// Verify that the SafeMode event was emitted
|
||||
let events = System::events();
|
||||
assert!(
|
||||
events.iter().any(|e| matches!(
|
||||
e.event,
|
||||
RuntimeEvent::SafeMode(pallet_safe_mode::Event::Entered { .. })
|
||||
)),
|
||||
"SafeMode::Entered event should be emitted"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safe_mode_allows_governance_during_migration_failure() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
// Simulate a failed migration
|
||||
use frame_support::migrations::FailedMigrationHandler;
|
||||
type Handler = <Runtime as pallet_migrations::Config>::FailedMigrationHandler;
|
||||
Handler::failed(Some(0));
|
||||
|
||||
// Verify SafeMode is active
|
||||
assert!(SafeMode::is_entered(), "SafeMode should be active");
|
||||
|
||||
// Test that SafeMode management calls are still allowed
|
||||
let force_exit_call = RuntimeCall::SafeMode(pallet_safe_mode::Call::force_exit {});
|
||||
let result = force_exit_call.dispatch(RuntimeOrigin::root());
|
||||
assert_ok!(result);
|
||||
|
||||
// Verify SafeMode is now inactive
|
||||
assert!(
|
||||
!SafeMode::is_entered(),
|
||||
"SafeMode should be inactive after force exit"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -21,8 +21,7 @@ mod common;
|
|||
|
||||
use common::{account_id, ExtBuilder, ALICE, BOB};
|
||||
use datahaven_stagenet_runtime::{
|
||||
Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SafeMode, System, TxPause,
|
||||
UncheckedExtrinsic,
|
||||
Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, System, UncheckedExtrinsic,
|
||||
};
|
||||
use frame_support::{assert_noop, assert_ok, BoundedVec};
|
||||
use pallet_safe_mode::EnteredUntil;
|
||||
|
|
|
|||
|
|
@ -79,14 +79,14 @@ use datahaven_runtime_common::{
|
|||
},
|
||||
gas::WEIGHT_PER_GAS,
|
||||
migrations::{
|
||||
FailedMigrationHandler as DefaultFailedMigrationHandler, MigrationCursorMaxLen,
|
||||
MigrationIdentifierMaxLen, MigrationStatusHandler,
|
||||
FailedMigrationHandler, MigrationCursorMaxLen, MigrationIdentifierMaxLen,
|
||||
MigrationStatusHandler,
|
||||
},
|
||||
safe_mode::{
|
||||
ReleaseDelayNone, RuntimeCallFilter, SafeModeDuration, SafeModeEnterDeposit,
|
||||
SafeModeExtendDeposit, TxPauseWhitelistedCalls,
|
||||
},
|
||||
time::{EpochDurationInBlocks, DAYS, MILLISECS_PER_BLOCK},
|
||||
time::{EpochDurationInBlocks, SessionsPerEra, DAYS, MILLISECS_PER_BLOCK},
|
||||
};
|
||||
use dhp_bridge::{EigenLayerMessageProcessor, NativeTokenTransferMessageProcessor};
|
||||
use frame_support::{
|
||||
|
|
@ -138,7 +138,7 @@ use sp_runtime::{
|
|||
traits::{Convert, ConvertInto, IdentityLookup, Keccak256, OpaqueKeys, UniqueSaturatedInto},
|
||||
FixedPointNumber, Perbill, Perquintill,
|
||||
};
|
||||
use sp_staking::{EraIndex, SessionIndex};
|
||||
use sp_staking::EraIndex;
|
||||
use sp_std::{
|
||||
convert::{From, Into},
|
||||
prelude::*,
|
||||
|
|
@ -164,7 +164,6 @@ const SS58_FORMAT: u16 = EVM_CHAIN_ID as u16;
|
|||
parameter_types! {
|
||||
pub const MaxAuthorities: u32 = 32;
|
||||
pub const BondingDuration: EraIndex = polkadot_runtime_common::prod_or_fast!(28, 3);
|
||||
pub const SessionsPerEra: SessionIndex = polkadot_runtime_common::prod_or_fast!(6, 1);
|
||||
pub const AuthorRewardPoints: u32 = 20;
|
||||
}
|
||||
|
||||
|
|
@ -511,7 +510,8 @@ impl pallet_beefy::Config for Runtime {
|
|||
type AncestryHelper = BeefyMmrLeaf;
|
||||
type WeightInfo = ();
|
||||
type KeyOwnerProof = <Historical as KeyOwnerProofSystem<(KeyTypeId, BeefyId)>>::Proof;
|
||||
type EquivocationReportSystem = ();
|
||||
type EquivocationReportSystem =
|
||||
pallet_beefy::EquivocationReportSystem<Self, Offences, Historical, ReportLongevity>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
|
@ -847,20 +847,13 @@ impl pallet_parameters::Config for Runtime {
|
|||
impl pallet_migrations::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
type Migrations = (
|
||||
datahaven_runtime_common::migrations::MultiBlockMigrationList<Runtime>,
|
||||
datahaven_runtime_common::migrations::evm_chain_id::EvmChainIdMigration<
|
||||
Runtime,
|
||||
EVM_CHAIN_ID,
|
||||
>,
|
||||
);
|
||||
type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type Migrations = datahaven_runtime_common::migrations::MultiBlockMigrationList;
|
||||
type CursorMaxLen = MigrationCursorMaxLen;
|
||||
type IdentifierMaxLen = MigrationIdentifierMaxLen;
|
||||
type MigrationStatusHandler = MigrationStatusHandler;
|
||||
// TODO: Remove this once we have a proper failed migration handler (Safe mode)
|
||||
type FailedMigrationHandler = DefaultFailedMigrationHandler;
|
||||
type FailedMigrationHandler = FailedMigrationHandler<SafeMode>;
|
||||
type MaxServiceWeight = MaxServiceWeight;
|
||||
type WeightInfo = testnet_weights::pallet_migrations::WeightInfo<Runtime>;
|
||||
}
|
||||
|
|
@ -1002,13 +995,10 @@ parameter_types! {
|
|||
pub PrecompilesValue: Precompiles = DataHavenPrecompiles::<Runtime>::new();
|
||||
pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0);
|
||||
pub SuicideQuickClearLimit: u32 = 0;
|
||||
/// The amount of gas per pov. A ratio of 16 if we convert ref_time to gas and we compare
|
||||
/// it with the pov_size for a block. E.g.
|
||||
/// ceil(
|
||||
/// (max_extrinsic.ref_time() / max_extrinsic.proof_size()) / WEIGHT_PER_GAS
|
||||
/// )
|
||||
/// The amount of gas per pov. Set to 0 because DataHaven is a solo chain and we don't
|
||||
/// account for POV (Proof-of-Validity) size constraints like parachains do.
|
||||
/// We should re-check `xcm_config::Erc20XcmBridgeTransferGasLimit` when changing this value
|
||||
pub const GasLimitPovSizeRatio: u64 = 16;
|
||||
pub const GasLimitPovSizeRatio: u64 = 0;
|
||||
/// The amount of gas per storage (in bytes): BLOCK_GAS_LIMIT / BLOCK_STORAGE_LIMIT
|
||||
/// (60_000_000 / 160 kb)
|
||||
pub GasLimitStorageGrowthRatio: u64 = 366;
|
||||
|
|
|
|||
146
operator/runtime/testnet/tests/migrations.rs
Normal file
146
operator/runtime/testnet/tests/migrations.rs
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
// Copyright 2025 DataHaven
|
||||
// This file is part of DataHaven.
|
||||
|
||||
// DataHaven is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// DataHaven is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with DataHaven. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
|
||||
use common::*;
|
||||
use datahaven_testnet_runtime::{
|
||||
Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SafeMode, System,
|
||||
};
|
||||
use frame_support::{assert_noop, assert_ok};
|
||||
use pallet_migrations::{Call as MigrationsCall, HistoricCleanupSelector};
|
||||
use sp_runtime::{traits::Dispatchable, DispatchError};
|
||||
|
||||
#[test]
|
||||
fn migrations_force_calls_are_root_only() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
let signed_origin = RuntimeOrigin::signed(account_id(ALICE));
|
||||
|
||||
let force_onboard =
|
||||
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::force_onboard_mbms {});
|
||||
assert_noop!(
|
||||
force_onboard.clone().dispatch(signed_origin.clone()),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(force_onboard.dispatch(RuntimeOrigin::root()));
|
||||
|
||||
let force_set_cursor =
|
||||
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::force_set_cursor {
|
||||
cursor: None,
|
||||
});
|
||||
assert_noop!(
|
||||
force_set_cursor.clone().dispatch(signed_origin.clone()),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(force_set_cursor.dispatch(RuntimeOrigin::root()));
|
||||
|
||||
let force_set_active =
|
||||
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::force_set_active_cursor {
|
||||
index: 0,
|
||||
inner_cursor: None,
|
||||
started_at: None,
|
||||
});
|
||||
assert_noop!(
|
||||
force_set_active.clone().dispatch(signed_origin.clone()),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(force_set_active.dispatch(RuntimeOrigin::root()));
|
||||
|
||||
let clear_historic =
|
||||
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::clear_historic {
|
||||
selector: HistoricCleanupSelector::Specific(Vec::new()),
|
||||
});
|
||||
assert_noop!(
|
||||
clear_historic.clone().dispatch(signed_origin),
|
||||
DispatchError::BadOrigin
|
||||
);
|
||||
assert_ok!(clear_historic.dispatch(RuntimeOrigin::root()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failed_migration_enters_safe_mode() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
// Verify SafeMode is not active initially
|
||||
assert!(
|
||||
!SafeMode::is_entered(),
|
||||
"SafeMode should not be active initially"
|
||||
);
|
||||
|
||||
// Simulate a failed migration by directly calling the FailedMigrationHandler
|
||||
// This tests that when migrations fail, the system enters SafeMode
|
||||
use frame_support::migrations::FailedMigrationHandler;
|
||||
type Handler = <Runtime as pallet_migrations::Config>::FailedMigrationHandler;
|
||||
|
||||
// Call the failed handler (simulating a migration failure)
|
||||
let result = Handler::failed(Some(0));
|
||||
|
||||
// The handler should indicate that SafeMode was entered
|
||||
assert_eq!(
|
||||
result,
|
||||
frame_support::migrations::FailedMigrationHandling::KeepStuck,
|
||||
"Handler should keep the chain stuck in SafeMode"
|
||||
);
|
||||
|
||||
// Verify that SafeMode is now active
|
||||
assert!(
|
||||
SafeMode::is_entered(),
|
||||
"SafeMode should be active after migration failure"
|
||||
);
|
||||
|
||||
// Get the block number when SafeMode should expire
|
||||
let entered_until = pallet_safe_mode::EnteredUntil::<Runtime>::get();
|
||||
assert!(
|
||||
entered_until.is_some(),
|
||||
"SafeMode should have an expiry block"
|
||||
);
|
||||
|
||||
// Verify that the SafeMode event was emitted
|
||||
let events = System::events();
|
||||
assert!(
|
||||
events.iter().any(|e| matches!(
|
||||
e.event,
|
||||
RuntimeEvent::SafeMode(pallet_safe_mode::Event::Entered { .. })
|
||||
)),
|
||||
"SafeMode::Entered event should be emitted"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safe_mode_allows_governance_during_migration_failure() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
// Simulate a failed migration
|
||||
use frame_support::migrations::FailedMigrationHandler;
|
||||
type Handler = <Runtime as pallet_migrations::Config>::FailedMigrationHandler;
|
||||
Handler::failed(Some(0));
|
||||
|
||||
// Verify SafeMode is active
|
||||
assert!(SafeMode::is_entered(), "SafeMode should be active");
|
||||
|
||||
// Test that SafeMode management calls are still allowed
|
||||
let force_exit_call = RuntimeCall::SafeMode(pallet_safe_mode::Call::force_exit {});
|
||||
let result = force_exit_call.dispatch(RuntimeOrigin::root());
|
||||
assert_ok!(result);
|
||||
|
||||
// Verify SafeMode is now inactive
|
||||
assert!(
|
||||
!SafeMode::is_entered(),
|
||||
"SafeMode should be inactive after force exit"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -21,8 +21,7 @@ mod common;
|
|||
|
||||
use common::{account_id, ExtBuilder, ALICE, BOB};
|
||||
use datahaven_testnet_runtime::{
|
||||
Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SafeMode, System, TxPause,
|
||||
UncheckedExtrinsic,
|
||||
Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, System, UncheckedExtrinsic,
|
||||
};
|
||||
use frame_support::{assert_noop, assert_ok, BoundedVec};
|
||||
use pallet_safe_mode::EnteredUntil;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ AUTHORS=(
|
|||
)
|
||||
NAMES=(
|
||||
"ring" # v0.16.20 has null license metadata but contains Apache-2.0 AND ISC LICENSE file
|
||||
"pq-src" # License is the same as postgres
|
||||
"shp-tx-implicits-runtime-api"
|
||||
)
|
||||
licenses_filter=$(printf ' .license != "%s" and' "${LICENSES[@]}")
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
# Copy this file to .env and fill in your values
|
||||
|
||||
# Private key for contract deployment (REQUIRED)
|
||||
PRIVATE_KEY=0x0000000000000000000000000000000000000000000000000000000000000000
|
||||
DEPLOYER_PRIVATE_KEY=0x0000000000000000000000000000000000000000000000000000000000000000
|
||||
|
||||
# AVS Owner private key (for post-deployment configuration)
|
||||
AVS_OWNER_PRIVATE_KEY=0x0000000000000000000000000000000000000000000000000000000000000000
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ cd test && cp cli/handlers/contracts/.env.example .env
|
|||
Edit `.env` with your values:
|
||||
```bash
|
||||
# Required: Private key with deployment funds
|
||||
PRIVATE_KEY=0x...
|
||||
DEPLOYER_PRIVATE_KEY=0x...
|
||||
|
||||
# Required: AVS owner private key (can be same as PRIVATE_KEY)
|
||||
# Required: AVS owner private key (can be same as DEPLOYER_PRIVATE_KEY)
|
||||
AVS_OWNER_PRIVATE_KEY=0x...
|
||||
|
||||
# Optional: For contract verification
|
||||
|
|
|
|||
|
|
@ -91,17 +91,19 @@ export const contractsPreActionHook = async (thisCommand: any) => {
|
|||
const privateKey = thisCommand.getOptionValue("privateKey");
|
||||
|
||||
if (!chain) {
|
||||
logger.error("❌ Chain is required. Use --chain option (hoodi, holesky, mainnet)");
|
||||
logger.error("❌ Chain is required. Use --chain option (hoodi, holesky, mainnet, anvil)");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const supportedChains = ["hoodi", "holesky", "mainnet"];
|
||||
const supportedChains = ["hoodi", "holesky", "mainnet", "anvil"];
|
||||
if (!supportedChains.includes(chain)) {
|
||||
logger.error(`❌ Unsupported chain: ${chain}. Supported chains: ${supportedChains.join(", ")}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!privateKey) {
|
||||
logger.warn("⚠️ Private key not provided. Will use PRIVATE_KEY environment variable");
|
||||
if (!privateKey && !process.env.DEPLOYER_PRIVATE_KEY) {
|
||||
logger.warn(
|
||||
"⚠️ Private key not provided. Will use DEPLOYER_PRIVATE_KEY environment variable if set, or default Anvil key."
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ export const showDeploymentPlanAndStatus = async (chain: string) => {
|
|||
await showEigenLayerContractStatus(
|
||||
config,
|
||||
deploymentParams.chainId.toString(),
|
||||
deploymentParams.rpcUrl
|
||||
deploymentParams.rpcUrl,
|
||||
chain
|
||||
);
|
||||
|
||||
printDivider();
|
||||
|
|
@ -109,27 +110,69 @@ const showDatahavenContractStatus = async (chain: string, rpcUrl: string) => {
|
|||
/**
|
||||
* Shows the status of EigenLayer contracts (verification only)
|
||||
*/
|
||||
const showEigenLayerContractStatus = async (config: any, chainId: string, rpcUrl: string) => {
|
||||
const showEigenLayerContractStatus = async (
|
||||
config: any,
|
||||
chainId: string,
|
||||
rpcUrl: string,
|
||||
chain: string
|
||||
) => {
|
||||
try {
|
||||
// For local/anvil deployments, read addresses from deployments file
|
||||
// For testnet/mainnet, use addresses from config file
|
||||
let eigenLayerAddresses: Record<string, string> = {};
|
||||
const isLocal = chain === "anvil" || chain === "local";
|
||||
|
||||
if (isLocal) {
|
||||
try {
|
||||
const deploymentsPath = `../contracts/deployments/${chain === "local" ? "anvil" : chain}.json`;
|
||||
const deploymentsFile = Bun.file(deploymentsPath);
|
||||
if (await deploymentsFile.exists()) {
|
||||
const deployments = await deploymentsFile.json();
|
||||
eigenLayerAddresses = {
|
||||
DelegationManager: deployments.DelegationManager,
|
||||
StrategyManager: deployments.StrategyManager,
|
||||
EigenPodManager: deployments.EigenPodManager,
|
||||
AVSDirectory: deployments.AVSDirectory,
|
||||
RewardsCoordinator: deployments.RewardsCoordinator,
|
||||
AllocationManager: deployments.AllocationManager,
|
||||
PermissionController: deployments.PermissionController
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
logger.debug(`Could not read deployments file for EigenLayer contracts: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
const contracts = [
|
||||
{
|
||||
name: "DelegationManager",
|
||||
address: config.eigenLayer.delegationManager
|
||||
address: eigenLayerAddresses.DelegationManager || config.eigenLayer?.delegationManager || ""
|
||||
},
|
||||
{
|
||||
name: "StrategyManager",
|
||||
address: eigenLayerAddresses.StrategyManager || config.eigenLayer?.strategyManager || ""
|
||||
},
|
||||
{
|
||||
name: "EigenPodManager",
|
||||
address: eigenLayerAddresses.EigenPodManager || config.eigenLayer?.eigenPodManager || ""
|
||||
},
|
||||
{
|
||||
name: "AVSDirectory",
|
||||
address: eigenLayerAddresses.AVSDirectory || config.eigenLayer?.avsDirectory || ""
|
||||
},
|
||||
{ name: "StrategyManager", address: config.eigenLayer.strategyManager },
|
||||
{ name: "EigenPodManager", address: config.eigenLayer.eigenPodManager },
|
||||
{ name: "AVSDirectory", address: config.eigenLayer.avsDirectory },
|
||||
{
|
||||
name: "RewardsCoordinator",
|
||||
address: config.eigenLayer.rewardsCoordinator
|
||||
address:
|
||||
eigenLayerAddresses.RewardsCoordinator || config.eigenLayer?.rewardsCoordinator || ""
|
||||
},
|
||||
{
|
||||
name: "AllocationManager",
|
||||
address: config.eigenLayer.allocationManager
|
||||
address: eigenLayerAddresses.AllocationManager || config.eigenLayer?.allocationManager || ""
|
||||
},
|
||||
{
|
||||
name: "PermissionController",
|
||||
address: config.eigenLayer.permissionController
|
||||
address:
|
||||
eigenLayerAddresses.PermissionController || config.eigenLayer?.permissionController || ""
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ const contractsCommand = program
|
|||
- update-metadata: Update the metadata URI of an existing AVS contract
|
||||
|
||||
Common options:
|
||||
--chain: Target chain (required: hoodi, holesky, mainnet)
|
||||
--chain: Target chain (required: hoodi, holesky, mainnet, anvil)
|
||||
--rpc-url: Chain RPC URL (optional, defaults based on chain)
|
||||
--private-key: Private key for deployment
|
||||
--skip-verification: Skip contract verification
|
||||
|
|
@ -210,9 +210,13 @@ const contractsCommand = program
|
|||
contractsCommand
|
||||
.command("status")
|
||||
.description("Show deployment plan, configuration, and status")
|
||||
.option("--chain <value>", "Target chain (hoodi, holesky, mainnet)")
|
||||
.option("--chain <value>", "Target chain (hoodi, holesky, mainnet, anvil)")
|
||||
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
||||
.option("--private-key <value>", "Private key for deployment", process.env.PRIVATE_KEY || "")
|
||||
.option(
|
||||
"--private-key <value>",
|
||||
"Private key for deployment",
|
||||
process.env.DEPLOYER_PRIVATE_KEY || ""
|
||||
)
|
||||
.option("--skip-verification", "Skip contract verification", false)
|
||||
.hook("preAction", contractsPreActionHook)
|
||||
.action(contractsCheck);
|
||||
|
|
@ -221,9 +225,13 @@ contractsCommand
|
|||
contractsCommand
|
||||
.command("deploy")
|
||||
.description("Deploy DataHaven AVS contracts to specified chain")
|
||||
.option("--chain <value>", "Target chain (hoodi, holesky, mainnet)")
|
||||
.option("--chain <value>", "Target chain (hoodi, holesky, mainnet, anvil)")
|
||||
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
||||
.option("--private-key <value>", "Private key for deployment", process.env.PRIVATE_KEY || "")
|
||||
.option(
|
||||
"--private-key <value>",
|
||||
"Private key for deployment",
|
||||
process.env.DEPLOYER_PRIVATE_KEY || ""
|
||||
)
|
||||
.option("--skip-verification", "Skip contract verification", false)
|
||||
.hook("preAction", contractsPreActionHook)
|
||||
.action(contractsDeploy);
|
||||
|
|
@ -232,7 +240,7 @@ contractsCommand
|
|||
contractsCommand
|
||||
.command("verify")
|
||||
.description("Verify deployed contracts on block explorer")
|
||||
.option("--chain <value>", "Target chain (hoodi, holesky, mainnet)")
|
||||
.option("--chain <value>", "Target chain (hoodi, holesky, mainnet, anvil)")
|
||||
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
||||
.option("--skip-verification", "Skip contract verification", false)
|
||||
.hook("preAction", contractsPreActionHook)
|
||||
|
|
@ -242,7 +250,7 @@ contractsCommand
|
|||
contractsCommand
|
||||
.command("update-metadata")
|
||||
.description("Update AVS metadata URI for the DataHaven Service Manager")
|
||||
.option("--chain <value>", "Target chain (hoodi, holesky, mainnet)")
|
||||
.option("--chain <value>", "Target chain (hoodi, holesky, mainnet, anvil)")
|
||||
.option("--uri <value>", "New metadata URI (required)")
|
||||
.option("--reset", "Use if you want to reset the metadata URI")
|
||||
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
||||
|
|
@ -270,9 +278,13 @@ contractsCommand
|
|||
// Default Contracts command (runs check)
|
||||
contractsCommand
|
||||
.description("Show deployment plan, configuration, and status")
|
||||
.option("--chain <value>", "Target chain (hoodi, holesky, mainnet)")
|
||||
.option("--chain <value>", "Target chain (hoodi, holesky, mainnet, anvil)")
|
||||
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
||||
.option("--private-key <value>", "Private key for deployment", process.env.PRIVATE_KEY || "")
|
||||
.option(
|
||||
"--private-key <value>",
|
||||
"Private key for deployment",
|
||||
process.env.DEPLOYER_PRIVATE_KEY || ""
|
||||
)
|
||||
.option("--skip-verification", "Skip contract verification", false)
|
||||
.hook("preAction", contractsPreActionHook)
|
||||
.action(contractsCheck);
|
||||
|
|
|
|||
|
|
@ -2045,13 +2045,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'BSPS_SET_ID',
|
||||
outputs: [{ name: '', internalType: 'uint32', type: 'uint32' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
|
|
@ -2059,13 +2052,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
outputs: [{ name: '', internalType: 'string', type: 'string' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'MSPS_SET_ID',
|
||||
outputs: [{ name: '', internalType: 'uint32', type: 'uint32' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
|
|
@ -2073,20 +2059,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
outputs: [{ name: '', internalType: 'uint32', type: 'uint32' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: 'bsp', internalType: 'address', type: 'address' }],
|
||||
name: 'addBspToAllowlist',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: 'msp', internalType: 'address', type: 'address' }],
|
||||
name: 'addMspToAllowlist',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: 'admin', internalType: 'address', type: 'address' }],
|
||||
|
|
@ -2094,32 +2066,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [
|
||||
{
|
||||
name: '_strategies',
|
||||
internalType: 'contract IStrategy[]',
|
||||
type: 'address[]',
|
||||
},
|
||||
],
|
||||
name: 'addStrategiesToBspsSupportedStrategies',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [
|
||||
{
|
||||
name: '_strategies',
|
||||
internalType: 'contract IStrategy[]',
|
||||
type: 'address[]',
|
||||
},
|
||||
],
|
||||
name: 'addStrategiesToMspsSupportedStrategies',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [
|
||||
|
|
@ -2161,22 +2107,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
outputs: [{ name: '', internalType: 'address', type: 'address' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: '', internalType: 'address', type: 'address' }],
|
||||
name: 'bspsAllowlist',
|
||||
outputs: [{ name: '', internalType: 'bool', type: 'bool' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'bspsSupportedStrategies',
|
||||
outputs: [
|
||||
{ name: '', internalType: 'contract IStrategy[]', type: 'address[]' },
|
||||
],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
|
|
@ -2390,16 +2320,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
internalType: 'contract IStrategy[]',
|
||||
type: 'address[]',
|
||||
},
|
||||
{
|
||||
name: 'bspsStrategies',
|
||||
internalType: 'contract IStrategy[]',
|
||||
type: 'address[]',
|
||||
},
|
||||
{
|
||||
name: 'mspsStrategies',
|
||||
internalType: 'contract IStrategy[]',
|
||||
type: 'address[]',
|
||||
},
|
||||
{
|
||||
name: '_snowbridgeGatewayAddress',
|
||||
internalType: 'address',
|
||||
|
|
@ -2410,22 +2330,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: '', internalType: 'address', type: 'address' }],
|
||||
name: 'mspsAllowlist',
|
||||
outputs: [{ name: '', internalType: 'bool', type: 'bool' }],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [],
|
||||
name: 'mspsSupportedStrategies',
|
||||
outputs: [
|
||||
{ name: '', internalType: 'contract IStrategy[]', type: 'address[]' },
|
||||
],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: '', internalType: 'uint32', type: 'uint32' }],
|
||||
|
|
@ -2516,20 +2420,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: 'bsp', internalType: 'address', type: 'address' }],
|
||||
name: 'removeBspFromAllowlist',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [{ name: 'msp', internalType: 'address', type: 'address' }],
|
||||
name: 'removeMspFromAllowlist',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [
|
||||
|
|
@ -2539,32 +2429,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [
|
||||
{
|
||||
name: '_strategies',
|
||||
internalType: 'contract IStrategy[]',
|
||||
type: 'address[]',
|
||||
},
|
||||
],
|
||||
name: 'removeStrategiesFromBspsSupportedStrategies',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [
|
||||
{
|
||||
name: '_strategies',
|
||||
internalType: 'contract IStrategy[]',
|
||||
type: 'address[]',
|
||||
},
|
||||
],
|
||||
name: 'removeStrategiesFromMspsSupportedStrategies',
|
||||
outputs: [],
|
||||
stateMutability: 'nonpayable',
|
||||
},
|
||||
{
|
||||
type: 'function',
|
||||
inputs: [
|
||||
|
|
@ -2760,22 +2624,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
],
|
||||
stateMutability: 'view',
|
||||
},
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{ name: 'bsp', internalType: 'address', type: 'address', indexed: true },
|
||||
],
|
||||
name: 'BspAddedToAllowlist',
|
||||
},
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{ name: 'bsp', internalType: 'address', type: 'address', indexed: true },
|
||||
],
|
||||
name: 'BspRemovedFromAllowlist',
|
||||
},
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
|
|
@ -2784,22 +2632,6 @@ export const dataHavenServiceManagerAbi = [
|
|||
],
|
||||
name: 'Initialized',
|
||||
},
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{ name: 'msp', internalType: 'address', type: 'address', indexed: true },
|
||||
],
|
||||
name: 'MspAddedToAllowlist',
|
||||
},
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{ name: 'msp', internalType: 'address', type: 'address', indexed: true },
|
||||
],
|
||||
name: 'MspRemovedFromAllowlist',
|
||||
},
|
||||
{
|
||||
type: 'event',
|
||||
anonymous: false,
|
||||
|
|
@ -11594,15 +11426,6 @@ export const readDataHavenServiceManager = /*#__PURE__*/ createReadContract({
|
|||
abi: dataHavenServiceManagerAbi,
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"BSPS_SET_ID"`
|
||||
*/
|
||||
export const readDataHavenServiceManagerBspsSetId =
|
||||
/*#__PURE__*/ createReadContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'BSPS_SET_ID',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"DATAHAVEN_AVS_METADATA"`
|
||||
*/
|
||||
|
|
@ -11612,15 +11435,6 @@ export const readDataHavenServiceManagerDatahavenAvsMetadata =
|
|||
functionName: 'DATAHAVEN_AVS_METADATA',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"MSPS_SET_ID"`
|
||||
*/
|
||||
export const readDataHavenServiceManagerMspsSetId =
|
||||
/*#__PURE__*/ createReadContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'MSPS_SET_ID',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"VALIDATORS_SET_ID"`
|
||||
*/
|
||||
|
|
@ -11638,24 +11452,6 @@ export const readDataHavenServiceManagerAvs = /*#__PURE__*/ createReadContract({
|
|||
functionName: 'avs',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"bspsAllowlist"`
|
||||
*/
|
||||
export const readDataHavenServiceManagerBspsAllowlist =
|
||||
/*#__PURE__*/ createReadContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'bspsAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"bspsSupportedStrategies"`
|
||||
*/
|
||||
export const readDataHavenServiceManagerBspsSupportedStrategies =
|
||||
/*#__PURE__*/ createReadContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'bspsSupportedStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"buildNewValidatorSetMessage"`
|
||||
*/
|
||||
|
|
@ -11683,24 +11479,6 @@ export const readDataHavenServiceManagerGetRestakeableStrategies =
|
|||
functionName: 'getRestakeableStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"mspsAllowlist"`
|
||||
*/
|
||||
export const readDataHavenServiceManagerMspsAllowlist =
|
||||
/*#__PURE__*/ createReadContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'mspsAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"mspsSupportedStrategies"`
|
||||
*/
|
||||
export const readDataHavenServiceManagerMspsSupportedStrategies =
|
||||
/*#__PURE__*/ createReadContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'mspsSupportedStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"operatorSetToRewardsRegistry"`
|
||||
*/
|
||||
|
|
@ -11780,24 +11558,6 @@ export const writeDataHavenServiceManager = /*#__PURE__*/ createWriteContract({
|
|||
abi: dataHavenServiceManagerAbi,
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addBspToAllowlist"`
|
||||
*/
|
||||
export const writeDataHavenServiceManagerAddBspToAllowlist =
|
||||
/*#__PURE__*/ createWriteContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'addBspToAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addMspToAllowlist"`
|
||||
*/
|
||||
export const writeDataHavenServiceManagerAddMspToAllowlist =
|
||||
/*#__PURE__*/ createWriteContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'addMspToAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addPendingAdmin"`
|
||||
*/
|
||||
|
|
@ -11807,24 +11567,6 @@ export const writeDataHavenServiceManagerAddPendingAdmin =
|
|||
functionName: 'addPendingAdmin',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addStrategiesToBspsSupportedStrategies"`
|
||||
*/
|
||||
export const writeDataHavenServiceManagerAddStrategiesToBspsSupportedStrategies =
|
||||
/*#__PURE__*/ createWriteContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'addStrategiesToBspsSupportedStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addStrategiesToMspsSupportedStrategies"`
|
||||
*/
|
||||
export const writeDataHavenServiceManagerAddStrategiesToMspsSupportedStrategies =
|
||||
/*#__PURE__*/ createWriteContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'addStrategiesToMspsSupportedStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addStrategiesToOperatorSet"`
|
||||
*/
|
||||
|
|
@ -11996,24 +11738,6 @@ export const writeDataHavenServiceManagerRemoveAppointee =
|
|||
functionName: 'removeAppointee',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removeBspFromAllowlist"`
|
||||
*/
|
||||
export const writeDataHavenServiceManagerRemoveBspFromAllowlist =
|
||||
/*#__PURE__*/ createWriteContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'removeBspFromAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removeMspFromAllowlist"`
|
||||
*/
|
||||
export const writeDataHavenServiceManagerRemoveMspFromAllowlist =
|
||||
/*#__PURE__*/ createWriteContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'removeMspFromAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removePendingAdmin"`
|
||||
*/
|
||||
|
|
@ -12023,24 +11747,6 @@ export const writeDataHavenServiceManagerRemovePendingAdmin =
|
|||
functionName: 'removePendingAdmin',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removeStrategiesFromBspsSupportedStrategies"`
|
||||
*/
|
||||
export const writeDataHavenServiceManagerRemoveStrategiesFromBspsSupportedStrategies =
|
||||
/*#__PURE__*/ createWriteContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'removeStrategiesFromBspsSupportedStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removeStrategiesFromMspsSupportedStrategies"`
|
||||
*/
|
||||
export const writeDataHavenServiceManagerRemoveStrategiesFromMspsSupportedStrategies =
|
||||
/*#__PURE__*/ createWriteContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'removeStrategiesFromMspsSupportedStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removeStrategiesFromOperatorSet"`
|
||||
*/
|
||||
|
|
@ -12182,24 +11888,6 @@ export const writeDataHavenServiceManagerUpdateSolochainAddressForValidator =
|
|||
export const simulateDataHavenServiceManager =
|
||||
/*#__PURE__*/ createSimulateContract({ abi: dataHavenServiceManagerAbi })
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addBspToAllowlist"`
|
||||
*/
|
||||
export const simulateDataHavenServiceManagerAddBspToAllowlist =
|
||||
/*#__PURE__*/ createSimulateContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'addBspToAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addMspToAllowlist"`
|
||||
*/
|
||||
export const simulateDataHavenServiceManagerAddMspToAllowlist =
|
||||
/*#__PURE__*/ createSimulateContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'addMspToAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addPendingAdmin"`
|
||||
*/
|
||||
|
|
@ -12209,24 +11897,6 @@ export const simulateDataHavenServiceManagerAddPendingAdmin =
|
|||
functionName: 'addPendingAdmin',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addStrategiesToBspsSupportedStrategies"`
|
||||
*/
|
||||
export const simulateDataHavenServiceManagerAddStrategiesToBspsSupportedStrategies =
|
||||
/*#__PURE__*/ createSimulateContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'addStrategiesToBspsSupportedStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addStrategiesToMspsSupportedStrategies"`
|
||||
*/
|
||||
export const simulateDataHavenServiceManagerAddStrategiesToMspsSupportedStrategies =
|
||||
/*#__PURE__*/ createSimulateContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'addStrategiesToMspsSupportedStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"addStrategiesToOperatorSet"`
|
||||
*/
|
||||
|
|
@ -12398,24 +12068,6 @@ export const simulateDataHavenServiceManagerRemoveAppointee =
|
|||
functionName: 'removeAppointee',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removeBspFromAllowlist"`
|
||||
*/
|
||||
export const simulateDataHavenServiceManagerRemoveBspFromAllowlist =
|
||||
/*#__PURE__*/ createSimulateContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'removeBspFromAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removeMspFromAllowlist"`
|
||||
*/
|
||||
export const simulateDataHavenServiceManagerRemoveMspFromAllowlist =
|
||||
/*#__PURE__*/ createSimulateContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'removeMspFromAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removePendingAdmin"`
|
||||
*/
|
||||
|
|
@ -12425,24 +12077,6 @@ export const simulateDataHavenServiceManagerRemovePendingAdmin =
|
|||
functionName: 'removePendingAdmin',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removeStrategiesFromBspsSupportedStrategies"`
|
||||
*/
|
||||
export const simulateDataHavenServiceManagerRemoveStrategiesFromBspsSupportedStrategies =
|
||||
/*#__PURE__*/ createSimulateContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'removeStrategiesFromBspsSupportedStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removeStrategiesFromMspsSupportedStrategies"`
|
||||
*/
|
||||
export const simulateDataHavenServiceManagerRemoveStrategiesFromMspsSupportedStrategies =
|
||||
/*#__PURE__*/ createSimulateContract({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
functionName: 'removeStrategiesFromMspsSupportedStrategies',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"removeStrategiesFromOperatorSet"`
|
||||
*/
|
||||
|
|
@ -12584,24 +12218,6 @@ export const simulateDataHavenServiceManagerUpdateSolochainAddressForValidator =
|
|||
export const watchDataHavenServiceManagerEvent =
|
||||
/*#__PURE__*/ createWatchContractEvent({ abi: dataHavenServiceManagerAbi })
|
||||
|
||||
/**
|
||||
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `eventName` set to `"BspAddedToAllowlist"`
|
||||
*/
|
||||
export const watchDataHavenServiceManagerBspAddedToAllowlistEvent =
|
||||
/*#__PURE__*/ createWatchContractEvent({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
eventName: 'BspAddedToAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `eventName` set to `"BspRemovedFromAllowlist"`
|
||||
*/
|
||||
export const watchDataHavenServiceManagerBspRemovedFromAllowlistEvent =
|
||||
/*#__PURE__*/ createWatchContractEvent({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
eventName: 'BspRemovedFromAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `eventName` set to `"Initialized"`
|
||||
*/
|
||||
|
|
@ -12611,24 +12227,6 @@ export const watchDataHavenServiceManagerInitializedEvent =
|
|||
eventName: 'Initialized',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `eventName` set to `"MspAddedToAllowlist"`
|
||||
*/
|
||||
export const watchDataHavenServiceManagerMspAddedToAllowlistEvent =
|
||||
/*#__PURE__*/ createWatchContractEvent({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
eventName: 'MspAddedToAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `eventName` set to `"MspRemovedFromAllowlist"`
|
||||
*/
|
||||
export const watchDataHavenServiceManagerMspRemovedFromAllowlistEvent =
|
||||
/*#__PURE__*/ createWatchContractEvent({
|
||||
abi: dataHavenServiceManagerAbi,
|
||||
eventName: 'MspRemovedFromAllowlist',
|
||||
})
|
||||
|
||||
/**
|
||||
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `eventName` set to `"OperatorDeregistered"`
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ describeSuite({
|
|||
feeResults.baseFeePerGas.length,
|
||||
"baseFeePerGas should always the requested block range + 1 (the next derived base fee)"
|
||||
).toBe(block_count + 1);
|
||||
expect(feeResults.gasUsedRatio).to.be.deep.eq(Array(block_count).fill(0.0105225));
|
||||
expect(feeResults.gasUsedRatio).to.be.deep.eq(Array(block_count).fill(0.00773915));
|
||||
expect(
|
||||
feeResults.reward.length,
|
||||
"should return two-dimensional reward list for the requested block range"
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export const constructDeployCommand = (options: ContractDeploymentOptions): stri
|
|||
const { chain, rpcUrl, verified, blockscoutBackendUrl } = options;
|
||||
|
||||
const deploymentScript =
|
||||
!chain || chain === "anvil" || chain === "local"
|
||||
!chain || chain === "anvil"
|
||||
? "script/deploy/DeployLocal.s.sol"
|
||||
: "script/deploy/DeployTestnet.s.sol";
|
||||
|
||||
|
|
@ -83,12 +83,16 @@ export const constructDeployCommand = (options: ContractDeploymentOptions): stri
|
|||
export const executeDeployment = async (
|
||||
deployCommand: string,
|
||||
parameterCollection?: ParameterCollection,
|
||||
chain?: string
|
||||
chain?: string,
|
||||
privateKey?: string
|
||||
) => {
|
||||
logger.info("⌛️ Deploying contracts (this might take a few minutes)...");
|
||||
|
||||
// Using custom shell command to improve logging with forge's stdoutput
|
||||
await runShellCommandWithLogger(deployCommand, { cwd: "../contracts" });
|
||||
await runShellCommandWithLogger(deployCommand, {
|
||||
cwd: "../contracts",
|
||||
env: privateKey ? { DEPLOYER_PRIVATE_KEY: privateKey } : undefined
|
||||
});
|
||||
|
||||
// After deployment, read the:
|
||||
// - Gateway address
|
||||
|
|
@ -198,7 +202,7 @@ export const deployContracts = async (options: {
|
|||
|
||||
// Construct and execute deployment
|
||||
const deployCommand = constructDeployCommand(deploymentOptions);
|
||||
await executeDeployment(deployCommand);
|
||||
await executeDeployment(deployCommand, undefined, options.chain, options.privateKey);
|
||||
|
||||
logger.success(`DataHaven contracts deployed successfully to ${options.chain}`);
|
||||
};
|
||||
|
|
@ -251,5 +255,5 @@ if (import.meta.main) {
|
|||
await buildContracts();
|
||||
|
||||
const deployCommand = constructDeployCommand(options);
|
||||
await executeDeployment(deployCommand);
|
||||
await executeDeployment(deployCommand, undefined, undefined, options.privateKey);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ export const fundValidators = async (options: FundValidatorsOptions): Promise<bo
|
|||
logger.debug(`Found token creator's private key for address ${tokenCreator}`);
|
||||
|
||||
// Get the ERC20 balance of the token creator and its ETH balance as well
|
||||
const getErc20BalanceCmd = `${castExecutable} balance --erc20 ${underlyingTokenAddress} ${tokenCreator} --rpc-url ${rpcUrl}`;
|
||||
const getErc20BalanceCmd = `${castExecutable} call ${underlyingTokenAddress} "balanceOf(address)(uint256)" ${tokenCreator} --rpc-url ${rpcUrl}`;
|
||||
const getEthBalanceCmd = `${castExecutable} balance ${tokenCreator} --rpc-url ${rpcUrl}`;
|
||||
const { stdout: erc20BalanceOutput } = await $`sh -c ${getErc20BalanceCmd}`.quiet();
|
||||
const { stdout: ethBalanceOutput } = await $`sh -c ${getEthBalanceCmd}`.quiet();
|
||||
|
|
|
|||
|
|
@ -11,9 +11,10 @@ export const runShellCommandWithLogger = async (
|
|||
env?: object;
|
||||
logLevel?: LogLevel;
|
||||
waitFor?: (...args: unknown[]) => Promise<void>;
|
||||
throwOnError?: boolean;
|
||||
}
|
||||
) => {
|
||||
const { cwd = ".", env = {}, logLevel = "info" as LogLevel } = options || {};
|
||||
const { cwd = ".", env = {}, logLevel = "info" as LogLevel, throwOnError = true } = options || {};
|
||||
|
||||
try {
|
||||
if (!existsSync(cwd)) {
|
||||
|
|
@ -92,6 +93,10 @@ export const runShellCommandWithLogger = async (
|
|||
trimmedStderr.includes("\n") ? `>_ \n${trimmedStderr}` : `>_ ${trimmedStderr}`
|
||||
);
|
||||
}
|
||||
|
||||
if (throwOnError) {
|
||||
throw new Error(`Command failed with exit code ${exitCode}`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error("❌ Error running shell command:", command, "in", cwd);
|
||||
|
|
|
|||
Loading…
Reference in a new issue