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.

Overview

The 0G Chain staking system enables OG 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 (Testnet)

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;
}
}
}

Getting Validator Signature

Prerequisites

Your directory structure should look like:

galileo/
├── bin/0gchaind
└── config/
├── genesis.json
├── priv_validator_key.json
└── ...

Step 1: Extract Public Key

# Set your home directory
HOMEDIR=/.tmp/0gchaind
CHAIN_SPEC=devnet

# Generate validator keys
./0gchaind deposit validator-keys --home $HOMEDIR --chaincfg.chain-spec=$CHAIN_SPEC

Output:

Eth/Beacon Pubkey (Compressed 48-byte Hex):
0xaa0f99735a6436d6b7ed763c2eaa8452d753c5152a4fb1e4dc0bd7e33bcfc8cd4fac0e2d6cbab941f423c17728fecc56

Step 2: Compute Validator Address

Use the public key from Step 1 to compute the validator's contract address. Choose your preferred method:

Recommended method - simpler syntax and better error handling.

cast call \
0xea224dBB52F57752044c0C86aD50930091F561B9 \
"computeValidatorAddress(bytes)(address)" \
"0xaa0f99735a6436d6b7ed763c2eaa8452d753c5152a4fb1e4dc0bd7e33bcfc8cd4fac0e2d6cbab941f423c17728fecc56" \
--rpc-url https://evmrpc-testnet.0g.ai

Step 3: Generate Signature

# Generate signature for validator initialization
./0gchaind deposit create-validator \
0x1E776a6b65892EC60537a885c17B820301E05400 \
32000000000 \
$HOMEDIR/config/genesis.json \
--home $HOMEDIR \
--chaincfg.chain-spec=$CHAIN_SPEC

Output:

✅ Deposit message created successfully!

pubkey: 0xaa0f99735a6436d6b7ed763c2eaa8452d753c5152a4fb1e4dc0bd7e33bcfc8cd4fac0e2d6cbab941f423c17728fecc56
signature: 0x123456789000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Data Structures

Description Struct
struct Description {
string moniker; // max 70 chars - Validator display name
string identity; // max 3000 chars - Keybase identity
string website; // max 140 chars - Website URL
string securityContact; // max 140 chars - Security contact
string details; // max 280 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

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
Testnet0xea224dBB52F57752044c0C86aD50930091F561B9

Resources


Need help? Join our Discord for developer support.