# call_decode

Decodes selector-free function return data into typed SQL columns defined by the function's ABI outputs.

Canonical HTML: <https://determica.com/docs/functions/call_decode>

- Kind: table function
- Category: [Contracts and ABI](/docs/category/contracts-and-abi.md)
- Tags: ABI

Decodes selector-free function return data into typed SQL columns defined by the function's ABI outputs.

## Overload 1: call_decode(JSON, VARCHAR, BYTES)

```sql
call_decode(JSON, VARCHAR, BYTES)
```

The ABI and function selection must be constant because they define the result columns; return bytes may vary by input row.

- Kind: table
- Execution context: Offline
- Behavior: Abi Return Decode
- Execution modes: Offline
- Input shape: Scalar Or Relation
- Planning contract: Bind Time Schema
- Cardinality: One Per Input
- Determinism: Deterministic
- Return shape: Dynamic Table
- Schema stability: Abi Dependent
- Stability: Stable
- Side effects: None documented

### Requirements

- foldable_abi
- foldable_function_selection
- selector_free_return_data

### Risks

- product_semantics:return_data_framing_not_validated

### Inputs

- `abi` (JSON; required; positional) — Contract ABI JSON containing the selected function and outputs.
- `function_name` (VARCHAR; required; positional) — Constant function name or canonical signature identifying one ABI function.
- `data` (BYTES; required; positional) — Raw standard ABI return bytes from a contract call or stored payload. Do not include a function selector.

### Relation input

The ABI and function columns must be constant across the relation. data may vary by row.

### Relation columns

- `abi` (JSON) — Foldable ABI JSON column that defines the output schema. Required
- `function_name` (VARCHAR) — Foldable function name or canonical signature column that selects one ABI function. Required
- `data` (BYTES) — Row-varying selector-free ABI return bytes. Required

```sql
SELECT *
FROM call_decode((
  SELECT
    '[{"type":"function","name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}]}]'::JSON AS abi,
    'balanceOf' AS function_name,
    from_hex('0000000000000000000000000000000000000000000000000000000000000001')::BYTES AS data
));
```

### Returns

ABI-derived output columns

Returns one column per selected function output. Exact names and SQL types come from abi + function_name before the query runs.

- `<abi_outputs>` (ANY) — Dynamic placeholder for ABI-derived output columns described by dynamicColumns.

### Dynamic columns

- Source: abi + function_name
- Names: ABI output names, or output{index} for unnamed outputs
- Types: Mapped from ABI output types
- Description: Returns one column per selected function output. The ABI and function name define the exact output columns.

ABI-derived output columns. Returns one column per selected function output. Exact names and SQL types come from abi + function_name before the query runs.

### Examples

_Local SQL · Local_

```sql
-- Decode literal ABI return bytes for balanceOf()
WITH call_result AS (
  SELECT '0x00000000000000000000000000000000000000000000000000000000000003e8'::BYTES AS response
)
SELECT decoded.*
FROM call_result
CROSS JOIN LATERAL call_decode(
  '[{
    "type": "function",
    "name": "balanceOf",
    "outputs": [{ "name": "balance", "type": "uint256" }]
  }]'::JSON,
  'balanceOf',
  call_result.response
) AS decoded;
```

## Guidance

### Decode return bytes

Use call_decode after a raw contract call or when return bytes are already stored. The ABI and function selection must be constant because they determine the SQL schema.

Pass exact selector-free return bytes. The current decoder does not reject a selector prefix or trailing bytes, and incorrectly framed data can decode to an unintended value.

- Use CROSS JOIN LATERAL when return bytes come from a table or CTE.
- Use the relation-input form when ABI/function columns are constant and the return-data column varies.
- Use read_contract when the RPC call and ABI decoding should happen in one helper.

```sql
WITH raw_response AS (
  SELECT '0x00000000000000000000000000000000000000000000000000000000000003e8'::BYTES AS data
)
SELECT decoded.*
FROM raw_response
CROSS JOIN LATERAL call_decode(
  '[{
    "type": "function",
    "name": "balanceOf",
    "outputs": [{ "name": "balance", "type": "uint256" }]
  }]'::JSON,
  'balanceOf',
  raw_response.data
) AS decoded;
```

### Choose the right ABI primitive

Choose by byte framing and direction: selector construction, standard arguments, calldata, packed bytes, raw words, calldata decoding, and return-data decoding are distinct operations.

- function_selector hashes already-canonical signature text exactly; function_selector_json builds a canonical signature from one JSON ABI fragment first.
- encode_function_args emits selector-free standard ABI arguments; encode_function_data prefixes those same bytes with the 4-byte selector.
- abi_encode_packed concatenates compact scalar encodings without standard ABI offsets, lengths, or 32-byte padding; evm_abi_word always emits exactly one padded 32-byte word.
- decode_function_data consumes and validates selector-prefixed calldata inputs; call_decode consumes selector-free function return bytes.

```sql
SELECT
  function_selector('transfer(address,uint256)') AS selector,
  encode_function_data(
    '[{"type":"function","name":"transfer","inputs":[{"type":"address"},{"type":"uint256"}]}]'::JSON,
    'transfer(address,uint256)',
    '0x000000000000000000000000000000000000dEaD'::ADDRESS,
    1::UINT256
  ) AS calldata;
```

## Related functions

- [raw_call](/docs/functions/raw_call.md) — Usually After
- [read_contract](/docs/functions/read_contract.md) — Alternative
- [read_contract_multicall](/docs/functions/read_contract_multicall.md) — Usually After
- [decode_function_data](/docs/functions/decode_function_data.md) — See Also
- [encode_function_data](/docs/functions/encode_function_data.md) — See Also
