Builder Guide
During Suzaku's testnet, we offer Avalanche L1 builders to become permissionless Suzaku-secured networks.
This guide walks you through the process of becoming a Suzaku Network.
Suzaku is a very modular protocol with many smart contracts involved. L1 builders looking to leverage Suzaku to enhance their decentralization and security are encouraged to reach out via X (opens in a new tab) or Discord (opens in a new tab).
What is a Suzaku Network?
A Suzaku Network is an Avalanche L1 using Suzaku smart contracts as their Validator Manager.
There are two contracts at the center of the Validator Manager setup:
BalancerValidatorManager
: an ACP-99-compliant smart contract that can be used to manage the validator set of Avalanche L1s by allowing to balance the weight of an L1 between multiple security modules. Learn more in the Progressive Decentralization section.AvalancheL1Middleware
: a security module used to interact with the Suzaku Core contracts, allowing L1 owner to set staking or dual-staking requirements for Operators to become validators. Learn more in the Dual staking model section.
L1 setup
I have already deployed an Avalanche L1
On which chain is the L1's Validator Manager? ChainID
was provided as a parameter during the ConvertSubnetToL1Tx
:
- If the Chain ID is not the C-Chain (ID
yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp
on Fuji), the L1 can not use Suzaku at the moment but will be soon when ACP-186 (opens in a new tab) is implemented! - If the L1's Validator Manager is on the C-Chain, the next step to make the L1 Suzaku-ready is Upgrade Validator Manager to BalancerValidatorManager
I have not deployed an Avalanche L1 yet
The best way to create a new L1 is to use the L1 Toolbox (opens in a new tab) from the Avalanche Builders Hub.
Here is an overview of the steps needed to create a new Suzaku-ready L1:
Create Subnet
Create Chain
Deploy Validator Manager contracts
git clone git@github.com:suzaku-network/suzaku-deployer.git && cd suzaku-deployer
forge install
Create the following JSON file at configs/mySuzakuL1.json
:
{
"proxyAddress": "0x0000000000000000000000000000000000000000",
"validatorManagerOwnerAddress": "0x0000000000000000000000000000000000000000",
"initialSecurityModuleMaxWeight": 0,
"migratedValidations": [],
"l1ID": "0x3cb97014ff27381387d35fbea2522ac5dfb4b5315f77a14fc2900f74e3207b8f",
"churnPeriodSeconds": 3600,
"maximumChurnPercentage": 20
}
l1ID
is the Chain ID from previous step, in can be converted form CB58 to Hex in the L1 Toolbox (opens in a new tab).- Only
l1ID
,churnPeriodSeconds
andmaximumChurnPercentage
are used in this step.
export PK=0x...
export FUJI_RPC_URL=https://api.avax-test.network/ext/bc/C/rpc
export VERIFY_URL=https://api-testnet.snowscan.xyz/api
export ETHERSCAN_API_KEY=your_snowscan_key...
forge script script/l1/DeployPoAValidatorManager.s.sol --sig "run(string, uint256, uint256)" configs/mySuzakuL1.json $PK $PK --rpc-url fuji --broadcast --verify $VERIFY_URL --etherscan-api-key $ETHERSCAN_API_KEY
--verify
andetherscan-api-key
can be omitted.
Output:
== Logs ==
Deployed PoA proxy at: 0xfC39EeA8Bf30de48B0Ff9AB60799CAA555a6e3ab
Convert Subnet to L1
ValidatorManager
from the previous step for Validator Manager Contract Address. To avoid churn issues, set the total Consensus Weight to a higher value, e.g.: 1,000,000.Initialize Validator Set
The L1 has now been created, the next step to make the L1 Suzaku-ready is Upgrade Validator Manager to BalancerValidatorManager
Upgrade Validator Manager to BalancerValidatorManager
This script will update the Validator Manager to a BalancerValidatorManager
with a PoA Security module.
Update the configs/mySuzakuL1.json
file:
{
"proxyAddress": "0xfC39EeA8Bf30de48B0Ff9AB60799CAA555a6e3ab",
"validatorManagerOwnerAddress": "your_address...",
"initialSecurityModuleMaxWeight": 0,
"migratedValidations": ["validation_id..."],
"l1ID": "0x3cb97014ff27381387d35fbea2522ac5dfb4b5315f77a14fc2900f74e3207b8f",
"churnPeriodSeconds": 3600,
"maximumChurnPercentage": 20
}
migratedValidations
are the validation ids from the Initialize Validator Set step. They can be queried from the "Query L1 Validator Set" page and converted in the L1 Toolbox (opens in a new tab).
export PK=0x...
export FUJI_RPC_URL=https://api.avax-test.network/ext/bc/C/rpc
export VERIFY_URL=https://api-testnet.snowscan.xyz/api
export ETHERSCAN_API_KEY=9JY13VKAWQA7CNX4J5HDM6MQRMB6USMVPR
forge script script/l1/UpgradePoAToBalancer.s.sol --sig "run(string, uint256)" configs/mySuzakuL1.json $PK --rpc-url fuji --broadcast --verify $VERIFY_URL --etherscan-api-key $ETHERSCAN_API_KEY
Output:
== Logs ==
Upgraded PoA proxy at: 0xfC39EeA8Bf30de48B0Ff9AB60799CAA555a6e3ab
Deployed PoA security module at: 0x876f6587A95d76f268Df67F3635bC4b33f241202
Output JSON => ./deployments/43113/2025-05-16/poAUpgrade.json
L1 Middleware deployment
Create the following JSON file at configs/mySuzakuL1Middleware.json
:
{
"l1MiddlewareOwnerAddress": "your_address...",
"validatorManager": "validator_manager_proxy...",
"operatorRegistry": "0x46D45D6be6214F6bd8124187caD1a5302755d7A2",
"vaultFactory": "0xC3b09a650c78daFb79e3C5B782402C8dc523fE88",
"operatorL1OptIn": "0x0360C1cB32A20D97b358538D9Db71339ce2c9592",
"primaryAsset": "0x59fbBa1845690Fb202d69a77CFEc5564df12D3DE",
"primaryAssetMaxStake": 5000000000000000000000,
"primaryAssetMinStake": 100000000000000000000,
"primaryAssetWeightScaleFactor": 2e16,
"epochDuration": 1800,
"slashingWindow": 2100,
"stakeUpdateWindow": 900
}
The main parameters are:
operatorRegistry
,vaultFactory
,operatorL1OptIn
are common to all Suzaku L1s, see DeploymentsprimaryAsset
: the address of a Collateral (see Vaults & Collateral Classes), 0x59fbBa1845690Fb202d69a77CFEc5564df12D3DE (opens in a new tab) is a mock $sAVAX Collateral that can be used for testingprimaryAssetMinStake
: the minimum stake in the Primary Asset an Operator has to receive delegation to become a validatorprimaryAssetMaxStake
the maximum stake in the Primary Asset an Operator can receive as delegationprimaryAssetWeightScaleFactor
: the stake to weight scale factor
export PK=0x...
export FUJI_RPC_URL=https://api.avax-test.network/ext/bc/C/rpc
export VERIFY_URL=https://api-testnet.snowscan.xyz/api
export ETHERSCAN_API_KEY=your_snowscan_key...
forge script script/l1/DeployMiddleware.s.sol --sig "run(string)" configs/mySuzakuL1Middleware.json --rpc-url fuji --private-key $PK --broadcast --verify $VERIFY_URL --etherscan-api-key $ETHERSCAN_API_KEY
Output:
== Logs ==
AvalancheL1Middleware deployed at: 0xB4Aa3dd44e34a2621474386DF42c99B837013522
MiddlewareVaultManager deployed at: 0xb098d078AaF75dBF4CE8478858bD7E280b46ED97
Using validatorManager at: 0xfC39EeA8Bf30de48B0Ff9AB60799CAA555a6e3ab
Using operatorRegistry at: 0x46D45D6be6214F6bd8124187caD1a5302755d7A2
Using vaultFactory at: 0xC3b09a650c78daFb79e3C5B782402C8dc523fE88
Using operatorL1OptIn at: 0x0360C1cB32A20D97b358538D9Db71339ce2c9592
Deployed L1 middleware to: 0xB4Aa3dd44e34a2621474386DF42c99B837013522
Deployed VaultManager to: 0xb098d078AaF75dBF4CE8478858bD7E280b46ED97
Output JSON => ./deployments/43113/2025-05-19/l1Middleware.json
Suzaku Core L1 interactions
Requirements
- suzaku-cli (opens in a new tab) installed
- A private key for the L1 owner with AVAX balance on the C-Chain
- An Avalanche L1 live on Fuji with its Validator Manager upgraded to
BalancerValidatorManager
contract on the C-Chain (see L1 Setup) AvalancheL1Middleware
contract deployed
- Setup the L1 Middleware as Security Module:
BALANCER_VALIDATOR_MANAGER=...
L1_MIDDLEWARE=...
SECURITY_MODULE_MAX_WEIGHT=200000
pnpm cli --network fuji balancer-set-up-security-module $BALANCER_VALIDATOR_MANAGER $L1_MIDDLEWARE $SECURITY_MODULE_MAX_WEIGHT --private-key $PK
The arguments are:
BALANCER_VALIDATOR_MANAGER
: TheBalanceValidatorManager
address, deployed previouslyL1_MIDDLEWARE
: TheAvalancheL1Middleware
address, deployed previouslySECURITY_MODULE_MAX_WEIGHT
: The total maximum weight in the P-Chain for the validators that are managed by the security module being set up, here theAvalancheL1Middleware
See Progressive Decentralization to learn more about BalanceValidatorManager
and AvalancheL1Middleware
.
- (Optional) Verify the Security Module has been set up:
pnpm cli --network fuji balancer-get-security-modules $BALANCER_VALIDATOR_MANAGER
L1 registration in the L1 Registry
- Register the L1 in the L1 Registry contract:
BALANCER_VALIDATOR_MANAGER=...
L1_MIDDLEWARE=...
L1_METADATA_URL=https://l1.com
pnpm cli --network fuji --private-key $PK register-l1 $BALANCER_VALIDATOR_MANAGER $L1_MIDDLEWARE $L1_METADATA_URL
The arguments are:
BALANCER_VALIDATOR_MANAGER
: TheBalanceValidatorManager
address, deployed previouslyL1_MIDDLEWARE
: TheAvalancheL1Middleware
address, deployed previouslyL1_METADATA_URL
: URL to a JSON file providing metadata for the L1, format is TBD, in the meantime L1s are encouraged to use any link to a website or social media profile
Registering an L1 in the L1 Registry costs 1 $AVAX (0.1 $AVAX in Fuji). This is to avoid malicious actors to flood the protocol.
- (Optional) Verify the L1 is registered in the L1 Registry:
pnpm cli --network fuji get-l1s
Vault registration in MiddlewareVaultManager
Stake vs Weight
In a typical Suzaku L1 setup, the BalancerValidatorManager
manages 2 security modules: a PoASecurityModule
and a AvalancheL1Middleware
, each managing a portion of the total weight of the Avalanche L1 as tracked in the P-Chain.
Assets deposited in Vaults are denominated in stake from which the AvalancheL1Middleware
will calculate a corresponding weight.
- Register a Vault in the
MiddlewareVaultManager
:
MIDDLEWARE_VAULT_MANAGER=...
VAULT=0x85F212C69f0C567011E1eCFf956dCc0014754A2c
ASSET_CLASS=1
MAX_LIMIT=200000000000000000000000
pnpm cli --network fuji --private-key $PK vault-manager-register-vault-l1 $MIDDLEWARE_VAULT_MANAGER $VAULT $ASSET_CLASS $MAX_LIMIT
The arguments are:
MIDDLEWARE_VAULT_MANAGER
: the address of theMiddlewareVaultManager
.VAULT
is the address of a Vault. The Suzaku team has deployed a Vault on the Fuji testnet at address.0x85F212C69f0C567011E1eCFf956dCc0014754A2c
(opens in a new tab) for testing purposes.ASSET_CLASS
is1
since we are setting up a Vault for the Primary Asset Class is the first requirement before adding other asset classes.MAX_LIMIT
is the maximum stake the L1 can receive from this Vault. It is set to an arbitrary high value of 200,000 sAVAX in the example and can be adapted accordingly.
This command calls SetMaxL1Limit
on the L1RestakeDelegator
contract managed by the Curator.
Set L1 limit
DONE BY THE L1???
DELEGATOR=...
L1_LIMIT=100000000000000000000000
ASSET_CLASS=1
pnpm cli --network fuji --private-key $PK set-l1-limit $DELEGATOR $BALANCER_VALIDATOR_MANAGER $L1_LIMIT $ASSET_CLASS
The arguments are:
DELEGATOR
it the address of theL1RestakeDelegator
L1_LIMIT
is the maximum stake the L1 can receive from theL1RestakeDelegator
. It is set to an arbitrary high value of 200,000 sAVAX in the example and can be adapted accordingly.ASSET_CLASS
is1
since we are setting the maxium stake for the Primary Asset Class.
Operator registration in L1
L1_MIDDLEWARE=...
OPERATOR=0xfFF4224c953682C0866cb45643512D8Eee6eB608
pnpm cli --network fuji --private-key $PK middleware-register-operator $L1_MIDDLEWARE $OPERATOR
The arguments are:
L1_MIDDLEWARE
: the address of theAvalancheL1Middleware
.OPERATOR
: the address of an Operator registered in the Operator Registry and opted-in to the L1 (see Operator Guide).
At this point, everything is setup on the L1 side and the Curator can delegate stake to an Operator, see Curator Guide.