Skip to main content

    Calldata Structure

    Encoded calldata format:
    [4 bytes: function selector][32-byte aligned parameter encoding]
    
    Example for transfer(address,uint256):
    0xa9059cbb  ← Selector (4 bytes)
    000000000000000000000000742d35cc6634c0532925a3b844bc9e7595f51e3e  ← address (32 bytes)
    00000000000000000000000000000000000000000000000000000000000003e8  ← uint256 (32 bytes)
    

    Usage Examples

    Basic Function Call

    import { Function } from 'tevm'
    
    const balanceOfFn = new Function({
      type: "function",
      name: "balanceOf",
      inputs: [{ type: "address", name: "owner" }]
    })
    
    const calldata = balanceOfFn.encodeParams([
      "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e"
    ])
    
    // Use in transaction
    const tx = {
      to: tokenAddress,
      data: calldata,
      value: 0n
    }
    

    Multiple Parameters

    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 = transferFromFn.encodeParams([
      "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e",
      "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
      1000n
    ])
    

    Dynamic Types (String)

    import { Function } from 'tevm'
    
    const setNameFn = new Function({
      type: "function",
      name: "setName",
      inputs: [{ type: "string", name: "name" }]
    })
    
    const calldata = setNameFn.encodeParams(["Alice"])
    // Encodes: selector + offset + length + padded string data
    

    Arrays

    import { Function } from 'tevm'
    
    const batchTransferFn = new Function({
      type: "function",
      name: "batchTransfer",
      inputs: [
        { type: "address[]", name: "recipients" },
        { type: "uint256[]", name: "amounts" }
      ]
    })
    
    const calldata = batchTransferFn.encodeParams([
      [
        "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e",
        "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4"
      ],
      [1000n, 2000n]
    ])
    

    Tuples (Structs)

    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 = createOrderFn.encodeParams([
      {
        maker: "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e",
        amount: 1000n,
        price: 5n
      }
    ])
    

    No Parameters

    import { Function } from 'tevm'
    
    const totalSupplyFn = new Function({
      type: "function",
      name: "totalSupply",
      inputs: []
    })
    
    const calldata = totalSupplyFn.encodeParams([])
    // Returns only selector: "0x18160ddd"
    

    Type-Safe Encoding

    TypeScript infers parameter types from function definition:
    import { Function } from 'tevm'
    
    const transferFn = new Function({
      type: "function",
      name: "transfer",
      inputs: [
        { type: "address", name: "to" },
        { type: "uint256", name: "amount" }
      ]
    } as const)
    
    // TypeScript knows args must be [address, bigint]
    const calldata = transferFn.encodeParams([
      "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e",
      1000n
    ])
    
    // Error: wrong type
    // transferFn.encodeParams(["0x...", "1000"])  // Type error
    

    Address Formats

    Multiple address input formats accepted:
    import { Function } from 'tevm'
    
    const setOwnerFn = new Function({
      type: "function",
      name: "setOwner",
      inputs: [{ type: "address", name: "owner" }]
    })
    
    // All valid
    setOwnerFn.encodeParams(["0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e"])
    setOwnerFn.encodeParams(["0x742d35cc6634c0532925a3b844bc9e7595f51e3e"])  // lowercase
    setOwnerFn.encodeParams([new Uint8Array(20)])  // raw bytes
    

    BigInt for Integers

    Use bigint for all integer types:
    import { Function } from 'tevm'
    
    const transferFn = new Function({
      type: "function",
      name: "transfer",
      inputs: [
        { type: "address", name: "to" },
        { type: "uint256", name: "amount" }
      ]
    })
    
    // Correct: use bigint
    transferFn.encodeParams(["0x...", 1000n])
    
    // Also works: number converts to bigint
    transferFn.encodeParams(["0x...", 1000])
    
    // Large numbers require bigint
    transferFn.encodeParams(["0x...", 1000000000000000000n])
    

    Error Handling

    import { Function } from 'tevm'
    import { AbiEncodingError, AbiParameterMismatchError } from 'tevm'
    
    const transferFn = new Function({
      type: "function",
      name: "transfer",
      inputs: [
        { type: "address", name: "to" },
        { type: "uint256", name: "amount" }
      ]
    })
    
    try {
      // Wrong parameter count
      transferFn.encodeParams(["0x..."])
    } catch (error) {
      if (error instanceof AbiParameterMismatchError) {
        console.error("Wrong number of parameters")
      }
    }
    
    try {
      // Invalid value
      transferFn.encodeParams(["invalid", 1000n])
    } catch (error) {
      if (error instanceof AbiEncodingError) {
        console.error("Invalid parameter value:", error.message)
      }
    }
    

    Advanced: Encoding Without Selector

    To encode only parameters without selector, use parameter encoding directly:
    import { Function } from 'tevm'
    import { encodeParameters } from 'tevm/Abi'
    
    const transferFn = new Function({
      type: "function",
      name: "transfer",
      inputs: [
        { type: "address", name: "to" },
        { type: "uint256", name: "amount" }
      ]
    })
    
    // With selector (encodeParams)
    const calldata = transferFn.encodeParams(["0x...", 1000n])
    // "0xa9059cbb00000..."
    
    // Without selector (encodeParameters)
    const paramsOnly = encodeParameters(transferFn.inputs, ["0x...", 1000n])
    // "0x00000..."
    

    See Also