Current section
Files
Jump to
Current section
Files
src/gleeth@ethereum@abi@decode.erl
-module(gleeth@ethereum@abi@decode).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleeth/ethereum/abi/decode.gleam").
-export([decode/2, decode_single/2, decode_calldata/2, decode_function_input/2, decode_function_output/2, decode_outputs/2, decode_revert_with_abi/2, decode_revert/1]).
-export_type([decoded_calldata/0, decoded_revert/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-type decoded_calldata() :: {decoded_calldata,
binary(),
list(gleeth@ethereum@abi@types:abi_value())}.
-type decoded_revert() :: {revert_string, binary()} |
{revert_panic, integer()} |
{revert_custom_error, binary(), list(gleeth@ethereum@abi@types:abi_value())} |
{revert_unknown, bitstring()}.
-file("src/gleeth/ethereum/abi/decode.gleam", 237).
?DOC(" Read `length` bytes from data starting at offset.\n").
-spec read_bytes_at(bitstring(), integer(), integer()) -> {ok, bitstring()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
read_bytes_at(Data, Offset, Length) ->
case gleam_stdlib:bit_array_slice(Data, Offset, Length) of
{ok, Bytes} ->
{ok, Bytes};
{error, _} ->
{error,
{decode_error,
<<<<<<<<<<"Data too short: need "/utf8,
(erlang:integer_to_binary(Length))/binary>>/binary,
" bytes at offset "/utf8>>/binary,
(erlang:integer_to_binary(Offset))/binary>>/binary,
", have "/utf8>>/binary,
(erlang:integer_to_binary(erlang:byte_size(Data)))/binary>>}}
end.
-file("src/gleeth/ethereum/abi/decode.gleam", 122).
-spec decode_address_at(bitstring(), integer()) -> {ok,
gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_address_at(Data, Offset) ->
gleam@result:'try'(
read_bytes_at(Data, Offset, 32),
fun(Slot) -> case gleam_stdlib:bit_array_slice(Slot, 12, 20) of
{ok, Addr_bytes} ->
Hex_str = <<"0x"/utf8,
(string:lowercase(
gleam_stdlib:base16_encode(Addr_bytes)
))/binary>>,
{ok, {address_value, Hex_str}};
{error, _} ->
{error,
{decode_error,
<<"Failed to extract address bytes"/utf8>>}}
end end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 140).
-spec decode_fixed_bytes_at(bitstring(), integer(), integer()) -> {ok,
gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_fixed_bytes_at(Data, Offset, Size) ->
gleam@result:'try'(
read_bytes_at(Data, Offset, 32),
fun(Slot) -> case gleam_stdlib:bit_array_slice(Slot, 0, Size) of
{ok, Bytes} ->
{ok, {fixed_bytes_value, Bytes}};
{error, _} ->
{error,
{decode_error, <<"Failed to extract fixed bytes"/utf8>>}}
end end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 257).
?DOC(" Convert a BitArray to an unsigned integer (big-endian).\n").
-spec bytes_to_uint(bitstring(), integer(), integer()) -> integer().
bytes_to_uint(Data, Index, Acc) ->
case gleam_stdlib:bit_array_slice(Data, Index, 1) of
{ok, <<Byte:8>>} ->
bytes_to_uint(Data, Index + 1, erlang:'bsl'(Acc, 8) + Byte);
_ ->
Acc
end.
-file("src/gleeth/ethereum/abi/decode.gleam", 231).
?DOC(" Read 32 bytes at the given offset and interpret as a big-endian unsigned int.\n").
-spec read_uint256_at(bitstring(), integer()) -> {ok, integer()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
read_uint256_at(Data, Offset) ->
gleam@result:'try'(
read_bytes_at(Data, Offset, 32),
fun(Slot) -> {ok, bytes_to_uint(Slot, 0, 0)} end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 94).
-spec decode_uint_at(bitstring(), integer(), integer()) -> {ok,
gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_uint_at(Data, Offset, Bit_size) ->
gleam@result:'try'(
read_uint256_at(Data, Offset),
fun(Raw) ->
Mask = erlang:'bsl'(1, Bit_size) - 1,
{ok, {uint_value, erlang:'band'(Raw, Mask)}}
end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 105).
-spec decode_int_at(bitstring(), integer(), integer()) -> {ok,
gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_int_at(Data, Offset, Bit_size) ->
gleam@result:'try'(
read_uint256_at(Data, Offset),
fun(Raw) ->
Mask = erlang:'bsl'(1, Bit_size) - 1,
Masked = erlang:'band'(Raw, Mask),
Sign_bit = erlang:'bsl'(1, Bit_size - 1),
Value = case erlang:'band'(Masked, Sign_bit) /= 0 of
true ->
Masked - erlang:'bsl'(1, Bit_size);
false ->
Masked
end,
{ok, {int_value, Value}}
end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 135).
-spec decode_bool_at(bitstring(), integer()) -> {ok,
gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_bool_at(Data, Offset) ->
gleam@result:'try'(
read_uint256_at(Data, Offset),
fun(Raw) -> {ok, {bool_value, Raw /= 0}} end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 189).
-spec decode_bytes_at(bitstring(), integer()) -> {ok,
gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_bytes_at(Data, Offset) ->
gleam@result:'try'(
read_uint256_at(Data, Offset),
fun(Length) ->
gleam@result:'try'(
read_bytes_at(Data, Offset + 32, Length),
fun(Bytes) -> {ok, {bytes_value, Bytes}} end
)
end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 195).
-spec decode_string_at(bitstring(), integer()) -> {ok,
gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_string_at(Data, Offset) ->
gleam@result:'try'(
read_uint256_at(Data, Offset),
fun(Length) ->
gleam@result:'try'(
read_bytes_at(Data, Offset + 32, Length),
fun(Bytes) -> case gleam@bit_array:to_string(Bytes) of
{ok, S} ->
{ok, {string_value, S}};
{error, _} ->
{error,
{decode_error,
<<"Invalid UTF-8 in string"/utf8>>}}
end end
)
end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 466).
?DOC(" Compute 4-byte selector from function name and parameter types.\n").
-spec compute_selector(binary(), list(gleeth@ethereum@abi@types:abi_type())) -> {ok,
bitstring()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
compute_selector(Name, Param_types) ->
Sig = <<<<<<Name/binary, "("/utf8>>/binary,
(gleam@string:join(
gleam@list:map(
Param_types,
fun gleeth@ethereum@abi@types:to_string/1
),
<<","/utf8>>
))/binary>>/binary,
")"/utf8>>,
Hash = gleeth@crypto@keccak:keccak256_binary(gleam_stdlib:identity(Sig)),
case gleam_stdlib:bit_array_slice(Hash, 0, 4) of
{ok, Sel} ->
{ok, Sel};
{error, _} ->
{error, {decode_error, <<"Failed to compute selector"/utf8>>}}
end.
-file("src/gleeth/ethereum/abi/decode.gleam", 441).
?DOC(" Match a 4-byte selector against ABI entries.\n").
-spec match_selector(bitstring(), list(gleeth@ethereum@abi@json:abi_entry())) -> {ok,
{binary(), list(gleeth@ethereum@abi@types:abi_type())}} |
{error, gleeth@ethereum@abi@types:abi_error()}.
match_selector(Selector, Entries) ->
case Entries of
[] ->
{error,
{decode_error,
<<"No matching function for selector "/utf8,
(gleeth@utils@hex:encode(Selector))/binary>>}};
[Entry | Rest] ->
case Entry of
{function_entry, Name, Inputs, _, _} ->
Param_types = gleam@list:map(
Inputs,
fun(P) -> erlang:element(3, P) end
),
case compute_selector(Name, Param_types) of
{ok, Computed} when Computed =:= Selector ->
{ok, {Name, Param_types}};
_ ->
match_selector(Selector, Rest)
end;
_ ->
match_selector(Selector, Rest)
end
end.
-file("src/gleeth/ethereum/abi/decode.gleam", 507).
?DOC(" Parse a comma-separated list of type strings.\n").
-spec parse_type_list(binary()) -> {ok,
list(gleeth@ethereum@abi@types:abi_type())} |
{error, gleeth@ethereum@abi@types:abi_error()}.
parse_type_list(Types_str) ->
Type_strings = gleam@string:split(Types_str, <<","/utf8>>),
gleam@list:try_map(
Type_strings,
fun(S) ->
gleeth@ethereum@abi@type_parser:parse(gleam@string:trim(S))
end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 483).
?DOC(" Parse a function signature like \"transfer(address,uint256)\" into name + types.\n").
-spec parse_function_signature(binary()) -> {ok,
{binary(), list(gleeth@ethereum@abi@types:abi_type())}} |
{error, gleeth@ethereum@abi@types:abi_error()}.
parse_function_signature(Signature) ->
case gleam@string:split_once(Signature, <<"("/utf8>>) of
{ok, {Name, Rest}} ->
Types_str = case gleam_stdlib:string_ends_with(Rest, <<")"/utf8>>) of
true ->
gleam@string:drop_end(Rest, 1);
false ->
Rest
end,
case Types_str of
<<""/utf8>> ->
{ok, {Name, []}};
_ ->
gleam@result:'try'(
parse_type_list(Types_str),
fun(Type_list) -> {ok, {Name, Type_list}} end
)
end;
{error, _} ->
{error,
{decode_error,
<<"Invalid function signature: "/utf8, Signature/binary>>}}
end.
-file("src/gleeth/ethereum/abi/decode.gleam", 72).
-spec decode_static_at(
gleeth@ethereum@abi@types:abi_type(),
bitstring(),
integer()
) -> {ok, gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_static_at(T, Data, Offset) ->
case T of
{uint, Size} ->
decode_uint_at(Data, Offset, Size);
{int, Size@1} ->
decode_int_at(Data, Offset, Size@1);
address ->
decode_address_at(Data, Offset);
bool ->
decode_bool_at(Data, Offset);
{fixed_bytes, Size@2} ->
decode_fixed_bytes_at(Data, Offset, Size@2);
{fixed_array, Element_type, Size@3} ->
decode_static_fixed_array_at(Element_type, Size@3, Data, Offset);
{tuple, Element_types} ->
gleam@result:'try'(
decode_tuple_at(Element_types, Data, Offset),
fun(Values) -> {ok, {tuple_value, Values}} end
);
_ ->
{error,
{decode_error, <<"Expected static type, got dynamic"/utf8>>}}
end.
-file("src/gleeth/ethereum/abi/decode.gleam", 153).
-spec decode_static_fixed_array_at(
gleeth@ethereum@abi@types:abi_type(),
integer(),
bitstring(),
integer()
) -> {ok, gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_static_fixed_array_at(Element_type, Count, Data, Offset) ->
Element_types = gleam@list:repeat(Element_type, Count),
gleam@result:'try'(
decode_tuple_at(Element_types, Data, Offset),
fun(Values) -> {ok, {array_value, Values}} end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 39).
?DOC(
" Decode a tuple from data starting at a given offset.\n"
" The tuple's head starts at `base_offset` within `data`.\n"
).
-spec decode_tuple_at(
list(gleeth@ethereum@abi@types:abi_type()),
bitstring(),
integer()
) -> {ok, list(gleeth@ethereum@abi@types:abi_value())} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_tuple_at(Type_list, Data, Base_offset) ->
gleam@result:'try'(
gleam@list:try_fold(
Type_list,
{[], Base_offset},
fun(Acc, T) ->
{Vals, Head_pos} = Acc,
Slot_size = gleeth@ethereum@abi@types:head_size(T),
case gleeth@ethereum@abi@types:is_dynamic(T) of
false ->
gleam@result:'try'(
decode_static_at(T, Data, Head_pos),
fun(Value) ->
{ok, {[Value | Vals], Head_pos + Slot_size}}
end
);
true ->
gleam@result:'try'(
read_uint256_at(Data, Head_pos),
fun(Offset) ->
Abs_offset = Base_offset + Offset,
gleam@result:'try'(
decode_dynamic_at(T, Data, Abs_offset),
fun(Value@1) ->
{ok, {[Value@1 | Vals], Head_pos + 32}}
end
)
end
)
end
end
),
fun(_use0) ->
{Values, _} = _use0,
{ok, lists:reverse(Values)}
end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 14).
?DOC(
" Decode ABI-encoded data given a list of expected types.\n"
" This is the top-level decoder for function return values or event data.\n"
).
-spec decode(list(gleeth@ethereum@abi@types:abi_type()), bitstring()) -> {ok,
list(gleeth@ethereum@abi@types:abi_value())} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode(Type_list, Data) ->
decode_tuple_at(Type_list, Data, 0).
-file("src/gleeth/ethereum/abi/decode.gleam", 22).
?DOC(" Decode a single value of a known type from ABI-encoded data.\n").
-spec decode_single(gleeth@ethereum@abi@types:abi_type(), bitstring()) -> {ok,
gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_single(Type_, Data) ->
gleam@result:'try'(decode([Type_], Data), fun(Values) -> case Values of
[Value] ->
{ok, Value};
_ ->
{error,
{decode_error, <<"Expected exactly one value"/utf8>>}}
end end).
-file("src/gleeth/ethereum/abi/decode.gleam", 204).
-spec decode_dynamic_array_at(
gleeth@ethereum@abi@types:abi_type(),
bitstring(),
integer()
) -> {ok, gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_dynamic_array_at(Element_type, Data, Offset) ->
gleam@result:'try'(
read_uint256_at(Data, Offset),
fun(Count) ->
Element_types = gleam@list:repeat(Element_type, Count),
gleam@result:'try'(
decode_tuple_at(Element_types, Data, Offset + 32),
fun(Values) -> {ok, {array_value, Values}} end
)
end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 215).
-spec decode_dynamic_fixed_array_at(
gleeth@ethereum@abi@types:abi_type(),
integer(),
bitstring(),
integer()
) -> {ok, gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_dynamic_fixed_array_at(Element_type, Count, Data, Offset) ->
Element_types = gleam@list:repeat(Element_type, Count),
gleam@result:'try'(
decode_tuple_at(Element_types, Data, Offset),
fun(Values) -> {ok, {array_value, Values}} end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 169).
-spec decode_dynamic_at(
gleeth@ethereum@abi@types:abi_type(),
bitstring(),
integer()
) -> {ok, gleeth@ethereum@abi@types:abi_value()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_dynamic_at(T, Data, Offset) ->
case T of
bytes ->
decode_bytes_at(Data, Offset);
string ->
decode_string_at(Data, Offset);
{array, Element_type} ->
decode_dynamic_array_at(Element_type, Data, Offset);
{fixed_array, Element_type@1, Size} ->
decode_dynamic_fixed_array_at(Element_type@1, Size, Data, Offset);
{tuple, Element_types} ->
gleam@result:'try'(
decode_tuple_at(Element_types, Data, Offset),
fun(Values) -> {ok, {tuple_value, Values}} end
);
_ ->
{error, {decode_error, <<"Expected dynamic type"/utf8>>}}
end.
-file("src/gleeth/ethereum/abi/decode.gleam", 281).
?DOC(
" Decode calldata by matching the 4-byte selector against parsed ABI entries.\n"
" Returns the function name and decoded argument values.\n"
).
-spec decode_calldata(binary(), list(gleeth@ethereum@abi@json:abi_entry())) -> {ok,
decoded_calldata()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_calldata(Calldata_hex, Entries) ->
gleam@result:'try'(
begin
_pipe = gleeth@utils@hex:decode(Calldata_hex),
gleam@result:map_error(
_pipe,
fun(_) -> {decode_error, <<"Invalid calldata hex"/utf8>>} end
)
end,
fun(Calldata_bytes) -> case Calldata_bytes of
<<Selector:32/bitstring, Params_data/bitstring>> ->
gleam@result:'try'(
match_selector(Selector, Entries),
fun(_use0) ->
{Name, Param_types} = _use0,
gleam@result:'try'(
decode(Param_types, Params_data),
fun(Values) ->
{ok, {decoded_calldata, Name, Values}}
end
)
end
);
_ ->
{error,
{decode_error,
<<"Calldata too short (need at least 4 bytes)"/utf8>>}}
end end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 301).
?DOC(
" Decode calldata given a function signature string like \"transfer(address,uint256)\".\n"
" Computes the selector from the signature and decodes the parameters.\n"
).
-spec decode_function_input(binary(), binary()) -> {ok,
list(gleeth@ethereum@abi@types:abi_value())} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_function_input(Signature, Calldata_hex) ->
gleam@result:'try'(
parse_function_signature(Signature),
fun(_use0) ->
{Name, Param_types} = _use0,
gleam@result:'try'(
compute_selector(Name, Param_types),
fun(Expected_selector) ->
gleam@result:'try'(
begin
_pipe = gleeth@utils@hex:decode(Calldata_hex),
gleam@result:map_error(
_pipe,
fun(_) ->
{decode_error,
<<"Invalid calldata hex"/utf8>>}
end
)
end,
fun(Calldata_bytes) -> case Calldata_bytes of
<<Actual_selector:32/bitstring,
Params_data/bitstring>> ->
case Actual_selector =:= Expected_selector of
true ->
decode(Param_types, Params_data);
false ->
{error,
{decode_error,
<<<<<<"Selector mismatch: expected "/utf8,
(gleeth@utils@hex:encode(
Expected_selector
))/binary>>/binary,
", got "/utf8>>/binary,
(gleeth@utils@hex:encode(
Actual_selector
))/binary>>}}
end;
_ ->
{error,
{decode_error,
<<"Calldata too short (need at least 4 bytes)"/utf8>>}}
end end
)
end
)
end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 330).
?DOC(
" Decode the return value of a function given its output type signature.\n"
" For example: decode_function_output(\"(uint256)\", result_hex)\n"
).
-spec decode_function_output(binary(), binary()) -> {ok,
list(gleeth@ethereum@abi@types:abi_value())} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_function_output(Output_types_sig, Result_hex) ->
gleam@result:'try'(
parse_type_list(Output_types_sig),
fun(Type_list) ->
gleam@result:'try'(
begin
_pipe = gleeth@utils@hex:decode(Result_hex),
gleam@result:map_error(
_pipe,
fun(_) ->
{decode_error, <<"Invalid result hex"/utf8>>}
end
)
end,
fun(Result_bytes) -> decode(Type_list, Result_bytes) end
)
end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 344).
?DOC(
" Decode the return value of a function using a parsed ABI entry.\n"
" Extracts output types from the FunctionEntry and decodes the hex data.\n"
).
-spec decode_outputs(gleeth@ethereum@abi@json:abi_entry(), binary()) -> {ok,
list(gleeth@ethereum@abi@types:abi_value())} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_outputs(Function_entry, Result_hex) ->
Output_type_list = gleeth@ethereum@abi@json:output_types(Function_entry),
gleam@result:'try'(
begin
_pipe = gleeth@utils@hex:decode(Result_hex),
gleam@result:map_error(
_pipe,
fun(_) -> {decode_error, <<"Invalid result hex"/utf8>>} end
)
end,
fun(Result_bytes) -> decode(Output_type_list, Result_bytes) end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 416).
-spec decode_custom_revert(
bitstring(),
list(gleeth@ethereum@abi@json:abi_entry())
) -> {ok, decoded_revert()} | {error, gleeth@ethereum@abi@types:abi_error()}.
decode_custom_revert(Revert_bytes, Entries) ->
Selector@1 = case gleam_stdlib:bit_array_slice(Revert_bytes, 0, 4) of
{ok, Selector} -> Selector;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleeth/ethereum/abi/decode"/utf8>>,
function => <<"decode_custom_revert"/utf8>>,
line => 420,
value => _assert_fail,
start => 14224,
'end' => 14285,
pattern_start => 14235,
pattern_end => 14247})
end,
Params_start = 4,
Data_len = erlang:byte_size(Revert_bytes) - Params_start,
Params_data@1 = case gleam_stdlib:bit_array_slice(
Revert_bytes,
Params_start,
Data_len
) of
{ok, Params_data} -> Params_data;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleeth/ethereum/abi/decode"/utf8>>,
function => <<"decode_custom_revert"/utf8>>,
line => 423,
value => _assert_fail@1,
start => 14377,
'end' => 14463,
pattern_start => 14388,
pattern_end => 14403})
end,
case match_selector(Selector@1, Entries) of
{ok, {Name, Param_types}} ->
gleam@result:'try'(
decode(Param_types, Params_data@1),
fun(Values) -> {ok, {revert_custom_error, Name, Values}} end
);
{error, _} ->
{ok, {revert_unknown, Revert_bytes}}
end.
-file("src/gleeth/ethereum/abi/decode.gleam", 379).
?DOC(" Decode revert data, matching custom errors against provided ABI entries.\n").
-spec decode_revert_with_abi(
binary(),
list(gleeth@ethereum@abi@json:abi_entry())
) -> {ok, decoded_revert()} | {error, gleeth@ethereum@abi@types:abi_error()}.
decode_revert_with_abi(Revert_hex, Entries) ->
gleam@result:'try'(
begin
_pipe = gleeth@utils@hex:decode(Revert_hex),
gleam@result:map_error(
_pipe,
fun(_) -> {decode_error, <<"Invalid revert hex"/utf8>>} end
)
end,
fun(Revert_bytes) -> case Revert_bytes of
<<>> ->
{ok, {revert_unknown, <<>>}};
<<16#08, 16#c3, 16#79, 16#a0, Params/bitstring>> ->
gleam@result:'try'(
decode([string], Params),
fun(Values) -> case Values of
[{string_value, Msg}] ->
{ok, {revert_string, Msg}};
_ ->
{ok, {revert_unknown, Revert_bytes}}
end end
);
<<16#4e, 16#48, 16#7b, 16#71, Params@1/bitstring>> ->
gleam@result:'try'(
decode([{uint, 256}], Params@1),
fun(Values@1) -> case Values@1 of
[{uint_value, Code}] ->
{ok, {revert_panic, Code}};
_ ->
{ok, {revert_unknown, Revert_bytes}}
end end
);
<<_:32/bitstring, _/bitstring>> ->
case Entries of
[] ->
{ok, {revert_unknown, Revert_bytes}};
_ ->
decode_custom_revert(Revert_bytes, Entries)
end;
_ ->
{ok, {revert_unknown, Revert_bytes}}
end end
).
-file("src/gleeth/ethereum/abi/decode.gleam", 374).
?DOC(
" Decode revert data. Handles standard Error(string) with selector 0x08c379a0,\n"
" Panic(uint256) with selector 0x4e487b71, and custom errors if an ABI is provided.\n"
).
-spec decode_revert(binary()) -> {ok, decoded_revert()} |
{error, gleeth@ethereum@abi@types:abi_error()}.
decode_revert(Revert_hex) ->
decode_revert_with_abi(Revert_hex, []).