You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
529 lines
16 KiB
529 lines
16 KiB
defmodule EXW3Test do
|
|
use ExUnit.Case
|
|
doctest ExW3
|
|
|
|
setup_all do
|
|
ExW3.Contract.start_link()
|
|
|
|
%{
|
|
simple_storage_abi: ExW3.load_abi("test/examples/build/SimpleStorage.abi"),
|
|
array_tester_abi: ExW3.load_abi("test/examples/build/ArrayTester.abi"),
|
|
event_tester_abi: ExW3.load_abi("test/examples/build/EventTester.abi"),
|
|
complex_abi: ExW3.load_abi("test/examples/build/Complex.abi"),
|
|
address_tester_abi: ExW3.load_abi("test/examples/build/AddressTester.abi"),
|
|
accounts: ExW3.accounts()
|
|
}
|
|
end
|
|
|
|
test "gets accounts" do
|
|
assert ExW3.accounts() |> is_list
|
|
end
|
|
|
|
test "gets balance", context do
|
|
assert ExW3.balance(Enum.at(context[:accounts], 0)) |> is_integer
|
|
end
|
|
|
|
test "gets block number" do
|
|
assert ExW3.block_number() |> is_integer
|
|
end
|
|
|
|
test "loads abi", context do
|
|
assert context[:simple_storage_abi] |> is_map
|
|
end
|
|
|
|
# Only works with ganache-cli
|
|
|
|
# test "mines a block" do
|
|
# block_number = ExW3.block_number()
|
|
# ExW3.mine()
|
|
# assert ExW3.block_number() == block_number + 1
|
|
# end
|
|
|
|
# test "mines multiple blocks" do
|
|
# block_number = ExW3.block_number()
|
|
# ExW3.mine(5)
|
|
# assert ExW3.block_number() == block_number + 5
|
|
# end
|
|
|
|
test "keccak256 hash some data" do
|
|
hash = ExW3.keccak256("foo")
|
|
assert String.slice(hash, 0..1) == "0x"
|
|
|
|
assert hash == "0x41b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d"
|
|
|
|
num_bytes =
|
|
hash
|
|
|> String.slice(2..-1)
|
|
|> byte_size
|
|
|
|
assert trunc(num_bytes / 2) == 32
|
|
end
|
|
|
|
test "starts a Contract GenServer for simple storage contract", context do
|
|
ExW3.Contract.register(:SimpleStorage, abi: context[:simple_storage_abi])
|
|
|
|
{:ok, address, _} =
|
|
ExW3.Contract.deploy(
|
|
:SimpleStorage,
|
|
bin: ExW3.load_bin("test/examples/build/SimpleStorage.bin"),
|
|
args: [],
|
|
options: %{
|
|
gas: 300_000,
|
|
from: Enum.at(context[:accounts], 0)
|
|
}
|
|
)
|
|
|
|
ExW3.Contract.at(:SimpleStorage, address)
|
|
|
|
assert address == ExW3.Contract.address(:SimpleStorage)
|
|
|
|
{:ok, data} = ExW3.Contract.call(:SimpleStorage, :get)
|
|
|
|
assert data == 0
|
|
|
|
ExW3.Contract.send(:SimpleStorage, :set, [1], %{
|
|
from: Enum.at(context[:accounts], 0),
|
|
gas: 50_000
|
|
})
|
|
|
|
{:ok, data} = ExW3.Contract.call(:SimpleStorage, :get)
|
|
|
|
assert data == 1
|
|
end
|
|
|
|
test "starts a Contract GenServer for array tester contract", context do
|
|
ExW3.Contract.register(:ArrayTester, abi: context[:array_tester_abi])
|
|
|
|
{:ok, address, _} =
|
|
ExW3.Contract.deploy(
|
|
:ArrayTester,
|
|
bin: ExW3.load_bin("test/examples/build/ArrayTester.bin"),
|
|
options: %{
|
|
gas: 300_000,
|
|
from: Enum.at(context[:accounts], 0)
|
|
}
|
|
)
|
|
|
|
ExW3.Contract.at(:ArrayTester, address)
|
|
|
|
assert address == ExW3.Contract.address(:ArrayTester)
|
|
|
|
arr = [1, 2, 3, 4, 5]
|
|
|
|
{:ok, result} = ExW3.Contract.call(:ArrayTester, :staticUint, [arr])
|
|
|
|
assert result == arr
|
|
|
|
{:ok, result} = ExW3.Contract.call(:ArrayTester, :dynamicUint, [arr])
|
|
|
|
assert result == arr
|
|
end
|
|
|
|
test "starts a Contract GenServer for event tester contract", context do
|
|
ExW3.Contract.register(:EventTester, abi: context[:event_tester_abi])
|
|
|
|
{:ok, address, _} =
|
|
ExW3.Contract.deploy(
|
|
:EventTester,
|
|
bin: ExW3.load_bin("test/examples/build/EventTester.bin"),
|
|
options: %{
|
|
gas: 300_000,
|
|
from: Enum.at(context[:accounts], 0)
|
|
}
|
|
)
|
|
|
|
ExW3.Contract.at(:EventTester, address)
|
|
|
|
assert address == ExW3.Contract.address(:EventTester)
|
|
|
|
{:ok, tx_hash} =
|
|
ExW3.Contract.send(:EventTester, :simple, ["Hello, World!"], %{
|
|
from: Enum.at(context[:accounts], 0),
|
|
gas: 30_000
|
|
})
|
|
|
|
{:ok, {receipt, logs}} = ExW3.Contract.tx_receipt(:EventTester, tx_hash)
|
|
|
|
assert receipt |> is_map
|
|
|
|
data =
|
|
logs
|
|
|> Enum.at(0)
|
|
|> Map.get("data")
|
|
|> ExW3.bytes_to_string()
|
|
|
|
assert data == "Hello, World!"
|
|
|
|
{:ok, tx_hash2} =
|
|
ExW3.Contract.send(:EventTester, :simpleIndex, ["Hello, World!"], %{
|
|
from: Enum.at(context[:accounts], 0),
|
|
gas: 30_000
|
|
})
|
|
|
|
{:ok, {_receipt, logs}} = ExW3.Contract.tx_receipt(:EventTester, tx_hash2)
|
|
|
|
otherNum =
|
|
logs
|
|
|> Enum.at(0)
|
|
|> Map.get("otherNum")
|
|
|
|
assert otherNum == 42
|
|
|
|
num =
|
|
logs
|
|
|> Enum.at(0)
|
|
|> Map.get("num")
|
|
|
|
assert num == 46
|
|
|
|
data =
|
|
logs
|
|
|> Enum.at(0)
|
|
|> Map.get("data")
|
|
|> ExW3.bytes_to_string()
|
|
|
|
assert data == "Hello, World!"
|
|
end
|
|
|
|
test "Testing formatted get filter changes", context do
|
|
ExW3.Contract.register(:EventTester, abi: context[:event_tester_abi])
|
|
|
|
{:ok, address, _} =
|
|
ExW3.Contract.deploy(
|
|
:EventTester,
|
|
bin: ExW3.load_bin("test/examples/build/EventTester.bin"),
|
|
options: %{
|
|
gas: 300_000,
|
|
from: Enum.at(context[:accounts], 0)
|
|
}
|
|
)
|
|
|
|
ExW3.Contract.at(:EventTester, address)
|
|
|
|
# Test non indexed events
|
|
|
|
{:ok, filter_id} = ExW3.Contract.filter(:EventTester, "Simple")
|
|
|
|
{:ok, _tx_hash} =
|
|
ExW3.Contract.send(
|
|
:EventTester,
|
|
:simple,
|
|
["Hello, World!"],
|
|
%{from: Enum.at(context[:accounts], 0), gas: 30_000}
|
|
)
|
|
|
|
{:ok, change_logs} = ExW3.Contract.get_filter_changes(filter_id)
|
|
|
|
event_log = Enum.at(change_logs, 0)
|
|
|
|
assert event_log |> is_map
|
|
log_data = Map.get(event_log, "data")
|
|
assert log_data |> is_map
|
|
assert Map.get(log_data, "num") == 42
|
|
assert ExW3.bytes_to_string(Map.get(log_data, "data")) == "Hello, World!"
|
|
|
|
ExW3.Contract.uninstall_filter(filter_id)
|
|
|
|
# Test indexed events
|
|
|
|
{:ok, indexed_filter_id} = ExW3.Contract.filter(:EventTester, "SimpleIndex")
|
|
|
|
{:ok, _tx_hash} =
|
|
ExW3.Contract.send(
|
|
:EventTester,
|
|
:simpleIndex,
|
|
["Hello, World!"],
|
|
%{from: Enum.at(context[:accounts], 0), gas: 30_000}
|
|
)
|
|
|
|
{:ok, change_logs} = ExW3.Contract.get_filter_changes(indexed_filter_id)
|
|
|
|
event_log = Enum.at(change_logs, 0)
|
|
|
|
assert event_log |> is_map
|
|
log_data = Map.get(event_log, "data")
|
|
assert log_data |> is_map
|
|
assert Map.get(log_data, "num") == 46
|
|
assert ExW3.bytes_to_string(Map.get(log_data, "data")) == "Hello, World!"
|
|
assert Map.get(log_data, "otherNum") == 42
|
|
ExW3.Contract.uninstall_filter(indexed_filter_id)
|
|
|
|
# Test Indexing Indexed Events
|
|
|
|
{:ok, indexed_filter_id} =
|
|
ExW3.Contract.filter(
|
|
:EventTester,
|
|
"SimpleIndex",
|
|
%{
|
|
topics: [nil, ["Hello, World", "Hello, World!"]],
|
|
fromBlock: 1,
|
|
toBlock: "latest"
|
|
}
|
|
)
|
|
|
|
{:ok, _tx_hash} =
|
|
ExW3.Contract.send(
|
|
:EventTester,
|
|
:simpleIndex,
|
|
["Hello, World!"],
|
|
%{from: Enum.at(context[:accounts], 0), gas: 30_000}
|
|
)
|
|
|
|
{:ok, change_logs} = ExW3.Contract.get_filter_changes(indexed_filter_id)
|
|
|
|
event_log = Enum.at(change_logs, 0)
|
|
assert event_log |> is_map
|
|
log_data = Map.get(event_log, "data")
|
|
assert log_data |> is_map
|
|
assert Map.get(log_data, "num") == 46
|
|
assert ExW3.bytes_to_string(Map.get(log_data, "data")) == "Hello, World!"
|
|
assert Map.get(log_data, "otherNum") == 42
|
|
|
|
ExW3.Contract.uninstall_filter(indexed_filter_id)
|
|
|
|
# Tests filter with map params
|
|
|
|
{:ok, indexed_filter_id} =
|
|
ExW3.Contract.filter(
|
|
:EventTester,
|
|
"SimpleIndex",
|
|
%{
|
|
topics: %{num: 46, data: "Hello, World!"}
|
|
}
|
|
)
|
|
|
|
{:ok, _tx_hash} =
|
|
ExW3.Contract.send(
|
|
:EventTester,
|
|
:simpleIndex,
|
|
["Hello, World!"],
|
|
%{from: Enum.at(context[:accounts], 0), gas: 30_000}
|
|
)
|
|
|
|
# Demonstrating the delay capability
|
|
{:ok, change_logs} = ExW3.Contract.get_filter_changes(indexed_filter_id)
|
|
|
|
event_log = Enum.at(change_logs, 0)
|
|
assert event_log |> is_map
|
|
log_data = Map.get(event_log, "data")
|
|
assert log_data |> is_map
|
|
assert Map.get(log_data, "num") == 46
|
|
assert ExW3.bytes_to_string(Map.get(log_data, "data")) == "Hello, World!"
|
|
assert Map.get(log_data, "otherNum") == 42
|
|
|
|
ExW3.Contract.uninstall_filter(indexed_filter_id)
|
|
end
|
|
|
|
test "starts a Contract GenServer for Complex contract", context do
|
|
ExW3.Contract.register(:Complex, abi: context[:complex_abi])
|
|
|
|
{:ok, address, _} =
|
|
ExW3.Contract.deploy(
|
|
:Complex,
|
|
bin: ExW3.load_bin("test/examples/build/Complex.bin"),
|
|
args: [42, "Hello, world!"],
|
|
options: %{
|
|
from: Enum.at(context[:accounts], 0),
|
|
gas: 300_000
|
|
}
|
|
)
|
|
|
|
ExW3.Contract.at(:Complex, address)
|
|
|
|
assert address == ExW3.Contract.address(:Complex)
|
|
|
|
{:ok, foo, foobar} = ExW3.Contract.call(:Complex, :getBoth)
|
|
|
|
assert foo == 42
|
|
|
|
assert ExW3.bytes_to_string(foobar) == "Hello, world!"
|
|
end
|
|
|
|
test "starts a Contract GenServer for AddressTester contract", context do
|
|
ExW3.Contract.register(:AddressTester, abi: context[:address_tester_abi])
|
|
|
|
{:ok, address, _} =
|
|
ExW3.Contract.deploy(
|
|
:AddressTester,
|
|
bin: ExW3.load_bin("test/examples/build/AddressTester.bin"),
|
|
options: %{
|
|
from: Enum.at(context[:accounts], 0),
|
|
gas: 300_000
|
|
}
|
|
)
|
|
|
|
ExW3.Contract.at(:AddressTester, address)
|
|
|
|
assert address == ExW3.Contract.address(:AddressTester)
|
|
|
|
formatted_address =
|
|
Enum.at(context[:accounts], 0)
|
|
|> ExW3.format_address()
|
|
|
|
{:ok, same_address} = ExW3.Contract.call(:AddressTester, :get, [formatted_address])
|
|
|
|
assert ExW3.to_address(same_address) == Enum.at(context[:accounts], 0)
|
|
end
|
|
|
|
test "returns checksum for all caps address" do
|
|
assert ExW3.to_checksum_address(String.downcase("0x52908400098527886E0F7030069857D2E4169EE7")) ==
|
|
"0x52908400098527886E0F7030069857D2E4169EE7"
|
|
|
|
assert ExW3.to_checksum_address(String.downcase("0x8617E340B3D01FA5F11F306F4090FD50E238070D")) ==
|
|
"0x8617E340B3D01FA5F11F306F4090FD50E238070D"
|
|
end
|
|
|
|
test "returns checksumfor all lowercase address" do
|
|
assert ExW3.to_checksum_address(String.downcase("0xde709f2102306220921060314715629080e2fb77")) ==
|
|
"0xde709f2102306220921060314715629080e2fb77"
|
|
|
|
assert ExW3.to_checksum_address(String.downcase("0x27b1fdb04752bbc536007a920d24acb045561c26")) ==
|
|
"0x27b1fdb04752bbc536007a920d24acb045561c26"
|
|
end
|
|
|
|
test "returns checksum for normal addresses" do
|
|
assert ExW3.to_checksum_address(String.downcase("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")) ==
|
|
"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
|
|
|
|
assert ExW3.to_checksum_address(String.downcase("0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359")) ==
|
|
"0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359"
|
|
|
|
assert ExW3.to_checksum_address(String.downcase("0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB")) ==
|
|
"0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB"
|
|
|
|
assert ExW3.to_checksum_address(String.downcase("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb")) ==
|
|
"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb"
|
|
end
|
|
|
|
test "returns valid check for is_valid_checksum_address()" do
|
|
assert ExW3.is_valid_checksum_address("0x52908400098527886E0F7030069857D2E4169EE7") == true
|
|
assert ExW3.is_valid_checksum_address("0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB") == true
|
|
assert ExW3.is_valid_checksum_address("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb") == true
|
|
assert ExW3.is_valid_checksum_address("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed") == true
|
|
assert ExW3.is_valid_checksum_address("0x27b1fdb04752bbc536007a920d24acb045561c26") == true
|
|
assert ExW3.is_valid_checksum_address("0xde709f2102306220921060314715629080e2fb77") == true
|
|
assert ExW3.is_valid_checksum_address("0x8617E340B3D01FA5F11F306F4090FD50E238070D") == true
|
|
assert ExW3.is_valid_checksum_address("0x52908400098527886E0F7030069857D2E4169EE7") == true
|
|
end
|
|
|
|
test "returns invalid check for is_valid_checksum_address()" do
|
|
assert ExW3.is_valid_checksum_address("0x2f015c60e0be116b1f0cd534704db9c92118fb6a") == false
|
|
end
|
|
|
|
test "returns proper error messages at contract deployment", context do
|
|
ExW3.Contract.register(:SimpleStorage, abi: context[:simple_storage_abi])
|
|
|
|
assert {:error, :missing_gas} ==
|
|
ExW3.Contract.deploy(
|
|
:SimpleStorage,
|
|
bin: ExW3.load_bin("test/examples/build/SimpleStorage.bin"),
|
|
args: [],
|
|
options: %{
|
|
from: Enum.at(context[:accounts], 0)
|
|
}
|
|
)
|
|
|
|
assert {:error, :missing_sender} ==
|
|
ExW3.Contract.deploy(
|
|
:SimpleStorage,
|
|
bin: ExW3.load_bin("test/examples/build/SimpleStorage.bin"),
|
|
args: [],
|
|
options: %{
|
|
gas: 300_000
|
|
}
|
|
)
|
|
|
|
assert {:error, :missing_binary} ==
|
|
ExW3.Contract.deploy(
|
|
:SimpleStorage,
|
|
args: [],
|
|
options: %{
|
|
gas: 300_000,
|
|
from: Enum.at(context[:accounts], 0)
|
|
}
|
|
)
|
|
end
|
|
|
|
test "return proper error messages at send and call", context do
|
|
ExW3.Contract.register(:SimpleStorage, abi: context[:simple_storage_abi])
|
|
|
|
{:ok, address, _} =
|
|
ExW3.Contract.deploy(
|
|
:SimpleStorage,
|
|
bin: ExW3.load_bin("test/examples/build/SimpleStorage.bin"),
|
|
args: [],
|
|
options: %{
|
|
gas: 300_000,
|
|
from: Enum.at(context[:accounts], 0)
|
|
}
|
|
)
|
|
|
|
assert {:error, :missing_address} == ExW3.Contract.call(:SimpleStorage, :get)
|
|
|
|
assert {:error, :missing_address} ==
|
|
ExW3.Contract.send(:SimpleStorage, :set, [1], %{
|
|
from: Enum.at(context[:accounts], 0),
|
|
gas: 50_000
|
|
})
|
|
|
|
ExW3.Contract.at(:SimpleStorage, address)
|
|
|
|
assert {:error, :missing_sender} ==
|
|
ExW3.Contract.send(:SimpleStorage, :set, [1], %{gas: 50_000})
|
|
|
|
assert {:error, :missing_gas} ==
|
|
ExW3.Contract.send(:SimpleStorage, :set, [1], %{from: Enum.at(context[:accounts], 0)})
|
|
end
|
|
|
|
test "unit conversion to_wei" do
|
|
assert ExW3.to_wei(1, :wei) == 1
|
|
assert ExW3.to_wei(1, :kwei) == 1_000
|
|
assert ExW3.to_wei(1, :Kwei) == 1_000
|
|
assert ExW3.to_wei(1, :babbage) == 1_000
|
|
assert ExW3.to_wei(1, :mwei) == 1_000_000
|
|
assert ExW3.to_wei(1, :Mwei) == 1_000_000
|
|
assert ExW3.to_wei(1, :lovelace) == 1_000_000
|
|
assert ExW3.to_wei(1, :gwei) == 1_000_000_000
|
|
assert ExW3.to_wei(1, :Gwei) == 1_000_000_000
|
|
assert ExW3.to_wei(1, :shannon) == 1_000_000_000
|
|
assert ExW3.to_wei(1, :szabo) == 1_000_000_000_000
|
|
assert ExW3.to_wei(1, :finney) == 1_000_000_000_000_000
|
|
assert ExW3.to_wei(1, :ether) == 1_000_000_000_000_000_000
|
|
assert ExW3.to_wei(1, :kether) == 1_000_000_000_000_000_000_000
|
|
assert ExW3.to_wei(1, :grand) == 1_000_000_000_000_000_000_000
|
|
assert ExW3.to_wei(1, :mether) == 1_000_000_000_000_000_000_000_000
|
|
assert ExW3.to_wei(1, :gether) == 1_000_000_000_000_000_000_000_000_000
|
|
assert ExW3.to_wei(1, :tether) == 1_000_000_000_000_000_000_000_000_000_000
|
|
|
|
assert ExW3.to_wei(1, :kwei) == ExW3.to_wei(1, :femtoether)
|
|
assert ExW3.to_wei(1, :szabo) == ExW3.to_wei(1, :microether)
|
|
assert ExW3.to_wei(1, :finney) == ExW3.to_wei(1, :milliether)
|
|
assert ExW3.to_wei(1, :milli) == ExW3.to_wei(1, :milliether)
|
|
assert ExW3.to_wei(1, :milli) == ExW3.to_wei(1000, :micro)
|
|
|
|
{:ok, agent} = Agent.start_link(fn -> false end)
|
|
|
|
try do
|
|
ExW3.to_wei(1, :wei1)
|
|
catch
|
|
_ -> Agent.update(agent, fn _ -> true end)
|
|
end
|
|
|
|
assert Agent.get(agent, fn state -> state end)
|
|
end
|
|
|
|
test "unit conversion from wei" do
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :wei) == 1_000_000_000_000_000_000
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :kwei) == 1_000_000_000_000_000
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :mwei) == 1_000_000_000_000
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :gwei) == 1_000_000_000
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :szabo) == 1_000_000
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :finney) == 1_000
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :ether) == 1
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :kether) == 0.001
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :grand) == 0.001
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :mether) == 0.000001
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :gether) == 0.000000001
|
|
assert ExW3.from_wei(1_000_000_000_000_000_000, :tether) == 0.000000000001
|
|
end
|
|
end
|
|
|