upgrade to ethermint v0.21.0 #99
@ -20,8 +20,8 @@ schema = 3
|
||||
version = "v1.0.0-beta.7"
|
||||
hash = "sha256-XblGvIx6Wvvq6wggXjp+KbeJGXoe7AZH7hXEdauCezU="
|
||||
[mod."cosmossdk.io/math"]
|
||||
version = "v1.0.0-beta.3"
|
||||
hash = "sha256-lTQ27ZlL+kWlc+S//sJmyiOwaf9qS+YLv61I4OXi9XE="
|
||||
version = "v1.0.0-beta.4"
|
||||
hash = "sha256-UYdq/46EubyjxkldGike8FlwJLWGCB576VB7th285ao="
|
||||
[mod."filippo.io/edwards25519"]
|
||||
version = "v1.0.0-rc.1"
|
||||
hash = "sha256-3DboBqby2ejRU33FG96Z8JF5AJ8HP2rC/v++VyoQ2LQ="
|
||||
|
@ -6,7 +6,7 @@ cd "$(dirname "$0")"
|
||||
export TMPDIR=/tmp
|
||||
|
||||
echo "build test contracts"
|
||||
cd ../tests/integration_tests/contracts
|
||||
cd ../tests/integration_tests/hardhat
|
||||
HUSKY_SKIP_INSTALL=1 npm install
|
||||
npm run typechain
|
||||
cd ..
|
||||
|
@ -1,9 +0,0 @@
|
||||
pragma solidity 0.8.10;
|
||||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||
|
||||
contract TestERC20A is ERC20 {
|
||||
|
||||
constructor() public ERC20("TestERC20", "Test") {
|
||||
_mint(msg.sender, 100000000000000000000000000);
|
||||
}
|
||||
}
|
25
tests/integration_tests/hardhat/contracts/Mars.sol
Normal file
25
tests/integration_tests/hardhat/contracts/Mars.sol
Normal file
@ -0,0 +1,25 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.10;
|
||||
|
||||
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
|
||||
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
||||
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
||||
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
|
||||
|
||||
contract Mars is Initializable, ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable {
|
||||
function initialize() public initializer {
|
||||
__ERC20_init("Mars", "MRS");
|
||||
__Ownable_init();
|
||||
_mint(msg.sender, 1000000 * 10 ** decimals());
|
||||
}
|
||||
|
||||
function _authorizeUpgrade(address newImplementation) internal
|
||||
override
|
||||
onlyOwner {}
|
||||
}
|
||||
|
||||
contract MarsV2 is Mars {
|
||||
function version() pure public returns (string memory) {
|
||||
return "v2";
|
||||
}
|
||||
}
|
10
tests/integration_tests/hardhat/contracts/TestERC20A.sol
Normal file
10
tests/integration_tests/hardhat/contracts/TestERC20A.sol
Normal file
@ -0,0 +1,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.10;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||
|
||||
contract TestERC20A is ERC20 {
|
||||
constructor() public ERC20("TestERC20", "Test") {
|
||||
_mint(msg.sender, 100000000000000000000000000);
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import { HardhatUserConfig } from "hardhat/config";
|
||||
import type { HardhatUserConfig } from "hardhat/config";
|
||||
import "hardhat-typechain";
|
||||
import "@openzeppelin/hardhat-upgrades";
|
||||
import "@nomiclabs/hardhat-ethers";
|
||||
|
||||
const config: HardhatUserConfig = {
|
||||
solidity: {
|
File diff suppressed because it is too large
Load Diff
@ -10,9 +10,11 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@nomiclabs/hardhat-ethers": "^2.1.0",
|
||||
"@nomiclabs/hardhat-waffle": "^2.0.3",
|
||||
"@openzeppelin/contracts": "^4.7.0",
|
||||
"@openzeppelin/contracts": "^4.8.0",
|
||||
"@nomiclabs/hardhat-ethers": "^2.2.1",
|
||||
"@openzeppelin/hardhat-upgrades": "^1.21.0",
|
||||
"@openzeppelin/contracts-upgradeable": "^4.3.1",
|
||||
"@typechain/ethers-v5": "^5.0.0",
|
||||
"hardhat": "^2.10.1",
|
||||
"hardhat-typechain": "^0.3.5",
|
@ -1,4 +1,6 @@
|
||||
import pytest
|
||||
from eth_abi import abi
|
||||
from hexbytes import HexBytes
|
||||
from web3 import Web3
|
||||
|
||||
from .utils import (
|
||||
@ -9,6 +11,15 @@ from .utils import (
|
||||
send_transaction,
|
||||
)
|
||||
|
||||
# Smart contract names
|
||||
GREETER_CONTRACT = "Greeter"
|
||||
ERC20_CONTRACT = "TestERC20A"
|
||||
|
||||
# ChangeGreeting topic from Greeter contract calculated from event signature
|
||||
CHANGE_GREETING_TOPIC = Web3.keccak(text="ChangeGreeting(address,string)")
|
||||
# ERC-20 Transfer event topic
|
||||
TRANSFER_TOPIC = Web3.keccak(text="Transfer(address,address,uint256)")
|
||||
|
||||
|
||||
def test_pending_transaction_filter(cluster):
|
||||
|
||||
w3: Web3 = cluster.w3
|
||||
@ -65,7 +76,9 @@ def test_event_log_filter_by_contract(cluster):
|
||||
assert flt.get_all_entries() == [] # GetFilterLogs
|
||||
|
||||
# with tx
|
||||
tx = contract.functions.setGreeting("world").build_transaction()
|
||||
tx = contract.functions.setGreeting("world").build_transaction(
|
||||
{"from": ADDRS["validator"]}
|
||||
)
|
||||
tx_receipt = send_transaction(w3, tx)
|
||||
assert tx_receipt.status == 1
|
||||
|
||||
@ -102,7 +115,9 @@ def test_event_log_filter_by_address(cluster):
|
||||
assert flt.get_all_entries() == [] # GetFilterLogs
|
||||
|
||||
# with tx
|
||||
tx = contract.functions.setGreeting("world").build_transaction()
|
||||
tx = contract.functions.setGreeting("world").build_transaction(
|
||||
{"from": ADDRS["validator"]}
|
||||
)
|
||||
receipt = send_transaction(w3, tx)
|
||||
assert receipt.status == 1
|
||||
|
||||
@ -110,19 +125,565 @@ def test_event_log_filter_by_address(cluster):
|
||||
assert len(flt2.get_new_entries()) == 0
|
||||
|
||||
|
||||
def test_get_logs(cluster):
|
||||
def test_event_log_filter_by_topic(cluster):
|
||||
w3: Web3 = cluster.w3
|
||||
|
||||
new_greeting = "world"
|
||||
|
||||
test_cases = [
|
||||
{
|
||||
"name": "one contract emiting one topic",
|
||||
"filters": [
|
||||
{"topics": [CHANGE_GREETING_TOPIC.hex()]},
|
||||
{
|
||||
"fromBlock": 1,
|
||||
"toBlock": "latest",
|
||||
"topics": [CHANGE_GREETING_TOPIC.hex()],
|
||||
},
|
||||
],
|
||||
"exp_len": 1,
|
||||
"exp_topics": [[CHANGE_GREETING_TOPIC]],
|
||||
"contracts": [GREETER_CONTRACT],
|
||||
},
|
||||
{
|
||||
"name": "multiple contracts emitting same topic",
|
||||
"filters": [
|
||||
{
|
||||
"topics": [CHANGE_GREETING_TOPIC.hex()],
|
||||
},
|
||||
{
|
||||
"fromBlock": 1,
|
||||
"toBlock": "latest",
|
||||
"topics": [CHANGE_GREETING_TOPIC.hex()],
|
||||
},
|
||||
],
|
||||
"exp_len": 5,
|
||||
"exp_topics": [[CHANGE_GREETING_TOPIC]],
|
||||
"contracts": [GREETER_CONTRACT] * 5,
|
||||
},
|
||||
{
|
||||
"name": "multiple contracts emitting different topics",
|
||||
"filters": [
|
||||
{
|
||||
"topics": [[CHANGE_GREETING_TOPIC.hex(), TRANSFER_TOPIC.hex()]],
|
||||
},
|
||||
{
|
||||
"fromBlock": 1,
|
||||
"toBlock": "latest",
|
||||
"topics": [[CHANGE_GREETING_TOPIC.hex(), TRANSFER_TOPIC.hex()]],
|
||||
},
|
||||
],
|
||||
"exp_len": 3, # 2 transfer events, mint&transfer on deploy (2)tx in test
|
||||
"exp_topics": [
|
||||
[CHANGE_GREETING_TOPIC],
|
||||
[
|
||||
TRANSFER_TOPIC,
|
||||
HexBytes(pad_left("0x0")),
|
||||
HexBytes(pad_left(ADDRS["validator"].lower())),
|
||||
],
|
||||
[
|
||||
TRANSFER_TOPIC,
|
||||
HexBytes(pad_left(ADDRS["validator"].lower())),
|
||||
HexBytes(pad_left(ADDRS["community"].lower())),
|
||||
],
|
||||
],
|
||||
"contracts": [GREETER_CONTRACT, ERC20_CONTRACT],
|
||||
},
|
||||
]
|
||||
|
||||
for tc in test_cases:
|
||||
print("\nCase: {}".format(tc["name"]))
|
||||
|
||||
# register filters
|
||||
filters = []
|
||||
for fltr in tc["filters"]:
|
||||
filters.append(w3.eth.filter(fltr))
|
||||
|
||||
# without tx: filters should not return any entries
|
||||
for flt in filters:
|
||||
assert flt.get_new_entries() == [] # GetFilterChanges
|
||||
|
||||
# deploy all contracts
|
||||
# perform tx that emits event in all contracts
|
||||
for c in tc["contracts"]:
|
||||
tx = None
|
||||
if c == GREETER_CONTRACT:
|
||||
contract, _ = deploy_contract(w3, CONTRACTS[c])
|
||||
# validate deploy was successfull
|
||||
assert contract.caller.greet() == "Hello"
|
||||
# create tx that emits event
|
||||
tx = contract.functions.setGreeting(new_greeting).build_transaction(
|
||||
{"from": ADDRS["validator"]}
|
||||
)
|
||||
elif c == ERC20_CONTRACT:
|
||||
contract, _ = deploy_contract(w3, CONTRACTS[c])
|
||||
# validate deploy was successfull
|
||||
assert contract.caller.name() == "TestERC20"
|
||||
# create tx that emits event
|
||||
tx = contract.functions.transfer(
|
||||
ADDRS["community"], 10
|
||||
).build_transaction({"from": ADDRS["validator"]})
|
||||
|
||||
receipt = send_transaction(w3, tx)
|
||||
assert receipt.status == 1
|
||||
|
||||
# check filters new entries
|
||||
for flt in filters:
|
||||
new_entries = flt.get_new_entries() # GetFilterChanges
|
||||
assert len(new_entries) == tc["exp_len"]
|
||||
|
||||
for log in new_entries:
|
||||
# check if the new_entries have valid information
|
||||
assert log["topics"] in tc["exp_topics"]
|
||||
assert_log_block(w3, log)
|
||||
|
||||
# on next call of GetFilterChanges, no entries should be found
|
||||
# because there were no new logs that meet the filters params
|
||||
for flt in filters:
|
||||
assert flt.get_new_entries() == [] # GetFilterChanges
|
||||
w3.eth.uninstall_filter(flt.filter_id)
|
||||
|
||||
|
||||
def test_multiple_filters(cluster):
|
||||
w3: Web3 = cluster.w3
|
||||
|
||||
contract, _ = deploy_contract(w3, CONTRACTS["Greeter"])
|
||||
# test the contract was deployed successfully
|
||||
assert contract.caller.greet() == "Hello"
|
||||
|
||||
# without tx
|
||||
new_greeting = "hello, world"
|
||||
|
||||
# calculate topic from event signature
|
||||
topic = CHANGE_GREETING_TOPIC
|
||||
# another topic not related to the contract deployed
|
||||
another_topic = TRANSFER_TOPIC
|
||||
|
||||
filters = [
|
||||
{
|
||||
"params": {"address": contract.address},
|
||||
"exp_len": 1,
|
||||
},
|
||||
{
|
||||
"params": {"topics": [topic.hex()]},
|
||||
"exp_len": 1,
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"topics": [
|
||||
topic.hex(),
|
||||
another_topic.hex(),
|
||||
], # 'with all topics' condition
|
||||
},
|
||||
"exp_len": 0,
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"topics": [
|
||||
[topic.hex(), another_topic.hex()]
|
||||
], # 'with any topic' condition
|
||||
},
|
||||
"exp_len": 1,
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"address": contract.address,
|
||||
"topics": [[topic.hex(), another_topic.hex()]],
|
||||
},
|
||||
"exp_len": 1,
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"fromBlock": 1,
|
||||
"toBlock": 2,
|
||||
"address": contract.address,
|
||||
"topics": [[topic.hex(), another_topic.hex()]],
|
||||
},
|
||||
"exp_len": 0,
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"fromBlock": 1,
|
||||
"toBlock": "latest",
|
||||
"address": contract.address,
|
||||
"topics": [[topic.hex(), another_topic.hex()]],
|
||||
},
|
||||
"exp_len": 1,
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"fromBlock": 1,
|
||||
"toBlock": "latest",
|
||||
"topics": [[topic.hex(), another_topic.hex()]],
|
||||
},
|
||||
"exp_len": 1,
|
||||
},
|
||||
]
|
||||
|
||||
test_cases = [
|
||||
{"name": "register multiple filters and check for updates", "filters": filters},
|
||||
{
|
||||
"name": "register more filters than allowed (default: 200)",
|
||||
"register_err": "error creating filter: max limit reached",
|
||||
"filters": make_filter_array(205),
|
||||
},
|
||||
{
|
||||
"name": "register some filters, remove 2 filters and check for updates",
|
||||
"filters": filters,
|
||||
"rm_filters_post_tx": 2,
|
||||
},
|
||||
]
|
||||
|
||||
for tc in test_cases:
|
||||
print("\nCase: {}".format(tc["name"]))
|
||||
|
||||
# register the filters
|
||||
fltrs = []
|
||||
try:
|
||||
for flt in tc["filters"]:
|
||||
fltrs.append(w3.eth.filter(flt["params"]))
|
||||
except Exception as err:
|
||||
if "register_err" in tc:
|
||||
# if exception was expected when registering filters
|
||||
# the test is finished
|
||||
assert tc["register_err"] in str(err)
|
||||
# remove the registered filters
|
||||
remove_filters(w3, fltrs, 300)
|
||||
continue
|
||||
else:
|
||||
print(f"Unexpected {err=}, {type(err)=}")
|
||||
raise
|
||||
|
||||
# without tx: filters should not return any entries
|
||||
for flt in fltrs:
|
||||
assert flt.get_new_entries() == [] # GetFilterChanges
|
||||
|
||||
# with tx
|
||||
tx = contract.functions.setGreeting(new_greeting).build_transaction(
|
||||
{"from": ADDRS["validator"]}
|
||||
)
|
||||
receipt = send_transaction(w3, tx)
|
||||
assert receipt.status == 1
|
||||
|
||||
if "rm_filters_post_tx" in tc:
|
||||
# remove the filters
|
||||
remove_filters(w3, fltrs, tc["rm_filters_post_tx"])
|
||||
|
||||
for i, flt in enumerate(fltrs):
|
||||
# if filters were removed, should get a 'filter not found' error
|
||||
try:
|
||||
new_entries = flt.get_new_entries() # GetFilterChanges
|
||||
except Exception as err:
|
||||
if "rm_filters_post_tx" in tc and i < tc["rm_filters_post_tx"]:
|
||||
assert_no_filter_err(flt, err)
|
||||
# filter was removed and error checked. Continue to next filter
|
||||
continue
|
||||
else:
|
||||
print(f"Unexpected {err=}, {type(err)=}")
|
||||
raise
|
||||
|
||||
assert len(new_entries) == tc["filters"][i]["exp_len"]
|
||||
|
||||
if tc["filters"][i]["exp_len"] == 1:
|
||||
# check if the new_entries have valid information
|
||||
log = new_entries[0]
|
||||
assert log["address"] == contract.address
|
||||
assert log["topics"] == [topic]
|
||||
assert_log_block(w3, log)
|
||||
assert_change_greet_log_data(log, new_greeting)
|
||||
|
||||
# on next call of GetFilterChanges, no entries should be found
|
||||
# because there were no new logs that meet the filters params
|
||||
for i, flt in enumerate(fltrs):
|
||||
# if filters were removed, should get a 'filter not found' error
|
||||
try:
|
||||
assert flt.get_new_entries() == [] # GetFilterChanges
|
||||
except Exception as err:
|
||||
if "rm_filters_post_tx" in tc and i < tc["rm_filters_post_tx"]:
|
||||
assert_no_filter_err(flt, err)
|
||||
continue
|
||||
else:
|
||||
print(f"Unexpected {err=}, {type(err)=}")
|
||||
raise
|
||||
# remove the filters added on this test
|
||||
# because the node is not reseted for each test
|
||||
# otherwise may get a max-limit error for registering
|
||||
# new filters
|
||||
w3.eth.uninstall_filter(flt.filter_id)
|
||||
|
||||
|
||||
def test_register_filters_before_contract_deploy(cluster):
|
||||
w3: Web3 = cluster.w3
|
||||
|
||||
new_greeting = "hello, world"
|
||||
|
||||
# calculate topic from event signature
|
||||
topic = CHANGE_GREETING_TOPIC
|
||||
# another topic not related to the contract deployed
|
||||
another_topic = TRANSFER_TOPIC
|
||||
|
||||
filters = [
|
||||
{
|
||||
"params": {"topics": [topic.hex()]},
|
||||
"exp_len": 1,
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"topics": [
|
||||
topic.hex(),
|
||||
another_topic.hex(),
|
||||
], # 'with all topics' condition
|
||||
},
|
||||
"exp_len": 0,
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"topics": [
|
||||
[topic.hex(), another_topic.hex()]
|
||||
], # 'with any topic' condition
|
||||
},
|
||||
"exp_len": 1,
|
||||
},
|
||||
{
|
||||
"params": {
|
||||
"fromBlock": 1,
|
||||
"toBlock": "latest",
|
||||
"topics": [[topic.hex(), another_topic.hex()]],
|
||||
},
|
||||
"exp_len": 1,
|
||||
},
|
||||
]
|
||||
|
||||
# register the filters
|
||||
fltrs = []
|
||||
for flt in filters:
|
||||
fltrs.append(w3.eth.filter(flt["params"]))
|
||||
|
||||
# deploy contract
|
||||
contract, _ = deploy_contract(w3, CONTRACTS["Greeter"])
|
||||
# test the contract was deployed successfully
|
||||
assert contract.caller.greet() == "Hello"
|
||||
|
||||
# without tx: filters should not return any entries
|
||||
for flt in fltrs:
|
||||
assert flt.get_new_entries() == [] # GetFilterChanges
|
||||
|
||||
# perform tx to call contract that emits event
|
||||
tx = contract.functions.setGreeting(new_greeting).build_transaction(
|
||||
{"from": ADDRS["validator"]}
|
||||
)
|
||||
receipt = send_transaction(w3, tx)
|
||||
assert receipt.status == 1
|
||||
|
||||
for i, flt in enumerate(fltrs):
|
||||
new_entries = flt.get_new_entries() # GetFilterChanges
|
||||
assert len(new_entries) == filters[i]["exp_len"]
|
||||
|
||||
if filters[i]["exp_len"] == 1:
|
||||
# check if the new_entries have valid information
|
||||
log = new_entries[0]
|
||||
assert log["address"] == contract.address
|
||||
assert log["topics"] == [topic]
|
||||
assert_log_block(w3, log)
|
||||
assert_change_greet_log_data(log, new_greeting)
|
||||
|
||||
# on next call of GetFilterChanges, no entries should be found
|
||||
# because there were no new logs that meet the filters params
|
||||
for flt in fltrs:
|
||||
assert flt.get_new_entries() == [] # GetFilterChanges
|
||||
w3.eth.uninstall_filter(flt.filter_id)
|
||||
|
||||
|
||||
def test_get_logs(cluster):
|
||||
w3: Web3 = cluster.w3
|
||||
|
||||
# deploy greeter contract
|
||||
contract, _ = deploy_contract(w3, CONTRACTS["Greeter"])
|
||||
# test the contract was deployed successfully
|
||||
assert contract.caller.greet() == "Hello"
|
||||
|
||||
# calculate topic from event signature
|
||||
topic = CHANGE_GREETING_TOPIC
|
||||
|
||||
# another topic not related to the contract deployed
|
||||
another_topic = TRANSFER_TOPIC
|
||||
|
||||
# without tx - logs should be empty
|
||||
assert w3.eth.get_logs({"address": contract.address}) == []
|
||||
assert w3.eth.get_logs({"address": ADDRS["validator"]}) == []
|
||||
|
||||
# with tx
|
||||
tx = contract.functions.setGreeting("world").build_transaction()
|
||||
# update greeting
|
||||
new_greeting = "hello, world"
|
||||
tx = contract.functions.setGreeting(new_greeting).build_transaction(
|
||||
{"from": ADDRS["validator"]}
|
||||
)
|
||||
receipt = send_transaction(w3, tx)
|
||||
assert receipt.status == 1
|
||||
|
||||
assert len(w3.eth.get_logs({"address": contract.address})) == 1
|
||||
assert len(w3.eth.get_logs({"address": ADDRS["validator"]})) == 0
|
||||
tx_block_num = w3.eth.block_number
|
||||
|
||||
test_cases = [
|
||||
{
|
||||
"name": "get logs by block range - tx block number is within the range",
|
||||
"logs": w3.eth.get_logs({"fromBlock": 1, "toBlock": tx_block_num}),
|
||||
"exp_log": True,
|
||||
"exp_len": None, # there are other events within the block range specified
|
||||
},
|
||||
{
|
||||
"name": "get logs by block range - tx block number outside the range",
|
||||
"logs": w3.eth.get_logs({"fromBlock": 1, "toBlock": 2}),
|
||||
"exp_log": False,
|
||||
"exp_len": 0,
|
||||
},
|
||||
{
|
||||
"name": "get logs by contract address",
|
||||
"logs": w3.eth.get_logs({"address": contract.address}),
|
||||
"exp_log": True,
|
||||
"exp_len": 1,
|
||||
},
|
||||
{
|
||||
"name": "get logs by topic",
|
||||
"logs": w3.eth.get_logs({"topics": [topic.hex()]}),
|
||||
"exp_log": True,
|
||||
"exp_len": 1,
|
||||
},
|
||||
{
|
||||
"name": "get logs by incorrect topic - should not have logs",
|
||||
"logs": w3.eth.get_logs({"topics": [another_topic.hex()]}),
|
||||
"exp_log": False,
|
||||
"exp_len": 0,
|
||||
},
|
||||
{
|
||||
"name": "get logs by multiple topics ('with all' condition)",
|
||||
"logs": w3.eth.get_logs(
|
||||
{
|
||||
"topics": [
|
||||
topic.hex(),
|
||||
another_topic.hex(),
|
||||
]
|
||||
}
|
||||
),
|
||||
"exp_log": False,
|
||||
"exp_len": 0,
|
||||
},
|
||||
{
|
||||
"name": "get logs by multiple topics ('match any' condition)",
|
||||
"logs": w3.eth.get_logs({"topics": [[topic.hex(), another_topic.hex()]]}),
|
||||
"exp_log": True,
|
||||
"exp_len": 1,
|
||||
},
|
||||
{
|
||||
"name": "get logs by topic and block range",
|
||||
"logs": w3.eth.get_logs(
|
||||
{
|
||||
"fromBlock": tx_block_num,
|
||||
"toBlock": "latest",
|
||||
"topics": [topic.hex()],
|
||||
}
|
||||
),
|
||||
"exp_log": True,
|
||||
"exp_len": 1,
|
||||
},
|
||||
]
|
||||
|
||||
for tc in test_cases:
|
||||
print("\nCase: {}".format(tc["name"]))
|
||||
|
||||
# logs for validator address should remain empty
|
||||
assert len(w3.eth.get_logs({"address": ADDRS["validator"]})) == 0
|
||||
|
||||
logs = tc["logs"]
|
||||
|
||||
if tc["exp_len"] is not None:
|
||||
assert len(logs) == tc["exp_len"]
|
||||
|
||||
if tc["exp_log"]:
|
||||
found_log = False
|
||||
|
||||
for log in logs:
|
||||
if log["address"] == contract.address:
|
||||
# for the current test cases,
|
||||
# this event was emitted only once
|
||||
# so one log from this contract should exist
|
||||
# we check the flag to know it is not repeated
|
||||
assert found_log is False
|
||||
|
||||
found_log = True
|
||||
|
||||
assert log["topics"] == [topic]
|
||||
assert_log_block(w3, log)
|
||||
assert_change_greet_log_data(log, new_greeting)
|
||||
|
||||
assert found_log is True
|
||||
|
||||
|
||||
#################################################
|
||||
# Helper functions to assert logs information
|
||||
#################################################
|
||||
|
||||
|
||||
def assert_log_block(w3, log):
|
||||
block_hash = log["blockHash"]
|
||||
# check if the returned block hash is correct
|
||||
# getBlockByHash
|
||||
block = w3.eth.get_block(block_hash)
|
||||
# block should exist
|
||||
assert block.hash == block_hash
|
||||
|
||||
# check tx hash is correct
|
||||
tx_data = w3.eth.get_transaction(log["transactionHash"])
|
||||
assert tx_data["blockHash"] == block.hash
|
||||
|
||||
|
||||
def assert_change_greet_log_data(log, new_greeting):
|
||||
# check event log data ('from' and 'value' fields)
|
||||
types = ["address", "string"]
|
||||
names = ["from", "value"]
|
||||
values = abi.decode_abi(types, log["data"])
|
||||
log_data = dict(zip(names, values))
|
||||
|
||||
# the address stored in the data field may defer on lower/upper case characters
|
||||
# then, set all as lowercase for assertion
|
||||
assert log_data["from"] == ADDRS["validator"].lower()
|
||||
assert log_data["value"] == new_greeting
|
||||
|
||||
|
||||
def assert_no_filter_err(flt, err):
|
||||
msg_without_id = "filter not found" in str(err)
|
||||
msg_with_id = f"filter {flt.filter_id} not found" in str(err)
|
||||
assert msg_without_id or msg_with_id is True
|
||||
|
||||
|
||||
#################################################
|
||||
# Helper functions to add/remove filters
|
||||
#################################################
|
||||
|
||||
|
||||
def make_filter_array(array_len):
|
||||
filters = []
|
||||
for _ in range(array_len):
|
||||
filters.append(
|
||||
{
|
||||
"params": {"fromBlock": 1, "toBlock": "latest"},
|
||||
"exp_len": 1,
|
||||
},
|
||||
)
|
||||
return filters
|
||||
|
||||
|
||||
# removes the number of filters defined in 'count' argument, starting from index 0
|
||||
def remove_filters(w3, filters, count):
|
||||
# if number of filters to remove exceeds the amount of filters passed
|
||||
# update the 'count' to the length of the filters array
|
||||
if count > len(filters):
|
||||
count = len(filters)
|
||||
|
||||
for i in range(count):
|
||||
assert w3.eth.uninstall_filter(filters[i].filter_id)
|
||||
|
||||
|
||||
# adds a padding of '0's to a hex address based on the total byte length desired
|
||||
def pad_left(address, byte_len=32):
|
||||
a = address.split("0x")
|
||||
b = a[1].zfill(byte_len * 2)
|
||||
return "0x" + b
|
||||
|
@ -30,13 +30,14 @@ TEST_CONTRACTS = {
|
||||
"Greeter": "Greeter.sol",
|
||||
"BurnGas": "BurnGas.sol",
|
||||
"TestChainID": "ChainID.sol",
|
||||
"Mars": "Mars.sol",
|
||||
}
|
||||
|
||||
|
||||
def contract_path(name, filename):
|
||||
return (
|
||||
Path(__file__).parent
|
||||
/ "contracts/artifacts/contracts/"
|
||||
/ "hardhat/artifacts/contracts/"
|
||||
/ filename
|
||||
/ (name + ".json")
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user
Variable defined multiple times
This assignment to 'test_get_logs_by_topic' is unnecessary as it is redefined before this value is used.
Show more details