allow bytes32 for name and symbol

pull/2052/head
Ayrat Badykov 6 years ago
parent 608485ff25
commit 1a97e35b2a
No known key found for this signature in database
GPG Key ID: B44668E265E9396F
  1. 8
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/contract.ex
  2. 18
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/encoder.ex
  3. 23
      apps/explorer/lib/explorer/token/metadata_retriever.ex
  4. 47
      apps/explorer/test/explorer/token/metadata_retriever_test.exs

@ -28,10 +28,11 @@ defmodule EthereumJSONRPC.Contract do
@spec execute_contract_functions([call()], [map()], EthereumJSONRPC.json_rpc_named_arguments()) :: [call_result()]
def execute_contract_functions(requests, abi, json_rpc_named_arguments) do
functions =
parsed_abi =
abi
|> ABI.parse_specification()
|> Enum.into(%{}, &{&1.function, &1})
functions = Enum.into(parsed_abi, %{}, &{&1.function, &1})
requests_with_index = Enum.with_index(requests)
@ -58,7 +59,8 @@ defmodule EthereumJSONRPC.Contract do
{:error, "No result"}
response ->
{^index, result} = Encoder.decode_result(response, functions[function_name])
selectors = Enum.filter(parsed_abi, fn p_abi -> p_abi.function == function_name end)
{^index, result} = Encoder.decode_result(response, selectors)
result
end
end)

@ -35,12 +35,28 @@ defmodule EthereumJSONRPC.Encoder do
@doc """
Given a result from the blockchain, and the function selector, returns the result decoded.
"""
@spec decode_result(map(), %ABI.FunctionSelector{}) ::
@spec decode_result(map(), %ABI.FunctionSelector{} | [%ABI.FunctionSelector{}]) ::
{String.t(), {:ok, any()} | {:error, String.t() | :invalid_data}}
def decode_result(%{error: %{code: code, message: message}, id: id}, _selector) do
{id, {:error, "(#{code}) #{message}"}}
end
def decode_result(result, selectors) when is_list(selectors) do
Enum.map(selectors, fn selector ->
try do
decode_result(result, selector)
rescue
_ -> :error
end
end)
|> Enum.find(fn decode ->
case decode do
{_id, {:ok, _}} -> true
_ -> false
end
end)
end
def decode_result(%{id: id, result: result}, function_selector) do
types_list = List.wrap(function_selector.returns)

@ -22,6 +22,16 @@ defmodule Explorer.Token.MetadataRetriever do
"payable" => false,
"type" => "function"
},
%{
"constant" => true,
"inputs" => [],
"name" => "name",
"outputs" => [
%{"name" => "", "type" => "bytes32"}
],
"payable" => false,
"type" => "function"
},
%{
"constant" => true,
"inputs" => [],
@ -60,6 +70,19 @@ defmodule Explorer.Token.MetadataRetriever do
],
"payable" => false,
"type" => "function"
},
%{
"constant" => true,
"inputs" => [],
"name" => "symbol",
"outputs" => [
%{
"name" => "",
"type" => "bytes32"
}
],
"payable" => false,
"type" => "function"
}
]

@ -426,4 +426,51 @@ defmodule Explorer.Token.MetadataRetrieverTest do
on_exit(fn -> Application.put_env(:explorer, :token_functions_reader_max_retries, original) end)
end
end
test "returns name and symbol when they are bytes32" do
token = insert(:token, contract_address: build(:contract_address))
expect(
EthereumJSONRPC.Mox,
:json_rpc,
1,
fn requests, _opts ->
{:ok,
Enum.map(requests, fn
%{id: id, method: "eth_call", params: [%{data: "0x313ce567", to: _}, "latest"]} ->
%{
id: id,
result: "0x0000000000000000000000000000000000000000000000000000000000000012"
}
%{id: id, method: "eth_call", params: [%{data: "0x06fdde03", to: _}, "latest"]} ->
%{
id: id,
result: "0x4d616b6572000000000000000000000000000000000000000000000000000000"
}
%{id: id, method: "eth_call", params: [%{data: "0x95d89b41", to: _}, "latest"]} ->
%{
id: id,
result: "0x4d4b520000000000000000000000000000000000000000000000000000000000"
}
%{id: id, method: "eth_call", params: [%{data: "0x18160ddd", to: _}, "latest"]} ->
%{
id: id,
result: "0x00000000000000000000000000000000000000000000d3c21bcecceda1000000"
}
end)}
end
)
expected = %{
decimals: 18,
name: "Maker",
symbol: "MKR",
total_supply: 1_000_000_000_000_000_000_000_000
}
assert MetadataRetriever.get_functions_of(token.contract_address_hash) == expected
end
end

Loading…
Cancel
Save