Skip to content

Commit ae08fca

Browse files
authored
Remove hexification of entries in TxData.to_map/2 (#184)
1 parent ae0b42d commit ae08fca

File tree

8 files changed

+137
-58
lines changed

8 files changed

+137
-58
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Enahncements
6+
7+
- Strict type checking for initializing transaction structs
8+
9+
### Bug Fixes
10+
11+
- Remove hexification of map entries in `Ethers.TxData.to_map/2`
12+
313
## v0.6.2 (2025-01-10)
414

515
### Enhancements

lib/ethers/transaction/eip1559.ex

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ defmodule Ethers.Transaction.Eip1559 do
66
See: https://eips.ethereum.org/EIPS/eip-1559
77
"""
88

9+
import Ethers.Transaction.Helpers
10+
911
alias Ethers.Types
1012
alias Ethers.Utils
1113

@@ -53,19 +55,29 @@ defmodule Ethers.Transaction.Eip1559 do
5355
@impl Ethers.Transaction
5456
def new(params) do
5557
to = params[:to]
56-
57-
{:ok,
58-
%__MODULE__{
59-
chain_id: params.chain_id,
60-
nonce: params.nonce,
61-
max_priority_fee_per_gas: params.max_priority_fee_per_gas,
62-
max_fee_per_gas: params.max_fee_per_gas,
63-
gas: params.gas,
64-
to: to && Utils.to_checksum_address(to),
65-
value: params[:value] || 0,
66-
input: params[:input] || params[:data] || "",
67-
access_list: params[:access_list] || []
68-
}}
58+
input = params[:input] || params[:data] || ""
59+
value = params[:value] || 0
60+
61+
with :ok <- validate_non_neg_integer(params.chain_id),
62+
:ok <- validate_non_neg_integer(params.nonce),
63+
:ok <- validate_non_neg_integer(params.max_priority_fee_per_gas),
64+
:ok <- validate_non_neg_integer(params.max_fee_per_gas),
65+
:ok <- validate_non_neg_integer(params.gas),
66+
:ok <- validate_non_neg_integer(value),
67+
:ok <- validate_binary(input) do
68+
{:ok,
69+
%__MODULE__{
70+
chain_id: params.chain_id,
71+
nonce: params.nonce,
72+
max_priority_fee_per_gas: params.max_priority_fee_per_gas,
73+
max_fee_per_gas: params.max_fee_per_gas,
74+
gas: params.gas,
75+
to: to && Utils.to_checksum_address(to),
76+
value: value,
77+
input: input,
78+
access_list: params[:access_list] || []
79+
}}
80+
end
6981
end
7082

7183
@impl Ethers.Transaction

lib/ethers/transaction/eip2930.ex

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ defmodule Ethers.Transaction.Eip2930 do
99
See: https://eips.ethereum.org/EIPS/eip-2930
1010
"""
1111

12+
import Ethers.Transaction.Helpers
13+
1214
alias Ethers.Types
1315
alias Ethers.Utils
1416

@@ -53,18 +55,25 @@ defmodule Ethers.Transaction.Eip2930 do
5355
@impl Ethers.Transaction
5456
def new(params) do
5557
to = params[:to]
56-
57-
{:ok,
58-
%__MODULE__{
59-
chain_id: params.chain_id,
60-
nonce: params.nonce,
61-
gas_price: params.gas_price,
62-
gas: params.gas,
63-
to: to && Utils.to_checksum_address(to),
64-
value: params[:value] || 0,
65-
input: params[:input] || params[:data] || "",
66-
access_list: params[:access_list] || []
67-
}}
58+
input = params[:input] || params[:data] || ""
59+
value = params[:value] || 0
60+
61+
with :ok <- validate_common_fields(params),
62+
:ok <- validate_non_neg_integer(params.gas_price),
63+
:ok <- validate_non_neg_integer(value),
64+
:ok <- validate_binary(input) do
65+
{:ok,
66+
%__MODULE__{
67+
chain_id: params.chain_id,
68+
nonce: params.nonce,
69+
gas_price: params.gas_price,
70+
gas: params.gas,
71+
to: to && Utils.to_checksum_address(to),
72+
value: value,
73+
input: input,
74+
access_list: params[:access_list] || []
75+
}}
76+
end
6877
end
6978

7079
@impl Ethers.Transaction

lib/ethers/transaction/eip4844.ex

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ defmodule Ethers.Transaction.Eip4844 do
77
See: https://eips.ethereum.org/EIPS/eip-4844
88
"""
99

10+
import Ethers.Transaction.Helpers
11+
1012
alias Ethers.Types
1113
alias Ethers.Utils
1214

@@ -67,21 +69,30 @@ defmodule Ethers.Transaction.Eip4844 do
6769
@impl Ethers.Transaction
6870
def new(params) do
6971
to = params[:to]
70-
71-
{:ok,
72-
%__MODULE__{
73-
chain_id: params.chain_id,
74-
nonce: params.nonce,
75-
max_priority_fee_per_gas: params.max_priority_fee_per_gas,
76-
max_fee_per_gas: params.max_fee_per_gas,
77-
gas: params.gas,
78-
to: to && Utils.to_checksum_address(to),
79-
value: params[:value] || 0,
80-
input: params[:input] || params[:data] || "",
81-
access_list: params[:access_list] || [],
82-
max_fee_per_blob_gas: params.max_fee_per_blob_gas,
83-
blob_versioned_hashes: params[:blob_versioned_hashes] || []
84-
}}
72+
input = params[:input] || params[:data] || ""
73+
value = params[:value] || 0
74+
75+
with :ok <- validate_common_fields(params),
76+
:ok <- validate_non_neg_integer(params.max_priority_fee_per_gas),
77+
:ok <- validate_non_neg_integer(params.max_fee_per_gas),
78+
:ok <- validate_non_neg_integer(params.max_fee_per_blob_gas),
79+
:ok <- validate_non_neg_integer(value),
80+
:ok <- validate_binary(input) do
81+
{:ok,
82+
%__MODULE__{
83+
chain_id: params.chain_id,
84+
nonce: params.nonce,
85+
max_priority_fee_per_gas: params.max_priority_fee_per_gas,
86+
max_fee_per_gas: params.max_fee_per_gas,
87+
gas: params.gas,
88+
to: to && Utils.to_checksum_address(to),
89+
value: value,
90+
input: input,
91+
access_list: params[:access_list] || [],
92+
max_fee_per_blob_gas: params.max_fee_per_blob_gas,
93+
blob_versioned_hashes: params[:blob_versioned_hashes] || []
94+
}}
95+
end
8596
end
8697

8798
@impl Ethers.Transaction

lib/ethers/transaction/helpers.ex

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
defmodule Ethers.Transaction.Helpers do
2+
@moduledoc false
3+
4+
@spec validate_non_neg_integer(term()) :: :ok | {:error, :expected_non_neg_integer_value}
5+
def validate_non_neg_integer(value) when is_integer(value) and value >= 0, do: :ok
6+
def validate_non_neg_integer(_), do: {:error, :expected_non_neg_integer_value}
7+
8+
@spec validate_binary(term()) :: :ok | {:error, :expected_binary_value}
9+
def validate_binary(value) when is_binary(value), do: :ok
10+
def validate_binary(_), do: {:error, :expected_binary_value}
11+
12+
@spec validate_address(term()) :: :ok | {:error, :invalid_address_length | :invalid_address}
13+
def validate_address("0x" <> address) do
14+
case Ethers.Utils.hex_decode(address) do
15+
{:ok, <<_address_bin::binary-20>>} -> :ok
16+
{:ok, _bad_address} -> {:error, :invalid_address_length}
17+
_ -> {:error, :invalid_address}
18+
end
19+
end
20+
21+
def validate_address(nil), do: :ok
22+
def validate_address(_invalid), do: {:error, :invalid_address}
23+
24+
@spec validate_common_fields(map()) ::
25+
:ok | {:error, :expected_non_neg_integer_value | :expected_binary_value}
26+
def validate_common_fields(params) do
27+
with :ok <- validate_non_neg_integer(params.chain_id),
28+
:ok <- validate_non_neg_integer(params.nonce),
29+
:ok <- validate_address(params[:to]) do
30+
validate_non_neg_integer(params.gas)
31+
end
32+
end
33+
end

lib/ethers/transaction/legacy.ex

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ defmodule Ethers.Transaction.Legacy do
33
Legacy transaction struct and implementation of Transaction.Protocol.
44
"""
55

6+
import Ethers.Transaction.Helpers
7+
68
alias Ethers.Types
79
alias Ethers.Utils
810

@@ -44,17 +46,24 @@ defmodule Ethers.Transaction.Legacy do
4446
@impl Ethers.Transaction
4547
def new(params) do
4648
to = params[:to]
47-
48-
{:ok,
49-
%__MODULE__{
50-
nonce: params.nonce,
51-
gas_price: params.gas_price,
52-
gas: params.gas,
53-
to: to && Utils.to_checksum_address(to),
54-
value: params[:value] || 0,
55-
input: params[:input] || params[:data] || "",
56-
chain_id: params[:chain_id]
57-
}}
49+
input = params[:input] || params[:data] || ""
50+
value = params[:value] || 0
51+
52+
with :ok <- validate_common_fields(params),
53+
:ok <- validate_non_neg_integer(params.gas_price),
54+
:ok <- validate_non_neg_integer(value),
55+
:ok <- validate_binary(input) do
56+
{:ok,
57+
%__MODULE__{
58+
nonce: params.nonce,
59+
gas_price: params.gas_price,
60+
gas: params.gas,
61+
to: to && Utils.to_checksum_address(to),
62+
value: value,
63+
input: input,
64+
chain_id: params[:chain_id]
65+
}}
66+
end
5867
end
5968

6069
@impl Ethers.Transaction

lib/ethers/tx_data.ex

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,7 @@ defmodule Ethers.TxData do
4646
end
4747

4848
def to_map(tx_map, overrides) when is_map(tx_map) do
49-
overrides
50-
|> Enum.into(tx_map)
51-
|> Map.new(fn
52-
{k, v} when is_integer(v) -> {k, Ethers.Utils.integer_to_hex(v)}
53-
kv -> kv
54-
end)
49+
Enum.into(overrides, tx_map)
5550
end
5651

5752
@doc """

test/ethers/tx_data_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ defmodule Ethers.TxDataTest do
4545
test "integer overrides are converted to hex" do
4646
tx_data = TxData.new("0xffff", @function_selector, nil, nil)
4747

48-
assert %{data: "0xffff", gas: "0x1"} ==
48+
assert %{data: "0xffff", gas: 1} ==
4949
TxData.to_map(tx_data, gas: 1)
5050
end
5151
end

0 commit comments

Comments
 (0)