Skip to content

Commit

Permalink
Fix trimmed zeros in transaction encoding
Browse files Browse the repository at this point in the history
Closes #91
  • Loading branch information
alisinabh committed Mar 5, 2024
1 parent 7220f20 commit 7dcea0d
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 38 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Bug fixes

- Fix `to` address trimmed zeros in transaction encoder with unified hex encoding for transaction

## v0.3.0 (2024-02-05)

### Breaking Changes
Expand Down
6 changes: 3 additions & 3 deletions lib/ethers/signer/local.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ defmodule Ethers.Signer.Local do
signed =
%Ethers.Transaction{
tx
| signature_r: r,
signature_s: s,
signature_y_parity_or_v: y_parity_or_v
| signature_r: Utils.hex_encode(r),
signature_s: Utils.hex_encode(s),
signature_y_parity_or_v: Utils.integer_to_hex(y_parity_or_v)
}
|> Transaction.encode()
|> Utils.hex_encode()
Expand Down
59 changes: 24 additions & 35 deletions lib/ethers/transaction.ex
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ defmodule Ethers.Transaction do
transaction
|> to_rlp_list()
|> maybe_append_signature(transaction)
|> convert_to_binary()
|> ExRLP.encode()
|> prepend_type_envelope(type)
end
Expand Down Expand Up @@ -184,11 +183,12 @@ defmodule Ethers.Transaction do
case tx do
%{signature_r: r, signature_s: s, signature_y_parity_or_v: y_parity}
when has_value(r) and has_value(s) and has_value(y_parity) ->
tx_list ++ [y_parity, trim_leading(r), trim_leading(s)]
tx_list ++
[Utils.hex_to_integer!(y_parity), Utils.hex_to_integer!(r), Utils.hex_to_integer!(s)]

%{type: :legacy, chain_id: chain_id} when not is_nil(chain_id) ->
# EIP-155 encoding for signature mitigation intra-chain replay attack
tx_list ++ [chain_id, 0, 0]
tx_list ++ [Utils.hex_to_integer!(chain_id), 0, 0]

_ ->
tx_list
Expand All @@ -197,26 +197,26 @@ defmodule Ethers.Transaction do

defp to_rlp_list(%{type: :eip1559} = tx) do
[
tx.chain_id,
tx.nonce,
tx.max_priority_fee_per_gas,
tx.max_fee_per_gas,
tx.gas,
tx.to,
tx.value,
tx.data,
tx.access_list || []
Utils.hex_to_integer!(tx.chain_id),
Utils.hex_to_integer!(tx.nonce),
Utils.hex_to_integer!(tx.max_priority_fee_per_gas),
Utils.hex_to_integer!(tx.max_fee_per_gas),
Utils.hex_to_integer!(tx.gas),
hex_decode(tx.to),
Utils.hex_to_integer!(tx.value),
hex_decode(tx.data),
hex_decode(tx.access_list || [])
]
end

defp to_rlp_list(%{type: :legacy} = tx) do
[
tx.nonce,
tx.gas_price,
tx.gas,
tx.to,
tx.value,
tx.data
Utils.hex_to_integer!(tx.nonce),
Utils.hex_to_integer!(tx.gas_price),
Utils.hex_to_integer!(tx.gas),
hex_decode(tx.to),
Utils.hex_to_integer!(tx.value),
hex_decode(tx.data)
]
end

Expand Down Expand Up @@ -257,22 +257,14 @@ defmodule Ethers.Transaction do

defp do_post_process(_key, {:error, reason}), do: {:error, reason}

defp convert_to_binary(list) do
Enum.map(list, fn
"0x" <> _ = bin ->
bin
|> Utils.hex_decode!()
|> trim_leading()
defp hex_decode(nil), do: nil

l when is_list(l) ->
convert_to_binary(l)

nil ->
""
defp hex_decode("0x" <> _ = bin) do
Utils.hex_decode!(bin)
end

item ->
item
end)
defp hex_decode(list) when is_list(list) do
Enum.map(list, &hex_decode/1)
end

def calculate_y_parity_or_v(tx, recovery_id) when has_value(recovery_id) do
Expand All @@ -292,9 +284,6 @@ defmodule Ethers.Transaction do
end
end

defp trim_leading(<<0, rest::binary>>), do: trim_leading(rest)
defp trim_leading(<<bin::binary>>), do: bin

defp decode_tx_type(type) do
case type do
"0x3" -> {:ok, :eip4844}
Expand Down
21 changes: 21 additions & 0 deletions test/ethers/transaction_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,25 @@ defmodule Ethers.TransactionTest do
Transaction.decode_values(%{@transaction_fixture | signature_y_parity_or_v: ""})
end
end

describe "encode/1" do
test "encodes transaction with address having leading zeros" do
transaction = %Ethers.Transaction{
type: :eip1559,
chain_id: "0x00539",
from: "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1",
to: "0x00008FDEE72ac11b5c542428B35EEF5769C409f0",
nonce: "0x1",
gas: "0x1234",
value: "0x0",
data: "0x0006fdde03",
gas_price: "0x10e7467522",
max_fee_per_gas: "0x1448BAF2F5",
max_priority_fee_per_gas: "0x0"
}

assert "0x02eb8205390180851448baf2f58212349400008fdee72ac11b5c542428b35eef5769c409f080850006fdde03c0" ==
Transaction.encode(transaction) |> Ethers.Utils.hex_encode()
end
end
end

0 comments on commit 7dcea0d

Please sign in to comment.