raw_traces dataset down to a specific function using its 4-byte selector, then decode the call’s inputs and outputs with a TypeScript transform.
Turbo’s SQL functions include
_gs_log_decode for decoding event logs, but there is no built-in SQL function for decoding trace calldata. The pattern in this guide (selector filtering in SQL plus a small TypeScript decoder) is the recommended way to decode traces in Turbo. To decode events instead, see Decode contract events.What you’ll need
- A Goldsky account and the CLI installed
Install Goldsky's CLI and log in
Install Goldsky's CLI and log in
-
Install the Goldsky CLI:
For macOS/Linux:
For Windows:Windows users need to have Node.js and npm installed first. Download from nodejs.org if not already installed.
-
Log into your Project by running:
This opens your browser to sign in (Google, GitHub, SSO, or email). Once you authenticate, the CLI is logged in automatically — there’s no API key to copy or paste.On a headless or remote machine (or in CI), create an API key on your Project Settings page and pass it directly with
goldsky login --token <API_KEY>. Usegoldsky login --no-browserto print the login URL instead of opening a browser. -
Now that you are logged in, run
goldskyto get started:
- A basic understanding of Turbo pipelines
- A destination sink to write your data to. In this example, we will use the PostgreSQL sink
Preface
This guide shows how to decode traces of a contract with Turbo. The example uses the Friendtech contract deployed on Base (specifically calls to itsgetBuyPriceAfterFee(address,uint256) function), but the same logic applies to any other contract and chain for which a raw_traces dataset is available (see supported chains).
Two columns of the raw traces schema (EVM schemas) hold the encoded call data:
input: the data sent along with the message call:0x, followed by the 4-byte function selector (8 hex characters), followed by the ABI-encoded arguments as 32-byte words (64 hex characters each).output: the data returned by the message call:0xfollowed by the ABI-encoded return values as 32-byte words.
Pipeline definition
traces-decoding-pipeline.yaml
- Your
secret_name. If you already created a secret, you can find it via the CLI commandgoldsky secret list. - The schema and table you want the data written to. By default it writes to
decoded_traces.friendtech.
Filtering by function selector
Let’s start analyzing the first transform:Transform: buy_price_calls
WHERE clause does two things:
to_address = ...keeps only traces where the Friendtech contract is the call target.- The
substrcomparison keeps only calls to the function we care about._gs_keccak256computes the keccak256 hash of the canonical function signature, and the first 10 characters (0xplus 8 hex characters) are the 4-byte selector that prefixes every call’sinput.
Decoding transform
The second transform is a TypeScript transform that slices the ABI-encoded hex into named, typed columns:- Inputs: after skipping
0xand the 8-character selector, each argument occupies one 32-byte word. Theaddressargument (sharesSubject) is the last 40 hex characters of its word; theuint256argument (amount) is the whole word, converted to a decimal string with JavaScript’s nativeBigIntso large values don’t lose precision. - Outputs: return data is encoded the same way but has no selector, so the function’s single
uint256return value is the first 64 hex characters after0x. - Filtering: returning
nullfrominvokedrops the record, which we use to discard calls with no return data (for example, reverted calls).
schema field declares the transform’s output columns, which is what the Postgres sink will create as the table structure.
This slicing approach works for statically-sized argument types:
address, uintN / intN, bool, and bytesN. Dynamically-sized types (string, bytes, arrays) are encoded as offset pointers into the calldata and need extra logic to follow. For complex signatures, consider decoding in your own service via an HTTP handler transform instead.Deploying the pipeline
As a last step, to deploy this pipeline and start sinking decoded data into your database simply execute:Conclusion
In this guide we have explored an example implementation of how to decode raw traces and stream them into a PostgreSQL database using a selector filter in SQL and a TypeScript decoding transform. This same methodology can be applied to any contract of interest on any chain withraw_logs and raw_traces datasets available (see supported chains).
Can’t find what you’re looking for? Reach out to us at support@goldsky.com for help.