> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# CallDataDecoded

> Decoded calldata structure with selector and parameters

CallDataDecoded represents the structured form of calldata after parsing the function selector and ABI-decoding the parameters.

## Structure

```typescript theme={null}
export type CallDataDecoded = {
  selector: [4]u8,
  signature: ?[]const u8,
  parameters: []AbiValue,
}
```

### Fields

**selector** - 4-byte function identifier

* First 4 bytes of keccak256 hash of function signature
* Required for all function calls
* Immutable once created

**signature** - Optional function signature string

* Human-readable like `"transfer(address,uint256)"`
* Useful for debugging and logging
* Not required for execution (EVM only uses selector)

**parameters** - Decoded ABI parameter values

* Array of structured ABI values
* Preserves type information
* Enables type-safe parameter access

## Decoding CallData

<Tabs>
  <Tab title="With ABI">
    ```typescript theme={null}
    import { CallData, Abi } from '@tevm/voltaire';

    const abi = Abi([{
      name: "transfer",
      type: "function",
      inputs: [
        { name: "to", type: "address" },
        { name: "amount", type: "uint256" }
      ]
    }]);

    const calldata = CallData("0xa9059cbb...");
    const decoded = CallData.decode(calldata, abi);

    console.log(decoded.selector); // [0xa9, 0x05, 0x9c, 0xbb]
    console.log(decoded.signature); // "transfer(address,uint256)"
    console.log(decoded.parameters[0]); // Address
    console.log(decoded.parameters[1]); // Uint256
    ```
  </Tab>

  <Tab title="Without ABI">
    ```typescript theme={null}
    import { CallData } from '@tevm/voltaire';

    const calldata = CallData("0xa9059cbb...");

    // Can still extract selector
    const selector = CallData.getSelector(calldata);
    console.log(selector); // [0xa9, 0x05, 0x9c, 0xbb]

    // But parameters remain encoded
    const rawParams = calldata.slice(4); // Everything after selector
    ```
  </Tab>
</Tabs>

## Encoding to CallData

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { CallData, Address, TokenBalance } from '@tevm/voltaire';

    const decoded: CallDataDecoded = {
      selector: [0xa9, 0x05, 0x9c, 0xbb],
      signature: "transfer(address,uint256)",
      parameters: [
        Address("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"),
        TokenBalance.fromUnits("1", 18)
      ]
    };

    const calldata = CallData.encode(decoded);
    console.log(CallData.toHex(calldata));
    // "0xa9059cbb00000000000000000000000070997970..."
    ```
  </Tab>

  <Tab title="Zig">
    ```zig theme={null}
    const std = @import("std");
    const CallData = @import("primitives").CallData;

    pub fn example(allocator: std.mem.Allocator) !void {
        var decoded = CallDataDecoded{
            .selector = [_]u8{ 0xa9, 0x05, 0x9c, 0xbb },
            .signature = "transfer(address,uint256)",
            .parameters = &[_]AbiValue{
                .{ .address = address_value },
                .{ .uint256 = amount_value },
            },
            .allocator = allocator,
        };

        const calldata = try decoded.encode(allocator);
        defer allocator.free(calldata.data);
    }
    ```
  </Tab>
</Tabs>

## Working with Parameters

### Type-Safe Access

```typescript theme={null}
import { CallData, Abi } from '@tevm/voltaire';

const abi = Abi([{
  name: "swap",
  type: "function",
  inputs: [
    { name: "tokenIn", type: "address" },
    { name: "tokenOut", type: "address" },
    { name: "amountIn", type: "uint256" },
    { name: "minAmountOut", type: "uint256" }
  ]
}]);

const calldata = CallData("0x...");
const decoded = CallData.decode(calldata, abi);

// Type-safe parameter access
const tokenIn: Address = decoded.parameters[0];
const tokenOut: Address = decoded.parameters[1];
const amountIn: Uint256 = decoded.parameters[2];
const minAmountOut: Uint256 = decoded.parameters[3];
```

### Dynamic Parameters

```typescript theme={null}
const abi = Abi([{
  name: "multicall",
  type: "function",
  inputs: [
    { name: "calls", type: "bytes[]" }
  ]
}]);

const decoded = CallData.decode(calldata, abi);

// Access dynamic array
const calls: CallData[] = decoded.parameters[0];
for (const call of calls) {
  console.log(CallData.toHex(call));
}
```

## Selector Operations

### Matching Selectors

```typescript theme={null}
import { CallData } from '@tevm/voltaire';

const TRANSFER_SELECTOR = [0xa9, 0x05, 0x9c, 0xbb];
const APPROVE_SELECTOR = [0x09, 0x5e, 0xa7, 0xb3];

function routeCall(calldata: CallData) {
  const selector = CallData.getSelector(calldata);

  if (equals(selector, TRANSFER_SELECTOR)) {
    return handleTransfer(calldata);
  } else if (equals(selector, APPROVE_SELECTOR)) {
    return handleApprove(calldata);
  } else {
    throw new Error("Unknown function");
  }
}
```

### Computing Selectors

```typescript theme={null}
import { Keccak256 } from '@tevm/voltaire';

function computeSelector(signature: string): [4]u8 {
  const hash = Keccak256.hashString(signature);
  return hash.slice(0, 4);
}

const selector = computeSelector("transfer(address,uint256)");
// [0xa9, 0x05, 0x9c, 0xbb]
```

## Memory Management (Zig)

In Zig, `CallDataDecoded` owns allocated memory:

```zig theme={null}
pub fn processCallData(
    allocator: std.mem.Allocator,
    calldata: CallData,
) !void {
    var decoded = try calldata.decode(allocator);
    defer decoded.deinit(); // Free allocated memory

    // Use decoded parameters
    for (decoded.parameters) |param| {
        std.debug.print("Param: {}\n", .{param});
    }
}
```

## Signature Resolution

### Known Signatures

```typescript theme={null}
const KNOWN_SIGNATURES = {
  "0xa9059cbb": "transfer(address,uint256)",
  "0x095ea7b3": "approve(address,uint256)",
  "0x70a08231": "balanceOf(address)",
};

function resolveSignature(calldata: CallData): string | null {
  const selector = CallData.getSelector(calldata);
  const selectorHex = Hex.fromBytes(selector);
  return KNOWN_SIGNATURES[selectorHex] ?? null;
}
```

### 4byte.directory API

```typescript theme={null}
async function lookupSelector(selector: [4]u8): Promise<string[]> {
  const selectorHex = Hex.fromBytes(selector);
  const response = await fetch(
    `https://www.4byte.directory/api/v1/signatures/?hex_signature=${selectorHex}`
  );
  const data = await response.json();
  return data.results.map(r => r.text_signature);
}
```

## See Also

* [Fundamentals](/primitives/calldata/fundamentals) - How calldata works
* [Encoding](/primitives/calldata/encoding) - ABI encoding details
* [Abi](/primitives/abi) - ABI encoding and decoding
* [Usage Patterns](/primitives/calldata/usage-patterns) - Common patterns
