# `X402.ERC6492`
[🔗](https://github.com/cardotrejos/x402/blob/v0.9.0/lib/x402/erc6492.ex#L1)

ERC-6492 signature wrapper parsing and building.

[ERC-6492](https://eips.ethereum.org/EIPS/eip-6492) lets a not-yet-deployed
("counterfactual") smart wallet produce a verifiable signature by wrapping
the wallet's inner signature together with the factory call that would
deploy it:

    abi.encode((factory, factoryCalldata, innerSignature)) || magic_suffix

where the magic suffix is the 32-byte value `0x6492...6492`.

This module is pure binary handling — no cryptography and no RPC. Whether a
wrapped signature is actually *valid* is decided by `X402.Verify.EVM`:
a counterfactual signature is never accepted until an on-chain simulation
proves the deployed wallet would accept it (fail-closed, mirroring the
reference Go implementation).

# `parsed`

```elixir
@type parsed() :: %{
  wrapped?: boolean(),
  factory: String.t() | nil,
  factory_calldata: binary() | nil,
  inner_signature: binary()
}
```

A parsed signature.

`wrapped?` is `true` when the ERC-6492 magic suffix was present. `factory`
and `factory_calldata` are `nil` unless the wrapper carried deployment
information (a non-zero factory address with non-empty calldata).
`inner_signature` is the raw signature bytes — the unwrapped inner
signature for wrapped input, the input itself otherwise.

# `magic_suffix`
*since 0.6.0* 

```elixir
@spec magic_suffix() :: &lt;&lt;_::256&gt;&gt;
```

Returns the 32-byte ERC-6492 magic suffix.

## Examples

    iex> byte_size(X402.ERC6492.magic_suffix())
    32

# `parse`
*since 0.6.0* 

```elixir
@spec parse(binary()) ::
  {:ok, parsed()} | {:error, :invalid_signature | :invalid_erc6492_wrapper}
```

Parses a signature, unwrapping the ERC-6492 envelope when present.

Accepts raw bytes or a `0x`-prefixed hex string. Signatures without the
magic suffix parse as `wrapped?: false` with the bytes passed through as
`inner_signature`. A wrapper whose factory is the zero address or whose
calldata is empty parses with `factory: nil` (no deployment information),
matching the reference implementations.

Returns `{:error, :invalid_erc6492_wrapper}` when the magic suffix is
present but the ABI-encoded prefix is malformed, and
`{:error, :invalid_signature}` for non-hex string input.

## Examples

    iex> {:ok, parsed} = X402.ERC6492.parse(:binary.copy(<<0x01>>, 65))
    iex> {parsed.wrapped?, parsed.factory, byte_size(parsed.inner_signature)}
    {false, nil, 65}

    iex> inner = :binary.copy(<<0x07>>, 65)
    iex> {:ok, wrapped} =
    ...>   X402.ERC6492.wrap("0x2222222222222222222222222222222222222222", <<0xAB, 0xCD>>, inner)
    iex> {:ok, parsed} = X402.ERC6492.parse(wrapped)
    iex> {parsed.wrapped?, parsed.factory, parsed.factory_calldata, parsed.inner_signature}
    {true, "0x2222222222222222222222222222222222222222", <<0xAB, 0xCD>>, inner}

    iex> X402.ERC6492.parse("0xzz")
    {:error, :invalid_signature}

# `parse_bytes`
*since 0.9.0* 

```elixir
@spec parse_bytes(binary()) :: {:ok, parsed()} | {:error, :invalid_erc6492_wrapper}
```

Parses already-decoded signature bytes without interpreting a hex prefix.

Useful after bounded wire decoding, including a raw signature that
happens to start with the ASCII characters `0x`.

## Examples

    iex> {:ok, parsed} = X402.ERC6492.parse_bytes(<<"0x", 1, 2>>)
    iex> parsed.inner_signature
    <<"0x", 1, 2>>

# `wrap`
*since 0.6.0* 

```elixir
@spec wrap(String.t(), binary(), binary()) ::
  {:ok, binary()} | {:error, :invalid_address}
```

Builds an ERC-6492 wrapped signature from its parts.

`factory` is a `0x`-prefixed EVM address; `factory_calldata` and
`inner_signature` are raw bytes. Returns the raw wrapped bytes
(`abi.encode((address, bytes, bytes)) || magic_suffix`).

## Examples

    iex> {:ok, wrapped} =
    ...>   X402.ERC6492.wrap(
    ...>     "0x2222222222222222222222222222222222222222",
    ...>     <<0xAB>>,
    ...>     :binary.copy(<<0x01>>, 65)
    ...>   )
    iex> X402.ERC6492.wrapped?(wrapped)
    true

    iex> X402.ERC6492.wrap("0x123", <<>>, <<>>)
    {:error, :invalid_address}

# `wrapped?`
*since 0.6.0* 

```elixir
@spec wrapped?(binary()) :: boolean()
```

Returns `true` when the signature carries the ERC-6492 magic suffix.

Accepts raw bytes or a `0x`-prefixed hex string.

## Examples

    iex> X402.ERC6492.wrapped?(<<1, 2, 3>>)
    false

    iex> {:ok, wrapped} =
    ...>   X402.ERC6492.wrap(
    ...>     "0x2222222222222222222222222222222222222222",
    ...>     <<0xAB>>,
    ...>     :binary.copy(<<0x01>>, 65)
    ...>   )
    iex> X402.ERC6492.wrapped?(wrapped)
    true

---

*Consult [api-reference.md](api-reference.md) for complete listing*
