Merge pull request #501 from poanetwork/denormalize-contract-creation-address-on-transaction

Denormalize contract creation address on transaction
pull/508/head
Luke Imhoff 6 years ago committed by GitHub
commit 8525f3d5fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      apps/explorer/lib/explorer/chain.ex
  2. 16
      apps/explorer/lib/explorer/chain/import.ex
  3. 209
      apps/explorer/lib/explorer/chain/transaction.ex
  4. 23
      apps/explorer/lib/explorer/etherscan.ex
  5. 2
      apps/explorer/priv/repo/migrations/20180117221923_create_transactions.exs
  6. 29
      apps/explorer/test/explorer/chain_test.exs
  7. 16
      apps/explorer/test/explorer/etherscan_test.exs
  8. 145
      apps/explorer/test/explorer/import_test.exs
  9. 20
      apps/explorer/test/support/factory.ex
  10. 10
      apps/explorer_web/test/explorer_web/controllers/transaction_internal_transaction_controller_test.exs
  11. 10
      apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs
  12. 10
      apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs
  13. 8
      apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs

@ -11,7 +11,6 @@ defmodule Explorer.Chain do
order_by: 2,
order_by: 3,
preload: 2,
select_merge: 3,
where: 2,
where: 3
]
@ -184,6 +183,7 @@ defmodule Explorer.Chain do
|> fetch_transactions()
|> Transaction.where_address_fields_match(address_hash, direction)
|> join_associations(necessity_by_association)
|> Transaction.preload_token_transfers(address_hash)
|> Repo.all()
end
@ -1535,21 +1535,6 @@ defmodule Explorer.Chain do
defp fetch_transactions(paging_options \\ nil) do
Transaction
|> select_merge([transaction], %{
created_contract_address_hash:
type(
fragment(
~s[
(SELECT i."created_contract_address_hash"
FROM "internal_transactions" AS i
WHERE (i."transaction_hash" = ?) AND (i."type" = 'create')
LIMIT 1)
],
transaction.hash
),
Explorer.Chain.Hash.Address
)
})
|> order_by([transaction], desc: transaction.block_number, desc: transaction.index)
|> handle_paging_options(paging_options)
end

@ -351,7 +351,7 @@ defmodule Explorer.Chain.Import do
end)
|> Multi.run(:internal_transactions_indexed_at_transactions, fn %{internal_transactions: internal_transactions}
when is_list(internal_transactions) ->
update_transactions_internal_transactions_indexed_at(
update_transactions(
internal_transactions,
%{
timeout: options[:transactions][:timeout] || @insert_transactions_timeout,
@ -604,7 +604,7 @@ defmodule Explorer.Chain.Import do
{:ok, inserted}
end
defp update_transactions_internal_transactions_indexed_at(internal_transactions, %{
defp update_transactions(internal_transactions, %{
timeout: timeout,
timestamps: timestamps
})
@ -618,7 +618,17 @@ defmodule Explorer.Chain.Import do
from(
t in Transaction,
where: t.hash in ^ordered_transaction_hashes,
update: [set: [internal_transactions_indexed_at: ^timestamps.updated_at]]
update: [
set: [
internal_transactions_indexed_at: ^timestamps.updated_at,
created_contract_address_hash:
fragment(
"(SELECT it.created_contract_address_hash FROM internal_transactions AS it WHERE it.transaction_hash = ? and it.type = 'create' and ? IS NULL)",
t.hash,
t.to_address_hash
)
]
]
)
transaction_count = Enum.count(ordered_transaction_hashes)

@ -19,7 +19,7 @@ defmodule Explorer.Chain.Transaction do
alias Explorer.Chain.Transaction.Status
@optional_attrs ~w(block_hash block_number cumulative_gas_used gas_used index internal_transactions_indexed_at status
@optional_attrs ~w(block_hash block_number created_contract_address_hash cumulative_gas_used gas_used index internal_transactions_indexed_at status
to_address_hash)a
@required_attrs ~w(from_address_hash gas gas_price hash input nonce r s v value)a
@ -66,6 +66,9 @@ defmodule Explorer.Chain.Transaction do
* `block` - the block in which this transaction was mined/validated. `nil` when transaction is pending.
* `block_hash` - `block` foreign key. `nil` when transaction is pending.
* `block_number` - Denormalized `block` `number`. `nil` when transaction is pending.
* `created_contract_address` - belongs_to association to `address` corresponding to `created_contract_address_hash`.
* `created_contract_address_hash` - Denormalized `internal_transaction` `created_contract_address_hash`
populated only when `to_address_hash` is nil.
* `cumulative_gas_used` - the cumulative gas used in `transaction`'s `t:Explorer.Chain.Block.t/0` before
`transaction`'s `index`. `nil` when transaction is pending.
* `from_address` - the source of `value`
@ -95,6 +98,8 @@ defmodule Explorer.Chain.Transaction do
block: %Ecto.Association.NotLoaded{} | Block.t() | nil,
block_hash: Hash.t() | nil,
block_number: Block.block_number() | nil,
created_contract_address: %Ecto.Association.NotLoaded{} | Address.t() | nil,
created_contract_address_hash: Hash.Address.t() | nil,
cumulative_gas_used: Gas.t() | nil,
from_address: %Ecto.Association.NotLoaded{} | Address.t(),
from_address_hash: Hash.Address.t(),
@ -133,7 +138,6 @@ defmodule Explorer.Chain.Transaction do
field(:status, Status)
field(:v, :integer)
field(:value, Wei)
field(:created_contract_address_hash, Hash.Address, virtual: true)
timestamps()
@ -158,6 +162,14 @@ defmodule Explorer.Chain.Transaction do
references: :hash,
type: Hash.Address
)
belongs_to(
:created_contract_address,
Address,
foreign_key: :created_contract_address_hash,
references: :hash,
type: Hash.Address
)
end
@doc """
@ -286,6 +298,117 @@ defmodule Explorer.Chain.Transaction do
|> unique_constraint(:hash)
end
def preload_token_transfers(query, address_hash) do
token_transfers_query =
from(
tt in TokenTransfer,
where:
tt.token_contract_address_hash == ^address_hash or tt.to_address_hash == ^address_hash or
tt.from_address_hash == ^address_hash,
preload: [:token, :from_address, :to_address]
)
preload(query, [tt], token_transfers: ^token_transfers_query)
end
@doc """
Adds to the given transaction's query a `where` with one of the conditions that the matched
function returns.
`where_address_fields_match(query, address, :to)`
- returns a query considering that the given address_hash is equal to to_address_hash from
transactions' table or is equal to to_address_hash from token transfers' table.
`where_address_fields_match(query, address, :from)`
- returns a query considering that the given address_hash is equal to from_address_hash from
transactions' table or is equal to from_address_hash from token transfers' table.
`where_address_fields_match(query, address, nil)`
- returns a query considering that the given address_hash can be: to_address_hash,
from_address_hash, created_contract_address_hash,
to_address_hash or from_address_hash from token_transfers' table.
### Token transfers' preload
Token transfers will be preloaded according to the given address_hash considering if it's equal
to token_contract_address_hash, to_address_hash or from_address_hash from Token Transfers's table.
"""
def where_address_fields_match(query, address_hash, :to) do
query
|> where(
[t],
t.hash in fragment(
"""
(
SELECT t0.hash AS hash
FROM transactions AS t0
WHERE t0.to_address_hash = ? OR t0.created_contract_address_hash = ?
)
UNION
(
SELECT tt.transaction_hash AS hash
FROM token_transfers AS tt
WHERE tt.to_address_hash = ?
)
""",
^address_hash.bytes,
^address_hash.bytes,
^address_hash.bytes
)
)
end
def where_address_fields_match(query, address_hash, :from) do
query
|> where(
[t],
t.hash in fragment(
"""
(
SELECT t0.hash AS hash
FROM transactions AS t0
WHERE t0.from_address_hash = ?
)
UNION
(
SELECT tt.transaction_hash AS hash
FROM token_transfers AS tt
WHERE tt.from_address_hash = ?
)
""",
^address_hash.bytes,
^address_hash.bytes
)
)
end
def where_address_fields_match(query, address_hash, nil) do
query
|> where(
[t],
t.hash in fragment(
"""
(
SELECT t0.hash AS hash
FROM transactions AS t0
WHERE t0.to_address_hash = ? OR t0.from_address_hash = ? OR t0.created_contract_address_hash = ?
)
UNION
(
SELECT tt.transaction_hash AS hash
FROM token_transfers AS tt
WHERE tt.to_address_hash = ? OR tt.from_address_hash = ?
)
""",
^address_hash.bytes,
^address_hash.bytes,
^address_hash.bytes,
^address_hash.bytes,
^address_hash.bytes
)
)
end
@collated_fields ~w(block_number cumulative_gas_used gas_used index status)a
@collated_message "can't be blank when the transaction is collated into a block"
@ -342,86 +465,4 @@ defmodule Explorer.Chain.Transaction do
_ -> changeset
end
end
defmacrop exists_contract_creation_with_matching_address_hash_fragment(transaction_hash, bytes) do
quote do
fragment(
~s[
EXISTS (
SELECT 1
FROM "internal_transactions" AS i
WHERE i."transaction_hash" = ? AND i."type" = 'create' AND i."created_contract_address_hash" = ?
)
],
unquote(transaction_hash),
unquote(bytes)
)
end
end
@doc """
Adds to the given transaction's query a `where` with one of the conditions that the matched
function returns.
`where_address_fields_match(query, address, :to)`
- returns a query considering that the given address_hash is equal to to_address_hash from
transactions' table or is equal to to_address_hash from token transfers' table.
`where_address_fields_match(query, address, :from)`
- returns a query considering that the given address_hash is equal to from_address_hash from
transactions' table or is equal to from_address_hash from token transfers't table.
`where_address_fields_match(query, address, nil)`
- returns a query considering that the given address_hash can be: to_address_hash,
from_address_hash, created_contract_address_hash from internal_transactions' table,
to_address_hash or from_address_hash from token_transfers' table.
### Token transfers' preload
Token transfers will be preloaded according to the given address_hash considering if it's equal
to token_contract_address_hash, to_address_hash or from_address_hash from Token Transfers's table.
"""
def where_address_fields_match(query, address_hash, :to) do
query
|> join_token_tranfers()
|> preload_token_transfers(address_hash)
|> where([t, tt], t.to_address_hash == ^address_hash or tt.to_address_hash == ^address_hash)
end
def where_address_fields_match(query, address_hash, :from) do
query
|> join_token_tranfers()
|> preload_token_transfers(address_hash)
|> where([t, tt], t.from_address_hash == ^address_hash or tt.from_address_hash == ^address_hash)
end
def where_address_fields_match(query, address_hash, nil) do
query
|> join_token_tranfers()
|> preload_token_transfers(address_hash)
|> where(
[t, tt],
t.to_address_hash == ^address_hash or t.from_address_hash == ^address_hash or tt.to_address_hash == ^address_hash or
tt.from_address_hash == ^address_hash or
(is_nil(t.to_address_hash) and
exists_contract_creation_with_matching_address_hash_fragment(t.hash, ^address_hash.bytes))
)
end
defp join_token_tranfers(query) do
join(query, :left, [t], tt in assoc(t, :token_transfers))
end
defp preload_token_transfers(query, address_hash) do
token_transfers_query =
from(
tt in TokenTransfer,
where:
tt.token_contract_address_hash == ^address_hash or tt.to_address_hash == ^address_hash or
tt.from_address_hash == ^address_hash,
preload: [:token, :from_address, :to_address]
)
preload(query, [tt], token_transfers: ^token_transfers_query)
end
end

@ -45,20 +45,21 @@ defmodule Explorer.Etherscan do
end
@transaction_fields [
:block_number,
:hash,
:nonce,
:block_hash,
:index,
:block_number,
:created_contract_address_hash,
:cumulative_gas_used,
:from_address_hash,
:to_address_hash,
:value,
:gas,
:gas_price,
:status,
:gas_used,
:hash,
:index,
:input,
:cumulative_gas_used,
:gas_used
:nonce,
:status,
:to_address_hash,
:value
]
defp list_transactions(address_hash, max_block_number, options) do
@ -66,17 +67,15 @@ defmodule Explorer.Etherscan do
from(
t in Transaction,
inner_join: b in assoc(t, :block),
left_join: it in assoc(t, :internal_transactions),
where: t.to_address_hash == ^address_hash,
or_where: t.from_address_hash == ^address_hash,
or_where: it.transaction_hash == t.hash and it.type == ^"create",
or_where: t.created_contract_address_hash == ^address_hash,
order_by: [{^options.order_by_direction, t.block_number}],
limit: ^options.page_size,
offset: ^offset(options),
select:
merge(map(t, ^@transaction_fields), %{
block_timestamp: b.timestamp,
created_contract_address_hash: it.created_contract_address_hash,
confirmations: fragment("? - ?", ^max_block_number, t.block_number)
})
)

@ -44,6 +44,7 @@ defmodule Explorer.Repo.Migrations.CreateTransactions do
add(:from_address_hash, references(:addresses, column: :hash, on_delete: :delete_all, type: :bytea), null: false)
# `null` when it is a contract creation transaction
add(:to_address_hash, references(:addresses, column: :hash, on_delete: :delete_all, type: :bytea), null: true)
add(:created_contract_address_hash, references(:addresses, column: :hash, type: :bytea), null: true)
end
create(
@ -129,6 +130,7 @@ defmodule Explorer.Repo.Migrations.CreateTransactions do
create(index(:transactions, :block_hash))
create(index(:transactions, :from_address_hash))
create(index(:transactions, :to_address_hash))
create(index(:transactions, :created_contract_address_hash))
create(index(:transactions, :inserted_at))
create(index(:transactions, :updated_at))

@ -474,23 +474,6 @@ defmodule Explorer.ChainTest do
)
end
test "created_contract_address_hash populated when existing" do
transaction =
%Transaction{hash: hash_with_block} =
:transaction
|> insert()
|> with_block()
%InternalTransaction{created_contract_address_hash: contract_hash} =
insert(:internal_transaction_create, transaction: transaction, index: 0)
assert {:ok, %Transaction{hash: ^hash_with_block, created_contract_address_hash: ^contract_hash}} =
Chain.hash_to_transaction(
hash_with_block,
necessity_by_association: %{block: :required}
)
end
test "transaction with multiple create internal transactions is returned" do
transaction =
%Transaction{hash: hash_with_block} =
@ -1041,18 +1024,6 @@ defmodule Explorer.ChainTest do
insert(:transaction)
assert [] == Explorer.Chain.recent_collated_transactions()
end
test "it has contract_creation_address_hash added" do
transaction =
:transaction
|> insert()
|> with_block()
%InternalTransaction{created_contract_address_hash: hash} =
insert(:internal_transaction_create, transaction: transaction, index: 0)
assert [%Transaction{created_contract_address_hash: ^hash}] = Explorer.Chain.recent_collated_transactions()
end
end
describe "smart_contract_bytecode/1" do

@ -54,14 +54,18 @@ defmodule Explorer.EtherscanTest do
test "with created contract address" do
address = insert(:address)
contract_address = insert(:contract_address)
transaction =
:transaction
|> insert(from_address: address)
|> insert(from_address: address, to_address: nil)
|> with_contract_creation(contract_address)
|> with_block()
%{created_contract_address_hash: contract_address_hash} =
insert(:internal_transaction_create, transaction: transaction, index: 0)
:internal_transaction_create
|> insert(transaction: transaction, index: 0)
|> with_contract_creation(contract_address)
[found_transaction] = Etherscan.list_transactions(contract_address_hash)
@ -121,14 +125,18 @@ defmodule Explorer.EtherscanTest do
test "loads created_contract_address_hash if available" do
address = insert(:address)
contract_address = insert(:contract_address)
transaction =
:transaction
|> insert(from_address: address)
|> insert(from_address: address, to_address: nil)
|> with_contract_creation(contract_address)
|> with_block()
%{created_contract_address_hash: contract_hash} =
insert(:internal_transaction_create, transaction: transaction, index: 0)
:internal_transaction_create
|> insert(transaction: transaction, index: 0)
|> with_contract_creation(contract_address)
[found_transaction] = Etherscan.list_transactions(address.hash)

@ -1,7 +1,8 @@
defmodule Explorer.Chain.ImportTest do
use Explorer.DataCase
alias Explorer.Chain.Import
alias Explorer.Chain
alias Explorer.Chain.{Address, Import, Transaction}
doctest Import
@ -50,9 +51,9 @@ defmodule Explorer.Chain.ImportTest do
assert {:ok, _} = Import.all(options)
address = Explorer.Repo.one(from(address in Explorer.Chain.Address, where: address.hash == ^address_hash))
address = Explorer.Repo.get(Address, address_hash)
assert address.contract_code != nil
assert address.contract_code != smart_contract_bytecode
end
test "with internal_transactions updates Transaction internal_transactions_indexed_at" do
@ -108,10 +109,144 @@ defmodule Explorer.Chain.ImportTest do
assert {:ok, _} = Import.all(options)
transaction =
Explorer.Repo.one(from(transaction in Explorer.Chain.Transaction, where: transaction.hash == ^transaction_hash))
transaction = Explorer.Repo.get(Transaction, transaction_hash)
refute transaction.internal_transactions_indexed_at == nil
end
test "when the transaction has no to_address and an internal transaction with type create it populates the denormalized created_contract_address_hash" do
smart_contract_bytecode =
"0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a7230582040d82a7379b1ee1632ad4d8a239954fd940277b25628ead95259a85c5eddb2120029"
from_address_hash = "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca"
created_contract_address_hash = "0x8bf38d4764929064f2d4d3a56520a76ab3df415b"
transaction_hash = "0x3a3eb134e6792ce9403ea4188e5e79693de9e4c94e499db132be086400da79e6"
options = %{
addresses: %{
params: [
%{hash: from_address_hash},
%{
contract_code: smart_contract_bytecode,
hash: created_contract_address_hash
}
]
},
transactions: %{
params: [
%{
from_address_hash: from_address_hash,
gas: 4_677_320,
gas_price: 1,
hash: transaction_hash,
input: "0x",
nonce: 0,
r: 0,
s: 0,
v: 0,
value: 0
}
],
on_conflict: :replace_all
},
internal_transactions: %{
params: [
%{
block_number: 35,
call_type: "call",
created_contract_code: smart_contract_bytecode,
created_contract_address_hash: created_contract_address_hash,
from_address_hash: from_address_hash,
gas: 4_677_320,
gas_used: 27770,
index: 0,
init:
"0x6060604052341561000c57fe5b5b6101a68061001c6000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631d3b9edf811461005b57806366098d4f1461007b578063a12f69e01461009b578063f4f3bdc1146100bb575bfe5b6100696004356024356100db565b60408051918252519081900360200190f35b61006960043560243561010a565b60408051918252519081900360200190f35b610069600435602435610124565b60408051918252519081900360200190f35b610069600435602435610163565b60408051918252519081900360200190f35b60008282028315806100f757508284828115156100f457fe5b04145b15156100ff57fe5b8091505b5092915050565b6000828201838110156100ff57fe5b8091505b5092915050565b60008080831161013057fe5b828481151561013b57fe5b049050828481151561014957fe5b0681840201841415156100ff57fe5b8091505b5092915050565b60008282111561016f57fe5b508082035b929150505600a165627a7a7230582020c944d8375ca14e2c92b14df53c2d044cb99dc30c3ba9f55e2bcde87bd4709b0029",
output: "0x",
trace_address: [],
transaction_hash: transaction_hash,
type: "create",
value: 0
}
]
}
}
assert {:ok, _} = Import.all(options)
transaction = Explorer.Repo.get(Transaction, transaction_hash)
assert {:ok, transaction.created_contract_address_hash} ==
Chain.string_to_address_hash(created_contract_address_hash)
end
test "when the transaction has a to_address and an internal transaction with type create it does not populates the denormalized created_contract_address_hash" do
smart_contract_bytecode =
"0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a7230582040d82a7379b1ee1632ad4d8a239954fd940277b25628ead95259a85c5eddb2120029"
from_address_hash = "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca"
to_address_hash = "0xf7ddc5c7a2d2f0d7a9798459c0104fdf5e9a7bbb"
created_contract_address_hash = "0x8bf38d4764929064f2d4d3a56520a76ab3df415b"
transaction_hash = "0x3a3eb134e6792ce9403ea4188e5e79693de9e4c94e499db132be086400da79e6"
options = %{
addresses: %{
params: [
%{hash: from_address_hash},
%{
contract_code: smart_contract_bytecode,
hash: created_contract_address_hash
},
%{hash: to_address_hash}
]
},
transactions: %{
params: [
%{
from_address_hash: from_address_hash,
gas: 4_677_320,
gas_price: 1,
hash: transaction_hash,
input: "0x",
nonce: 0,
r: 0,
s: 0,
to_address_hash: to_address_hash,
v: 0,
value: 0
}
],
on_conflict: :replace_all
},
internal_transactions: %{
params: [
%{
block_number: 35,
call_type: "call",
created_contract_code: smart_contract_bytecode,
created_contract_address_hash: created_contract_address_hash,
from_address_hash: from_address_hash,
gas: 4_677_320,
gas_used: 27770,
index: 0,
init:
"0x6060604052341561000c57fe5b5b6101a68061001c6000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631d3b9edf811461005b57806366098d4f1461007b578063a12f69e01461009b578063f4f3bdc1146100bb575bfe5b6100696004356024356100db565b60408051918252519081900360200190f35b61006960043560243561010a565b60408051918252519081900360200190f35b610069600435602435610124565b60408051918252519081900360200190f35b610069600435602435610163565b60408051918252519081900360200190f35b60008282028315806100f757508284828115156100f457fe5b04145b15156100ff57fe5b8091505b5092915050565b6000828201838110156100ff57fe5b8091505b5092915050565b60008080831161013057fe5b828481151561013b57fe5b049050828481151561014957fe5b0681840201841415156100ff57fe5b8091505b5092915050565b60008282111561016f57fe5b508082035b929150505600a165627a7a7230582020c944d8375ca14e2c92b14df53c2d044cb99dc30c3ba9f55e2bcde87bd4709b0029",
output: "0x",
to_address_hash: to_address_hash,
trace_address: [],
transaction_hash: transaction_hash,
type: "create",
value: 0
}
]
}
}
assert {:ok, _} = Import.all(options)
transaction = Explorer.Repo.get(Transaction, transaction_hash)
assert transaction.created_contract_address_hash == nil
end
end
end

@ -160,6 +160,26 @@ defmodule Explorer.Factory do
|> Repo.preload(:block)
end
def with_contract_creation(%Transaction{} = transaction, %Address{hash: contract_address_hash}) do
transaction
|> Transaction.changeset(%{
created_contract_address_hash: contract_address_hash
})
|> Repo.update!()
end
def with_contract_creation(%InternalTransaction{} = internal_transaction, %Address{
contract_code: contract_code,
hash: contract_address_hash
}) do
internal_transaction
|> InternalTransaction.changeset(%{
contract_code: contract_code,
created_contract_address_hash: contract_address_hash
})
|> Repo.update!()
end
def data(sequence_name) do
unpadded =
sequence_name

@ -61,12 +61,18 @@ defmodule ExplorerWeb.TransactionInternalTransactionControllerTest do
end
test "with no to_address_hash overview contains contract create address", %{conn: conn} do
contract_address = insert(:contract_address)
transaction =
:transaction
|> insert()
|> insert(to_address: nil)
|> with_contract_creation(contract_address)
|> with_block()
internal_transaction = insert(:internal_transaction_create, transaction: transaction, index: 0)
internal_transaction =
:internal_transaction_create
|> insert(transaction: transaction, index: 0)
|> with_contract_creation(contract_address)
conn =
get(

@ -50,8 +50,8 @@ defmodule ExplorerWeb.ViewingAddressesTest do
describe "viewing contract creator" do
test "see the contract creator and transaction links", %{session: session} do
address = insert(:address)
transaction = insert(:transaction, from_address: address)
contract = insert(:address, contract_code: Explorer.Factory.data("contract_code"))
transaction = insert(:transaction, from_address: address, created_contract_address: contract)
internal_transaction =
insert(
@ -148,18 +148,22 @@ defmodule ExplorerWeb.ViewingAddressesTest do
} do
lincoln = addresses.lincoln
contract_address = insert(:contract_address)
from_lincoln =
:transaction
|> insert(from_address: lincoln, to_address: nil)
|> with_contract_creation(contract_address)
|> with_block(block)
internal_transaction =
insert(
:internal_transaction_create,
:internal_transaction_create
|> insert(
transaction: from_lincoln,
from_address: lincoln,
index: 0
)
|> with_contract_creation(contract_address)
session
|> AddressPage.visit_page(addresses.lincoln)

@ -76,12 +76,18 @@ defmodule ExplorerWeb.ViewingBlocksTest do
test "contract creation is shown for to_address in transaction list", %{session: session} do
block = insert(:block, number: 42)
contract_address = insert(:contract_address)
transaction =
:transaction
|> insert(to_address: nil, to_address: nil)
|> insert(to_address: nil)
|> with_contract_creation(contract_address)
|> with_block(block)
internal_transaction = insert(:internal_transaction_create, transaction: transaction, index: 0)
internal_transaction =
:internal_transaction_create
|> insert(transaction: transaction, index: 0)
|> with_contract_creation(contract_address)
session
|> BlockPage.visit_page(block)

@ -117,12 +117,18 @@ defmodule ExplorerWeb.ViewingTransactionsTest do
end
test "contract creation is shown for to_address on home page", %{session: session} do
contract_address = insert(:contract_address)
transaction =
:transaction
|> insert(to_address: nil)
|> with_contract_creation(contract_address)
|> with_block()
internal_transaction = insert(:internal_transaction_create, transaction: transaction, index: 0)
internal_transaction =
:internal_transaction_create
|> insert(transaction: transaction, index: 0)
|> with_contract_creation(contract_address)
session
|> HomePage.visit_page()

Loading…
Cancel
Save