Add parsing constructor arguments for sourcify contracts

np-sourcify-constructor-args
Nikita Pozdniakov 1 year ago
parent f7eef31a70
commit 348a8acc1e
No known key found for this signature in database
GPG Key ID: F344106F9804FE5F
  1. 34
      apps/explorer/lib/explorer/chain.ex
  2. 34
      apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex

@ -98,6 +98,7 @@ defmodule Explorer.Chain do
alias Explorer.Market.MarketHistoryCache
alias Explorer.{PagingOptions, Repo}
alias Explorer.SmartContract.Helper
alias Explorer.SmartContract.Solidity.Verifier
alias Explorer.Tags.{AddressTag, AddressToTag}
alias Dataloader.Ecto, as: DataloaderEcto
@ -1913,7 +1914,7 @@ defmodule Explorer.Chain do
if smart_contract do
CheckBytecodeMatchingOnDemand.trigger_check(address_result, smart_contract)
LookUpSmartContractSourcesOnDemand.trigger_fetch(address_result, smart_contract)
address_result
check_and_update_constructor_args(address_result)
else
LookUpSmartContractSourcesOnDemand.trigger_fetch(address_result, nil)
@ -1936,6 +1937,35 @@ defmodule Explorer.Chain do
end
end
defp check_and_update_constructor_args(
%SmartContract{address_hash: address_hash, constructor_arguments: nil} = smart_contract
) do
if args = Verifier.parse_constructor_arguments_for_sourcify_contract(address_hash, smart_contract.abi) do
smart_contract |> SmartContract.changeset(%{constructor_arguments: args}) |> Repo.update()
%SmartContract{smart_contract | constructor_arguments: args}
else
smart_contract
end
end
defp check_and_update_constructor_args(
%Address{
hash: address_hash,
contract_code: deployed_bytecode,
smart_contract: %SmartContract{constructor_arguments: nil} = smart_contract
} = address
) do
if args =
Verifier.parse_constructor_arguments_for_sourcify_contract(address_hash, smart_contract.abi, deployed_bytecode) do
smart_contract |> SmartContract.changeset(%{constructor_arguments: args}) |> Repo.update()
%Address{address | smart_contract: %SmartContract{smart_contract | constructor_arguments: args}}
else
address
end
end
defp check_and_update_constructor_args(other), do: other
defp add_twin_info_to_contract(address_result, address_verified_twin_contract, _hash)
when is_nil(address_verified_twin_contract),
do: address_result
@ -4310,7 +4340,7 @@ defmodule Explorer.Chain do
verified_contract_twin_additional_sources = get_contract_additional_sources(verified_contract_twin, options)
%{
:verified_contract => verified_contract_twin,
:verified_contract => check_and_update_constructor_args(verified_contract_twin),
:additional_sources => verified_contract_twin_additional_sources
}
else

@ -13,6 +13,7 @@ defmodule Explorer.SmartContract.Solidity.Verifier do
alias ABI.{FunctionSelector, TypeDecoder}
alias Explorer.Chain
alias Explorer.Chain.Data
alias Explorer.SmartContract.RustVerifierInterface
alias Explorer.SmartContract.Solidity.CodeCompiler
@ -533,4 +534,37 @@ defmodule Explorer.SmartContract.Solidity.Verifier do
def parse_boolean(false), do: false
def parse_boolean(_), do: false
def parse_constructor_arguments_for_sourcify_contract(address_hash, abi) do
parse_constructor_arguments_for_sourcify_contract(address_hash, abi, Chain.smart_contract_bytecode(address_hash))
end
def parse_constructor_arguments_for_sourcify_contract(address_hash, abi, deployed_bytecode)
when is_binary(deployed_bytecode) do
creation_tx_input =
case Chain.smart_contract_creation_tx_bytecode(address_hash) do
%{init: init, created_contract_code: _created_contract_code} ->
"0x" <> init_without_0x = init
init_without_0x
_ ->
nil
end
with true <- has_constructor_with_params?(abi),
check_function <- parse_constructor_and_return_check_function(abi),
false <- is_nil(creation_tx_input) || deployed_bytecode == "0x",
{meta, meta_length} <- extract_meta_from_deployed_bytecode(deployed_bytecode),
[_bytecode, constructor_args] <- String.split(creation_tx_input, meta <> meta_length),
^constructor_args <- check_function.(constructor_args) do
constructor_args
else
_ ->
nil
end
end
def parse_constructor_arguments_for_sourcify_contract(address_hash, abi, deployed_bytecode) do
parse_constructor_arguments_for_sourcify_contract(address_hash, abi, Data.to_string(deployed_bytecode))
end
end

Loading…
Cancel
Save