Return contexts
A return context marks an instruction associated with a successful function return. It extends the function identity schema with an optional pointer to the return data and, for external calls, the success status.
- Explore
- View source
- Playground
- YAML
- JSON
$schema: "https://json-schema.org/draft/2020-12/schema"
$id: "schema:ethdebug/format/program/context/function/return"
title: ethdebug/format/program/context/function/return
description: |
This context indicates that the marked instruction is
associated with a successful function return. Extends the
function identity schema with an optional pointer to the
return data and, for external calls, the success status.
All fields are optional. A bare `return: {}` is permitted
when the compiler knows a return occurred but has no further
detail—for example, at a tail-call-optimized back-edge where
the intermediate return value is not materialized, or for a
void function with no return value.
type: object
properties:
return:
type: object
$ref: "schema:ethdebug/format/program/context/function"
properties:
data:
type: object
title: Return data
description: |
Pointer to the data being returned from the function.
Optional: may be omitted when no return value is
observable at this instruction (e.g., void functions,
tail-call-optimized returns where the intermediate
value is not materialized).
properties:
pointer:
$ref: "schema:ethdebug/format/pointer"
required:
- pointer
success:
type: object
title: Call success status
description: |
Pointer to the success status of an external call.
Typically points to a boolean value on the stack.
properties:
pointer:
$ref: "schema:ethdebug/format/pointer"
required:
- pointer
unevaluatedProperties: false
required:
- return
examples:
# -----------------------------------------------------------
# Internal return: transfer(address, uint256) returns (bool)
# -----------------------------------------------------------
# This context would mark the JUMP instruction that returns
# control to the caller. The function has left its return
# value on the stack:
#
# slot 0: return value (`bool success`)
- return:
identifier: "transfer"
declaration:
source:
id: 0
range:
offset: 128
length: 95
data:
pointer:
location: stack
slot: 0
# -----------------------------------------------------------
# External call return: processing result of a CALL
# -----------------------------------------------------------
# This context would mark an instruction after a CALL that
# completed successfully. The EVM places a success flag on
# the stack, and the callee's return data is accessible via
# the returndata buffer:
#
# stack slot 0: success flag (1 = success)
# returndata 0x00..0x1f: ABI-encoded return value (32 bytes)
- return:
data:
pointer:
location: returndata
offset: 0
length: "0x20"
success:
pointer:
location: stack
slot: 0
# -----------------------------------------------------------
# Minimal return: only the data pointer
# -----------------------------------------------------------
# When the compiler cannot attribute the return to a named
# function, the context may contain only the return data.
# Here, a single stack value is being returned.
#
# slot 0: return value
- return:
data:
pointer:
location: stack
slot: 0
# -----------------------------------------------------------
# Return without observable data: TCO back-edge
# -----------------------------------------------------------
# At a tail-call-optimized back-edge JUMP, the intermediate
# return value is not materialized on the stack — it would
# have been the argument to the next iteration, which the
# compiler has already folded into the new call's setup.
# A return semantically happens (the outer activation's
# iteration N is returning), but there is no pointer to
# record for `data`.
- return:
identifier: "fact"
declaration:
source:
id: 0
range:
offset: 64
length: 120
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "schema:ethdebug/format/program/context/function/return",
"title": "ethdebug/format/program/context/function/return",
"description": "This context indicates that the marked instruction is\nassociated with a successful function return. Extends the\nfunction identity schema with an optional pointer to the\nreturn data and, for external calls, the success status.\n\nAll fields are optional. A bare `return: {}` is permitted\nwhen the compiler knows a return occurred but has no further\ndetail—for example, at a tail-call-optimized back-edge where\nthe intermediate return value is not materialized, or for a\nvoid function with no return value.\n",
"type": "object",
"properties": {
"return": {
"type": "object",
"$ref": "schema:ethdebug/format/program/context/function",
"properties": {
"data": {
"type": "object",
"title": "Return data",
"description": "Pointer to the data being returned from the function.\nOptional: may be omitted when no return value is\nobservable at this instruction (e.g., void functions,\ntail-call-optimized returns where the intermediate\nvalue is not materialized).\n",
"properties": {
"pointer": {
"$ref": "schema:ethdebug/format/pointer"
}
},
"required": [
"pointer"
]
},
"success": {
"type": "object",
"title": "Call success status",
"description": "Pointer to the success status of an external call.\nTypically points to a boolean value on the stack.\n",
"properties": {
"pointer": {
"$ref": "schema:ethdebug/format/pointer"
}
},
"required": [
"pointer"
]
}
},
"unevaluatedProperties": false
}
},
"required": [
"return"
],
"examples": [
{
"return": {
"identifier": "transfer",
"declaration": {
"source": {
"id": 0
},
"range": {
"offset": 128,
"length": 95
}
},
"data": {
"pointer": {
"location": "stack",
"slot": 0
}
}
}
},
{
"return": {
"data": {
"pointer": {
"location": "returndata",
"offset": 0,
"length": "0x20"
}
},
"success": {
"pointer": {
"location": "stack",
"slot": 0
}
}
}
},
{
"return": {
"data": {
"pointer": {
"location": "stack",
"slot": 0
}
}
}
},
{
"return": {
"identifier": "fact",
"declaration": {
"source": {
"id": 0
},
"range": {
"offset": 64,
"length": 120
}
}
}
}
]
}
Return data
The data field contains a pointer to the value being returned.
For internal calls this typically points to a stack location;
for external calls it points into the returndata buffer.
data is optional. Omit it when no return value is observable
at this instruction—see
Field optionality below.
Internal return
An internal return marks the JUMP instruction that transfers
control back to the caller within the same contract. The
function leaves its return value on the stack, so data points
to the relevant stack slot.
Internal returns do not use the success field—internal calls
either return normally or revert, with no separate success flag.
External call return
An external call return marks an instruction after a CALL, DELEGATECALL, or STATICCALL that completed successfully. The EVM places a success flag on the stack (1 for success, 0 for failure), and the callee's output is accessible via the returndata buffer.
The success field is specific to external call returns. It
contains a pointer to the boolean success value on the stack,
letting the debugger distinguish successful returns from
reverts at the EVM level.
Field optionality
All fields on a return context are optional. A bare return: {}
is permitted when the compiler knows a return occurred but has
no further detail to record.
The data pointer is omitted when no return value is observable
at the marked instruction. This occurs in several legitimate
cases:
- Void functions. The function produces no return value, so there is nothing to point at.
- Tail-call-optimized back-edges. When a tail call is rewritten to a back-edge JUMP, the intermediate return value is not materialized—it would have become the next iteration's argument, which the compiler has already folded into the new call's setup. A return semantically happens, but no pointer records where the value lives (it does not live anywhere).
- Lost compiler precision. The compiler knows a return occurred but has dropped the location tracking for the value.
The success field is optional and only meaningful for external
call returns, where it points to the boolean status placed on
the stack by CALL/DELEGATECALL/STATICCALL.
Function identity fields (identifier, declaration, type)
are all optional. A compiler may omit them when it cannot
attribute the return to a specific named function, for instance
when returning from a fallback function or an anonymous code
path.