Search documentation of Cartouche

# Cartouche.Transaction.V2 (Cartouche v0.1.3)

Copy Markdown View Source

Represents a V2 or EIP-1559 transaction.

## Summary

### Types

t()

### Functions

add_signature(transaction, arg)

Adds a signature to a transaction from a packed binary (`r <> s <> v`), deriving `signature_y_parity` from `v`.

add_signature(transaction, v, r, s)

Adds a signature to a transaction. This overwrites the `signature_y_parity`, `signature_r` and `signature_s` fields.

decode(arg)

Decode an RLP-encoded transaction. Note: the signature must have been signed (i.e. properly encoded), not simply encoded for signing.

encode(v2)

Build an RLP-encoded transaction. Note: if the transaction does not have a signature set (that is, `signature_y_parity`, `signature_r` or `signature_s` are `nil`), then we will encode a partial transaction (which can be used for signing).

get_signature(v2)

Recovers a signature from a transaction, if it's been signed. Otherwise returns an error.

new(nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, chain_id \\ nil)

Constructs a new V2 (EIP-1559) Ethereum transaction.

new(nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s, chain_id \\ nil)

Like `new/9` but also accepts explicit signature fields (`signature_y_parity`, `signature_r`, `signature_s`).

recover_signer(transaction)

Recovers the signer from a given transaction, if it's been signed.

## Types

# t()

    @type t() :: %Cartouche.Transaction.V2{
      access_list: [{<<_::160>>, [<<_::256>>]}],
      amount: integer(),
      chain_id: integer(),
      data: binary(),
      destination: <<_::160>>,
      gas_limit: integer(),
      max_fee_per_gas: integer(),
      max_priority_fee_per_gas: integer(),
      nonce: integer(),
      signature_r: <<_::256>>,
      signature_s: <<_::256>>,
      signature_y_parity: boolean()
    }

## Functions

# add_signature(transaction, arg)

    @spec add_signature(t(), <<_::512, _::_*8>>) :: t()

Adds a signature to a transaction from a packed binary (`r <> s <> v`), deriving `signature_y_parity` from `v`.

# add_signature(transaction, v, r, s)

    @spec add_signature(t(), boolean(), <<_::256>>, <<_::256>>) :: t()

Adds a signature to a transaction. This overwrites the `signature_y_parity`, `signature_r` and `signature_s` fields.

## Examples

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [<<2::160>>, <<3::160>>], 1, 0x01, 0x02, :goerli)
    ...> |> Cartouche.Transaction.V2.add_signature(true, <<1::256>>, <<2::256>>)
    %Cartouche.Transaction.V2{
      chain_id: 5,
      nonce: 1,
      max_priority_fee_per_gas: 1000000000,
      max_fee_per_gas: 100000000000,
      gas_limit: 100000,
      destination: <<1::160>>,
      amount: 2,
      data: <<1, 2, 3>>,
      access_list: [<<2::160>>, <<3::160>>],
      signature_y_parity: true,
      signature_r: <<0x01::256>>,
      signature_s: <<0x02::256>>
    }

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [<<2::160>>, <<3::160>>], 1, 0x01, 0x02, :goerli)
    ...> |> Cartouche.Transaction.V2.add_signature(<<1::256, 2::256, 1::8>>)
    %Cartouche.Transaction.V2{
      chain_id: 5,
      nonce: 1,
      max_priority_fee_per_gas: 1000000000,
      max_fee_per_gas: 100000000000,
      gas_limit: 100000,
      destination: <<1::160>>,
      amount: 2,
      data: <<1, 2, 3>>,
      access_list: [<<2::160>>, <<3::160>>],
      signature_y_parity: true,
      signature_r: <<0x01::256>>,
      signature_s: <<0x02::256>>
    }

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [<<2::160>>, <<3::160>>], 1, 0x01, 0x02, :goerli)
    ...> |> Cartouche.Transaction.V2.add_signature(<<1::256, 2::256, 27::8>>)
    %Cartouche.Transaction.V2{
      chain_id: 5,
      nonce: 1,
      max_priority_fee_per_gas: 1000000000,
      max_fee_per_gas: 100000000000,
      gas_limit: 100000,
      destination: <<1::160>>,
      amount: 2,
      data: <<1, 2, 3>>,
      access_list: [<<2::160>>, <<3::160>>],
      signature_y_parity: false,
      signature_r: <<0x01::256>>,
      signature_s: <<0x02::256>>
    }

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [<<2::160>>, <<3::160>>], 1, 0x01, 0x02, :goerli)
    ...> |> Cartouche.Transaction.V2.add_signature(<<1::256, 2::256, 38::8>>)
    %Cartouche.Transaction.V2{
      chain_id: 5,
      nonce: 1,
      max_priority_fee_per_gas: 1000000000,
      max_fee_per_gas: 100000000000,
      gas_limit: 100000,
      destination: <<1::160>>,
      amount: 2,
      data: <<1, 2, 3>>,
      access_list: [<<2::160>>, <<3::160>>],
      signature_y_parity: true,
      signature_r: <<0x01::256>>,
      signature_s: <<0x02::256>>
    }

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [<<2::160>>, <<3::160>>], 1, 0x01, 0x02, :goerli)
    ...> |> Cartouche.Transaction.V2.add_signature(<<1::256, 2::256, 3838::16>>)
    %Cartouche.Transaction.V2{
      chain_id: 5,
      nonce: 1,
      max_priority_fee_per_gas: 1000000000,
      max_fee_per_gas: 100000000000,
      gas_limit: 100000,
      destination: <<1::160>>,
      amount: 2,
      data: <<1, 2, 3>>,
      access_list: [<<2::160>>, <<3::160>>],
      signature_y_parity: true,
      signature_r: <<0x01::256>>,
      signature_s: <<0x02::256>>
    }

# decode(arg)

    @spec decode(binary()) :: {:ok, t()} | {:error, String.t()}

Decode an RLP-encoded transaction. Note: the signature must have been signed (i.e. properly encoded), not simply encoded for signing.

## Examples

    iex> use Cartouche.Hex
    iex> Cartouche.Transaction.V2.decode(~h[0x02EF0501843B9ACA0085174876E800830186A09400000000000000000000000000000000000000010283010203C0010102])
    {:ok, %Cartouche.Transaction.V2{
      chain_id: 5,
      nonce: 1,
      max_priority_fee_per_gas: 1000000000,
      max_fee_per_gas: 100000000000,
      gas_limit: 100000,
      destination: <<1::160>>,
      amount: 2,
      data: <<1, 2, 3>>,
      access_list: [],
      signature_y_parity: true,
      signature_r: <<0x01::256>>,
      signature_s: <<0x02::256>>
    }}

    iex> use Cartouche.Hex
    iex> Cartouche.Transaction.V2.decode(~h[0x02F87F0501843B9ACA0085174876E800830186A09400000000000000000000000000000000000000010283010203F84FF7940000000000000000000000000000000000000002E1A00000000000000000000000000000000000000000000000000000000000000016D6940000000000000000000000000000000000000003C0010102])
    {:ok, %Cartouche.Transaction.V2{
      chain_id: 5,
      nonce: 1,
      max_priority_fee_per_gas: 1000000000,
      max_fee_per_gas: 100000000000,
      gas_limit: 100000,
      destination: <<1::160>>,
      amount: 2,
      data: <<1, 2, 3>>,
      access_list: [{<<2::160>>, [<<22::256>>]}, {<<3::160>>, []}],
      signature_y_parity: true,
      signature_r: <<0x01::256>>,
      signature_s: <<0x02::256>>
    }}

    iex> use Cartouche.Hex
    iex> Cartouche.Transaction.V2.decode(~h[ ])
    {:ok, %Cartouche.Transaction.V2{
      chain_id: 8453,
      nonce: 1,
      max_priority_fee_per_gas: 1000000000,
      max_fee_per_gas: 1008963825,
      gas_limit: 300000,
      destination: ~h[0x00aea4b2242abc8bb4bb78d537a67a245a7bec64],
      amount: 0,
      data: ~h[ ],
      access_list: [],
      signature_y_parity: false,
      signature_r: ~h[0x019c8102cb582c309b0d2ababb6aeb683a8fbc7e2044665f84669f0a73865b9a],
      signature_s: ~h[0x3732eb6644fc11e850a0fed8ebe403b4c2f5d1f1aec961eaccf1f7baa55615a6]
    }}

# encode(v2)

    @spec encode(
      t()
      | %Cartouche.Transaction.V2{
          access_list: list() | nil,
          amount: integer() | nil,
          chain_id: integer() | nil,
          data: binary() | nil,
          destination: <<_::160>> | nil,
          gas_limit: integer() | nil,
          max_fee_per_gas: integer() | nil,
          max_priority_fee_per_gas: integer() | nil,
          nonce: integer() | nil,
          signature_r: nil,
          signature_s: nil,
          signature_y_parity: nil
        }
    ) :: binary()

Build an RLP-encoded transaction. Note: if the transaction does not have a signature set (that is, `signature_y_parity`, `signature_r` or `signature_s` are `nil`), then we will encode a partial transaction (which can be used for signing).

## Examples

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [], :goerli)
    ...> |> Cartouche.Transaction.V2.encode()
    ...> |> Cartouche.Hex.encode_big_hex()
    "0x02EC0501843B9ACA0085174876E800830186A09400000000000000000000000000000000000000010283010203C0"

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [], true, <<0x01::256>>, <<0x02::256>>, :goerli)
    ...> |> Cartouche.Transaction.V2.encode()
    ...> |> Cartouche.Hex.encode_big_hex()
    "0x02EF0501843B9ACA0085174876E800830186A09400000000000000000000000000000000000000010283010203C0010102"

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [{<<2::160>>, [<<22::256>>]}, {<<3::160>>, []}], true, <<0x01::256>>, <<0x00, 0x02::248>>, :goerli)
    ...> |> Cartouche.Transaction.V2.encode()
    ...> |> Cartouche.Hex.encode_big_hex()
    "0x02F87F0501843B9ACA0085174876E800830186A09400000000000000000000000000000000000000010283010203F84FF7940000000000000000000000000000000000000002E1A00000000000000000000000000000000000000000000000000000000000000016D6940000000000000000000000000000000000000003C0010102"

    iex> use Cartouche.Hex
    iex> %Cartouche.Transaction.V2{
    ...>   chain_id: 8453,
    ...>   nonce: 1,
    ...>   max_priority_fee_per_gas: 1000000000,
    ...>   max_fee_per_gas: 1008963825,
    ...>   gas_limit: 300000,
    ...>   destination: ~h[0x00aea4b2242abc8bb4bb78d537a67a245a7bec64],
    ...>   amount: 0,
    ...>   data: ~h[ ],
    ...>   access_list: [],
    ...>   signature_y_parity: false,
    ...>   signature_r: ~h[0x019c8102cb582c309b0d2ababb6aeb683a8fbc7e2044665f84669f0a73865b9a],
    ...>   signature_s: ~h[0x3732eb6644fc11e850a0fed8ebe403b4c2f5d1f1aec961eaccf1f7baa55615a6]
    ...> }
    ...> |> Cartouche.Transaction.V2.encode()
    ...> |> Cartouche.Hex.encode_big_hex()
    " "

# get_signature(v2)

    @spec get_signature(t()) :: {:ok, binary()} | {:error, String.t()}

Recovers a signature from a transaction, if it's been signed. Otherwise returns an error.

## Examples

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [<<2::160>>, <<3::160>>], true, <<0x01::256>>, <<0x02::256>>, :goerli)
    ...> |> Cartouche.Transaction.V2.get_signature()
    {:ok, <<1::256, 2::256, 1::8>>}

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [<<2::160>>, <<3::160>>], :goerli)
    ...> |> Cartouche.Transaction.V2.get_signature()
    {:error, "transaction missing signature"}

# new(nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, chain_id \\ nil)

    @spec new(
      integer(),
      integer() | {integer(), :wei | :gwei} | nil,
      integer() | {integer(), :wei | :gwei} | nil,
      integer(),
      <<_::160>>,
      integer() | {integer(), :wei | :gwei},
      binary(),
      list(),
      atom() | integer() | nil
    ) :: t()

Constructs a new V2 (EIP-1559) Ethereum transaction.

## Examples

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [{<<2::160>>, [<<22::256>>]}, {<<3::160>>, []}], :goerli)
    %Cartouche.Transaction.V2{
      chain_id: 5,
      nonce: 1,
      max_priority_fee_per_gas: 1000000000,
      max_fee_per_gas: 100000000000,
      gas_limit: 100000,
      destination: <<1::160>>,
      amount: 2,
      data: <<1, 2, 3>>,
      access_list: [{<<2::160>>, [<<22::256>>]}, {<<3::160>>, []}],
      signature_y_parity: nil,
      signature_r: nil,
      signature_s: nil
    }

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [{<<2::160>>, [<<22::256>>]}, {<<3::160>>, []}], true, <<0x01::256>>, <<0x02::256>>, :goerli)
    %Cartouche.Transaction.V2{
      chain_id: 5,
      nonce: 1,
      max_priority_fee_per_gas: 1000000000,
      max_fee_per_gas: 100000000000,
      gas_limit: 100000,
      destination: <<1::160>>,
      amount: 2,
      data: <<1, 2, 3>>,
      access_list: [{<<2::160>>, [<<22::256>>]}, {<<3::160>>, []}],
      signature_y_parity: true,
      signature_r: <<0x01::256>>,
      signature_s: <<0x02::256>>
    }

# new(nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s, chain_id \\ nil)

    @spec new(
      integer(),
      integer() | {integer(), :wei | :gwei} | nil,
      integer() | {integer(), :wei | :gwei} | nil,
      integer(),
      <<_::160>>,
      integer() | {integer(), :wei | :gwei},
      binary(),
      list(),
      boolean() | nil,
      <<_::256>> | nil,
      <<_::256>> | nil,
      atom() | integer() | nil
    ) :: t()

Like `new/9` but also accepts explicit signature fields (`signature_y_parity`, `signature_r`, `signature_s`).

# recover_signer(transaction)

    @spec recover_signer(t()) :: {:ok, <<_::160>>} | {:error, String.t()}

Recovers the signer from a given transaction, if it's been signed.

## Examples

    iex> {:ok, address} =
    ...>   Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [<<2::160>>, <<3::160>>], true, <<0x01::256>>, <<0x02::256>>, :goerli)
    ...>   |> Cartouche.Transaction.V2.recover_signer()
    ...> Cartouche.Hex.to_address(address)
    "0xC002Ca628F93e1550b5f30Ed10902A9e7783364B"

    iex> Cartouche.Transaction.V2.new(1, {1, :gwei}, {100, :gwei}, 100_000, <<1::160>>, {2, :wei}, <<1, 2, 3>>, [<<2::160>>, <<3::160>>], :goerli)
    ...> |> Cartouche.Transaction.V2.recover_signer()
    {:error, "transaction missing signature"}