> ## 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.

# Function.decodeParams

> Decode function parameters from calldata

<Tabs />

## Usage Examples

### Basic Decoding

```typescript theme={null}
import { Function } from 'tevm'

const balanceOfFn = new Function({
  type: "function",
  name: "balanceOf",
  inputs: [{ type: "address", name: "owner" }]
})

const calldata = "0x70a08231000000000000000000000000742d35cc6634c0532925a3b844bc9e7595f51e3e"

const [owner] = balanceOfFn.decodeParams(calldata)
console.log(owner)  // "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e"
```

### Multiple Parameters

```typescript theme={null}
import { Function } from 'tevm'

const transferFromFn = new Function({
  type: "function",
  name: "transferFrom",
  inputs: [
    { type: "address", name: "from" },
    { type: "address", name: "to" },
    { type: "uint256", name: "amount" }
  ]
})

const calldata = "0x23b872dd..."

const [from, to, amount] = transferFromFn.decodeParams(calldata)
console.log({ from, to, amount })
// {
//   from: "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e",
//   to: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
//   amount: 1000n
// }
```

### Destructuring with Names

```typescript theme={null}
import { Function } from 'tevm'

const transferFn = new Function({
  type: "function",
  name: "transfer",
  inputs: [
    { type: "address", name: "to" },
    { type: "uint256", name: "amount" }
  ]
})

const calldata = "0xa9059cbb..."

// Destructure directly
const [to, amount] = transferFn.decodeParams(calldata)

// Or use named destructuring
const params = transferFn.decodeParams(calldata)
const to = params[0]
const amount = params[1]
```

### Dynamic Types (Strings)

```typescript theme={null}
import { Function } from 'tevm'

const setNameFn = new Function({
  type: "function",
  name: "setName",
  inputs: [{ type: "string", name: "name" }]
})

const calldata = "0x..."  // Encoded with offset + length + data

const [name] = setNameFn.decodeParams(calldata)
console.log(name)  // "Alice"
```

### Arrays

```typescript theme={null}
import { Function } from 'tevm'

const batchTransferFn = new Function({
  type: "function",
  name: "batchTransfer",
  inputs: [
    { type: "address[]", name: "recipients" },
    { type: "uint256[]", name: "amounts" }
  ]
})

const calldata = "0x..."

const [recipients, amounts] = batchTransferFn.decodeParams(calldata)
console.log(recipients)  // ["0x...", "0x..."]
console.log(amounts)     // [1000n, 2000n]
```

### Tuples (Structs)

```typescript theme={null}
import { Function } from 'tevm'

const createOrderFn = new Function({
  type: "function",
  name: "createOrder",
  inputs: [
    {
      type: "tuple",
      name: "order",
      components: [
        { type: "address", name: "maker" },
        { type: "uint256", name: "amount" },
        { type: "uint256", name: "price" }
      ]
    }
  ]
})

const calldata = "0x..."

const [order] = createOrderFn.decodeParams(calldata)
console.log(order)
// {
//   maker: "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e",
//   amount: 1000n,
//   price: 5n
// }
```

### Decoding Transaction Calldata

```typescript theme={null}
import { Function } from 'tevm'

const transferFn = new Function({
  type: "function",
  name: "transfer",
  inputs: [
    { type: "address", name: "to" },
    { type: "uint256", name: "amount" }
  ]
})

// Get transaction from blockchain
const tx = await provider.getTransaction(txHash)

// Check if it's a transfer call
const selector = tx.data.slice(0, 10)
if (selector === transferFn.getSelector()) {
  const [to, amount] = transferFn.decodeParams(tx.data)
  console.log(`Transfer ${amount} to ${to}`)
}
```

### With or Without Selector

The decoder automatically handles both formats:

```typescript theme={null}
import { Function } from 'tevm'

const transferFn = new Function({
  type: "function",
  name: "transfer",
  inputs: [
    { type: "address", name: "to" },
    { type: "uint256", name: "amount" }
  ]
})

// With selector (full calldata)
const withSelector = "0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b844bc9e7595f51e3e00000000000000000000000000000000000000000000000000000000000003e8"
const params1 = transferFn.decodeParams(withSelector)

// Without selector (parameters only)
const withoutSelector = "0x000000000000000000000000742d35cc6634c0532925a3b844bc9e7595f51e3e00000000000000000000000000000000000000000000000000000000000003e8"
const params2 = transferFn.decodeParams(withoutSelector)

// Both return same result
console.log(params1)  // ["0x742d...", 1000n]
console.log(params2)  // ["0x742d...", 1000n]
```

## Type-Safe Decoding

TypeScript infers return types from function definition:

```typescript theme={null}
import { Function } from 'tevm'

const balanceOfFn = new Function({
  type: "function",
  name: "balanceOf",
  inputs: [{ type: "address", name: "owner" }]
} as const)

const params = balanceOfFn.decodeParams(calldata)
//    ^-- Type: [string] (address inferred)

const [owner] = params
//    ^-- Type: string
```

## Error Handling

```typescript theme={null}
import { Function } from 'tevm'
import { AbiDecodingError } from 'tevm'

const transferFn = new Function({
  type: "function",
  name: "transfer",
  inputs: [
    { type: "address", name: "to" },
    { type: "uint256", name: "amount" }
  ]
})

try {
  // Invalid calldata (too short)
  transferFn.decodeParams("0xa9059cbb")
} catch (error) {
  if (error instanceof AbiDecodingError) {
    console.error("Failed to decode:", error.message)
  }
}

try {
  // Wrong selector
  transferFn.decodeParams("0xdeadbeef00000...")
} catch (error) {
  if (error instanceof AbiDecodingError) {
    console.error("Selector mismatch or invalid data")
  }
}
```

## Parsing Contract Logs

Decode function calls from event logs or traces:

```typescript theme={null}
import { Function } from 'tevm'

const transferFn = new Function({
  type: "function",
  name: "transfer",
  inputs: [
    { type: "address", name: "to" },
    { type: "uint256", name: "amount" }
  ]
})

// Parse trace data
const traces = await provider.getTrace(txHash)

for (const trace of traces) {
  if (trace.type === 'call') {
    const selector = trace.input.slice(0, 10)
    if (selector === transferFn.getSelector()) {
      const [to, amount] = transferFn.decodeParams(trace.input)
      console.log(`Transfer: ${amount} to ${to}`)
    }
  }
}
```

## See Also

* [encodeParams](/primitives/abi/function/encode-params) - Encode function parameters
* [decodeResult](/primitives/abi/function/decode-result) - Decode function return values
* [getSelector](/primitives/abi/function/get-selector) - Get function selector
* [Decoding](/primitives/abi/decoding) - Low-level decoding details
