From 7f35d04bede4c260bb9e2719d96d05a5c6cd83ce Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Tue, 11 Nov 2025 17:31:28 +0100 Subject: [PATCH] blockscout genesis import --- apps/explorer/lib/explorer/genesis.ex | 71 +++++++++++++++++ apps/explorer/lib/mix/tasks/genesis_import.ex | 78 +++++++++++++++++++ apps/explorer/test/explorer/genesis_test.exs | 30 +++++++ docker/Makefile | 14 ++-- genesis.json | 74 ++++++++++++++++++ 5 files changed, 260 insertions(+), 7 deletions(-) create mode 100644 apps/explorer/lib/explorer/genesis.ex create mode 100644 apps/explorer/lib/mix/tasks/genesis_import.ex create mode 100644 apps/explorer/test/explorer/genesis_test.exs create mode 100644 genesis.json diff --git a/apps/explorer/lib/explorer/genesis.ex b/apps/explorer/lib/explorer/genesis.ex new file mode 100644 index 000000000000..fe2e7d6cd75e --- /dev/null +++ b/apps/explorer/lib/explorer/genesis.ex @@ -0,0 +1,71 @@ +defmodule Explorer.Genesis do + @moduledoc """ + Helpers for importing genesis data into the Explorer database. + + Acts as a thin wrapper around the existing chain spec importers so callers (CLI tasks, + scripts, etc.) can load a spec, optionally dry-run validation, and invoke the correct + importer without needing to know the underlying modules. + """ + + alias Explorer.ChainSpec.{Geth, Parity} + + @type format :: :geth | :parity | String.t() + @type import_result :: Explorer.Chain.Import.all_result() + + @importers %{ + geth: Geth.Importer, + parity: Parity.Importer + } + + @doc """ + Imports the provided chain specification. + + ## Options + + * `:dry_run` - when true, no data is written; the function returns counts of the + derived params so callers can verify the spec ahead of time. + """ + @spec import(any(), format(), keyword()) :: import_result() | {:ok, map()} | {:error, term()} + def import(spec, format \\ :geth, opts \\ []) + + def import(spec, format, opts) do + importer = fetch_importer!(format) + dry_run? = Keyword.get(opts, :dry_run, false) + + if dry_run? do + dry_run(importer, spec) + else + importer.import_genesis_accounts(spec) + end + end + + defp dry_run(importer, spec) do + accounts = importer.genesis_accounts(spec) + + {:ok, + %{ + addresses: length(accounts), + has_contract_code?: Enum.any?(accounts, &Map.get(&1, :contract_code)), + has_nonce?: Enum.any?(accounts, &Map.get(&1, :nonce)) + }} + rescue + error -> {:error, error} + end + + defp fetch_importer!(format) when is_binary(format) do + format + |> String.downcase() + |> String.to_existing_atom() + |> fetch_importer!() + rescue + ArgumentError -> + raise ArgumentError, "Unsupported genesis format: #{format}" + end + + defp fetch_importer!(format) when is_atom(format) do + Map.fetch!(@importers, format) + rescue + KeyError -> + raise ArgumentError, "Unsupported genesis format: #{format}" + end +end diff --git a/apps/explorer/lib/mix/tasks/genesis_import.ex b/apps/explorer/lib/mix/tasks/genesis_import.ex new file mode 100644 index 000000000000..2f0184b63b2e --- /dev/null +++ b/apps/explorer/lib/mix/tasks/genesis_import.ex @@ -0,0 +1,78 @@ +defmodule Mix.Tasks.Explorer.GenesisImport do + @moduledoc """ + CLI helper for seeding the database with genesis data. + + mix explorer.genesis_import --spec path/to/genesis.json --format geth + + Pass `--dry-run` to validate the spec without touching the database. + """ + @shortdoc "Imports genesis data (addresses/balances) into Explorer" + + use Mix.Task + + alias Explorer.Genesis + + @switches [spec: :string, format: :string, dry_run: :boolean] + @aliases [s: :spec, f: :format] + + @impl Mix.Task + def run(args) do + Mix.Task.run("app.start") + + {opts, _rest, invalid} = OptionParser.parse(args, strict: @switches, aliases: @aliases) + + if invalid != [] do + Mix.raise("Invalid options: #{inspect(invalid)}") + end + + spec_path = + opts[:spec] || + Mix.raise(""" + Missing --spec option. + + Example: + mix explorer.genesis_import --spec config/genesis.json --format geth + """) + + format = opts[:format] || "geth" + dry_run? = opts[:dry_run] || false + + spec_map = load_spec(spec_path) + + Mix.shell().info( + "Importing genesis spec from #{spec_label(spec_path)} (format=#{format}, dry_run=#{dry_run?})" + ) + + case Genesis.import(spec_map, format, dry_run: dry_run?) do + {:ok, summary} -> + Mix.shell().info("Genesis import finished: #{inspect(summary)}") + + {:error, reason} -> + Mix.raise("Genesis import failed: #{inspect(reason)}") + end + end + + defp load_spec("-") do + IO.read(:stdio, :all) + |> decode_spec!("") + end + + defp load_spec(path) do + path + |> File.read!() + |> decode_spec!(path) + end + + defp decode_spec!(raw, label) do + case Jason.decode(raw) do + {:ok, spec} -> + spec + + {:error, reason} -> + Mix.raise("Could not parse genesis spec from #{label}: #{inspect(reason)}") + end + end + + defp spec_label("-"), do: "" + defp spec_label(path), do: path +end diff --git a/apps/explorer/test/explorer/genesis_test.exs b/apps/explorer/test/explorer/genesis_test.exs new file mode 100644 index 000000000000..3c29ff644316 --- /dev/null +++ b/apps/explorer/test/explorer/genesis_test.exs @@ -0,0 +1,30 @@ +defmodule Explorer.GenesisTest do + use ExUnit.Case, async: true + + alias Explorer.Genesis + + describe "import/3 dry-run" do + test "summarizes geth specs" do + spec = %{ + "alloc" => %{ + "0x0000000000000000000000000000000000000001" => %{"balance" => "0x1"}, + "0x0000000000000000000000000000000000000002" => %{ + "balance" => "0x2", + "bytecode" => "0x6000" + } + } + } + + assert {:ok, summary} = Genesis.import(spec, :geth, dry_run: true) + assert summary.addresses == 2 + assert summary.has_contract_code? + refute summary.has_nonce? + end + + test "fails fast on unknown format" do + assert_raise ArgumentError, fn -> + Genesis.import(%{}, :unknown, dry_run: true) + end + end + end +end diff --git a/docker/Makefile b/docker/Makefile index 3a6653f78529..0251c772dbcd 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -16,19 +16,19 @@ STABLE_TAG := $(RELEASE_VERSION) start: @echo "==> Starting blockscout db" - @docker-compose -f ../docker-compose/services/db.yml up -d + @docker compose -f ../docker-compose/services/db.yml up -d @echo "==> Starting blockscout backend" - @docker-compose -f ../docker-compose/services/backend.yml up -d + @docker compose -f ../docker-compose/services/backend.yml up -d @echo "==> Starting stats microservice" - @docker-compose -f ../docker-compose/services/stats.yml up -d + @docker compose -f ../docker-compose/services/stats.yml up -d @echo "==> Starting visualizer microservice" - @docker-compose -f ../docker-compose/services/visualizer.yml up -d + @docker compose -f ../docker-compose/services/visualizer.yml up -d @echo "==> Starting sig-provider microservice" - @docker-compose -f ../docker-compose/services/sig-provider.yml up -d + @docker compose -f ../docker-compose/services/sig-provider.yml up -d @echo "==> Starting blockscout frontend" - @docker-compose -f ../docker-compose/services/frontend.yml up -d + @docker compose -f ../docker-compose/services/frontend.yml up -d @echo "==> Starting Nginx proxy" - @docker-compose -f ../docker-compose/services/nginx.yml up -d + @docker compose -f ../docker-compose/services/nginx.yml up -d BS_BACKEND_STARTED := $(shell docker ps --no-trunc --filter name=^/${BACKEND_CONTAINER_NAME}$ | grep ${BACKEND_CONTAINER_NAME}) BS_FRONTEND_STARTED := $(shell docker ps --no-trunc --filter name=^/${FRONTEND_CONTAINER_NAME}$ | grep ${FRONTEND_CONTAINER_NAME}) diff --git a/genesis.json b/genesis.json new file mode 100644 index 000000000000..74a74ced163d --- /dev/null +++ b/genesis.json @@ -0,0 +1,74 @@ +{ + "config": { + "chainId": 31337, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "shanghaiTime": 0, + "cancunTime": 0, + "pragueTime": 0 + }, + "nonce": "0x0", + "timestamp": "0x0", + "extraData": "0x", + "gasLimit": "0x1C9C380", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "alloc": { + "0x5fbdb2315678afecb367f032d93f642f64180aa3": { + "code": "0x608060405234801561000f575f5ffd5b5060043610610297575f3560e01c80636c525d0411610161578063a217fddf116100ca578063d547cfb711610084578063d547cfb7146105fe578063e985e9c514610606578063ed24911d14610619578063ef8a07f314610621578063f56c433214610634578063fcd4d96914610653575f5ffd5b8063a217fddf14610597578063a22cb4651461059e578063b88d4fde146105b1578063c87b56dd146105c4578063d5391393146105d7578063d547741f146105eb575f5ffd5b806384b0196e1161011b57806384b0196e146105275780638ed6b0161461054257806391d148541461055657806394a5dc9e1461056957806395d89b411461057c578063a144819414610584575f5ffd5b80636c525d04146104b457806370a08231146104bc57806370d5ae05146104cf57806372102077146104e25780637b47ec1a1461050157806382afd23b14610514575f5ffd5b806336568abe116102035780634f558e79116101bd5780634f558e791461043557806352d0a6bb1461044857806355f804b3146104685780636352211e1461047b57806363f20fa71461048e57806368573107146104a1575f5ffd5b806336568abe146103c35780634035884b146103d657806340c10f19146103e957806342842e0e146103fc57806342966c681461040f5780634b0e721614610422575f5ffd5b80631eb8ed88116102545780631eb8ed881461033e57806323b872dd14610351578063248a9ca3146103645780632913daa0146103945780632b26a6bf1461039d5780632f2ff15d146103b0575f5ffd5b806301ffc9a71461029b57806306fdde03146102c3578063081812fc146102d8578063095ea7b3146103035780631397ea85146103185780631535fc571461032b575b5f5ffd5b6102ae6102a936600461278f565b610666565b60405190151581526020015b60405180910390f35b6102cb610676565b6040516102ba91906127d8565b6102eb6102e63660046127ea565b610705565b6040516001600160a01b0390911681526020016102ba565b61031661031136600461281c565b61072c565b005b610316610326366004612888565b61073b565b6102ae6103393660046127ea565b6108fd565b61031661034c36600461293a565b610924565b61031661035f3660046129a4565b610a7c565b6103866103723660046127ea565b5f9081526006602052604090206001015490565b6040519081526020016102ba565b610386600b5481565b6103166103ab3660046127ea565b610b0a565b6103166103be3660046129de565b610b4d565b6103166103d13660046129de565b610b71565b6103166103e4366004612a08565b610ba9565b6103166103f736600461281c565b610d65565b61031661040a3660046129a4565b610d98565b61031661041d3660046127ea565b610db2565b610316610430366004612a6a565b610dc9565b6102ae6104433660046127ea565b610e8b565b61045b610456366004612a83565b610ea7565b6040516102ba9190612ac1565b610316610476366004612b05565b610f55565b6102eb6104893660046127ea565b61103e565b61031661049c3660046127ea565b611048565b6103166104af36600461293a565b61108f565b6103166111a8565b6103866104ca366004612a6a565b6111fd565b600e546102eb906001600160a01b031681565b6103866104f03660046127ea565b5f908152600c602052604090205490565b61031661050f3660046127ea565b611242565b6102ae6105223660046127ea565b6112d8565b61052f611312565b6040516102ba9796959493929190612b37565b600e546102ae90600160a01b900460ff1681565b6102ae6105643660046129de565b611354565b610316610577366004612a83565b61137e565b6102cb611481565b61031661059236600461281c565b611490565b6103865f81565b6103166105ac366004612bcd565b6114b9565b6103166105bf366004612c1a565b6114c4565b6102cb6105d23660046127ea565b6114dc565b6103865f516020612faf5f395f51905f5281565b6103166105f93660046129de565b611540565b6102cb611564565b6102ae610614366004612cf4565b6115f0565b61038661161d565b61031661062f366004612a83565b61162b565b6103866106423660046127ea565b600c6020525f908152604090205481565b610316610661366004612d1c565b611743565b5f6106708261183b565b92915050565b60605f805461068490612d3c565b80601f01602080910402602001604051908101604052809291908181526020018280546106b090612d3c565b80156106fb5780601f106106d2576101008083540402835291602001916106fb565b820191905f5260205f20905b8154815290600101906020018083116106de57829003601f168201915b5050505050905090565b5f61070f8261185f565b505f828152600460205260409020546001600160a01b0316610670565b610737828233611896565b5050565b8242111561075c5760405163068568f360e21b815260040160405180910390fd5b5f848152600c602090815260408083205481517fdf963ddca5176e1c03271f329b1083437b292565f11c80154b48cf25cb457bf7818501526001600160a01b038b8116828501528a1660608201526080810189905260a0810182905260c08082018990528351808303909101815260e09091019092528151919092012090916107e4826118a3565b9050610826898287878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118cf92505050565b61084357604051638baa579f60e01b815260040160405180910390fd5b886001600160a01b03166108568861103e565b6001600160a01b03161461087d576040516349e27cff60e01b815260040160405180910390fd5b610888898989611940565b86886001600160a01b03168a6001600160a01b03167f92e0101d74afe614cacd43cf8dfe38ecf00ba58ada6ca1512c3e913652162ca6866040516108ce91815260200190565b60405180910390a46108e1836001612d74565b5f978852600c6020526040909720969096555050505050505050565b600e545f906001600160a01b0316610914836119ed565b6001600160a01b03161492915050565b5f516020612faf5f395f51905f5261093b81611a07565b610943611a11565b83828114610967576040516001621398b960e31b0319815260040160405180910390fd5b805f036109875760405163c2e5347d60e01b815260040160405180910390fd5b600b54158015906109995750600b5481115b156109b7576040516305beb17160e11b815260040160405180910390fd5b5f5b81811015610a3d575f8787838181106109d4576109d4612d93565b90506020020160208101906109e99190612a6a565b90506001600160a01b038116610a125760405163d27b444360e01b815260040160405180910390fd5b610a3481878785818110610a2857610a28612d93565b90506020020135611a3b565b506001016109b9565b50604051819033907f6174e73d7eb2fee6c482f87f81961b83cfa577f50c963bd1516f282497260fcd905f90a350610a756001600755565b5050505050565b6001600160a01b038216610aaa57604051633250574960e11b81525f60048201526024015b60405180910390fd5b5f610ab6838333611a54565b9050836001600160a01b0316816001600160a01b031614610b04576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610aa1565b50505050565b5f610b1481611a07565b600b805490839055604051839082907f6b141d34195f1cbfa2080571bebbe19ad6d201cc0d1d53c70550795d14a4be83905f90a3505050565b5f82815260066020526040902060010154610b6781611a07565b610b048383611b16565b6001600160a01b0381163314610b9a5760405163334bd91960e11b815260040160405180910390fd5b610ba48282611ba7565b505050565b82421115610bca5760405163068568f360e21b815260040160405180910390fd5b5f848152600c602090815260408083205481517f78685c77cdd502453266db9bd5a8341b9346cafaf73f5e82a59f886211bae9f4818501526001600160a01b038a1681840152606081018990526080810182905260a08082018990528351808303909101815260c0909101909252815191909201209091610c4a826118a3565b9050610c8c888287878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118cf92505050565b610ca957604051638baa579f60e01b815260040160405180910390fd5b876001600160a01b0316610cbc8861103e565b6001600160a01b031614610ce3576040516349e27cff60e01b815260040160405180910390fd5b600e54610cfa906001600160a01b0316888a611a54565b5086886001600160a01b03167f8ae37f6a78e90ba0b5c2ade1b7755902614624b6b4e8d5b4113dd1200aaf9ee385604051610d3791815260200190565b60405180910390a3610d4a836001612d74565b5f978852600c60205260409097209690965550505050505050565b5f516020612faf5f395f51905f52610d7c81611a07565b610d84611a11565b610d8e8383611c12565b610ba46001600755565b610ba483838360405180602001604052805f8152506114c4565b600e54610737906001600160a01b03168233611a54565b600e54600160a01b900460ff16610df357604051632c7ac17360e01b815260040160405180910390fd5b5f610dfd81611a07565b6001600160a01b038216610e245760405163d27b444360e01b815260040160405180910390fd5b600e546001600160a01b0383811691161461073757600e80546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f6916992076a314a5a1e633990a54e2faf68c86a488d238e99176649060987527905f90a3505050565b5f80610e96836119ed565b6001600160a01b0316141592915050565b6060816001600160401b03811115610ec157610ec1612c06565b604051908082528060200260200182016040528015610eea578160200160208202803683370190505b5090505f5b82811015610f4e575f610f19858584818110610f0d57610f0d612d93565b905060200201356119ed565b6001600160a01b03161415828281518110610f3657610f36612d93565b91151560209283029190910190910152600101610eef565b5092915050565b5f610f5f81611a07565b5f600a8054610f6d90612d3c565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9990612d3c565b8015610fe45780601f10610fbb57610100808354040283529160200191610fe4565b820191905f5260205f20905b815481529060010190602001808311610fc757829003601f168201915b505050505090508383600a9182610ffc929190612deb565b507f309b29ded109b9e28fb9885757b3e0096eb75c51d23aa4635d68bcd569f6adc181858560405161103093929190612ea4565b60405180910390a150505050565b5f6106708261185f565b336110528261103e565b6001600160a01b031614611079576040516349e27cff60e01b815260040160405180910390fd5b5f908152600c6020526040902080546001019055565b5f516020612faf5f395f51905f526110a681611a07565b6110ae611a11565b838281146110d2576040516001621398b960e31b0319815260040160405180910390fd5b805f036110f25760405163c2e5347d60e01b815260040160405180910390fd5b600b54158015906111045750600b5481115b15611122576040516305beb17160e11b815260040160405180910390fd5b5f5b81811015610a3d575f87878381811061113f5761113f612d93565b90506020020160208101906111549190612a6a565b90506001600160a01b03811661117d5760405163d27b444360e01b815260040160405180910390fd5b61119f8187878581811061119357611193612d93565b90506020020135611c12565b50600101611124565b5f6111b281611a07565b600e54600160a01b900460ff16156111fa57600e805460ff60a01b191690556040517f3c54182e5351fc24c03b50bfbda8f6593f80f3cafa736edd37ada42cede67cb4905f90a15b50565b5f6001600160a01b038216611227576040516322718ad960e21b81525f6004820152602401610aa1565b506001600160a01b03165f9081526003602052604090205490565b5f516020612faf5f395f51905f5261125981611a07565b5f611263836119ed565b600e549091506001600160a01b03908116908216036112975760405162cac31b60e31b815260048101849052602401610aa1565b6001600160a01b038116156112c2576040516322d1d39560e21b815260048101849052602401610aa1565b600e54610ba4906001600160a01b031684611c12565b5f5f6112e3836119ed565b90506001600160a01b0381161580159061130b5750600e546001600160a01b03828116911614155b9392505050565b5f6060805f5f5f6060611323611c73565b61132b611ca0565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b5f9182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b5f61138881611a07565b600e54600160a01b900460ff166113b257604051632c7ac17360e01b815260040160405180910390fd5b815f5b81811015610a75575f8585838181106113d0576113d0612d93565b90506020020135905061140181600881901c5f908152600d6020526040902054600160ff9092169190911b16151590565b611478575f61140f826119ed565b90506001600160a01b038116156114765760405182906001600160a01b038316905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4600882901c5f908152600d602052604090208054600160ff85161b1790555b505b506001016113b5565b60606001805461068490612d3c565b5f516020612faf5f395f51905f526114a781611a07565b6114af611a11565b610d8e8383611a3b565b610737338383611ccd565b6114cf848484610a7c565b610b043385858585611d6b565b60606114e78261185f565b505f6114f1611e92565b90505f81511161150f5760405180602001604052805f81525061130b565b8061151984611ea1565b60405160200161152a929190612eff565b6040516020818303038152906040529392505050565b5f8281526006602052604090206001015461155a81611a07565b610b048383611ba7565b600a805461157190612d3c565b80601f016020809104026020016040519081016040528092919081815260200182805461159d90612d3c565b80156115e85780601f106115bf576101008083540402835291602001916115e8565b820191905f5260205f20905b8154815290600101906020018083116115cb57829003601f168201915b505050505081565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b5f611626611f30565b905090565b5f516020612faf5f395f51905f5261164281611a07565b815f8190036116645760405163c2e5347d60e01b815260040160405180910390fd5b600b54158015906116765750600b5481115b15611694576040516305beb17160e11b815260040160405180910390fd5b5f5b81811015610a75575f8585838181106116b1576116b1612d93565b9050602002013590505f6116c4826119ed565b600e549091506001600160a01b03908116908216036116f85760405162cac31b60e31b815260048101839052602401610aa1565b6001600160a01b03811615611723576040516322d1d39560e21b815260048101839052602401610aa1565b600e54611739906001600160a01b031683611c12565b5050600101611696565b5f61174d81611a07565b600e54600160a01b900460ff1661177757604051632c7ac17360e01b815260040160405180910390fd5b828210156117985760405163561ce9bb60e01b815260040160405180910390fd5b825b828111610b0457600881901c5f908152600d6020526040902054600160ff83161b16611833575f6117ca826119ed565b90506001600160a01b038116156118315760405182906001600160a01b038316905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4600882901c5f908152600d602052604090208054600160ff85161b1790555b505b60010161179a565b5f6001600160e01b03198216637965db0b60e01b1480610670575061067082612059565b5f5f61186a836119ed565b90506001600160a01b03811661067057604051637e27328960e01b815260048101849052602401610aa1565b610ba483838360016120a8565b5f6106706118af611f30565b8360405161190160f01b8152600281019290925260228201526042902090565b5f836001600160a01b03163b5f0361192d575f5f6118ed85856121ac565b5090925090505f81600381111561190657611906612f13565b1480156119245750856001600160a01b0316826001600160a01b0316145b9250505061130b565b6119388484846121f5565b949350505050565b6001600160a01b03821661196957604051633250574960e11b81525f6004820152602401610aa1565b5f61197583835f611a54565b90506001600160a01b0381166119a157604051637e27328960e01b815260048101839052602401610aa1565b836001600160a01b0316816001600160a01b031614610b04576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610aa1565b5f908152600260205260409020546001600160a01b031690565b6111fa81336122cc565b600260075403611a3457604051633ee5aeb560e01b815260040160405180910390fd5b6002600755565b610737828260405180602001604052805f815250612305565b600e545f90600160a01b900460ff1615611a815760405163fb0f360560e01b815260040160405180910390fd5b600e546001600160a01b0316611a96846119ed565b6001600160a01b031603611abf5760405162cac31b60e31b815260048101849052602401610aa1565b5f611acb85858561231c565b600e549091506001600160a01b03908116908616036119385760405184907f565971faa25ef64563a22f57a0a388514d28cdb0b3314003c37c51defdeffa8a905f90a2949350505050565b5f611b218383611354565b611ba0575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff19166001179055611b583390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610670565b505f610670565b5f611bb28383611354565b15611ba0575f8381526006602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610670565b6001600160a01b038216611c3b57604051633250574960e11b81525f6004820152602401610aa1565b5f611c4783835f611a54565b90506001600160a01b03811615610ba4576040516339e3563760e11b81525f6004820152602401610aa1565b60606116267f436f6c6c6563742054657374204e4654000000000000000000000000000000106008612409565b60606116267f31000000000000000000000000000000000000000000000000000000000000016009612409565b6001600160a01b038216611cff57604051630b61174360e31b81526001600160a01b0383166004820152602401610aa1565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b15610a7557604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611dad908890889087908790600401612f27565b6020604051808303815f875af1925050508015611de7575060408051601f3d908101601f19168201909252611de491810190612f59565b60015b611e4e573d808015611e14576040519150601f19603f3d011682016040523d82523d5f602084013e611e19565b606091505b5080515f03611e4657604051633250574960e11b81526001600160a01b0385166004820152602401610aa1565b805160208201fd5b6001600160e01b03198116630a85bd0160e11b14611e8a57604051633250574960e11b81526001600160a01b0385166004820152602401610aa1565b505050505050565b6060600a805461068490612d3c565b60605f611ead836124b2565b60010190505f816001600160401b03811115611ecb57611ecb612c06565b6040519080825280601f01601f191660200182016040528015611ef5576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084611eff57509392505050565b5f306001600160a01b037f0000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa316148015611f8857507f0000000000000000000000000000000000000000000000000000000000007a6946145b15611fb257507fe5a661033ed2ac3ff71ea3f7ee0fa7db7d4b4a791c055ab183eb8edde76fbb0390565b611626604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527fe8d829e6263e098c4daf78f06da016906d00de911e3f2a6f272403b8880e2cd2918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f6001600160e01b031982166380ac58cd60e01b148061208957506001600160e01b03198216635b5e139f60e01b145b8061067057506301ffc9a760e01b6001600160e01b0319831614610670565b80806120bc57506001600160a01b03821615155b1561217d575f6120cb8461185f565b90506001600160a01b038316158015906120f75750826001600160a01b0316816001600160a01b031614155b801561210a575061210881846115f0565b155b156121335760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610aa1565b811561217b5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b5f5f5f83516041036121e3576020840151604085015160608601515f1a6121d588828585612589565b9550955095505050506121ee565b505081515f91506002905b9250925092565b5f5f5f856001600160a01b03168585604051602401612215929190612f74565b60408051601f198184030181529181526020820180516001600160e01b0316630b135d3f60e11b1790525161224a9190612f8c565b5f60405180830381855afa9150503d805f8114612282576040519150601f19603f3d011682016040523d82523d5f602084013e612287565b606091505b509150915081801561229b57506020815110155b80156122c257508051630b135d3f60e11b906122c09083016020908101908401612f97565b145b9695505050505050565b6122d68282611354565b6107375760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610aa1565b61230f8383611c12565b610ba4335f858585611d6b565b5f5f612327846119ed565b90506001600160a01b0383161561234357612343818486612651565b6001600160a01b0381161561237d5761235e5f855f5f6120a8565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b038516156123ab576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b606060ff83146124235761241c836126b5565b9050610670565b81805461242f90612d3c565b80601f016020809104026020016040519081016040528092919081815260200182805461245b90612d3c565b80156124a65780601f1061247d576101008083540402835291602001916124a6565b820191905f5260205f20905b81548152906001019060200180831161248957829003601f168201915b50505050509050610670565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106124f05772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061251c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061253a57662386f26fc10000830492506010015b6305f5e1008310612552576305f5e100830492506008015b612710831061256657612710830492506004015b60648310612578576064830492506002015b600a83106106705760010192915050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156125c257505f91506003905082612647565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015612613573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b03811661263e57505f925060019150829050612647565b92505f91508190505b9450945094915050565b61265c8383836126f2565b610ba4576001600160a01b03831661268a57604051637e27328960e01b815260048101829052602401610aa1565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610aa1565b60605f6126c183612753565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f6001600160a01b038316158015906119385750826001600160a01b0316846001600160a01b0316148061272b575061272b84846115f0565b806119385750505f908152600460205260409020546001600160a01b03908116911614919050565b5f60ff8216601f81111561067057604051632cd44ac360e21b815260040160405180910390fd5b6001600160e01b0319811681146111fa575f5ffd5b5f6020828403121561279f575f5ffd5b813561130b8161277a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61130b60208301846127aa565b5f602082840312156127fa575f5ffd5b5035919050565b80356001600160a01b0381168114612817575f5ffd5b919050565b5f5f6040838503121561282d575f5ffd5b61283683612801565b946020939093013593505050565b5f5f83601f840112612854575f5ffd5b5081356001600160401b0381111561286a575f5ffd5b602083019150836020828501011115612881575f5ffd5b9250929050565b5f5f5f5f5f5f60a0878903121561289d575f5ffd5b6128a687612801565b95506128b460208801612801565b9450604087013593506060870135925060808701356001600160401b038111156128dc575f5ffd5b6128e889828a01612844565b979a9699509497509295939492505050565b5f5f83601f84011261290a575f5ffd5b5081356001600160401b03811115612920575f5ffd5b6020830191508360208260051b8501011115612881575f5ffd5b5f5f5f5f6040858703121561294d575f5ffd5b84356001600160401b03811115612962575f5ffd5b61296e878288016128fa565b90955093505060208501356001600160401b0381111561298c575f5ffd5b612998878288016128fa565b95989497509550505050565b5f5f5f606084860312156129b6575f5ffd5b6129bf84612801565b92506129cd60208501612801565b929592945050506040919091013590565b5f5f604083850312156129ef575f5ffd5b823591506129ff60208401612801565b90509250929050565b5f5f5f5f5f60808688031215612a1c575f5ffd5b612a2586612801565b9450602086013593506040860135925060608601356001600160401b03811115612a4d575f5ffd5b612a5988828901612844565b969995985093965092949392505050565b5f60208284031215612a7a575f5ffd5b61130b82612801565b5f5f60208385031215612a94575f5ffd5b82356001600160401b03811115612aa9575f5ffd5b612ab5858286016128fa565b90969095509350505050565b602080825282518282018190525f918401906040840190835b81811015612afa5783511515835260209384019390920191600101612ada565b509095945050505050565b5f5f60208385031215612b16575f5ffd5b82356001600160401b03811115612b2b575f5ffd5b612ab585828601612844565b60ff60f81b8816815260e060208201525f612b5560e08301896127aa565b8281036040840152612b6781896127aa565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015612bbc578351835260209384019390920191600101612b9e565b50909b9a5050505050505050505050565b5f5f60408385031215612bde575f5ffd5b612be783612801565b915060208301358015158114612bfb575f5ffd5b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f5f60808587031215612c2d575f5ffd5b612c3685612801565b9350612c4460208601612801565b92506040850135915060608501356001600160401b03811115612c65575f5ffd5b8501601f81018713612c75575f5ffd5b80356001600160401b03811115612c8e57612c8e612c06565b604051601f8201601f19908116603f011681016001600160401b0381118282101715612cbc57612cbc612c06565b604052818152828201602001891015612cd3575f5ffd5b816020840160208301375f6020838301015280935050505092959194509250565b5f5f60408385031215612d05575f5ffd5b612d0e83612801565b91506129ff60208401612801565b5f5f60408385031215612d2d575f5ffd5b50508035926020909101359150565b600181811c90821680612d5057607f821691505b602082108103612d6e57634e487b7160e01b5f52602260045260245ffd5b50919050565b8082018082111561067057634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b601f821115610ba457805f5260205f20601f840160051c81016020851015612dcc5750805b601f840160051c820191505b81811015610a75575f8155600101612dd8565b6001600160401b03831115612e0257612e02612c06565b612e1683612e108354612d3c565b83612da7565b5f601f841160018114612e47575f8515612e305750838201355b5f19600387901b1c1916600186901b178355610a75565b5f83815260208120601f198716915b82811015612e765786850135825560209485019460019092019101612e56565b5086821015612e92575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b604081525f612eb660408301866127aa565b8281036020840152838152838560208301375f602085830101526020601f19601f860116820101915050949350505050565b5f81518060208401855e5f93019283525090919050565b5f611938612f0d8386612ee8565b84612ee8565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03858116825284166020820152604081018390526080606082018190525f906122c2908301846127aa565b5f60208284031215612f69575f5ffd5b815161130b8161277a565b828152604060208201525f61193860408301846127aa565b5f61130b8284612ee8565b5f60208284031215612fa7575f5ffd5b505191905056fe9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6a26469706673582212209253ba24c5d13d5cffc27d6fe1bd7449c13e915e44e4f98bfdbce0f065799e9964736f6c634300081e0033", + "nonce": "0x1", + "balance": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x436f6c6c6563742054657374204e465400000000000000000000000000000020", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x435445535400000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x436f6c6c6563742054657374204e465400000000000000000000000000000020", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x3100000000000000000000000000000000000000000000000000000000000002", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000059", + "0xc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8": "0x68747470733a2f2f6170692e6465762e766576652e636c6f75642f6170692f6e", + "0xc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a9": "0x66742f6d657461646174612f0000000000000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000015cb152dfe4d56802d1b9596d7be87afc86da7a5b", + "0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x679795a0195a1b76cdebb7c51d74e058aee92919b8c3389af86ef24535e8a28c": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", + "0x88601476d11616a71c5be67555bd1dff4b1cbf21533d2669b768b61518cfe1c3": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "0xee60d0579bcffd98e668647d59fec1ff86a7fb340ce572e844f234ae73a6918f": "0x00000000000000000000000090f79bf6eb2c4f870365e785982e1f101e93b906", + "0xb98b78633099fa36ed8b8680c4f8092689e1e04080eb9cbb077ca38a14d7e384": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65", + "0xddfe746303372e8d2ea45aa78e3e91478f7307894b155f7ff4ebb7ddaa345272": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x961ec03a078fec1e350bb1ca3bff1afa4bae5fb83d9d8382550c2fd26a7d7527": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x9c35da83f88043b3115f30d93beacec49ca14b6238430bdff196a249c29baa80": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x53c8a5ff8e9eee17be03169c30dedc5882673fcdd4fbdb8a32244385ed269978": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc651ee22c6951bb8b5bd29e8210fb394645a94315fe10eff2cc73de1aa75c137": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x542805723ffda23528c9bda67fbd7162733a7e5cd1f5a4f41bcade67be3e0fd4": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc28683c493cad7c448bad837aba472f2734766d8620c4196cfde0a68a5916439": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f9": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x3195c024b2ddd6d9b8f6c836aa52f67fe69376c8903d009b80229b3ce4425f52": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266": { + "balance": "0x3635c9adc5dea00000" + }, + "0x70997970c51812dc3a010c7d01b50e0d17dc79c8": { + "balance": "0x3635c9adc5dea00000" + }, + "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc": { + "balance": "0x3635c9adc5dea00000" + }, + "0x90f79bf6eb2c4f870365e785982e1f101e93b906": { + "balance": "0x3635c9adc5dea00000" + }, + "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65": { + "balance": "0x3635c9adc5dea00000" + } + } +}