Delegated Staking
π§ Overview
The following steps outline the creation of a staking pool with a single validator node.
βοΈ Prerequisites
Clone the delegated staking repository or pull the main
branch if you have already cloned it.
To deploy and interact with staking contracts via the CLI, use the provided Forge scripts. Follow these steps before proceeding with the deployment:
-
Install Foundry: Follow the official link for foundry installation.
-
Install OpenZeppenlin Contracts:
forge install OpenZeppelin/openzeppelin-contracts-upgradeable --no-commit forge install OpenZeppelin/openzeppelin-contracts --no-commit
- Set the RPC URL:
export FOUNDRY_ETH_RPC_URL=http://localhost:4202
- Set the Private Key:
export PRIVATE_KEY=0x...
PRIVATE_KEY
refers to the staking pool contract owner's private key.
β Step 1: Contract Deployment & Verification
Choose which variant of the staking contract to deploy, then verify the implementation and proxy contracts on Sourcify.
πΉ Deploying NonLiquidDelegation Contract
forge script script/Deploy.s.sol --broadcast --legacy --sig "nonLiquidDelegation()"
Example output:
Signer is 0x15fc323DFE5D5DCfbeEdc25CEcbf57f676634d77
Proxy deployed: 0x7A0b7e6D24eDe78260c9ddBD98e828B0e11A8EA2
Implementation deployed: 0x7C623e01c5ce2e313C223ef2aEc1Ae5C6d12D9DD
Owner is 0x15fc323DFE5D5DCfbeEdc25CEcbf57f676634d77
Upgraded to version: 0.3.4
β Verify Implementation Contract
forge verify-contract 0x7C623e01c5ce2e313C223ef2aEc1Ae5C6d12D9DD NonLiquidDelegation --verifier sourcify
β Verify Proxy Contract
forge verify-contract 0x7A0b7e6D24eDe78260c9ddBD98e828B0e11A8EA2 ERC1967Proxy \
--verifier sourcify \
--constructor-args $(cast abi-encode "_(address,bytes)" \
0x7C623e01c5ce2e313C223ef2aEc1Ae5C6d12D9DD \
$(cast calldata "initialize(address)" 0x15fc323DFE5D5DCfbeEdc25CEcbf57f676634d77))
Where:
0x7A0b7e6D24eDe78260c9ddBD98e828B0e11A8EA2
β Proxy contract address0x7C623e01c5ce2e313C223ef2aEc1Ae5C6d12D9DD
β Implementation contract address0x15fc323DFE5D5DCfbeEdc25CEcbf57f676634d77
β Signer address (i.e. the contract owner who deployed the contract)
πΉ Deploying LiquidDelegation Contract
forge script script/Deploy.s.sol --broadcast --legacy --sig "liquidDelegation(string,string)" Name Symbol
Name
and Symbol
represent your Liquid Staking Token (LST).
Example output:
Signer is 0x15fc323DFE5D5DCfbeEdc25CEcbf57f676634d77
Proxy deployed: 0x7A0b7e6D24eDe78260c9ddBD98e828B0e11A8EA2
Implementation deployed: 0x7C623e01c5ce2e313C223ef2aEc1Ae5C6d12D9DD
Owner is 0x15fc323DFE5D5DCfbeEdc25CEcbf57f676634d77
Upgraded to version: 0.3.4
β Verify Implementation Contract
forge verify-contract 0x7C623e01c5ce2e313C223ef2aEc1Ae5C6d12D9DD LiquidDelegation --verifier sourcify
β Verify Proxy Contract
forge verify-contract 0x7A0b7e6D24eDe78260c9ddBD98e828B0e11A8EA2 ERC1967Proxy \
--verifier sourcify \
--constructor-args $(cast abi-encode "_(address,bytes)" \
0x7C623e01c5ce2e313C223ef2aEc1Ae5C6d12D9DD \
$(cast calldata "initialize(address,string,string)" \
0x15fc323DFE5D5DCfbeEdc25CEcbf57f676634d77 Name Symbol))
Where:
0x7A0b7e6D24eDe78260c9ddBD98e828B0e11A8EA2
β Proxy contract address0x7C623e01c5ce2e313C223ef2aEc1Ae5C6d12D9DD
β Implementation contract address0x15fc323DFE5D5DCfbeEdc25CEcbf57f676634d77
β Signer address (i.e. the contract owner who deployed the contract)Name
andSymbol
β Token metadata provided during deployment (e.g.,"Zilliqa LST"
,"zLST"
)
π Notes
- Ensure that your
remappings.txt
includes the local path to the ZQ2 repository, otherwise you may encounter errors during contract verification. For example:
@zilliqa/zq2/=/home/your-user/zq2/zilliqa/src/contracts/
-
Always verify both the implementation and proxy contracts after deployment.
-
You must repeat implementation contract verification after every contract upgrade.
-
Proxy contract needs to be verified only once after the initial deployment.
π οΈ Step 2: Contract Configuration
Configure the validatorβs commission rate (e.g., 10%):
forge script script/Configure.s.sol --broadcast --legacy --sig "commissionRate(address payable, uint16)" <DELEGATION_CONTRACT_PROXY_ADDRESS> 1000
You can find DELEGATION_CONTRACT_PROXY_ADDRESS
in the output of step 1.
Expected output:
Running version: 0.3.4
Commission rate: 0.0%
New commission rate: 10.0%
π§© Step 3: Validator Addition
Follow one of the approaches below, depending on whether you have already deposited the required stake with your validator node or you need delegations to accumulate enough stake to deposit the required stake.
π Scenario 1: Node with Deposited Stake
If you are operating a validator node with the required stake already deposited, execute the following steps:
- Register the Control Address:
here
cast send --legacy --private-key <0x...> \ <DELEGATION_CONTRACT_PROXY_ADDRESS> "registerControlAddress(bytes)" \ <BLS_PUBLIC_KEY>
--private-key <0x...>
refers to the private key previously used to deposit stake for the validator node. For details, refer to the staking.md. Example:cast send --legacy --private-key 0x... \ 0x7A0b7e6D24eDe78260c9ddBD98e828B0e11A8EA2 "registerControlAddress(bytes)" \ 0x92fbe50544dce63cfdcc88301d7412f0edea024c91ae5d6a04c7cd3819edfc1b9d75d9121080af12e00f054d221f876c
- Change the Control Address:
here
cast send --legacy --private-key <0x...> \ 0x00000000005a494c4445504f53495450524f5859 "setControlAddress(bytes,address)" \ <BLS_PUBLIC_KEY> \ <DELEGATION_CONTRACT_PROXY_ADDRESS>
--private-key <0x...>
refers to the private key used in the previous step. Example:cast send --legacy --private-key 0x... \ 0x00000000005a494c4445504f53495450524f5859 "setControlAddress(bytes,address)" \ 0x92fbe50544dce63cfdcc88301d7412f0edea024c91ae5d6a04c7cd3819edfc1b9d75d9121080af12e00f054d221f876c \ 0x7A0b7e6D24eDe78260c9ddBD98e828B0e11A8EA2
- Join the Staking Pool:
Example:
cast send --legacy --private-key $PRIVATE_KEY \ <DELEGATION_CONTRACT_PROXY_ADDRESS> "joinPool(bytes)" \ <BLS_PUBLIC_KEY>
cast send --legacy --private-key $PRIVATE_KEY \ 0x7A0b7e6D24eDe78260c9ddBD98e828B0e11A8EA2 "joinPool(bytes)" \ 0x92fbe50544dce63cfdcc88301d7412f0edea024c91ae5d6a04c7cd3819edfc1b9d75d9121080af12e00f054d221f876c
π§ Scenario 2: Node Without Deposited Stake
If you are operating a node that does not yet have the required stake deposited, and you do not own the minimum ZIL stake required of validators, proceeding with step 4 will enable your contract to collect the delegated stake you need to deposit with your validator node. Once the stake delegated to the contract plus your ZIL balance as the contract owner exceeds the required minimum, you can add your fully synced node to the staking pool and activate it as a validator by executing:
cast send --legacy --value <YOUR_ZIL>ether --private-key $PRIVATE_KEY \
<DELEGATION_CONTRACT_PROXY_ADDRESS> "depositFromPool(bytes,bytes,bytes)" \
<BLS_PUBLIC_KEY> \
<HEX_PEER_ID> \
<DEPOSIT_AUTH_SIGNATURE>
<BLS_PUBLIC_KEY>
, and <DEPOSIT_AUTH_SIGNATURE>
are the values corresponding from the JSON output
of the convert-key
utility and <HEX_PEER_ID>
is the <PEER_ID>
output value converted from base58
to hexadecimal encoding.
For the conversion you can use the following command:
echo <PEER_ID> | base58 -d | xxd -ps -c 1000
echo 12D3KooWQDT1rcThrxoSmnCt9n35jrhy5wo4BHsM5JuVz8LstQpN | base58 -d | xxd -ps -c 1000
002408011220d5ed74b09dcbe84d3b32a56c01ab721cf82809848b6604535212a219d35c412f
<DELEGATION_CONTRACT_PROXY_ADDRESS>
must be set as the value of control_address
in the JSON input passed to convert-key
.
Example: If your contract has collected 8M ZIL from delegators but is still short of another 2M ZIL, you can complete the deposit by transferring the remaining 2M ZIL out of your balance.
cast send --legacy --value 2000000ether --private-key $PRIVATE_KEY \
0x7A0b7e6D24eDe78260c9ddBD98e828B0e11A8EA2 "depositFromPool(bytes,bytes,bytes)" \
0x92fbe50544dce63cfdcc88301d7412f0edea024c91ae5d6a04c7cd3819edfc1b9d75d9121080af12e00f054d221f876c \
0x002408011220d5ed74b09dcbe84d3b32a56c01ab721cf82809848b6604535212a219d35c412f \
0xb14832a866a49ddf8a3104f8ee379d29c136f29aeb8fccec9d7fb17180b99e8ed29bee2ada5ce390cb704bc6fd7f5ce814f914498376c4b8bc14841a57ae22279769ec8614e2673ba7f36edc5a4bf5733aa9d70af626279ee2b2cde939b4bd8a
π Step 4: Staking Pool Registration
Share the
π§Ύ Summary
By following these steps, you have successfully deployed and configured a Non-Liquid Staking Pool or a Liquid Staking Pool, and added a validator node to it. ZIL holders who delegate to the pool will earn rewards or see their liquid staking token's value increase, and you will receive a commission on the delegated amounts.