From 1ab80877ce99c2d8c5cbd0a9662d48bffb0ec77d Mon Sep 17 00:00:00 2001 From: Viktor Baranov Date: Tue, 5 Mar 2024 12:39:23 +0300 Subject: [PATCH 1/4] Fix EIP-1967 beacon proxy pattern detection --- CHANGELOG.md | 1 + .../controllers/smart_contract_controller_test.exs | 2 +- apps/explorer/lib/explorer/chain/smart_contract/proxy.ex | 4 ++-- .../lib/explorer/chain/smart_contract/proxy/eip_1967.ex | 4 ++-- .../lib/explorer/chain/smart_contract/proxy/master_copy.ex | 4 ++-- .../test/explorer/chain/smart_contract/proxy_test.exs | 2 +- apps/explorer/test/explorer/chain/smart_contract_test.exs | 4 ++-- 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b349ed60de73..d60943c096f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - [#9572](https://github.com/blockscout/blockscout/pull/9572) - Fix Shibarium L1 fetcher - [#9563](https://github.com/blockscout/blockscout/pull/9563) - Fix timestamp handler for unfinalized zkEVM batches - [#9560](https://github.com/blockscout/blockscout/pull/9560) - Fix fetch pending transaction for hyperledger besu client +- [#9555](https://github.com/blockscout/blockscout/pull/9555) - Fix EIP-1967 beacon proxy pattern detection - [#9514](https://github.com/blockscout/blockscout/pull/9514) - Fix missing `0x` prefix for `blockNumber`, `logIndex`, `transactionIndex` and remove `transactionLogIndex` in `eth_getLogs` response. - [#9512](https://github.com/blockscout/blockscout/pull/9512) - Docker-compose 2.24.6 compatibility - [#9262](https://github.com/blockscout/blockscout/pull/9262) - Fix withdrawal status diff --git a/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs index 8d2889876964..5ecc075a44fa 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs @@ -288,7 +288,7 @@ defmodule BlockScoutWeb.SmartContractControllerTest do ] }, _options -> - {:ok, "0xcebb2CCCFe291F0c442841cBE9C1D06EED61Ca02"} + {:ok, "0x000000000000000000000000" <> "cebb2CCCFe291F0c442841cBE9C1D06EED61Ca02"} end) end diff --git a/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex b/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex index 845f8f6e08e8..9bec8a284a63 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex @@ -149,8 +149,8 @@ defmodule Explorer.Chain.SmartContract.Proxy do when is_burn_signature_or_nil(empty_address_hash_string) -> nil - {:ok, implementation_logic_address_hash_string} -> - implementation_logic_address_hash_string + {:ok, "0x000000000000000000000000" <> implementation_logic_address_hash_string} -> + "0x" <> implementation_logic_address_hash_string _ -> nil diff --git a/apps/explorer/lib/explorer/chain/smart_contract/proxy/eip_1967.ex b/apps/explorer/lib/explorer/chain/smart_contract/proxy/eip_1967.ex index 5cc06c75ed9e..a80f0a94a45f 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract/proxy/eip_1967.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract/proxy/eip_1967.ex @@ -75,10 +75,10 @@ defmodule Explorer.Chain.SmartContract.Proxy.EIP1967 do when is_burn_signature_or_nil(empty_address) -> nil - {:ok, beacon_contract_address} -> + {:ok, "0x000000000000000000000000" <> beacon_contract_address} -> case @implementation_signature |> Basic.get_implementation_address_hash_string( - beacon_contract_address, + "0x" <> beacon_contract_address, implementation_method_abi ) do <> -> diff --git a/apps/explorer/lib/explorer/chain/smart_contract/proxy/master_copy.ex b/apps/explorer/lib/explorer/chain/smart_contract/proxy/master_copy.ex index 97b927981392..0680ba64ad29 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract/proxy/master_copy.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract/proxy/master_copy.ex @@ -29,8 +29,8 @@ defmodule Explorer.Chain.SmartContract.Proxy.MasterCopy do when is_burn_signature(empty_address) -> {:ok, "0x"} - {:ok, logic_contract_address} -> - {:ok, logic_contract_address} + {:ok, "0x000000000000000000000000" <> logic_contract_address} -> + {:ok, "0x" <> logic_contract_address} _ -> {:ok, nil} diff --git a/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs b/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs index f5fd83b562a2..582355a9ad45 100644 --- a/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs +++ b/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs @@ -442,7 +442,7 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do id: _id, method: "eth_call", params: [ - %{data: "0x5c60da1b", to: "0x000000000000000000000000" <> ^beacon_contract_address_hash_string}, + %{data: "0x5c60da1b", to: "0x" <> ^beacon_contract_address_hash_string}, "latest" ] } diff --git a/apps/explorer/test/explorer/chain/smart_contract_test.exs b/apps/explorer/test/explorer/chain/smart_contract_test.exs index f0e5b2075e3f..6eda196e2108 100644 --- a/apps/explorer/test/explorer/chain/smart_contract_test.exs +++ b/apps/explorer/test/explorer/chain/smart_contract_test.exs @@ -119,7 +119,7 @@ defmodule Explorer.Chain.SmartContractTest do ] }, _options -> - {:ok, string_implementation_address_hash} + {:ok, "0x000000000000000000000000" <> string_implementation_address_hash} end) assert {^string_implementation_address_hash, "proxy"} = @@ -834,7 +834,7 @@ defmodule Explorer.Chain.SmartContractTest do ] }, _options -> - {:ok, string_implementation_address_hash} + {:ok, "0x000000000000000000000000" <> string_implementation_address_hash} end) end From 70fdae23d0f0c6919cdbc248959a5c4a216b4618 Mon Sep 17 00:00:00 2001 From: Viktor Baranov Date: Tue, 5 Mar 2024 21:42:02 +0300 Subject: [PATCH 2/4] Processing of eth_getStorageAt might return less 32 bytes --- .../smart_contract_controller_test.exs | 2 +- .../lib/explorer/chain/smart_contract.ex | 6 +- .../explorer/chain/smart_contract/proxy.ex | 40 ++++++++- .../chain/smart_contract/proxy/eip_1967.ex | 53 ++++++----- .../chain/smart_contract/proxy/master_copy.ex | 5 +- .../chain/smart_contract/proxy_test.exs | 90 +++++++++++++++++++ .../explorer/chain/smart_contract_test.exs | 4 +- 7 files changed, 164 insertions(+), 36 deletions(-) diff --git a/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs index 5ecc075a44fa..8d2889876964 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs @@ -288,7 +288,7 @@ defmodule BlockScoutWeb.SmartContractControllerTest do ] }, _options -> - {:ok, "0x000000000000000000000000" <> "cebb2CCCFe291F0c442841cBE9C1D06EED61Ca02"} + {:ok, "0xcebb2CCCFe291F0c442841cBE9C1D06EED61Ca02"} end) end diff --git a/apps/explorer/lib/explorer/chain/smart_contract.ex b/apps/explorer/lib/explorer/chain/smart_contract.ex index 7d5ba48d0c96..cb9ac24ea5a6 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract.ex @@ -41,9 +41,7 @@ defmodule Explorer.Chain.SmartContract do @burn_address_hash_string "0x0000000000000000000000000000000000000000" @burn_address_hash_string_32 "0x0000000000000000000000000000000000000000000000000000000000000000" - defguard is_burn_signature(term) when term in ["0x", "0x0", @burn_address_hash_string_32] - defguard is_burn_signature_or_nil(term) when is_burn_signature(term) or term == nil - defguard is_burn_signature_extended(term) when is_burn_signature(term) or term == @burn_address_hash_string + defguard is_burn_signature(term) when term in ["0x", "0x0", @burn_address_hash_string, @burn_address_hash_string_32] @doc """ Returns burn address hash @@ -594,7 +592,7 @@ defmodule Explorer.Chain.SmartContract do def save_implementation_data(nil, _, _, _), do: {nil, nil} def save_implementation_data(empty_address_hash_string, proxy_address_hash, metadata_from_verified_twin, options) - when is_burn_signature_extended(empty_address_hash_string) do + when is_burn_signature(empty_address_hash_string) do if is_nil(metadata_from_verified_twin) or !metadata_from_verified_twin do proxy_address_hash |> address_hash_to_smart_contract_without_twin(options) diff --git a/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex b/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex index 9bec8a284a63..a4235c1f703f 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex @@ -13,7 +13,7 @@ defmodule Explorer.Chain.SmartContract.Proxy do string_to_address_hash: 1 ] - import Explorer.Chain.SmartContract, only: [burn_address_hash_string: 0, is_burn_signature_or_nil: 1] + import Explorer.Chain.SmartContract, only: [burn_address_hash_string: 0, is_burn_signature: 1] # supported signatures: # 5c60da1b = keccak256(implementation()) @@ -146,11 +146,11 @@ defmodule Explorer.Chain.SmartContract.Proxy do json_rpc_named_arguments ) do {:ok, empty_address_hash_string} - when is_burn_signature_or_nil(empty_address_hash_string) -> + when is_burn_signature(empty_address_hash_string) -> nil - {:ok, "0x000000000000000000000000" <> implementation_logic_address_hash_string} -> - "0x" <> implementation_logic_address_hash_string + {:ok, "0x" <> storage_value} -> + extract_address_hex_from_storage_pointer(storage_value) _ -> nil @@ -289,4 +289,36 @@ defmodule Explorer.Chain.SmartContract.Proxy do Map.get(input, "name") == name end) end + + @doc """ + Decodes 20 bytes address hex from smart-contract storage pointer value + """ + @spec extract_address_hex_from_storage_pointer(binary) :: binary + def extract_address_hex_from_storage_pointer(storage_value) when is_binary(storage_value) do + hex_bytes = Base.decode16!(storage_value, case: :mixed) + hex_bytes_count = byte_size(hex_bytes) + + cond do + hex_bytes_count == 20 -> + "0x" <> storage_value + + hex_bytes_count > 20 -> + << + reversed_address_hex::binary-size(20), + _right::binary + >> = hex_bytes |> :binary.bin_to_list() |> Enum.reverse() |> :binary.list_to_bin() + + hex = + reversed_address_hex + |> :binary.bin_to_list() + |> Enum.reverse() + |> :binary.list_to_bin() + |> Base.encode16(case: :lower) + + "0x" <> hex + + hex_bytes_count < 20 -> + "0x" <> String.pad_leading(storage_value, 40) + end + end end diff --git a/apps/explorer/lib/explorer/chain/smart_contract/proxy/eip_1967.ex b/apps/explorer/lib/explorer/chain/smart_contract/proxy/eip_1967.ex index a80f0a94a45f..24549c96a132 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract/proxy/eip_1967.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract/proxy/eip_1967.ex @@ -7,7 +7,7 @@ defmodule Explorer.Chain.SmartContract.Proxy.EIP1967 do alias Explorer.Chain.SmartContract.Proxy alias Explorer.Chain.SmartContract.Proxy.Basic - import Explorer.Chain.SmartContract, only: [is_burn_signature_or_nil: 1] + import Explorer.Chain.SmartContract, only: [is_burn_signature: 1] # supported signatures: # 5c60da1b = keccak256(implementation()) @@ -65,31 +65,38 @@ defmodule Explorer.Chain.SmartContract.Proxy.EIP1967 do } ] - case Contract.eth_get_storage_at_request( - proxy_address_hash, - storage_slot_beacon_contract_address, - nil, - json_rpc_named_arguments - ) do - {:ok, empty_address} - when is_burn_signature_or_nil(empty_address) -> - nil + beacon_contract_address = + case Contract.eth_get_storage_at_request( + proxy_address_hash, + storage_slot_beacon_contract_address, + nil, + json_rpc_named_arguments + ) do + {:ok, empty_address} + when is_burn_signature(empty_address) -> + nil - {:ok, "0x000000000000000000000000" <> beacon_contract_address} -> - case @implementation_signature - |> Basic.get_implementation_address_hash_string( - "0x" <> beacon_contract_address, - implementation_method_abi - ) do - <> -> - implementation_address + {:ok, "0x" <> storage_value} -> + Proxy.extract_address_hex_from_storage_pointer(storage_value) - _ -> - nil - end + _ -> + nil + end + + if beacon_contract_address do + case @implementation_signature + |> Basic.get_implementation_address_hash_string( + beacon_contract_address, + implementation_method_abi + ) do + <> -> + implementation_address - _ -> - nil + _ -> + nil + end + else + nil end end end diff --git a/apps/explorer/lib/explorer/chain/smart_contract/proxy/master_copy.ex b/apps/explorer/lib/explorer/chain/smart_contract/proxy/master_copy.ex index 0680ba64ad29..ce5a7aed49aa 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract/proxy/master_copy.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract/proxy/master_copy.ex @@ -29,8 +29,9 @@ defmodule Explorer.Chain.SmartContract.Proxy.MasterCopy do when is_burn_signature(empty_address) -> {:ok, "0x"} - {:ok, "0x000000000000000000000000" <> logic_contract_address} -> - {:ok, "0x" <> logic_contract_address} + {:ok, "0x" <> storage_value} -> + logic_contract_address = Proxy.extract_address_hex_from_storage_pointer(storage_value) + {:ok, logic_contract_address} _ -> {:ok, nil} diff --git a/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs b/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs index 582355a9ad45..01d7101f3a82 100644 --- a/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs +++ b/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs @@ -466,4 +466,94 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do assert implementation_abi == @implementation_abi end + + test "get_implementation_abi_from_proxy/2 returns implementation abi in case of EIP-1967 proxy pattern (beacon contract) when eth_getStorageAt returns less 32 bytes" do + proxy_contract_address = insert(:contract_address) + + smart_contract = + insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: [], contract_code_md5: "123") + + beacon_contract_address = insert(:contract_address) + + insert(:smart_contract, + address_hash: beacon_contract_address.hash, + abi: @beacon_abi, + contract_code_md5: "123" + ) + + beacon_contract_address_hash_string = Base.encode16(beacon_contract_address.hash.bytes, case: :lower) + + implementation_contract_address = insert(:contract_address) + + insert(:smart_contract, + address_hash: implementation_contract_address.hash, + abi: @implementation_abi, + contract_code_md5: "123" + ) + + implementation_contract_address_hash_string = + Base.encode16(implementation_contract_address.hash.bytes, case: :lower) + + EthereumJSONRPC.Mox + |> expect( + :json_rpc, + fn %{ + id: _id, + method: "eth_getStorageAt", + params: [ + _, + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", + "latest" + ] + }, + _options -> + {:ok, "0x0000000000000000000000000000000000000000"} + end + ) + |> expect( + :json_rpc, + fn %{ + id: _id, + method: "eth_getStorageAt", + params: [ + _, + "0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50", + "latest" + ] + }, + _options -> + {:ok, "0x" <> beacon_contract_address_hash_string} + end + ) + |> expect( + :json_rpc, + fn [ + %{ + id: _id, + method: "eth_call", + params: [ + %{data: "0x5c60da1b", to: "0x" <> ^beacon_contract_address_hash_string}, + "latest" + ] + } + ], + _options -> + { + :ok, + [ + %{ + id: _id, + jsonrpc: "2.0", + result: "0x000000000000000000000000" <> implementation_contract_address_hash_string + } + ] + } + end + ) + + implementation_abi = Proxy.get_implementation_abi_from_proxy(smart_contract, []) + verify!(EthereumJSONRPC.Mox) + + assert implementation_abi == @implementation_abi + end end diff --git a/apps/explorer/test/explorer/chain/smart_contract_test.exs b/apps/explorer/test/explorer/chain/smart_contract_test.exs index 6eda196e2108..f0e5b2075e3f 100644 --- a/apps/explorer/test/explorer/chain/smart_contract_test.exs +++ b/apps/explorer/test/explorer/chain/smart_contract_test.exs @@ -119,7 +119,7 @@ defmodule Explorer.Chain.SmartContractTest do ] }, _options -> - {:ok, "0x000000000000000000000000" <> string_implementation_address_hash} + {:ok, string_implementation_address_hash} end) assert {^string_implementation_address_hash, "proxy"} = @@ -834,7 +834,7 @@ defmodule Explorer.Chain.SmartContractTest do ] }, _options -> - {:ok, "0x000000000000000000000000" <> string_implementation_address_hash} + {:ok, string_implementation_address_hash} end) end From ce36a5d71443fba60e680c4b9ad68a2a19c65120 Mon Sep 17 00:00:00 2001 From: Viktor Baranov Date: Tue, 5 Mar 2024 22:51:18 +0300 Subject: [PATCH 3/4] Fix case for less 20 bytes in response --- .../explorer/chain/smart_contract/proxy.ex | 2 +- .../chain/smart_contract/proxy_test.exs | 129 +++++++++--------- 2 files changed, 69 insertions(+), 62 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex b/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex index a4235c1f703f..22a5ab5d3d24 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex @@ -318,7 +318,7 @@ defmodule Explorer.Chain.SmartContract.Proxy do "0x" <> hex hex_bytes_count < 20 -> - "0x" <> String.pad_leading(storage_value, 40) + "0x" <> String.pad_leading(storage_value, 40, "0") end end end diff --git a/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs b/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs index 01d7101f3a82..c61b10c795a4 100644 --- a/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs +++ b/apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs @@ -404,61 +404,49 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do implementation_contract_address_hash_string = Base.encode16(implementation_contract_address.hash.bytes, case: :lower) - EthereumJSONRPC.Mox - |> expect( - :json_rpc, - fn %{ - id: _id, - method: "eth_getStorageAt", - params: [ - _, - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", - "latest" - ] - }, - _options -> - {:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"} - end + eip_1967_beacon_proxy_mock_requests( + beacon_contract_address_hash_string, + implementation_contract_address_hash_string, + :full_32 ) - |> expect( - :json_rpc, - fn %{ - id: _id, - method: "eth_getStorageAt", - params: [ - _, - "0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50", - "latest" - ] - }, - _options -> - {:ok, "0x000000000000000000000000" <> beacon_contract_address_hash_string} - end + + implementation_abi = Proxy.get_implementation_abi_from_proxy(smart_contract, []) + verify!(EthereumJSONRPC.Mox) + + assert implementation_abi == @implementation_abi + end + + test "get_implementation_abi_from_proxy/2 returns implementation abi in case of EIP-1967 proxy pattern (beacon contract) when eth_getStorageAt returns 20 bytes address" do + proxy_contract_address = insert(:contract_address) + + smart_contract = + insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: [], contract_code_md5: "123") + + beacon_contract_address = insert(:contract_address) + + insert(:smart_contract, + address_hash: beacon_contract_address.hash, + abi: @beacon_abi, + contract_code_md5: "123" ) - |> expect( - :json_rpc, - fn [ - %{ - id: _id, - method: "eth_call", - params: [ - %{data: "0x5c60da1b", to: "0x" <> ^beacon_contract_address_hash_string}, - "latest" - ] - } - ], - _options -> - { - :ok, - [ - %{ - id: _id, - jsonrpc: "2.0", - result: "0x000000000000000000000000" <> implementation_contract_address_hash_string - } - ] - } - end + + beacon_contract_address_hash_string = Base.encode16(beacon_contract_address.hash.bytes, case: :lower) + + implementation_contract_address = insert(:contract_address) + + insert(:smart_contract, + address_hash: implementation_contract_address.hash, + abi: @implementation_abi, + contract_code_md5: "123" + ) + + implementation_contract_address_hash_string = + Base.encode16(implementation_contract_address.hash.bytes, case: :lower) + + eip_1967_beacon_proxy_mock_requests( + beacon_contract_address_hash_string, + implementation_contract_address_hash_string, + :exact_20 ) implementation_abi = Proxy.get_implementation_abi_from_proxy(smart_contract, []) @@ -467,7 +455,7 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do assert implementation_abi == @implementation_abi end - test "get_implementation_abi_from_proxy/2 returns implementation abi in case of EIP-1967 proxy pattern (beacon contract) when eth_getStorageAt returns less 32 bytes" do + test "get_implementation_abi_from_proxy/2 returns implementation abi in case of EIP-1967 proxy pattern (beacon contract) when eth_getStorageAt returns less 20 bytes address" do proxy_contract_address = insert(:contract_address) smart_contract = @@ -494,6 +482,30 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do implementation_contract_address_hash_string = Base.encode16(implementation_contract_address.hash.bytes, case: :lower) + eip_1967_beacon_proxy_mock_requests( + beacon_contract_address_hash_string, + implementation_contract_address_hash_string, + :short + ) + + implementation_abi = Proxy.get_implementation_abi_from_proxy(smart_contract, []) + verify!(EthereumJSONRPC.Mox) + + assert implementation_abi == @implementation_abi + end + + defp eip_1967_beacon_proxy_mock_requests( + beacon_contract_address_hash_string, + implementation_contract_address_hash_string, + mode + ) do + response = + case mode do + :full_32 -> "0x000000000000000000000000" <> beacon_contract_address_hash_string + :exact_20 -> "0x" <> beacon_contract_address_hash_string + :short -> "0x" <> String.slice(beacon_contract_address_hash_string, 10..-1) + end + EthereumJSONRPC.Mox |> expect( :json_rpc, @@ -507,7 +519,7 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do ] }, _options -> - {:ok, "0x0000000000000000000000000000000000000000"} + {:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"} end ) |> expect( @@ -522,7 +534,7 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do ] }, _options -> - {:ok, "0x" <> beacon_contract_address_hash_string} + {:ok, response} end ) |> expect( @@ -550,10 +562,5 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do } end ) - - implementation_abi = Proxy.get_implementation_abi_from_proxy(smart_contract, []) - verify!(EthereumJSONRPC.Mox) - - assert implementation_abi == @implementation_abi end end From 843a9e3657261f3bca20447c9d1b1fc248e69bfe Mon Sep 17 00:00:00 2001 From: Viktor Baranov Date: Tue, 5 Mar 2024 22:58:45 +0300 Subject: [PATCH 4/4] Refactoring --- .../explorer/chain/smart_contract/proxy.ex | 26 ++----------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex b/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex index 22a5ab5d3d24..672b17ddd65b 100644 --- a/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex +++ b/apps/explorer/lib/explorer/chain/smart_contract/proxy.ex @@ -295,30 +295,8 @@ defmodule Explorer.Chain.SmartContract.Proxy do """ @spec extract_address_hex_from_storage_pointer(binary) :: binary def extract_address_hex_from_storage_pointer(storage_value) when is_binary(storage_value) do - hex_bytes = Base.decode16!(storage_value, case: :mixed) - hex_bytes_count = byte_size(hex_bytes) + address_hex = storage_value |> String.slice(-40, 40) |> String.pad_leading(40, ["0"]) - cond do - hex_bytes_count == 20 -> - "0x" <> storage_value - - hex_bytes_count > 20 -> - << - reversed_address_hex::binary-size(20), - _right::binary - >> = hex_bytes |> :binary.bin_to_list() |> Enum.reverse() |> :binary.list_to_bin() - - hex = - reversed_address_hex - |> :binary.bin_to_list() - |> Enum.reverse() - |> :binary.list_to_bin() - |> Base.encode16(case: :lower) - - "0x" <> hex - - hex_bytes_count < 20 -> - "0x" <> String.pad_leading(storage_value, 40, "0") - end + "0x" <> address_hex end end