Skip to content

StateUpdate

Retrieves the state update for a specific block, including storage diffs, declared classes, deployed contracts, and nonces.

Method Signature

func (p *Provider) StateUpdate(
    ctx context.Context,
    blockID BlockID,
) (*StateUpdateOutput, error)

Parameters

  • ctx (context.Context): Context for request cancellation and timeouts
  • blockID (BlockID): The identifier of the block (hash, number, or tag)

Returns

  • *StateUpdateOutput: The state changes that occurred in the block
  • error: Error if the block is not found

Description

StateUpdate returns all state changes that occurred in a specific block, including:

  • Storage Diffs: Changes to contract storage
  • Declared Classes: New contract classes declared
  • Deployed Contracts: New contract instances deployed
  • Replaced Classes: Contract class upgrades
  • Nonces: Account nonce updates

This is essential for indexing, analytics, and understanding blockchain state transitions.

Usage Example

package main
 
import (
    "context"
    "fmt"
    "log"
 
    "github.com/NethermindEth/starknet.go/rpc"
)
 
func main() {
    client, err := rpc.NewProvider(context.Background(), "https://starknet-sepolia.public.blastapi.io/rpc/v0_7")
    if err != nil {
        log.Fatal(err)
    }
 
    // Get state update for latest block
    blockID := rpc.BlockID{Tag: "latest"}
    
    stateUpdate, err := client.StateUpdate(context.Background(), blockID)
    if err != nil {
        log.Fatal(err)
    }
 
    fmt.Printf("Block Hash: %s\n", stateUpdate.BlockHash)
    fmt.Printf("New Root: %s\n", stateUpdate.NewRoot)
    fmt.Printf("Old Root: %s\n", stateUpdate.OldRoot)
    fmt.Printf("Storage Diffs: %d contracts\n", len(stateUpdate.StateDiff.StorageDiffs))
    fmt.Printf("Declared Classes: %d\n", len(stateUpdate.StateDiff.DeclaredClasses))
    fmt.Printf("Deployed Contracts: %d\n", len(stateUpdate.StateDiff.DeployedContracts))
    fmt.Printf("Nonce Updates: %d\n", len(stateUpdate.StateDiff.Nonces))
    
    // Example output:
    // Block Hash: 0x1a2b3c4d...
    // New Root: 0x5e6f7a8b...
    // Old Root: 0x9c0d1e2f...
    // Storage Diffs: 12 contracts
    // Declared Classes: 2
    // Deployed Contracts: 1
    // Nonce Updates: 5
}

StateUpdateOutput Structure

type StateUpdateOutput struct {
    BlockHash *felt.Felt
    NewRoot   *felt.Felt
    OldRoot   *felt.Felt
    StateDiff StateDiff
}
 
type StateDiff struct {
    StorageDiffs      []ContractStorageDiff
    DeclaredClasses   []DeclaredClass
    DeployedContracts []DeployedContract
    ReplacedClasses   []ReplacedClass
    Nonces            []NonceUpdate
}
 
type ContractStorageDiff struct {
    Address      *felt.Felt
    StorageEntries []StorageEntry
}
 
type StorageEntry struct {
    Key   *felt.Felt
    Value *felt.Felt
}

Detailed Usage

Tracking Storage Changes

stateUpdate, err := client.StateUpdate(ctx, blockID)
if err != nil {
    log.Fatal(err)
}
 
// Iterate through storage diffs
for _, diff := range stateUpdate.StateDiff.StorageDiffs {
    fmt.Printf("Contract: %s\n", diff.Address)
    for _, entry := range diff.StorageEntries {
        fmt.Printf("  Key: %s -> Value: %s\n", entry.Key, entry.Value)
    }
}

Monitoring Declared Classes

// Check for newly declared contract classes
for _, declaredClass := range stateUpdate.StateDiff.DeclaredClasses {
    fmt.Printf("Declared Class Hash: %s\n", declaredClass.ClassHash)
    fmt.Printf("Compiled Class Hash: %s\n", declaredClass.CompiledClassHash)
}

Tracking Deployments

// Monitor new contract deployments
for _, deployed := range stateUpdate.StateDiff.DeployedContracts {
    fmt.Printf("Deployed Contract: %s\n", deployed.Address)
    fmt.Printf("Class Hash: %s\n", deployed.ClassHash)
}

Nonce Updates

// Track account nonce changes
for _, nonceUpdate := range stateUpdate.StateDiff.Nonces {
    fmt.Printf("Account: %s, New Nonce: %s\n", 
        nonceUpdate.ContractAddress, 
        nonceUpdate.Nonce)
}

Use Cases

  1. Blockchain Indexing: Index all state changes for analytics
  2. Event Monitoring: Track contract deployments and upgrades
  3. State Verification: Verify state root transitions
  4. Audit Trails: Create complete audit logs of state changes
  5. Analytics: Analyze storage patterns and contract interactions

Error Handling

stateUpdate, err := client.StateUpdate(ctx, blockID)
if err != nil {
    if errors.Is(err, rpc.ErrBlockNotFound) {
        log.Println("Block not found")
        return
    }
    log.Printf("RPC error: %v", err)
}

Block ID Options

// Latest block
blockID := rpc.BlockID{Tag: "latest"}
 
// Pending block
blockID := rpc.BlockID{Tag: "pending"}
 
// Specific block number
blockID := rpc.BlockID{Number: 12345}
 
// Specific block hash
blockHash, _ := new(felt.Felt).SetString("0xabc...")
blockID := rpc.BlockID{Hash: blockHash}

Related Methods

RPC Specification

  • Method: starknet_getStateUpdate
  • Version: RPC v0.9.0
  • Returns: Complete state diff for the block

Performance Notes

  • State updates for old blocks may be slow to retrieve
  • Consider caching state updates for frequently accessed blocks
  • Large state updates may take significant time to process
  • Use specific block numbers instead of "latest" for consistency