Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,34 @@ docker run --rm --network host -v ./.nodes:/root/.nodes \
| `REGISTRY_ADDRESS` | if not mounted | From `.nodes/avs_deploy.json` | Volume | AVS registrar address |
| `FUNDED_KEY` | if not mounted | From `.nodes/deployer` | Volume | Deployer private key |

### Transfer Ownership

Transfers ownership of the service contracts to new owners.

```bash
PROXY_OWNER=$(cast wallet new --json | jq -r '.[0].private_key')
PROXY_OWNER_ADDRESS=$(cast wallet addr --private-key "$PROXY_OWNER")
echo "Proxy owner address: $PROXY_OWNER_ADDRESS"
AVS_OWNER=$(cast wallet new --json | jq -r '.[0].private_key')
AVS_OWNER_ADDRESS=$(cast wallet addr --private-key "$AVS_OWNER")
echo "Avs owner address: $AVS_OWNER_ADDRESS"

# WAVS_SERVICE_MANAGER_ADDRESS=$(jq -r '.addresses.WavsServiceManager' .nodes/avs_deploy.json)

docker run --rm --network host -v ./.nodes:/root/.nodes \
--env-file .env \
wavs-middleware transfer_ownership ${PROXY_OWNER} ${AVS_OWNER}
```

| Environment Variable | Required | Default | Source | Description |
| ------------------------------ | --------------------- | ----------------------------- | ------ | ---------------------------------------------- |
| `DEPLOY_ENV` | for non-default value | `LOCAL` | `.env` | Deployment environment (`LOCAL` or `TESTNET`) |
| `RPC_URL` | for non-default value | `http://localhost:8545` | `.env` | RPC URL |
| `WAVS_SERVICE_MANAGER_ADDRESS` | if not mounted | From `.nodes/avs_deploy.json` | volume | Service manager contract address |
| `FUNDED_KEY` | if not mounted | From `.nodes/deployer` | Volume | Deployer private key |
| `PROXY_OWNER` | Yes | - | Params | New owner for proxy admin |
| `AVS_OWNER` | Yes | - | Params | New owner for AVS registrar and stake registry |

### Delegate to Operator

Delegates tokens to an operator.
Expand Down Expand Up @@ -433,6 +461,32 @@ docker run --rm --network host -v ./.nodes:/root/.nodes \
| `DEPLOY_FILE_MOCK` | for non-default value | `mock` | Command line | File name to store mock deployment |
| `CONFIGURE_FILE` | for non-default value | `wavs-mock-config` | Command line | File name to read configuration data |

### 5. Mock Transfer Ownership

Transfers ownership of the mock service contracts to new owners.

```bash
PROXY_OWNER=$(cast wallet new --json | jq -r '.[0].private_key')
PROXY_OWNER_ADDRESS=$(cast wallet addr --private-key "$PROXY_OWNER")
echo "Proxy owner address: $PROXY_OWNER_ADDRESS"
AVS_OWNER=$(cast wallet new --json | jq -r '.[0].private_key')
AVS_OWNER_ADDRESS=$(cast wallet addr --private-key "$AVS_OWNER")
echo "Avs owner address: $AVS_OWNER_ADDRESS"

docker run --rm --network host -v ./.nodes:/root/.nodes \
--env-file .env \
wavs-middleware -m mock transfer_ownership ${PROXY_OWNER} ${AVS_OWNER}
```

| Environment Variable | Required | Default | Source | Description |
| ------------------------------ | --------------------- | --------------------------- | ------------ | ---------------------------------------------- |
| `DEPLOY_ENV` | for non-default value | `LOCAL` | `.env` | Deployment environment (`LOCAL` or `TESTNET`) |
| `MOCK_RPC_URL` | for non-default value | `http://localhost:8546` | Command line | RPC URL for mock blockchain |
| `MOCK_DEPLOYER_KEY` | if not mounted | From `.nodes/mock-deployer` | Volume | Deployer private key |
| `WAVS_SERVICE_MANAGER_ADDRESS` | if not mounted | From `.nodes/mock.json` | Volume | Service manager contract address |
| `PROXY_OWNER` | Yes | - | Params | New owner for proxy admin |
| `AVS_OWNER` | Yes | - | Params | New owner for AVS registrar and stake registry |

## Deploy Testnet

Same as the local deploy, change `DEPLOY_ENV` to `"TESTNET"` and make sure the `FUNDED_KEY` is actually funded on testnet
Expand Down
180 changes: 7 additions & 173 deletions contracts/script/eigenlayer/bls/WavsListOperators.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@
pragma solidity ^0.8.27;

import {Script} from "forge-std/Script.sol";
import {console} from "forge-std/console.sol";
import {IStakeRegistry} from "@eigenlayer-middleware/src/interfaces/IStakeRegistry.sol";
import {IAllocationManager} from "@eigenlayer/contracts/interfaces/IAllocationManager.sol";
import {OperatorSet} from "@eigenlayer/contracts/libraries/OperatorSetLib.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";

import {WavsServiceManager} from "src/eigenlayer/bls/WavsServiceManager.sol";
import {WavsListOperatorsLib} from "script/eigenlayer/bls/utils/WavsListOperatorsLib.sol";

/**
* @title WavsListOperators
Expand All @@ -17,182 +12,21 @@ import {WavsServiceManager} from "src/eigenlayer/bls/WavsServiceManager.sol";
* @dev This script is used to list the operators for the WAVS service manager.
*/
contract WavsListOperators is Script {
/**
* @notice The operator info struct.
* @param stakeRegistry The stake registry address.
* @param totalWeight The total weight of the operators.
* @param minimumStake The minimum stake of the operators.
* @param operators The operators.
* @param weights The weights of the operators.
* @param strategies The strategies of the operators.
*/
struct OperatorInfo {
address stakeRegistry;
uint96 totalWeight;
uint96 minimumStake;
address[] operators;
uint96[] weights;
IStakeRegistry.StrategyParams[] strategies;
}

/// @notice The environment variable for the WAVS service manager address.
string public constant ENV_SERVICE_MANAGER = "WAVS_SERVICE_MANAGER_ADDRESS";

WavsServiceManager private serviceManager;
uint256 private _quorumNumerator;
uint256 private _quorumDenominator;
address private _serviceManager;

/// @notice The setup function for the script.
function setUp() public virtual {
serviceManager = WavsServiceManager(vm.envAddress(ENV_SERVICE_MANAGER));
_serviceManager = vm.envAddress(ENV_SERVICE_MANAGER);
}

/// @notice The run function for the script.
function run() external {
vm.startBroadcast();
OperatorInfo memory opInfo = _listOperators(serviceManager.getStakeRegistry());
_quorumNumerator = serviceManager.quorumNumerator();
_quorumDenominator = serviceManager.quorumDenominator();
_writeOperatorListJson(opInfo);
vm.stopBroadcast();

console.log("=== List Operators ===");
console.log("Service Manager Address:", address(serviceManager));
console.log("Stake Registry Address:", serviceManager.getStakeRegistry());
console.log("Strategies:");
for (uint256 i = 0; i < opInfo.strategies.length; ++i) {
console.log(
string.concat(
"Strategy ",
Strings.toString(i),
": ",
Strings.toHexString(uint160(address(opInfo.strategies[i].strategy)), 20),
" (",
Strings.toString(opInfo.strategies[i].multiplier),
")"
)
);
}

console.log(" "); // Blank line for separation
console.log("=== Quorum Information ===");
console.log(string.concat("Total Weight: ", Strings.toString(uint256(opInfo.totalWeight))));
console.log(
string.concat("Minimum Stake: ", Strings.toString(uint256(opInfo.minimumStake)))
);

console.log(" "); // Blank line for separation
console.log("=== Registered Operators ===");
for (uint256 i = 0; i < opInfo.operators.length; ++i) {
string memory op = string.concat(
"Operator ",
Strings.toString(i + 1),
": ",
Strings.toHexString(uint160(opInfo.operators[i]), 20)
);
string memory weight = string.concat("= ", Strings.toString(uint256(opInfo.weights[i])));
console.log(op, weight);
}

console.log(" "); // Blank line for separation
console.log("=== Service Manager Quorum Information ===");
console.log(string.concat("Quorum Numerator: ", Strings.toString(_quorumNumerator)));
console.log(string.concat("Quorum Denominator: ", Strings.toString(_quorumDenominator)));
}

/**
* @notice The list operators function.
* @param _stakeRegistry The stake registry address.
* @return opInfo The operator info.
*/
function _listOperators(
address _stakeRegistry
) private view returns (OperatorInfo memory) {
IStakeRegistry stakeRegistry = IStakeRegistry(_stakeRegistry);

uint96 totalWeight = stakeRegistry.getCurrentTotalStake(0);

IAllocationManager allocationManager =
IAllocationManager(serviceManager.getAllocationManager());
OperatorSet memory opSetQuery = OperatorSet({avs: address(serviceManager), id: 0});
address[] memory operators = allocationManager.getMembers(opSetQuery);

uint96[] memory weights = new uint96[](operators.length);
for (uint256 i = 0; i < operators.length; ++i) {
weights[i] = stakeRegistry.weightOfOperatorForQuorum(0, operators[i]);
}

uint256 strategyParamsLength = stakeRegistry.strategyParamsLength(0);
IStakeRegistry.StrategyParams[] memory strategies =
new IStakeRegistry.StrategyParams[](strategyParamsLength);
for (uint256 i = 0; i < strategyParamsLength; ++i) {
strategies[i] = stakeRegistry.strategyParamsByIndex(uint8(0), i);
}

return OperatorInfo({
stakeRegistry: address(stakeRegistry),
totalWeight: totalWeight,
minimumStake: stakeRegistry.minimumStakeForQuorum(0),
operators: operators,
weights: weights,
strategies: strategies
});
}

/**
* @notice The write operator list JSON function.
* @param opInfo The operator info.
*/
function _writeOperatorListJson(
OperatorInfo memory opInfo
) internal {
if (!vm.exists("deployments/wavs-bls")) {
vm.createDir("deployments/wavs-bls", true);
}

string memory json = "{\"serviceManager\":\"";
json = string.concat(json, Strings.toHexString(uint160(address(serviceManager)), 20));
json = string.concat(json, "\",\"stakeRegistry\":\"");
json = string.concat(json, Strings.toHexString(uint160(opInfo.stakeRegistry), 20));
json = string.concat(json, "\",\"totalWeight\":\"");
json = string.concat(json, Strings.toString(opInfo.totalWeight));
json = string.concat(json, "\",\"minimumStake\":\"");
json = string.concat(json, Strings.toString(opInfo.minimumStake));
json = string.concat(json, "\",\"strategies\":[");

for (uint256 i = 0; i < opInfo.strategies.length; ++i) {
if (i > 0) {
json = string.concat(json, ",");
}
json = string.concat(json, "{\"strategy\":\"");
json = string.concat(
json, Strings.toHexString(uint160(address(opInfo.strategies[i].strategy)), 20)
);
json = string.concat(json, "\",\"multiplier\":\"");
json = string.concat(json, Strings.toString(opInfo.strategies[i].multiplier));
json = string.concat(json, "\"}");
}

json = string.concat(json, "],\"operators\":[");

for (uint256 i = 0; i < opInfo.operators.length; ++i) {
if (i > 0) {
json = string.concat(json, ",");
}
json = string.concat(json, "{\"operator\":\"");
json = string.concat(json, Strings.toHexString(uint160(opInfo.operators[i]), 20));
json = string.concat(json, "\",\"weight\":\"");
json = string.concat(json, Strings.toString(opInfo.weights[i]));
json = string.concat(json, "\"}");
}

json = string.concat(json, "],\"quorumNumerator\":\"");
json = string.concat(json, Strings.toString(_quorumNumerator));
json = string.concat(json, "\",\"quorumDenominator\":\"");
json = string.concat(json, Strings.toString(_quorumDenominator));
json = string.concat(json, "\"");
json = string.concat(json, "}");

vm.writeFile("deployments/wavs-bls/list_operators.json", json);
address[] memory operators = WavsListOperatorsLib.getOperators(_serviceManager, uint8(0));
WavsListOperatorsLib.ConfigData memory configData =
WavsListOperatorsLib.getConfigData(_serviceManager, uint8(0), operators);
WavsListOperatorsLib.writeOperatorListJson(configData);
}
}
12 changes: 5 additions & 7 deletions contracts/script/eigenlayer/bls/WavsMiddlewareDeployer.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ pragma solidity ^0.8.27;

import {Script} from "forge-std/Script.sol";

import {RegistryCoordinator} from "@eigenlayer-middleware/src/RegistryCoordinator.sol";
import {StakeRegistry} from "@eigenlayer-middleware/src/StakeRegistry.sol";
import {BLSApkRegistry} from "@eigenlayer-middleware/src/BLSApkRegistry.sol";
import {IndexRegistry} from "@eigenlayer-middleware/src/IndexRegistry.sol";
import {SocketRegistry} from "@eigenlayer-middleware/src/SocketRegistry.sol";
import {PauserRegistry} from "@eigenlayer/contracts/permissions/PauserRegistry.sol";
import {IStakeRegistryTypes} from "@eigenlayer-middleware/src/interfaces/IStakeRegistry.sol";
import {SlashingRegistryCoordinator} from
"@eigenlayer-middleware/src/SlashingRegistryCoordinator.sol";

import {WavsMiddlewareDeploymentLib} from "./utils/WavsMiddlewareDeploymentLib.sol";
import {WavsServiceManager} from "src/eigenlayer/bls/WavsServiceManager.sol";
Expand Down Expand Up @@ -100,8 +101,8 @@ contract WavsMiddlewareDeployer is Script {
WavsServiceManager wavsServiceManager =
WavsServiceManager(wavsMiddlewareDeployment.wavsServiceManager);
StakeRegistry stakeRegistry = StakeRegistry(wavsMiddlewareDeployment.stakeRegistry);
RegistryCoordinator registryCoordinator =
RegistryCoordinator(wavsMiddlewareDeployment.registryCoordinator);
SlashingRegistryCoordinator registryCoordinator =
SlashingRegistryCoordinator(wavsMiddlewareDeployment.registryCoordinator);
BLSApkRegistry blsApkRegistry = BLSApkRegistry(wavsMiddlewareDeployment.blsApkRegistry);
IndexRegistry indexRegistry = IndexRegistry(wavsMiddlewareDeployment.indexRegistry);
SocketRegistry socketRegistry = SocketRegistry(wavsMiddlewareDeployment.socketRegistry);
Expand All @@ -120,10 +121,7 @@ contract WavsMiddlewareDeployer is Script {
revert WavsMiddlewareDeployer__StakeRegistryMismatch();
}
if (
address(registryCoordinator.serviceManager())
!= wavsMiddlewareDeployment.wavsServiceManager
|| address(registryCoordinator.stakeRegistry())
!= wavsMiddlewareDeployment.stakeRegistry
address(registryCoordinator.stakeRegistry()) != wavsMiddlewareDeployment.stakeRegistry
|| address(registryCoordinator.blsApkRegistry())
!= wavsMiddlewareDeployment.blsApkRegistry
|| address(registryCoordinator.indexRegistry())
Expand Down
Loading
Loading