Skip to main content

Local Deployment Deep Dive

Relay Contracts deployment follows a 4-step process. Understanding what happens under the hood is crucial for customizing deployments and troubleshooting issues.

Overview of the Steps

InitSetup → MasterSetup → GenesisGeneration → GenesisSetup
↓ ↓ ↓ ↓
Core & Network Initial Settlement
Base Config ValSet Commitment

Step 1: InitSetup

Purpose: Deploy core infrastructure and Symbiotic Core integration

Configuration

# Environment variables that affect InitSetup
SYMBIOTIC_CORE_NUMBER_OF_VAULTS=3
SYMBIOTIC_CORE_NUMBER_OF_OPERATORS=5
SYMBIOTIC_CORE_NUMBER_OF_STAKERS=1
SYMBIOTIC_CORE_TOKENS_TO_SET_TIMES_1e18=0.03

What Gets Deployed

Symbiotic Core Setup

InitSetup also configures the underlying Symbiotic infrastructure:

  • Tokens: Creates test tokens for staking (configurable via SYMBIOTIC_CORE_* env vars)
  • Vaults: Deploys vaults that will hold operator stake
  • Operators: Registers test operators in the OperatorRegistry
  • Stakers: Creates test stakers with token balances

Network Middleware

// 5 Core Contracts
MyNetwork network = new MyNetwork(networkRegistry, networkMiddlewareService);
MyKeyRegistry keyRegistry = new MyKeyRegistry();
MyVotingPowerProvider votingPowerProvider = new MyVotingPowerProvider(operatorRegistry, vaultFactory);
MyValSetDriver valSetDriver = new MyValSetDriver();
MySettlement settlement = new MySettlement();

Step 2: MasterSetup

Purpose: Configure network parameters, set up extensions, and register operators

Network Configuration

// Key parameters from environment
networkSetupParams.OPERATORS_TO_REGISTER = vm.envOr("OPERATORS", 4);
networkSetupParams.EPOCH_DURATION = uint48(vm.envOr("EPOCH_DURATION", 60));
networkSetupParams.SLASHING_WINDOW = uint48(vm.envOr("SLASHING_WINDOW", 1200));
networkSetupParams.VERIFICATION_TYPE = uint32(vm.envOr("VERIFICATION_TYPE", 1));

VotingPowerProvider Initialization

Sample initialization:

votingPowerProvider.initialize(
// Core parameters
IVotingPowerProvider.VotingPowerProviderInitParams({
networkManagerInitParams: INetworkManager.NetworkManagerInitParams({
network: vars.network.addr,
subnetworkID: IDENTIFIER
}),
ozEip712InitParams: IOzEIP712.OzEIP712InitParams({name: "VotingPowerProvider", version: "1"}),
slashingWindow: networkSetupParams.SLASHING_WINDOW,
token: tokens[0]
}),
// Ownership
IOzOwnable.OzOwnableInitParams({owner: vars.network.addr}),
// Extensions
IOperatorsWhitelist.OperatorsWhitelistInitParams({isWhitelistEnabled: false}),
IBaseSlashing.BaseSlashingInitParams({slasher: address(1)}),
IBaseRewards.BaseRewardsInitParams({rewarder: address(1)})
);

Operator Registration Flow

For each operator being registered:

  1. Generate Keys: Creates BLS and ECDSA key pairs
// BLS key generation
BN254.G1Point memory blsPublicKey = BN254.generatorG1().scalar_mul(privateKey);

// ECDSA key from private key
address ecdsaPublicKey = vm.addr(privateKey);
  1. Register Keys: Adds keys to KeyRegistry
keyRegistry.registerKey(
operator,
KEY_TYPE_BLS_BN254,
blsKeyBytes,
signature
);

keyRegistry.registerKey(
operator,
KEY_TYPE_ECDSA_SECP256K1,
ecdsaKeyBytes,
signature
);
  1. Operator Registration: Registers with VotingPowerProvider
votingPowerProvider.registerOperator(
operator,
signature
);

Signature Verifier Setup

The verification type is set to "BLS" (1) by default, but can be overridden by setting the VERIFICATION_TYPE environment variable to 0 (ZK).

The number of operators is set to 4 by default, but can be overridden by setting the OPERATORS environment variable.

If the verification type is set to 0 or the number of operators exceeds 100, SigVerifierBlsBn254ZK is used.

Otherwise, SigVerifierBlsBn254Simple is used.

Middleware Integration

Connects the VotingPowerProvider to Symbiotic's middleware system:

// Set network middleware to our VotingPowerProvider
INetworkMiddlewareService(networkMiddlewareService).setMiddleware(
network,
address(votingPowerProvider)
);

Step 3: GenesisGeneration

Purpose: Create initial validator set data using external tooling

What Happens

  1. Binary Execution: Runs script/test/utils/generate_genesis binary
  2. Data Collection: Gathers operator keys and voting power from deployed contracts
  3. Validator Set Creation: Constructs initial validator set with:
    • Operator addresses
    • BLS public keys
    • Voting power weights
    • Aggregated public key

Output Format

Generates JSON data structure:

{
"validators": [
{
"address": "0x...",
"blsPublicKey": "0x...",
"votingPower": "1000000000000000000"
}
],
"aggregatedPublicKey": "0x...",
"totalVotingPower": "4000000000000000000"
}

Binary Details

The generate_genesis tool:

  • Queries deployed contracts for current state
  • Validates operator keys and registration
  • Computes BLS key aggregation
  • Outputs validator set in format expected by GenesisSetup

Step 4: GenesisSetup

Purpose: Initialize Settlement contract with initial validator set

ValSetDriver Initialization

valSetDriver.initialize(
IValSetDriver.ValSetDriverInitParams({
networkManagerInitParams: INetworkManager.NetworkManagerInitParams({
network: vars.network.addr,
subnetworkID: IDENTIFIER
}),
ozEip712InitParams: IOzEIP712.OzEIP712InitParams({name: "ValSetDriver", version: "1"}),
votingPowerProvider: address(votingPowerProvider),
keyRegistry: address(keyRegistry),
epochDuration: EPOCH_DURATION
}),
defaultAdmin
);

Settlement Contract Setup

settlement.initialize(
ISettlement.SettlementInitParams({
networkManagerInitParams: INetworkManager.NetworkManagerInitParams({
network: vars.network.addr,
subnetworkID: IDENTIFIER
}),
ozEip712InitParams: IOzEIP712.OzEIP712InitParams({name: "Settlement", version: "1"}),
valSetDriver: address(valSetDriver),
sigVerifier: address(sigVerifier)
}),
defaultAdmin
);

Genesis Commitment

Commits the initial validator set to the Settlement contract:

// Create validator set header from genesis data
bytes32 headerHash = keccak256(abi.encode(
validatorSetData.validators,
validatorSetData.totalVotingPower,
validatorSetData.aggregatedPublicKey
));

// Commit to settlement
settlement.commitValSetHeader(
0, // epoch 0
headerHash,
extraDataHash
);

Configuration Parameters

Core Parameters

  • OPERATORS: Number of operators (affects gas costs and verification type choice)
  • EPOCH_DURATION: How often validator sets can change (seconds)
  • SLASHING_WINDOW: Time window for slashing events (seconds)
  • VERIFICATION_TYPE: Signature verification approach (0=ZK, 1=Simple)

Advanced Parameters

  • DEPLOYMENT_BUFFER: Wait time between deployment steps
  • SUBNETWORK_ID: Unique identifier for your network

Post-Deployment State

After successful completion:

  • Active Network: Ready to accept Relay binary connections
  • Registered Operators: With verified BLS and ECDSA keys
  • Initial Validator Set: Committed to Settlement contract
  • Epoch 0: System ready for first epoch transition