From e9cb1634a20bb6527caccbc7f7426cee04e133b4 Mon Sep 17 00:00:00 2001 From: "g. nicholas d'andrea" Date: Sat, 4 Jul 2026 04:23:14 -0400 Subject: [PATCH] format: add activation identifier to correlate invocations with returns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An invocation and the return (or revert) that ends the same activation can now carry a matching `activation` string. A debugger uses it to pair a call with its return directly — independent of trace order, without relying on strictly nested invoke/return ordering. Distinct activations carry distinct values, unique within a program. - Schema: add an optional `activation` string to the invoke, return, and revert contexts; add a worked example pairing an invoke with its return by a shared value. - TS types: add `activation` to the invoke/return/revert types and validate it in their guards. --- packages/format/src/types/program/context.ts | 14 ++++++++++---- .../program/context/function/invoke.schema.yaml | 15 +++++++++++++++ .../program/context/function/return.schema.yaml | 14 ++++++++++++++ .../program/context/function/revert.schema.yaml | 11 +++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/packages/format/src/types/program/context.ts b/packages/format/src/types/program/context.ts index b9ec6fc4f..500d5d1a6 100644 --- a/packages/format/src/types/program/context.ts +++ b/packages/format/src/types/program/context.ts @@ -155,8 +155,9 @@ export namespace Context { Invoke.isInvocation(value.invoke); export namespace Invoke { - export type Invocation = Function.Identity & - ( + export type Invocation = Function.Identity & { + activation?: string; + } & ( | Invocation.InternalCall | Invocation.ExternalCall | Invocation.ContractCreation @@ -164,6 +165,7 @@ export namespace Context { export const isInvocation = (value: unknown): value is Invocation => Function.isIdentity(value) && + (!("activation" in value) || typeof value.activation === "string") && (Invocation.isInternalCall(value) || Invocation.isExternalCall(value) || Invocation.isContractCreation(value)); @@ -241,6 +243,7 @@ export namespace Context { export interface Info extends Function.Identity { data?: Function.PointerRef; success?: Function.PointerRef; + activation?: string; } export const isInfo = (value: unknown): value is Info => @@ -248,7 +251,8 @@ export namespace Context { typeof value === "object" && !!value && (!("data" in value) || Function.isPointerRef(value.data)) && - (!("success" in value) || Function.isPointerRef(value.success)); + (!("success" in value) || Function.isPointerRef(value.success)) && + (!("activation" in value) || typeof value.activation === "string"); } export interface Revert { @@ -265,6 +269,7 @@ export namespace Context { export interface Info extends Function.Identity { reason?: Function.PointerRef; panic?: number; + activation?: string; } export const isInfo = (value: unknown): value is Info => @@ -272,6 +277,7 @@ export namespace Context { typeof value === "object" && !!value && (!("reason" in value) || Function.isPointerRef(value.reason)) && - (!("panic" in value) || typeof value.panic === "number"); + (!("panic" in value) || typeof value.panic === "number") && + (!("activation" in value) || typeof value.activation === "string"); } } diff --git a/schemas/program/context/function/invoke.schema.yaml b/schemas/program/context/function/invoke.schema.yaml index 41ef71d77..b68950aa6 100644 --- a/schemas/program/context/function/invoke.schema.yaml +++ b/schemas/program/context/function/invoke.schema.yaml @@ -43,6 +43,18 @@ properties: $ref: "schema:ethdebug/format/program/context/function" + properties: + activation: + type: string + title: Activation identifier + description: | + Correlation identifier pairing this invocation with its + matching return or revert. The invoke that opens an + activation and the return or revert that closes it carry + the same value; distinct activations carry distinct + values, unique within the program. Lets a debugger pair a + call with its return independent of trace order. Optional. + allOf: - oneOf: - required: [jump] @@ -283,6 +295,9 @@ examples: - name: "amount" location: stack slot: 2 + # The matching return context carries the same `activation` + # value, pairing this call with its return. + activation: "transfer#0" # ----------------------------------------------------------- # External CALL: token.balanceOf(account) diff --git a/schemas/program/context/function/return.schema.yaml b/schemas/program/context/function/return.schema.yaml index 4a4376048..eb9c67ebd 100644 --- a/schemas/program/context/function/return.schema.yaml +++ b/schemas/program/context/function/return.schema.yaml @@ -49,6 +49,17 @@ properties: required: - pointer + activation: + type: string + title: Activation identifier + description: | + Correlation identifier for the activation this return + ends. Matches the `activation` on the `invoke` that + opened the same activation; distinct activations carry + distinct values, unique within the program. Lets a + debugger pair a return with its invocation independent + of trace order. Optional. + unevaluatedProperties: false required: @@ -75,6 +86,9 @@ examples: pointer: location: stack slot: 0 + # Same `activation` value as the opening `invoke`, pairing + # this return with its call. + activation: "transfer#0" # ----------------------------------------------------------- # External call return: processing result of a CALL diff --git a/schemas/program/context/function/revert.schema.yaml b/schemas/program/context/function/revert.schema.yaml index 9aecc9026..5a3585783 100644 --- a/schemas/program/context/function/revert.schema.yaml +++ b/schemas/program/context/function/revert.schema.yaml @@ -37,6 +37,17 @@ properties: (e.g., Solidity uses codes like 0x11 for arithmetic overflow). + activation: + type: string + title: Activation identifier + description: | + Correlation identifier for the activation this revert + ends. Matches the `activation` on the `invoke` that + opened the same activation; distinct activations carry + distinct values, unique within the program. Lets a + debugger pair an abnormal exit with its invocation + independent of trace order. Optional. + unevaluatedProperties: false required: