Skip to main content

Pointers

Pointers describe where data lives in the EVM. They're recipes that tell a debugger how to find bytes at runtime—recipes that can depend on the current machine state.

Why pointers are complex

In high-level languages, a variable like uint256 balance seems simple. But at the EVM level, finding that value might require:

  1. Reading a storage slot whose address depends on a mapping key
  2. Following a memory pointer stored on the stack
  3. Computing an offset based on array indices

A pointer in ethdebug/format captures all this complexity in a self-contained description.

Core concepts

Pointers are recursive

A pointer is either:

  • A region: a single, continuous sequence of bytes
  • A collection: an aggregation of other pointers

This recursive structure lets you build up complex allocations from simple pieces.

Regions locate bytes

A region identifies a contiguous block of bytes in a specific data location:

{
"location": "memory",
"offset": "0x40",
"length": 32
}

This says: "32 bytes in memory starting at offset 0x40."

Different locations use different addressing schemes:

  • Memory, calldata, returndata, code: byte offsets (offset + length)
  • Storage, transient, stack: slot-based (slot)

Collections group pointers

When data spans multiple regions (like struct members), collections aggregate them:

{
"group": [
{
"name": "balance",
"location": "memory",
"offset": "0x40",
"length": 32
},
{
"name": "owner",
"location": "memory",
"offset": "0x60",
"length": 32
}
]
}

Collection types include group, list, conditional, and more. See collections for the complete reference.

Expressions make pointers dynamic

Real allocations rarely use constant offsets. Expressions let you compute addresses from runtime state—reading values from named regions, performing arithmetic, and computing keccak256 hashes for storage slot calculation.

See expressions for the full expression language.

Named regions enable composition

Regions can have names that other parts of the pointer reference. This allows one region's address to be computed from another's properties, or its value to be read and used in expressions. See expressions for the full expression language.

What's next

Regions

How to specify byte ranges in different data locations.

Expressions

Computing dynamic locations with arithmetic and hashing.

Collections

Grouping pointers for structs, arrays, and conditionals.

Implementation guide

Build a pointer resolver for your debugger.

Full specification

Complete JSON schemas and expression reference.