Change order of proxy contracts patterns detection: existing popular EIPs to the top of the list

pull/8882/head
Viktor Baranov 11 months ago
parent dfd05f936f
commit e8b0c463f4
  1. 1
      CHANGELOG.md
  2. 93
      apps/block_scout_web/test/block_scout_web/controllers/api/v2/smart_contract_controller_test.exs
  3. 69
      apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs
  4. 69
      apps/explorer/lib/explorer/chain/smart_contract/proxy.ex
  5. 16
      apps/explorer/lib/explorer/chain/smart_contract/proxy/eip_1967.ex
  6. 117
      apps/explorer/test/explorer/chain/smart_contract/proxy_test.exs
  7. 224
      apps/explorer/test/explorer/chain/smart_contract_test.exs

@ -10,6 +10,7 @@
- [#8917](https://github.com/blockscout/blockscout/pull/8917) - Proxy detection hotfix in API v2
- [#8915](https://github.com/blockscout/blockscout/pull/8915) - smart-contract: delete embeds_many relation on replace
- [#8882](https://github.com/blockscout/blockscout/pull/8882) - Change order of proxy contracts patterns detection: existing popular EIPs to the top of the list
### Chore

@ -2026,18 +2026,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
target_contract = insert(:smart_contract, abi: abi)
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x000000000000000000000000#{target_contract.address_hash |> to_string() |> String.replace("0x", "")}"}
end)
mock_logic_storage_pointer_request(target_contract.address_hash)
expect(
EthereumJSONRPC.Mox,
@ -2136,18 +2125,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
target_contract = insert(:smart_contract, abi: abi)
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x000000000000000000000000#{target_contract.address_hash |> to_string() |> String.replace("0x", "")}"}
end)
mock_logic_storage_pointer_request(target_contract.address_hash)
expect(
EthereumJSONRPC.Mox,
@ -2221,18 +2199,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
target_contract = insert(:smart_contract, abi: abi)
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x000000000000000000000000#{target_contract.address_hash |> to_string() |> String.replace("0x", "")}"}
end)
mock_logic_storage_pointer_request(target_contract.address_hash)
expect(
EthereumJSONRPC.Mox,
@ -2290,18 +2257,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
target_contract = insert(:smart_contract, abi: abi)
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x000000000000000000000000#{target_contract.address_hash |> to_string() |> String.replace("0x", "")}"}
end)
mock_logic_storage_pointer_request(target_contract.address_hash)
expect(
EthereumJSONRPC.Mox,
@ -2358,18 +2314,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
target_contract = insert(:smart_contract, abi: abi)
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x000000000000000000000000#{target_contract.address_hash |> to_string() |> String.replace("0x", "")}"}
end)
mock_logic_storage_pointer_request(target_contract.address_hash)
expect(
EthereumJSONRPC.Mox,
@ -2450,18 +2395,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
target_contract = insert(:smart_contract, abi: abi)
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x000000000000000000000000#{target_contract.address_hash |> to_string() |> String.replace("0x", "")}"}
end)
mock_logic_storage_pointer_request(target_contract.address_hash)
contract = insert(:smart_contract)
@ -2579,4 +2513,19 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
"solidity"
end
end
defp mock_logic_storage_pointer_request(address_hash) do
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x000000000000000000000000#{address_hash |> to_string() |> String.replace("0x", "")}"}
end)
end
end

@ -86,6 +86,8 @@ defmodule BlockScoutWeb.SmartContractControllerTest do
contract_code_md5: "123"
)
get_eip1967_implementation_zero_addresses()
path =
smart_contract_path(BlockScoutWeb.Endpoint, :index,
hash: token_contract_address.hash,
@ -304,4 +306,71 @@ defmodule BlockScoutWeb.SmartContractControllerTest do
{:ok, "0x000000000000000000000000cebb2CCCFe291F0c442841cBE9C1D06EED61Ca02"}
end)
end
defp mock_empty_logic_storage_pointer_request do
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
end
defp mock_empty_beacon_storage_pointer_request(mox) do
expect(mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
end
defp mock_empty_eip_1822_storage_pointer_request(mox) do
expect(mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
end
defp mock_empty_oz_storage_pointer_request(mox) do
expect(mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
end
def get_eip1967_implementation_zero_addresses do
mock_empty_logic_storage_pointer_request()
|> mock_empty_beacon_storage_pointer_request()
|> mock_empty_oz_storage_pointer_request()
|> mock_empty_eip_1822_storage_pointer_request()
end
end

@ -13,7 +13,7 @@ defmodule Explorer.Chain.SmartContract.Proxy do
string_to_address_hash: 1
]
import Explorer.Chain.SmartContract, only: [is_burn_signature_or_nil: 1]
import Explorer.Chain.SmartContract, only: [burn_address_hash_string: 0, is_burn_signature_or_nil: 1]
# supported signatures:
# 5c60da1b = keccak256(implementation())
@ -114,7 +114,8 @@ defmodule Explorer.Chain.SmartContract.Proxy do
def gnosis_safe_contract?(abi) when is_nil(abi), do: false
@doc """
Checks if the input of the smart-contract follows master-copy proxy pattern
Checks if the input of the smart-contract follows master-copy (or Safe) proxy pattern before
fetching its implementation from 0x0 storage pointer
"""
@spec master_copy_pattern?(map()) :: any()
def master_copy_pattern?(method) do
@ -155,6 +156,66 @@ defmodule Explorer.Chain.SmartContract.Proxy do
end
defp get_implementation_address_hash_string(proxy_address_hash, proxy_abi) do
get_implementation_address_hash_string_eip1967(
proxy_address_hash,
proxy_abi
)
end
@doc """
Returns EIP-1967 implementation address or tries next proxy pattern
"""
@spec get_implementation_address_hash_string_eip1967(Hash.Address.t(), any()) :: String.t() | nil
def get_implementation_address_hash_string_eip1967(proxy_address_hash, proxy_abi) do
get_implementation_address_hash_string_by_module(
EIP1967,
:get_implementation_address_hash_string_eip1167,
[
proxy_address_hash,
proxy_abi
]
)
end
@doc """
Returns EIP-1167 implementation address or tries next proxy pattern
"""
@spec get_implementation_address_hash_string_eip1167(Hash.Address.t(), any()) :: String.t() | nil
def get_implementation_address_hash_string_eip1167(proxy_address_hash, proxy_abi) do
get_implementation_address_hash_string_by_module(
EIP1167,
:get_implementation_address_hash_string_eip1822,
[
proxy_address_hash,
proxy_abi
]
)
end
@doc """
Returns EIP-1822 implementation address or tries next proxy pattern
"""
@spec get_implementation_address_hash_string_eip1822(Hash.Address.t(), any()) :: String.t() | nil
def get_implementation_address_hash_string_eip1822(proxy_address_hash, proxy_abi) do
get_implementation_address_hash_string_by_module(EIP1822, [proxy_address_hash, proxy_abi])
end
defp get_implementation_address_hash_string_by_module(
module,
next_func \\ :fallback_proxy_detection,
[proxy_address_hash, _proxy_abi] = args
) do
implementation_address_hash_string = module.get_implementation_address_hash_string(proxy_address_hash)
if !is_nil(implementation_address_hash_string) && implementation_address_hash_string !== burn_address_hash_string() do
implementation_address_hash_string
else
apply(__MODULE__, next_func, args)
end
end
@spec fallback_proxy_detection(Hash.Address.t(), any()) :: String.t() | nil
def fallback_proxy_detection(proxy_address_hash, proxy_abi) do
implementation_method_abi = get_naive_implementation_abi(proxy_abi, "implementation")
get_implementation_method_abi = get_naive_implementation_abi(proxy_abi, "getImplementation")
@ -177,9 +238,7 @@ defmodule Explorer.Chain.SmartContract.Proxy do
EIP930.get_implementation_address_hash_string(@get_address_signature, proxy_address_hash, proxy_abi)
true ->
EIP1967.get_implementation_address_hash_string(proxy_address_hash) ||
EIP1167.get_implementation_address_hash_string(proxy_address_hash) ||
EIP1822.get_implementation_address_hash_string(proxy_address_hash)
nil
end
end

@ -27,18 +27,24 @@ defmodule Explorer.Chain.SmartContract.Proxy.EIP1967 do
def get_implementation_address_hash_string(proxy_address_hash) do
json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
implementation_address_hash_string =
eip1967_implementation_address_hash_string =
Proxy.get_implementation_from_storage(
proxy_address_hash,
@storage_slot_logic_contract_address,
json_rpc_named_arguments
) ||
fetch_beacon_proxy_implementation(proxy_address_hash, json_rpc_named_arguments) ||
fetch_beacon_proxy_implementation(proxy_address_hash, json_rpc_named_arguments)
implementation_address_hash_string =
if eip1967_implementation_address_hash_string do
eip1967_implementation_address_hash_string
else
Proxy.get_implementation_from_storage(
proxy_address_hash,
@storage_slot_openzeppelin_contract_address,
json_rpc_named_arguments
)
end
Proxy.abi_decode_address_output(implementation_address_hash_string)
end
@ -70,17 +76,17 @@ defmodule Explorer.Chain.SmartContract.Proxy.EIP1967 do
nil
{:ok, beacon_contract_address} ->
case beacon_contract_address
case @implementation_signature
|> Proxy.abi_decode_address_output()
|> Basic.get_implementation_address_hash_string(
@implementation_signature,
beacon_contract_address,
implementation_method_abi
) do
<<implementation_address::binary-size(42)>> ->
implementation_address
_ ->
beacon_contract_address
nil
end
_ ->

@ -129,8 +129,7 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do
}
]
# EIP-1967 + EIP-1822
defp request_zero_implementations do
defp request_EIP1967_zero_implementations do
EthereumJSONRPC.Mox
|> expect(:json_rpc, fn %{
id: 0,
@ -168,6 +167,11 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
end
# EIP-1967 + EIP-1822
defp request_zero_implementations do
request_EIP1967_zero_implementations()
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
@ -206,6 +210,8 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do
smart_contract =
insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi, contract_code_md5: "123")
request_zero_implementations()
assert Proxy.combine_proxy_implementation_abi(smart_contract) == @proxy_abi
end
@ -226,6 +232,8 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do
implementation_contract_address_hash_string =
Base.encode16(implementation_contract_address.hash.bytes, case: :lower)
request_zero_implementations()
expect(
EthereumJSONRPC.Mox,
:json_rpc,
@ -276,6 +284,8 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do
smart_contract =
insert(:smart_contract, address_hash: proxy_contract_address.hash, abi: @proxy_abi, contract_code_md5: "123")
request_zero_implementations()
assert Proxy.get_implementation_abi_from_proxy(smart_contract, []) == []
end
@ -296,6 +306,8 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do
implementation_contract_address_hash_string =
Base.encode16(implementation_contract_address.hash.bytes, case: :lower)
request_zero_implementations()
expect(
EthereumJSONRPC.Mox,
:json_rpc,
@ -316,7 +328,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" do
test "get_implementation_abi_from_proxy/2 returns implementation abi in case of EIP-1967 proxy pattern (logic contract)" do
proxy_contract_address = insert(:contract_address)
smart_contract =
@ -355,4 +367,103 @@ defmodule Explorer.Chain.SmartContract.ProxyTest do
assert implementation_abi == @implementation_abi
end
end
@beacon_abi [
%{
"type" => "function",
"stateMutability" => "view",
"outputs" => [%{"type" => "address", "name" => "", "internalType" => "address"}],
"name" => "implementation",
"inputs" => []
}
]
test "get_implementation_abi_from_proxy/2 returns implementation abi in case of EIP-1967 proxy pattern (beacon contract)" 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, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end
)
|> expect(
:json_rpc,
fn %{
id: _id,
method: "eth_getStorageAt",
params: [
_,
"0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50",
"latest"
]
},
_options ->
{:ok, "0x000000000000000000000000" <> beacon_contract_address_hash_string}
end
)
|> expect(
:json_rpc,
fn [
%{
id: _id,
method: "eth_call",
params: [
%{data: "0x5c60da1b", to: "0x000000000000000000000000" <> 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

@ -75,30 +75,8 @@ defmodule Explorer.Chain.SmartContractTest do
string_implementation_address_hash = to_string(implementation_smart_contract.address_hash)
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
mock_empty_logic_storage_pointer_request()
|> mock_empty_beacon_storage_pointer_request()
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
@ -296,82 +274,15 @@ defmodule Explorer.Chain.SmartContractTest do
end
def get_eip1967_implementation_zero_addresses do
EthereumJSONRPC.Mox
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
mock_empty_logic_storage_pointer_request()
|> mock_empty_beacon_storage_pointer_request()
|> mock_empty_oz_storage_pointer_request()
|> mock_empty_eip_1822_storage_pointer_request()
end
def get_eip1967_implementation_non_zero_address do
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
mock_empty_logic_storage_pointer_request()
|> mock_empty_beacon_storage_pointer_request()
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
@ -400,42 +311,9 @@ defmodule Explorer.Chain.SmartContractTest do
_options ->
{:error, "error"}
end)
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
|> mock_empty_beacon_storage_pointer_request()
|> mock_empty_oz_storage_pointer_request()
|> mock_empty_eip_1822_storage_pointer_request()
end
def assert_empty_implementation(address_hash) do
@ -893,6 +771,23 @@ defmodule Explorer.Chain.SmartContractTest do
end
defp expect_address_in_response(string_implementation_address_hash) do
mock_empty_logic_storage_pointer_request()
|> mock_empty_beacon_storage_pointer_request()
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3",
"latest"
]
},
_options ->
{:ok, string_implementation_address_hash}
end)
end
defp mock_empty_logic_storage_pointer_request do
expect(EthereumJSONRPC.Mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
@ -905,29 +800,50 @@ defmodule Explorer.Chain.SmartContractTest do
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50",
"latest"
]
},
_options ->
end
defp mock_empty_beacon_storage_pointer_request(mox) do
expect(mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
|> expect(:json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3",
"latest"
]
},
_options ->
{:ok, string_implementation_address_hash}
end
defp mock_empty_eip_1822_storage_pointer_request(mox) do
expect(mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
end
defp mock_empty_oz_storage_pointer_request(mox) do
expect(mox, :json_rpc, fn %{
id: 0,
method: "eth_getStorageAt",
params: [
_,
"0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3",
"latest"
]
},
_options ->
{:ok, "0x0000000000000000000000000000000000000000000000000000000000000000"}
end)
end
end

Loading…
Cancel
Save