Skip to main content

Staking Interfaces

Welcome to the 0G Chain Staking Interfaces documentation. This guide provides comprehensive information about interacting with the 0G Chain staking system through smart contracts, enabling you to build applications that leverage validator operations and delegations.

Running a Validator?

If you want to set up and initialize a validator, see the Validator Initialization Guide below.

Quick Navigation


Overview

The 0G Chain staking system enables 0G token holders to participate in network consensus and earn rewards through two primary mechanisms:

  1. Becoming a Validator: Run infrastructure to validate transactions and produce blocks
  2. Delegating to Validators: Stake tokens with existing validators to earn rewards without running infrastructure

The staking system is built on two core smart contract interfaces:

  • IStakingContract: Central registry managing validators and global staking parameters
  • IValidatorContract: Individual validator operations including delegations and reward distribution

Prerequisites

Before working with the staking interfaces:

  • Familiarity with Solidity and smart contract development
  • Basic knowledge of consensus mechanisms and staking concepts

Quick Start

// Create a validator
IStakingContract staking = IStakingContract(0xea224dBB52F57752044c0C86aD50930091F561B9);
address validator = staking.createAndInitializeValidatorIfNecessary{value: msg.value}(
description, commissionRate, withdrawalFee, pubkey, signature
);

// Delegate to validator
IValidatorContract(validator).delegate{value: msg.value}(msg.sender);

Core Concepts

Validators

Validators process transactions and produce blocks:

  • Unique Identity: Identified by 48-byte consensus public key
  • Operator Control: Managed by an Ethereum address
  • Commission: Set their own reward commission rates
  • Self-Delegation: Required minimum stake from operator

Delegations

Token holders earn rewards by delegating to validators:

  • Share-Based: Delegations represented as shares in validator pool
  • Proportional Rewards: Earnings based on share percentage
  • Withdrawal Delay: Undelegation subject to network delay period

Reward Distribution

Rewards flow through multiple layers:

  1. Community Tax: Applied to all rewards first
  2. Validator Commission: Taken from remaining rewards
  3. Delegator Distribution: Proportional to shares held

Contract Interfaces

IStakingContract

0xea224dBB52F57752044c0C86aD50930091F561B9 (Mainnet)

Central registry for validators and global parameters.

Validator Management

// Create validator contract
function createValidator(bytes calldata pubkey) external returns (address);

// Initialize validator with self-delegation
function initializeValidator(
Description calldata description,
uint32 commissionRate,
uint96 withdrawalFeeInGwei,
bytes calldata pubkey,
bytes calldata signature
) external payable;

// Create and initialize in one call
function createAndInitializeValidatorIfNecessary(
Description calldata description,
uint32 commissionRate,
uint96 withdrawalFeeInGwei,
bytes calldata pubkey,
bytes calldata signature
) external payable;

Query Functions

function getValidator(bytes memory pubkey) external view returns (address);
function computeValidatorAddress(bytes calldata pubkey) external view returns (address);
function validatorCount() external view returns (uint32);
function maxValidatorCount() external view returns (uint32);

IValidatorContract

Individual validator operations and delegation management.

Delegation Management

// Delegate tokens (msg.value = amount)
function delegate(address delegatorAddress) external payable returns (uint);

// Undelegate shares (msg.value = withdrawal fee)
function undelegate(address withdrawalAddress, uint shares) external payable returns (uint);

// Withdraw validator commission (only validator operator)
function withdrawCommission(address withdrawalAddress) external returns (uint);
Access Control

The withdrawCommission function is restricted to the validator operator only - the address that originally created and manages the validator.

Information Queries

function tokens() external view returns (uint);           // Total tokens (delegated + rewards)
function delegatorShares() external view returns (uint); // Total shares issued
function getDelegation(address delegator) external view returns (address, uint);
function commissionRate() external view returns (uint32);
function withdrawalFeeInGwei() external view returns (uint96);
Understanding tokens()

The tokens() function returns the complete validator balance, including both the original delegated amounts and any accumulated rewards that haven't been distributed yet.

Examples

Creating a Validator

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./IStakingContract.sol";

contract ValidatorExample {
IStakingContract constant STAKING = IStakingContract(0xea224dBB52F57752044c0C86aD50930091F561B9);

function createValidator(
bytes calldata pubkey,
bytes calldata signature
) external payable {
Description memory desc = Description({
moniker: "My Validator",
identity: "keybase-id",
website: "https://validator.example.com",
securityContact: "security@example.com",
details: "A reliable 0G Chain validator"
});

STAKING.createAndInitializeValidatorIfNecessary{value: msg.value}(
desc,
50000, // 5% commission
1, // 1 Gwei withdrawal fee
pubkey,
signature
);
}
}

Delegation Management

contract DelegationHelper {
IStakingContract constant STAKING = IStakingContract(0xea224dBB52F57752044c0C86aD50930091F561B9);

function delegateToValidator(bytes calldata pubkey) external payable {
address validator = STAKING.getValidator(pubkey);
require(validator != address(0), "Validator not found");

IValidatorContract(validator).delegate{value: msg.value}(msg.sender);
}

function getDelegationInfo(
bytes calldata pubkey,
address delegator
) external view returns (uint shares, uint estimatedTokens) {
address validator = STAKING.getValidator(pubkey);
IValidatorContract v = IValidatorContract(validator);

(, shares) = v.getDelegation(delegator);

uint totalTokens = v.tokens();
uint totalShares = v.delegatorShares();

if (totalShares > 0) {
estimatedTokens = (shares * totalTokens) / totalShares;
}
}
}

Validator Initialization

This section covers the complete workflow for setting up and initializing a validator on the 0G Chain.

Step 1: Generate Validator Signature

The validator signature creation process is simplified with a single command:

# Set your environment variables
HOMEDIR={your data path}/0g-home/0gchaind-home
STAKING_ADDRESS=0xea224dBB52F57752044c0C86aD50930091F561B9
AMOUNT=500000000000 # Amount in wei (e.g., 500 for 500 0G tokens)

# Generate validator signature
./bin/0gchaind deposit create-delegation-validator \
$STAKING_ADDRESS \
$AMOUNT \
$HOMEDIR/config/genesis.json \
--home $HOMEDIR \
--chaincfg.chain-spec=mainnet \
--override-rpc-url \
--rpc-dial-url https://evmrpc.0g.ai

Output:

✅ Staking message created successfully!
Note: This is NOT a transaction receipt; use these values to create a validator initialize transaction by Staking Contract.

stakingAddress: 0xea224dBB52F57752044c0C86aD50930091F561B9
pubkey: 0x8497312cd37eef3a7a50017cfbebcb00a9bc400c5881ffb1011cba1c3f29e5d005a980880b7b919b558b95565bc1e628
validatorAddress: 0xA47171b1be26C75732766Ea3433a90A724b3590d
amount: 500000000000
signature: 0xb1dae1164d931c46178785246203eb1c4496b403a7c417bfb33bdfd3c26b552bdbec8e466ed6712ade0b99cc9b0ee8b004cc766687565ba5b0929a1382997a6cc548cf5e390b69f849933c7ac017fbddc612cb3de285fdf89e6fe32e0ccbfc43

Step 2: Validate the Signature

Before submitting the validator initialization transaction, validate the signature:

# Validate the deposit message
./bin/0gchaind deposit validate-delegation \
{pubkey} \
{staking_address} \
{amount} \
{signature} \
$HOMEDIR/config/genesis.json \
--home $HOMEDIR \
--chaincfg.chain-spec=mainnet \
--override-rpc-url \
--rpc-dial-url https://evmrpc.0g.ai

Example:

./bin/0gchaind deposit validate-delegation \
0x8497312cd37eef3a7a50017cfbebcb00a9bc400c5881ffb1011cba1c3f29e5d005a980880b7b919b558b95565bc1e628 \
0xea224dBB52F57752044c0C86aD50930091F561B9 \
500000000000 \
0xb1dae1164d931c46178785246203eb1c4496b403a7c417bfb33bdfd3c26b552bdbec8e466ed6712ade0b99cc9b0ee8b004cc766687565ba5b0929a1382997a6cc548cf5e390b69f849933c7ac017fbddc612cb3de285fdf89e6fe32e0ccbfc43 \
$HOMEDIR/config/genesis.json \
--home $HOMEDIR \
--chaincfg.chain-spec=mainnet \
--override-rpc-url \
--rpc-dial-url https://evmrpc.0g.ai

Output:

✅ Deposit message is valid!

Step 3: Prepare Validator Description and Settings

Description Structure

The Description struct contains your validator's public information. All fields have character limits that must be respected:

FieldMax LengthDescription
moniker70 charsYour validator's display name
identity100 charsOptional: Keybase identity
website140 charsYour validator website URL
securityContact140 charsSecurity contact email
details200 charsAdditional validator description

Example Description Object:

{
moniker: "Your Validator Name", // Max 70 chars
identity: "keybase_id", // Optional
website: "https://yoursite.com", // Max 140 chars
securityContact: "security@you.com", // Max 140 chars
details: "Professional validator" // Max 200 chars
}

Commission Rate Configuration

The commission rate determines what percentage of staking rewards your validator keeps

ValueCommission
1000.01%
10000.1%
100001%
500005%
10000010%

Withdrawal Fee Configuration

The withdrawal fee (in Gwei) is charged when delegators undelegate from your validator.

Recommended value: 1 (equivalent to 1 Gneuron, ~1 Gwei)

Step 4: Execute Initialization Transaction

The easiest way to initialize your validator using the web interface:

  1. Navigate to https://chainscan.0g.ai/address/0xea224dBB52F57752044c0C86aD50930091F561B9
  2. Under Contracts Tab, click on the Write As Proxy button
  3. Find and click on createAndInitializeValidatorIfNecessary
  4. Fill in all the required parameters:
    • description (struct):
      • moniker: Your validator name (max 70 chars)
      • identity: Keybase ID (optional)
      • website: Your website URL
      • securityContact: Security contact email
      • details: Additional description
    • commissionRate: Commission percentage (e.g., 10000 for 1%)
    • withdrawalFeeInGwei: Withdrawal fee in Gwei (e.g.,1 Gneuron ~ 1 Gwei)
    • pubkey: The public key from Step 1
    • signature: The signature from Step 1
  5. Set the payable amount to 500 OG tokens
  6. Connect your wallet and execute the transaction
Tip

Using the Chain Scan interface requires no coding knowledge and is the safest option for most users.

Step 5: Verify Initialization

After successful initialization, you can verify your validator status:

Activation Time

Your validator may initially appear as inactive on the explorer. This is normal. Validators typically take 30-60 minutes to activate on the network after successful initialization.

You can check the transaction status and logs to confirm the initialization was successful while waiting for activation.

Troubleshooting

Error: "Insufficient funds"

Ensure you have at least 500 OG tokens plus gas fees in your wallet.

# Check balance
cast balance $YOUR_ADDRESS --rpc-url https://evmrpc.0g.ai
Error: "Validator already exists"

Your validator has already been created. Use the getValidator function to retrieve your validator address:

const validatorAddress = await stakingContract.getValidator("0x...");
Error: "Invalid signature"

Regenerate your signature using 0gchaind with the correct validator contract address and delegation amount:

./bin/0gchaind deposit create-delegation-validator \
0xea224dBB52F57752044c0C86aD50930091F561B9 \
500000000000 \
$HOMEDIR/config/genesis.json \
--home $HOMEDIR \
--chaincfg.chain-spec=mainnet \
--override-rpc-url \
--rpc-dial-url https://evmrpc.0g.ai
Error: "Description field too long"

Ensure all Description fields are within character limits:

  • moniker: max 70 chars
  • identity: max 100 chars
  • website: max 140 chars
  • securityContact: max 140 chars
  • details: max 200 chars

Data Structures

Description Struct
struct Description {
string moniker; // max 70 chars - Validator display name
string identity; // max 100 chars - Keybase identity
string website; // max 140 chars - Website URL
string securityContact; // max 140 chars - Security contact
string details; // max 200 chars - Additional details
}
Withdrawal Entry
struct WithdrawEntry {
uint completionHeight; // Block height when withdrawal completes
address delegatorAddress; // Address receiving withdrawal
uint amount; // Amount being withdrawn
}

Configuration Parameters

ParameterDescription
maxValidatorCountMaximum validators allowed
minActivationStakesInGweiMinimum stake for activation
maxEffectiveStakesInGweiMaximum effective stake
communityTaxRateTax on all rewards
minWithdrawabilityDelayWithdrawal delay blocks

General Troubleshooting

Error: "Validator not found"

The validator hasn't been created yet. Use createValidator() first:

address validator = staking.createValidator(pubkey);
Error: "DelegationBelowMinimum"

Your delegation amount is below the minimum required. Check:

uint96 minDelegation = staking.effectiveDelegationInGwei();
require(msg.value >= minDelegation * 1 gwei, "Insufficient delegation");
Error: "NotEnoughWithdrawalFee"

Include the withdrawal fee when undelegating:

uint96 fee = validator.withdrawalFeeInGwei();
validator.undelegate{value: fee * 1 gwei}(recipient, shares);

Contract Addresses

NetworkStaking Contract
Mainnet0xea224dBB52F57752044c0C86aD50930091F561B9

Resources


Need help? Join our Discord for developer support.