diff --git a/.gitignore b/.gitignore index 8d8a628e73..29549dd07f 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ build/ **/testnet.toml *~ .DS_Store +tests/artifacts/**/*.dbg.json diff --git a/.gitmodules b/.gitmodules index c3eed8eb08..7b90af6f1c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "tests/extra-test-toolkits"] path = tests/extra-test-toolkits url = https://github.com/Conflux-Chain/conflux-rust-test-toolkits.git +[submodule "tests/test_contracts"] + path = tests/test_contracts + url = https://github.com/Conflux-Chain/conflux-rust-dev-contracts.git + branch = main diff --git a/tests/admin_at_creation_test.py b/tests/admin_at_creation_test.py index 0167e9b9df..153d3cbfa9 100755 --- a/tests/admin_at_creation_test.py +++ b/tests/admin_at_creation_test.py @@ -1,125 +1,57 @@ #!/usr/bin/env python3 -from eth_utils import decode_hex - -from conflux.rpc import RpcClient -from conflux.transactions import CONTRACT_DEFAULT_GAS, COLLATERAL_UNIT_IN_DRIP -from conflux.utils import encode_hex, priv_to_addr, parse_as_int from test_framework.block_gen_thread import BlockGenThread -from test_framework.blocktools import create_transaction, encode_hex_0x -from test_framework.test_framework import ConfluxTestFramework +from test_framework.contracts import ConfluxTestFrameworkForContract, ZERO_ADDRESS, Contract from test_framework.mininode import * from test_framework.util import * from web3 import Web3 -class ClearAdminTest(ConfluxTestFramework): +class ClearAdminTest(ConfluxTestFrameworkForContract): def set_test_params(self): self.num_nodes = 8 + self.conf_parameters["executive_trace"] = "true" def setup_network(self): self.setup_nodes() connect_sample_nodes(self.nodes, self.log) sync_blocks(self.nodes) - self.rpc = RpcClient(self.nodes[0]) def run_test(self): - start_p2p_connection(self.nodes) block_gen_thread = BlockGenThread(self.nodes, self.log) block_gen_thread.start() - gas_price = 1 - gas = CONTRACT_DEFAULT_GAS - genesis_key = default_config["GENESIS_PRI_KEY"] - genesis_addr = encode_hex_0x(priv_to_addr(genesis_key)) - nonce = 0 - test_account_key = default_config["GENESIS_PRI_KEY_2"] - test_account_addr = encode_hex_0x(priv_to_addr(test_account_key)) - null_addr = "0x0000000000000000000000000000000000000000" - - file_dir = os.path.dirname(os.path.realpath(__file__)) - control_contract_file_path =os.path.join(file_dir, "..", "internal_contract", "metadata", "AdminControl.json") - control_contract_dict = json.loads(open(control_contract_file_path, "r").read()) - admin_control_contract = get_contract_instance(contract_dict=control_contract_dict) - admin_control_contract_addr = "0x0888000000000000000000000000000000000000" - - # Deploy a new instance of the create2factory other than the genesis block, - # so that the admin is the genesis_addr, in order to test hijackAdmin function - # in clear_admin_test_contract_addr.sol. - self.tx_conf = {"from":Web3.toChecksumAddress(genesis_addr), "nonce":int_to_hex(nonce), "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0} - create2factory = get_contract_instance( - abi_file = os.path.join(file_dir, "contracts/create2factory_abi.json"), - bytecode_file = os.path.join(file_dir, "contracts/create2factory_bytecode.dat"), - ) - raw_create = create2factory.constructor().buildTransaction(self.tx_conf) - tx_data = decode_hex(raw_create["data"]) - tx_create = create_transaction(pri_key=genesis_key, receiver=b'', nonce=nonce, gas_price=gas_price, data=tx_data, gas=gas, value=0, storage_limit=1920) - nonce += 1 - self.rpc.send_tx(tx_create, True) - receipt = self.rpc.get_transaction_receipt(tx_create.hash_hex()) - create2factory_addr = receipt['contractCreated'] + genesis_addr = self.genesis_addr + test_account_key = self.genesis_key2 + test_account_addr = self.genesis_addr2 + create2factory_addr = self.create2factory.address # Clear admin by non-admin (fail) self.log.info("Test unable to clear admin by non-admin.") - set_admin = admin_control_contract.functions \ - .setAdmin(Web3.toChecksumAddress(create2factory_addr), null_addr) \ - .buildTransaction({"to":admin_control_contract_addr, **self.tx_conf}) - tx_data = set_admin["data"] - self.call_contract(test_account_addr, test_account_key, admin_control_contract_addr, tx_data) - assert_equal(self.rpc.get_admin(create2factory_addr), genesis_addr) + self.adminControl.functions.setAdmin(create2factory_addr, ZERO_ADDRESS).cfx_transact(priv_key=test_account_key) + assert_equal(self.client.get_admin(create2factory_addr), genesis_addr) - clear_admin_test_contract = get_contract_instance( - abi_file = os.path.join(file_dir, "contracts/clear_admin_at_creation.json"), - bytecode_file = os.path.join(file_dir, "contracts/clear_admin_at_creation.bytecode"), - ) self.log.info("Test contract creation by itself") - raw_create = clear_admin_test_contract.constructor().buildTransaction(self.tx_conf) - tx_data = decode_hex(raw_create["data"]) - tx_create = create_transaction(pri_key=genesis_key, receiver=b'', nonce=nonce, gas_price=gas_price, data=tx_data, gas=gas, value=0, storage_limit=1920) - nonce += 1 - self.rpc.send_tx(tx_create, True) - receipt = self.rpc.get_transaction_receipt(tx_create.hash_hex()) - address = receipt["contractCreated"] - self.log.info(" contract created at %s" % address) - assert(address is not None) + clear_admin_test_contract: Contract = self.cfx_contract("AdminTestContract").deploy() + self.log.info(" contract created at %s" % clear_admin_test_contract.address) self.log.info("Test clear admin at contract creation through create2factory") - create_data = raw_create["data"] - salt = 0 - data = create2factory.functions.deploy(create_data, salt).buildTransaction({"to":create2factory_addr, **self.tx_conf})["data"] - # Compute the contract address. - clear_admin_test_contract_addr = Web3.toChecksumAddress("0x" + self.rpc.call(create2factory_addr, data)[-40:]) # Deploy the contract. - self.call_contract(genesis_addr, genesis_key, create2factory_addr, data, value=0) - assert_equal(self.rpc.get_admin(clear_admin_test_contract_addr), null_addr) + clear_admin_test_contract2: Contract = self.cfx_contract("AdminTestContract").deploy2(seed = 0) + assert_equal(self.client.get_admin(clear_admin_test_contract2.address), ZERO_ADDRESS) # The owner of create2factory_addr isn't hijacked. self.log.info("Test unable to hijack set admin.") - assert_equal(self.rpc.get_admin(create2factory_addr), genesis_addr) + assert_equal(self.client.get_admin(create2factory_addr), genesis_addr) self.log.info("Test unable to hijack owner through deployAndHijackAdmin") # Create a new contract through deployAndHijackAdmin. - new_contract_to_deploy = get_contract_instance( - abi_file = os.path.join(file_dir, "contracts/blackhole.json"), - bytecode_file = os.path.join(file_dir, "contracts/blackhole.bytecode"), - ) - self.tx_conf["nonce"] = 1 - self.tx_conf["from"] = Web3.toChecksumAddress(test_account_addr) - new_raw_create = new_contract_to_deploy.constructor().buildTransaction(self.tx_conf) - create_data = new_raw_create["data"] - data = clear_admin_test_contract.functions.deployAndHijackAdmin(create_data).buildTransaction({"to":clear_admin_test_contract_addr, **self.tx_conf})["data"] - new_contract_addr = "0x" + self.rpc.call(clear_admin_test_contract_addr, data)[-40:] - self.call_contract(test_account_addr, test_account_key, clear_admin_test_contract_addr, data, value=123) - # Check owner of the new contract isn't the "evil address" or null address. - assert_equal(self.rpc.get_admin(new_contract_addr), test_account_addr) + create_data = self.cfx_contract("BlackHole").constructor().data() - self.log.info("Pass") + fn_call = clear_admin_test_contract.functions.deployAndHijackAdmin(create_data) + created_address = fn_call.cfx_call(sender = test_account_addr) + fn_call.cfx_transact(priv_key = test_account_key, value = 123, decimals = 1) + assert_equal(self.client.get_admin(created_address), test_account_addr) - def call_contract(self, sender, priv_key, contract, data_hex, value=0, storage_limit=10000, gas=CONTRACT_DEFAULT_GAS): - c0 = self.rpc.get_collateral_for_storage(sender) - tx = self.rpc.new_contract_tx(receiver=contract, data_hex=data_hex, sender=sender, priv_key=priv_key, value=value, storage_limit=storage_limit, gas=gas) - assert_equal(self.rpc.send_tx(tx, True), tx.hash_hex()) - receipt = self.rpc.get_transaction_receipt(tx.hash_hex()) - self.log.info("call_contract storage collateral change={}".format((self.rpc.get_collateral_for_storage(sender) - c0) // COLLATERAL_UNIT_IN_DRIP)) - return receipt + self.log.info("Pass") if __name__ == "__main__": ClearAdminTest().main() diff --git a/tests/admin_control_test.py b/tests/admin_control_test.py index 7ec3ea63fa..d2b8e0a363 100755 --- a/tests/admin_control_test.py +++ b/tests/admin_control_test.py @@ -141,7 +141,7 @@ def run_test(self): check_status=True) assert_equal(client.get_balance(contract_addr), 10 ** 18) assert_equal(client.get_balance(addr), b0 - 10 ** 18 - charged_of_huge_gas(gas)) - assert_equal(client.get_admin(contract_addr), addr) + assert_equal(client.get_admin(contract_addr), addr.lower()) # transfer admin (fail) tx = self.call_contract_function( @@ -152,7 +152,7 @@ def run_test(self): contract_addr=Web3.toChecksumAddress("0x0888000000000000000000000000000000000000"), wait=True, check_status=True) - assert_equal(client.get_admin(contract_addr), addr) + assert_equal(client.get_admin(contract_addr), addr.lower()) assert_equal(client.get_balance(addr2), 5 * 10 ** 18 - charged_of_huge_gas(gas)) # transfer admin (success) diff --git a/tests/cip107_test.py b/tests/cip107_test.py index 2efdab5514..8af1318f96 100644 --- a/tests/cip107_test.py +++ b/tests/cip107_test.py @@ -3,13 +3,9 @@ from conflux.rpc import RpcClient from conflux.utils import * -from test_framework.test_framework import ConfluxTestFramework from test_framework.util import * from test_framework.mininode import * -from conflux.address import hex_to_b32_address, b32_address_to_hex - - -from os.path import dirname, realpath, join +from test_framework.contracts import ConfluxTestFrameworkForContract BASE = int(1e18) CIP107_NUMBER = 100 @@ -17,60 +13,9 @@ ZERO_ADDRESS = f"0x{'0'*40}" -def add_contract_address(contract, address): - w3 = Web3() - return w3.eth.contract(abi=contract.abi, bytecode=contract.bytecode, address=Web3.toChecksumAddress(address)) - - -def get_admin_contract(): - file_path = os.path.join(os.path.dirname( - __file__), "..", "internal_contract", "metadata", "AdminControl.json") - contract_dict = json.loads(open(file_path, "r").read()) - return get_contract_instance(contract_dict=contract_dict, address="0x0888000000000000000000000000000000000000") - - -def get_sponsor_contract(): - file_path = os.path.join(os.path.dirname( - __file__), "..", "internal_contract", "metadata", "SponsorWhitelistControl.json") - contract_dict = json.loads(open(file_path, "r").read()) - return get_contract_instance(contract_dict=contract_dict, address="0x0888000000000000000000000000000000000001") - - -def get_staking_contract(): - file_path = os.path.join(os.path.dirname( - __file__), "..", "internal_contract", "metadata", "Staking.json") - contract_dict = json.loads(open(file_path, "r").read()) - return get_contract_instance(contract_dict=contract_dict, address="0x0888000000000000000000000000000000000002") - - -def get_dao_contract(): - file_path = os.path.join(os.path.dirname( - __file__), "..", "internal_contract", "metadata", "ParamsControl.json") - contract_dict = json.loads(open(file_path, "r").read()) - return get_contract_instance(contract_dict=contract_dict, address="0x0888000000000000000000000000000000000007") - - -def get_create2factory_contract(): - abi_file = os.path.join(os.path.dirname(__file__), - "contracts", "simple_create2_factory.abi") - bytecode_file = os.path.join(os.path.dirname( - __file__), "contracts", "simple_create2_factory.bytecode") - return get_contract_instance(abi_file=abi_file, bytecode_file=bytecode_file) - - -def get_storage_contract(): - abi_file = os.path.join(os.path.dirname(__file__), - "contracts", "storage_test_for_cip107.json") - bytecode_file = os.path.join(os.path.dirname( - __file__), "contracts", "storage_test_for_cip107.bytecode") - return get_contract_instance(abi_file=abi_file, bytecode_file=bytecode_file) - - class CheckCollateral: - def __init__(self, framework, account): - self.rpc = framework.rpc - self.client = framework.client - self.read_contract = framework.read_contract + def __init__(self, framework: ConfluxTestFrameworkForContract, account): + self.framework = framework self.account = account self.total_collateral = None @@ -87,27 +32,28 @@ def __init__(self, framework, account): self.tick() def tick(self): - collateralInfo = self.client.get_collateral_info() + client = self.framework.client + collateralInfo = client.get_collateral_info() self.total_storage_point = int( collateralInfo["convertedStoragePoints"], 0) self.total_collateral = int(collateralInfo["totalStorageTokens"], 0) self.total_used_storage_point = int( collateralInfo["usedStoragePoints"], 0) - self.account_used_storage_point = self.client.get_used_storage_points( + self.account_used_storage_point = client.get_used_storage_points( self.account) - self.account_unused_storage_point = self.client.get_unused_storage_points( + self.account_unused_storage_point = client.get_unused_storage_points( self.account) - self.account_used_collateral = self.client.get_collateral_for_storage( + self.account_used_collateral = client.get_collateral_for_storage( self.account) - self.account_unused_collateral = self.client.get_sponsor_balance_for_collateral( + self.account_unused_collateral = client.get_sponsor_balance_for_collateral( self.account) # Compute adjusted total_issued, elimating influence from block reward and storage interest - supplyInfo = self.client.get_supply_info() + supplyInfo = client.get_supply_info() x = int(supplyInfo["totalIssued"], 0) // (BASE//160) * (BASE//160) - x -= self.client.epoch_number() * 2 * BASE + x -= client.epoch_number() * 2 * BASE self.total_issued = x def checked_tick(self, **kwargs): @@ -135,8 +81,10 @@ def checked_tick(self, **kwargs): if actual_diff != expect_diff: raise AssertionError( f"Assert attribute {attr} failed: expected {expect_diff}, actual {actual_diff}: {old[attr]} --> {getattr(self, attr)}") - - assert_equal(self.account_unused_storage_point, int(self.read_contract(get_sponsor_contract().functions.getAvailableStoragePoints(self.account)),0)) + + actual_value = self.framework.sponsorControl.functions.getAvailableStoragePoints( + self.account).cfx_call() + assert_equal(self.account_unused_storage_point, actual_value) def __str__(self): return f''' @@ -148,48 +96,42 @@ def __str__(self): account_used_collateral\t{self.account_used_collateral / BASE * 16} account_unused_collateral\t{self.account_unused_collateral / BASE * 16}''' + class StorageContract: - def __init__(self, framework, seed=0): + def __init__(self, framework: ConfluxTestFrameworkForContract, seed=0): self.framework = framework - storage = get_storage_contract() - receipt = framework.call_contract( - framework.create2factory.functions.callCreate2(seed, storage.bytecode)) - created_address = b32_address_to_hex([t for t in framework.rpc.trace_transaction( - receipt["transactionHash"]) if t["type"] == "create_result"][0]["action"]["addr"]) - storage = add_contract_address(storage, created_address) - self.storage = storage + self.storage = framework.cfx_contract("Storage").deploy2(seed).functions def set_sponsor(self, value): - self.framework.call_contract(get_sponsor_contract().functions.addPrivilegeByAdmin(self.storage.address, [ZERO_ADDRESS])) - self.framework.call_contract(get_sponsor_contract().functions.setSponsorForCollateral(self.storage.address), value=value) + sponsorContract = self.framework.sponsorControl.functions + sponsorContract.addPrivilegeByAdmin( + self.storage.address, [ZERO_ADDRESS]).cfx_transact() + sponsorContract.setSponsorForCollateral( + self.storage.address).cfx_transact(value=value) def set_entry(self, index): if isinstance(index, list): for i in index: - self.framework.call_contract( - self.storage.functions.change(i), storage_limit=64) + self.storage.change(i).cfx_transact(storage_limit=64) else: - self.framework.call_contract( - self.storage.functions.change(index), storage_limit=64) + self.storage.change(index).cfx_transact(storage_limit=64) def reset_entry(self, index): if isinstance(index, list): for i in index: - self.framework.call_contract( - self.storage.functions.reset(i), storage_limit=64) + self.storage.reset(i).cfx_transact(storage_limit=64) else: - self.framework.call_contract( - self.storage.functions.reset(index), storage_limit=64) + self.storage.reset(index).cfx_transact(storage_limit=64) def suicide(self): - self.framework.call_contract( - get_admin_contract().functions.destroy(self.storage.address)) + adminControl = self.framework.adminControl.functions + adminControl.destroy(self.storage.address).cfx_transact() def address(self): return self.storage.address -class CIP107Test(ConfluxTestFramework): +class CIP107Test(ConfluxTestFrameworkForContract): def set_test_params(self): self.num_nodes = 1 self.conf_parameters["executive_trace"] = "true" @@ -200,15 +142,6 @@ def set_test_params(self): self.conf_parameters["dao_vote_transition_height"] = 1 def run_test(self): - start_p2p_connection(self.nodes) - self.rpc = self.nodes[0].rpc - self.client = RpcClient(self.nodes[0]) - - create2factory = get_create2factory_contract() - receipt = self.call_contract(create2factory.constructor()) - self.create2factory = add_contract_address( - create2factory, receipt["contractCreated"]) - # Task 1: test if the collateral can be maintained correctly self.test_collateral_maintain() @@ -226,8 +159,7 @@ def test_change_sponsor(self): check.checked_tick( total_storage_point=2, total_collateral=None, total_issued=-2, account_unused_collateral=2, account_unused_storage_point=2) - self.call_contract(get_sponsor_contract().functions.setSponsorForCollateral( - storage.address()), value=0.5, priv_key=-1) + self.sponsorControl.functions.setSponsorForCollateral(storage.address()).cfx_transact(value=0.5, priv_key=-1) check.checked_tick( total_storage_point=3, total_collateral=None, total_issued=-3, account_unused_collateral=3, account_unused_storage_point=3) @@ -236,12 +168,15 @@ def test_params_update(self): storage = StorageContract(self, seed=2) check = CheckCollateral(self, storage.address()) + stakingControl = self.internal_contract("Staking").functions + paramsControl = self.internal_contract("ParamsControl").functions + # Obtain DAO Votes - self.call_contract(get_staking_contract().functions.deposit(1_000_000 * BASE)) + stakingControl.deposit(1_000_000 * BASE).cfx_transact() current_block_number = int(self.client.get_status()["blockNumber"], 0) locked_time = 5 * 15_768_000 # MINED_BLOCK_COUNT_PER_QUARTER - self.call_contract(get_staking_contract().functions.voteLock( - 1_000_000 * BASE, current_block_number + locked_time)) + stakingControl.voteLock( + 1_000_000 * BASE, current_block_number + locked_time).cfx_transact() # Set block number to the middle of a voting period vote_tick = int((self.client.epoch_number() + CIP104_PERIOD / 2) // @@ -249,42 +184,41 @@ def test_params_update(self): self.wait_for_block(vote_tick) # Vote - current_round = int(self.read_contract( - get_dao_contract().functions.currentRound()), 0) - self.call_contract(get_dao_contract().functions.castVote( - current_round, [{"topic_index": 2, "votes": [0, 1_000_000 * BASE, 0]}])) + current_round = paramsControl.currentRound().cfx_call() + paramsControl.castVote(current_round, [{"topic_index": 2, "votes": [ + 0, 1_000_000 * BASE, 0]}]).cfx_transact() storage.set_sponsor(3.75) check.checked_tick( total_storage_point=30, total_issued=-30, total_collateral=None, account_unused_collateral=30, account_unused_storage_point=30) self.wait_for_block(vote_tick + CIP104_PERIOD * 1, have_not_reach=True) - self.call_contract(get_dao_contract().functions.castVote( - current_round + 1, [{"topic_index": 2, "votes": [0, 1_000_000 * BASE, 0]}])) + paramsControl.castVote( + current_round + 1, [{"topic_index": 2, "votes": [0, 1_000_000 * BASE, 0]}]).cfx_transact() storage.set_sponsor(3.75) check.checked_tick( total_storage_point=30, total_issued=-30, total_collateral=None, account_unused_collateral=30, account_unused_storage_point=30) self.wait_for_block(vote_tick + CIP104_PERIOD * 2, have_not_reach=True) - self.call_contract(get_dao_contract().functions.castVote( - current_round + 2, [{"topic_index": 2, "votes": [0, 0, 1_000_000 * BASE]}])) + paramsControl.castVote( + current_round + 2, [{"topic_index": 2, "votes": [0, 0, 1_000_000 * BASE]}]).cfx_transact() storage.set_sponsor(3.75) check.checked_tick( total_storage_point=40, total_issued=-40, total_collateral=None, account_unused_collateral=20, account_unused_storage_point=40) self.wait_for_block(vote_tick + CIP104_PERIOD * 3, have_not_reach=True) - self.call_contract(get_dao_contract().functions.castVote( - current_round + 3, [{"topic_index": 2, "votes": [0, 0, 1_000_000 * BASE]}])) + paramsControl.castVote( + current_round + 3, [{"topic_index": 2, "votes": [0, 0, 1_000_000 * BASE]}]).cfx_transact() storage.set_sponsor(3.75) check.checked_tick( total_storage_point=48, total_issued=-48, total_collateral=None, account_unused_collateral=12, account_unused_storage_point=48) self.wait_for_block(vote_tick + CIP104_PERIOD * 4, have_not_reach=True) - self.call_contract(get_dao_contract().functions.castVote( - current_round + 4, [{"topic_index": 2, "votes": [0, 0, 1_000_000 * BASE]}])) + paramsControl.castVote( + current_round + 4, [{"topic_index": 2, "votes": [0, 0, 1_000_000 * BASE]}]).cfx_transact() self.wait_for_block(vote_tick + CIP104_PERIOD * 5, have_not_reach=True) - self.call_contract(get_dao_contract().functions.castVote( - current_round + 5, [{"topic_index": 2, "votes": [0, 0, 1_000_000 * BASE]}])) + paramsControl.castVote( + current_round + 5, [{"topic_index": 2, "votes": [0, 0, 1_000_000 * BASE]}]).cfx_transact() self.wait_for_block(vote_tick + CIP104_PERIOD * 7, have_not_reach=True) storage.set_sponsor(3.75) @@ -369,52 +303,6 @@ def wait_for_block(self, block_number, have_not_reach=False): def wait_for_cip107_activation(self): self.wait_for_block(CIP107_NUMBER, have_not_reach=True) - def read_contract(self, contract_function: ContractFunction): - tx = contract_function.build_transaction( - {"gas": 3000000, "gasPrice": 1, "chainId": 1}) - return self.client.call(tx["to"], tx["data"]) - - def call_contract(self, contract_function: ContractFunction, value=None, decimals: int = 18, gas=None, storage_limit=None, priv_key=None): - tx = contract_function.build_transaction( - {"gas": 3000000, "gasPrice": 1, "chainId": 1}) - data = bytes.fromhex(tx["data"][2:]) - - if value is not None: - value = int(value * (10**decimals)) - else: - value = 0 - - if storage_limit is None: - if len(tx["to"]) == 0: - storage_limit = 30000 - else: - storage_limit = 1024 - - if gas is None: - if len(tx["to"]) == 0: - gas = 10_000_000 - else: - gas = 3_000_000 - - if len(tx["to"]) == 0: - receiver = None - else: - receiver = tx["to"] - - if gas is None: - if len(data) > 0: - gas = 3000000 - else: - gas = 21000 - - tx = self.client.new_contract_tx( - receiver=receiver, value=value, data_hex=tx["data"], priv_key=priv_key, gas=gas, storage_limit=storage_limit) - self.client.send_tx(tx, True) - self.wait_for_tx([tx], True) - receipt = self.client.get_transaction_receipt(tx.hash_hex()) - # self.log.info(receipt) - return receipt - if __name__ == "__main__": CIP107Test().main() diff --git a/tests/cip118_activation_test.py b/tests/cip118_activation_test.py index bc52fe7d94..6193333644 100644 --- a/tests/cip118_activation_test.py +++ b/tests/cip118_activation_test.py @@ -3,40 +3,28 @@ from conflux.rpc import RpcClient from conflux.utils import * -from test_framework.test_framework import ConfluxTestFramework +from test_framework.contracts import ConfluxTestFrameworkForContract, ZERO_ADDRESS from test_framework.util import * from test_framework.mininode import * -from conflux.address import hex_to_b32_address, b32_address_to_hex -BASE = int(1e18) CIP118_NUMBER = 100 -ZERO_ADDRESS = f"0x{'0'*40}" -def get_sponsor_contract(): - file_path = os.path.join(os.path.dirname( - __file__), "..", "internal_contract", "metadata", "SponsorWhitelistControl.json") - contract_dict = json.loads(open(file_path, "r").read()) - return get_contract_instance(contract_dict=contract_dict, address="0x0888000000000000000000000000000000000001") - -class CIP118ActivationTest(ConfluxTestFramework): +class CIP118ActivationTest(ConfluxTestFrameworkForContract): def set_test_params(self): self.num_nodes = 1 self.conf_parameters["cip118_transition_number"] = CIP118_NUMBER + self.conf_parameters["executive_trace"] = "true" def run_test(self): - start_p2p_connection(self.nodes) - self.rpc = self.nodes[0].rpc - self.client = RpcClient(self.nodes[0]) - try: - self.read_contract(get_sponsor_contract().functions.getAvailableStoragePoints(ZERO_ADDRESS)) + self.sponsorControl.functions.getAvailableStoragePoints(ZERO_ADDRESS).cfx_call() raise Exception("Should fail") except Exception as e: assert_equal(e.response.data, 'VmError(InternalContract("unsupported function"))') self.wait_for_block(CIP118_NUMBER + 5) - self.read_contract(get_sponsor_contract().functions.getAvailableStoragePoints(ZERO_ADDRESS)) + self.sponsorControl.functions.getAvailableStoragePoints(ZERO_ADDRESS).cfx_call() def wait_for_block(self, block_number, have_not_reach=False): if have_not_reach: @@ -48,10 +36,5 @@ def wait_for_block(self, block_number, have_not_reach=False): time.sleep(0.1) self.log.info(f"block_number: {self.client.epoch_number()}") - def read_contract(self, contract_function: ContractFunction): - tx = contract_function.build_transaction( - {"gas": 3000000, "gasPrice": 1, "chainId": 1}) - return self.client.call(tx["to"], tx["data"]) - if __name__ == "__main__": CIP118ActivationTest().main() diff --git a/tests/cip97_test.py b/tests/cip97_test.py index af6d1cfa05..b2c53b0273 100644 --- a/tests/cip97_test.py +++ b/tests/cip97_test.py @@ -1,6 +1,6 @@ from conflux.rpc import RpcClient from conflux.utils import * -from test_framework.test_framework import ConfluxTestFramework +from test_framework.contracts import ConfluxTestFrameworkForContract, BASE from test_framework.util import * from test_framework.mininode import * @@ -8,69 +8,48 @@ CFX = 10 ** 18 -class CIP97Test(ConfluxTestFramework): +class CIP97Test(ConfluxTestFrameworkForContract): def set_test_params(self): self.num_nodes = 1 self.conf_parameters["dao_vote_transition_number"] = 100 self.conf_parameters["hydra_transition_number"] = 90 def run_test(self): - rpc = RpcClient(self.nodes[0]) - w3 = web3.Web3() - start_p2p_connection(self.nodes) priv = default_config["GENESIS_PRI_KEY"] sender = encode_hex(priv_to_addr(priv)) - - def send_tx(tx): - rpc.send_tx(tx, True) - self.wait_for_tx([tx], True) - - def send_tx_with_gas_used(tx): - tx_hash = rpc.send_tx(tx, True) - receipt = rpc.get_transaction_receipt(tx_hash) - assert_equal(receipt["outcomeStatus"], "0x0") - return int(receipt["gasUsed"], 16) + staking = self.internal_contract("Staking").functions def get_current_epoch(): - return int(self.nodes[0].cfx_getBlockByEpochNumber("latest_mined", False)["epochNumber"], 16) - - control_contract_file_path = join(dirname(realpath(__file__)), - *"../internal_contract/metadata/Staking.json".split("/")) - control_contract_dict = json.loads(open(control_contract_file_path, "r").read()) - staking = w3.eth.contract(abi=control_contract_dict["abi"]) - - def deposit_tx(): - return rpc.new_contract_tx(receiver="0888000000000000000000000000000000000002", - data_hex=staking.encodeABI(fn_name="deposit", args=[1 * CFX])) - - def withdraw_tx(): - return rpc.new_contract_tx(receiver="0888000000000000000000000000000000000002", - data_hex=staking.encodeABI(fn_name="withdraw", args=[int(1.1 * CFX)])) + return int(self.rpc.cfx_getBlockByEpochNumber("latest_mined", False)["epochNumber"], 16) + + def deposit(): + receipt = staking.deposit(1 * BASE).cfx_transact() + return int(receipt["gasUsed"], 16) + + def withdraw(): + receipt = staking.withdraw(int(1.1 * BASE)).cfx_transact() + return int(receipt["gasUsed"], 16) for i in range(5): self.log.debug(f"deposit {i}") - send_tx(deposit_tx()) + deposit() - tx = withdraw_tx() - old_withdraw_gas = send_tx_with_gas_used(tx) - assert_equal(len(rpc.get_deposit_list(sender)), 4) + old_withdraw_gas = withdraw() + assert_equal(len(self.client.get_deposit_list(sender)), 4) current_epoch = get_current_epoch() if current_epoch < 100: - rpc.generate_blocks(110 - current_epoch) + self.client.generate_blocks(110 - current_epoch) wait_until(lambda: get_current_epoch() > 100, timeout=20) - tx = deposit_tx() - old_deposit_gas = send_tx_with_gas_used(tx) - assert_equal(len(rpc.get_deposit_list(sender)), 5) + old_deposit_gas = deposit() + assert_equal(len(self.client.get_deposit_list(sender)), 5) - tx = withdraw_tx() - new_withdraw_gas = send_tx_with_gas_used(tx) - assert_equal(len(rpc.get_deposit_list(sender)), 0) + new_withdraw_gas = withdraw() + assert_equal(len(self.client.get_deposit_list(sender)), 0) - tx = deposit_tx() - new_deposit_gas = send_tx_with_gas_used(tx) - assert_equal(len(rpc.get_deposit_list(sender)), 0) + new_deposit_gas = deposit() + assert_equal(len(self.client.get_deposit_list(sender)), 0) assert_equal(old_deposit_gas - new_deposit_gas, 40000) assert_equal(old_withdraw_gas - new_withdraw_gas, 49600) diff --git a/tests/commission_privilege_test.py b/tests/commission_privilege_test.py index 4231a25a3b..15eb5d0dd2 100755 --- a/tests/commission_privilege_test.py +++ b/tests/commission_privilege_test.py @@ -1,190 +1,64 @@ #!/usr/bin/env python3 -from eth_utils import decode_hex from conflux.rpc import RpcClient from conflux.transactions import CONTRACT_DEFAULT_GAS, COLLATERAL_UNIT_IN_DRIP, charged_of_huge_gas -from conflux.utils import priv_to_addr, parse_as_int from test_framework.block_gen_thread import BlockGenThread -from test_framework.blocktools import create_transaction, encode_hex_0x, wait_for_initial_nonce_for_address -from test_framework.test_framework import ConfluxTestFramework +from test_framework.contracts import ConfluxTestFrameworkForContract, Contract, ZERO_ADDRESS from test_framework.mininode import * from test_framework.util import * -from web3 import Web3 - -class CommissionPrivilegeTest(ConfluxTestFramework): - REQUEST_BASE = { - 'gas': CONTRACT_DEFAULT_GAS, - 'gasPrice': 1, - 'chainId': 1, - } - - def __init__(self): - super().__init__() - - self.nonce_map = {} - self.genesis_priv_key = default_config['GENESIS_PRI_KEY'] - self.genesis_addr = priv_to_addr(self.genesis_priv_key) - self.balance_map = {self.genesis_priv_key: default_config['TOTAL_COIN']} +class CommissionPrivilegeTest(ConfluxTestFrameworkForContract): def set_test_params(self): self.num_nodes = 1 - def setup_network(self): - self.setup_nodes() - sync_blocks(self.nodes) - - def get_nonce(self, sender, inc=True): - if sender not in self.nonce_map: - self.nonce_map[sender] = wait_for_initial_nonce_for_address(self.nodes[0], sender) - else: - self.nonce_map[sender] += 1 - return self.nonce_map[sender] - - def send_transaction(self, transaction, wait, check_status): - self.nodes[0].p2p.send_protocol_msg(Transactions(transactions=[transaction])) - if wait: - self.wait_for_tx([transaction], check_status) - - def call_contract_function(self, contract, name, args, sender_key, value=None, - contract_addr=None, wait=False, - check_status=False, - storage_limit=0, - gas=None): - if contract_addr: - func = getattr(contract.functions, name) - else: - func = getattr(contract, name) - attrs = { - 'nonce': self.get_nonce(priv_to_addr(sender_key)), - ** CommissionPrivilegeTest.REQUEST_BASE - } - if contract_addr: - attrs['receiver'] = decode_hex(contract_addr) - attrs['to'] = contract_addr - else: - attrs['receiver'] = b'' - tx_data = func(*args).buildTransaction(attrs) - tx_data['data'] = decode_hex(tx_data['data']) - tx_data['pri_key'] = sender_key - tx_data['gas_price'] = tx_data['gasPrice'] - if value: - tx_data['value'] = value - tx_data.pop('gasPrice', None) - tx_data.pop('chainId', None) - tx_data.pop('to', None) - tx_data['storage_limit'] = storage_limit - if gas is not None: - tx_data['gas'] = gas - transaction = create_transaction(**tx_data) - self.send_transaction(transaction, wait, check_status) - return transaction - def run_test(self): - sponsor_whitelist_contract_addr = Web3.toChecksumAddress("0888000000000000000000000000000000000001") bytes_per_key = 64 collateral_per_storage_key = COLLATERAL_UNIT_IN_DRIP * 64 # change upper tx gas limit to (GENESIS_GAS_LIMIT/2 - 1); -1 because below gas is set to upper_bound + 1 - tx_gas_upper_bound = int(default_config["GENESIS_GAS_LIMIT"]/2 - 1) - - file_dir = os.path.dirname(os.path.realpath(__file__)) - - control_contract_file_path =os.path.join(file_dir, "..", "internal_contract", "metadata", "SponsorWhitelistControl.json") - control_contract_dict = json.loads(open(control_contract_file_path, "r").read()) - - control_contract = get_contract_instance(contract_dict=control_contract_dict) - - test_contract = get_contract_instance( - abi_file = os.path.join(file_dir, "contracts/commission_privilege_test_abi.json"), - bytecode_file = os.path.join(file_dir, "contracts/commission_privilege_test_bytecode.dat"), - ) - - start_p2p_connection(self.nodes) + tx_gas_upper_bound = int(default_config["GENESIS_GAS_LIMIT"] / 2 - 1) self.log.info("Initializing contract") - genesis_key = self.genesis_priv_key - genesis_addr = encode_hex_0x(self.genesis_addr) + genesis_addr = self.genesis_addr self.log.info("genesis_addr={}".format(genesis_addr)) - nonce = 0 gas_price = 1 gas = CONTRACT_DEFAULT_GAS block_gen_thread = BlockGenThread(self.nodes, self.log) block_gen_thread.start() - self.tx_conf = { - "from": Web3.toChecksumAddress(genesis_addr), - "nonce": int_to_hex(nonce), - "gas": int_to_hex(gas), - "gasPrice": int_to_hex(gas_price), - "chainId": 0 - } - - # Setup balance for node 0 - node = self.nodes[0] - client = RpcClient(node) + + client = self.client (addr1, priv_key1) = client.rand_account() (addr2, priv_key2) = client.rand_account() (addr3, priv_key3) = client.rand_account() (addr4, priv_key4) = client.rand_account() - tx = client.new_tx( - sender=genesis_addr, - priv_key=genesis_key, - value=10 ** 18, - nonce=self.get_nonce(self.genesis_addr), - receiver=addr1) - client.send_tx(tx, True) + self.cfx_transfer(addr1, value = 1) assert_equal(client.get_balance(addr1), 10 ** 18) - tx = client.new_tx( - sender=genesis_addr, - priv_key=genesis_key, - value=10 ** 18, - nonce=self.get_nonce(self.genesis_addr), - receiver=addr2) - client.send_tx(tx, True) + + self.cfx_transfer(addr2, value = 1) assert_equal(client.get_balance(addr2), 10 ** 18) - tx = client.new_tx( - sender=genesis_addr, - priv_key=genesis_key, - value=3 * 10 ** 18, - nonce=self.get_nonce(self.genesis_addr), - receiver=addr3) - client.send_tx(tx, True) + + self.cfx_transfer(addr3, value = 3) assert_equal(client.get_balance(addr3), 3 * 10 ** 18) # setup contract - transaction = self.call_contract_function( - contract=test_contract, - name="constructor", - args=[], - sender_key=self.genesis_priv_key, - storage_limit=1536) - contract_addr = self.wait_for_tx([transaction], True)[0]['contractCreated'] - self.log.info("contract_addr={}".format(contract_addr)) + before_setup_collateral = client.get_collateral_for_storage(genesis_addr) + test_contract: Contract = self.cfx_contract("CommissionPrivilegeTest").deploy() + after_setup_collateral = client.get_collateral_for_storage(genesis_addr) + contract_addr = test_contract.address assert_equal(client.get_balance(contract_addr), 0) - assert_equal(client.get_collateral_for_storage(genesis_addr), 1536 * COLLATERAL_UNIT_IN_DRIP) + assert_equal(after_setup_collateral - before_setup_collateral, 2048 * COLLATERAL_UNIT_IN_DRIP) # sponsor the contract failed due to sponsor_balance < 1000 * upper_bound b0 = client.get_balance(genesis_addr) - self.call_contract_function( - contract=control_contract, - name="setSponsorForGas", - args=[Web3.toChecksumAddress(contract_addr), tx_gas_upper_bound], - value=tx_gas_upper_bound * 1000 - 1, - sender_key=self.genesis_priv_key, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 0) - assert_equal(client.get_sponsor_for_gas(contract_addr), "0x0000000000000000000000000000000000000000") + self.sponsorControl.functions.setSponsorForGas(contract_addr, tx_gas_upper_bound).cfx_transact( + value = tx_gas_upper_bound * 1000 - 1, decimals = 0, err_msg='VmError(InternalContract("sponsor should at least sponsor upper_bound * 1000"))') + assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 0) + assert_equal(client.get_sponsor_for_gas(contract_addr), ZERO_ADDRESS) assert_equal(client.get_sponsor_gas_bound(contract_addr), 0) assert_equal(client.get_balance(genesis_addr), b0 - gas) # sponsor the contract succeed b0 = client.get_balance(genesis_addr) - self.call_contract_function( - contract=control_contract, - name="setSponsorForGas", - args=[Web3.toChecksumAddress(contract_addr), tx_gas_upper_bound], - value=10 ** 18, - sender_key=self.genesis_priv_key, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + self.sponsorControl.functions.setSponsorForGas(contract_addr, tx_gas_upper_bound).cfx_transact(value = 1, gas = gas) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 10 ** 18) assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr) assert_equal(client.get_sponsor_gas_bound(contract_addr), tx_gas_upper_bound) @@ -203,17 +77,9 @@ def run_test(self): # set privilege for addr4 b0 = client.get_balance(genesis_addr) c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="add", - args=[Web3.toChecksumAddress(addr4)], - sender_key=genesis_key, - contract_addr=contract_addr, - wait=True, - check_status=True, - storage_limit=64) + test_contract.functions.add(addr4).cfx_transact(storage_limit = 64) assert_equal(client.get_balance(genesis_addr), b0 - charged_of_huge_gas(gas) - collateral_per_storage_key) - assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + collateral_per_storage_key) + assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + collateral_per_storage_key) check_info = client.check_balance_against_transaction(addr4, contract_addr, gas, gas_price, storage_limit=0) assert_equal(check_info['willPayTxFee'], False) @@ -223,143 +89,71 @@ def run_test(self): # remove privilege for addr4 b0 = client.get_balance(genesis_addr) c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="remove", - args=[Web3.toChecksumAddress(addr4)], - sender_key=genesis_key, - contract_addr=contract_addr, - wait=True, - check_status=True) + test_contract.functions.remove(addr4).cfx_transact(storage_limit = 0) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 - collateral_per_storage_key) assert_equal(client.get_balance(genesis_addr), b0 - charged_of_huge_gas(gas) + collateral_per_storage_key) # set privilege for addr1 b0 = client.get_balance(genesis_addr) c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="add", - args=[Web3.toChecksumAddress(addr1)], - sender_key=genesis_key, - contract_addr=contract_addr, - wait=True, - check_status=True, - storage_limit=64) + test_contract.functions.add(addr1).cfx_transact(storage_limit=64) assert_equal(client.get_balance(genesis_addr), b0 - charged_of_huge_gas(gas) - collateral_per_storage_key) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + collateral_per_storage_key) # addr1 call contract with privilege sb = client.get_sponsor_balance_for_gas(contract_addr) b1 = client.get_balance(addr1) - self.call_contract_function( - contract=test_contract, - name="foo", - args=[], - sender_key=priv_key1, - contract_addr=contract_addr, - wait=True, - check_status=True) + test_contract.functions.foo().cfx_transact(priv_key=priv_key1, storage_limit=0) assert_equal(client.get_balance(addr1), b1) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb - charged_of_huge_gas(gas)) # addr1 call contract with privilege and large tx fee b1 = client.get_balance(addr1) sb = client.get_sponsor_balance_for_gas(contract_addr) - self.call_contract_function( - contract=test_contract, - name="foo", - args=[], - sender_key=priv_key1, - contract_addr=contract_addr, - wait=True, - check_status=True, - gas=tx_gas_upper_bound + 1) + test_contract.functions.foo().cfx_transact(priv_key=priv_key1, gas=tx_gas_upper_bound+1, storage_limit=0) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb) assert_equal(client.get_balance(addr1), b1 - charged_of_huge_gas(tx_gas_upper_bound + 1)) - + # addr2 call contract without privilege b2 = client.get_balance(addr2) sb = client.get_sponsor_balance_for_gas(contract_addr) - self.call_contract_function( - contract=test_contract, - name="foo", - args=[], - sender_key=priv_key2, - contract_addr=contract_addr, - wait=True, - check_status=True) + test_contract.functions.foo().cfx_transact(priv_key=priv_key2, storage_limit=0) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb) assert_equal(client.get_balance(addr2), b2 - charged_of_huge_gas(gas)) # set privilege for addr2 b0 = client.get_balance(genesis_addr) c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="add", - args=[Web3.toChecksumAddress(addr2)], - sender_key=genesis_key, - contract_addr=contract_addr, - wait=True, - check_status=True, - storage_limit=64) + test_contract.functions.add(addr2).cfx_transact(storage_limit = 64) assert_equal(client.get_balance(genesis_addr), b0 - charged_of_huge_gas(gas) - collateral_per_storage_key) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + collateral_per_storage_key) # now, addr2 call contract with privilege sb = client.get_sponsor_balance_for_gas(contract_addr) b2 = client.get_balance(addr2) - self.call_contract_function( - contract=test_contract, - name="foo", - args=[], - sender_key=priv_key2, - contract_addr=contract_addr, - wait=True, - check_status=True) + test_contract.functions.foo().cfx_transact(priv_key = priv_key2, storage_limit = 0) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb - charged_of_huge_gas(gas)) assert_equal(client.get_balance(addr2), b2) # remove privilege for addr1 b0 = client.get_balance(genesis_addr) c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="remove", - args=[Web3.toChecksumAddress(addr1)], - sender_key=genesis_key, - contract_addr=contract_addr, - wait=True, - check_status=True) + test_contract.functions.remove(addr1).cfx_transact(storage_limit = 0) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 - collateral_per_storage_key) assert_equal(client.get_balance(genesis_addr), b0 - charged_of_huge_gas(gas) + collateral_per_storage_key) # addr1 call contract without privilege sb = client.get_sponsor_balance_for_gas(contract_addr) b1 = client.get_balance(addr1) - self.call_contract_function( - contract=test_contract, - name="foo", - args=[], - sender_key=priv_key1, - contract_addr=contract_addr, - wait=True, - check_status=True) + test_contract.functions.foo().cfx_transact(priv_key = priv_key1, storage_limit = 0) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb) assert_equal(client.get_balance(addr1), b1 - charged_of_huge_gas(gas)) # new sponsor failed due to small sponsor_balance b3 = client.get_balance(addr3) sb = client.get_sponsor_balance_for_gas(contract_addr) - self.call_contract_function( - contract=control_contract, - name="setSponsorForGas", - args=[Web3.toChecksumAddress(contract_addr), tx_gas_upper_bound], - value=5 * 10 ** 17, - sender_key=priv_key3, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + self.sponsorControl.functions.setSponsorForGas(contract_addr, tx_gas_upper_bound).cfx_transact( + value = 0.5, storage_limit = 0, priv_key = priv_key3, err_msg = 'VmError(InternalContract("sponsor_balance is not exceed previous sponsor"))') assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb) assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr) assert_equal(client.get_balance(addr3), b3 - gas) @@ -367,14 +161,8 @@ def run_test(self): # new sponsor failed due to small upper bound b3 = client.get_balance(addr3) sb = client.get_sponsor_balance_for_gas(contract_addr) - self.call_contract_function( - contract=control_contract, - name="setSponsorForGas", - args=[Web3.toChecksumAddress(contract_addr), tx_gas_upper_bound - 1], - value=10 ** 18, - sender_key=priv_key3, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + self.sponsorControl.functions.setSponsorForGas(contract_addr, tx_gas_upper_bound - 1).cfx_transact( + value = 1, storage_limit = 0, priv_key = priv_key3, err_msg = 'VmError(InternalContract("upper_bound is not exceed previous sponsor"))') assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb) assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr) assert_equal(client.get_balance(addr3), b3 - gas) @@ -383,46 +171,27 @@ def run_test(self): b0 = client.get_balance(genesis_addr) b3 = client.get_balance(addr3) sb = client.get_sponsor_balance_for_gas(contract_addr) - self.call_contract_function( - contract=control_contract, - name="setSponsorForGas", - args=[Web3.toChecksumAddress(contract_addr), tx_gas_upper_bound + 1], - value=10 ** 18, - sender_key=priv_key3, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + self.sponsorControl.functions.setSponsorForGas(contract_addr, tx_gas_upper_bound + 1).cfx_transact(value = 1, storage_limit = 0, priv_key = priv_key3) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 10 ** 18) assert_equal(client.get_sponsor_gas_bound(contract_addr), tx_gas_upper_bound + 1) - assert_equal(client.get_sponsor_for_gas(contract_addr), addr3) + assert_equal(client.get_sponsor_for_gas(contract_addr), addr3.lower()) assert_equal(client.get_balance(addr3), b3 - 10 ** 18 - charged_of_huge_gas(gas)) assert_equal(client.get_balance(genesis_addr), b0 + sb) # sponsor the contract for collateral failed due to zero sponsor balance b3 = client.get_balance(addr3) - self.call_contract_function( - contract=control_contract, - name="setSponsorForCollateral", - args=[Web3.toChecksumAddress(contract_addr)], - value=0, - sender_key=priv_key3, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + self.sponsorControl.functions.setSponsorForCollateral(contract_addr).cfx_transact( + priv_key = priv_key3, storage_limit = 0, err_msg = 'VmError(InternalContract("zero sponsor balance is not allowed"))') assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), 0) - assert_equal(client.get_sponsor_for_collateral(contract_addr), "0x0000000000000000000000000000000000000000") + assert_equal(client.get_sponsor_for_collateral(contract_addr), ZERO_ADDRESS) assert_equal(client.get_balance(addr3), b3 - gas) # sponsor the contract for collateral succeed b3 = client.get_balance(addr3) - self.call_contract_function( - contract=control_contract, - name="setSponsorForCollateral", - args=[Web3.toChecksumAddress(contract_addr)], - value=10 ** 18 - 1, - sender_key=priv_key3, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + self.sponsorControl.functions.setSponsorForCollateral(contract_addr).cfx_transact( + value = 10 ** 18 - 1, decimals = 0, storage_limit = 0, priv_key = priv_key3) assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), 10 ** 18 - 1) - assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3) + assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3.lower()) assert_equal(client.get_balance(addr3), b3 - charged_of_huge_gas(gas) - 10 ** 18 + 1) check_info = client.check_balance_against_transaction(addr1, contract_addr, gas, gas_price, storage_limit=0) @@ -434,42 +203,21 @@ def run_test(self): b1 = client.get_balance(addr1) assert_equal(client.get_collateral_for_storage(contract_addr), 0) assert_equal(client.get_collateral_for_storage(addr1), 0) - self.call_contract_function( - contract=test_contract, - name="par_add", - args=[0, 2], - sender_key=priv_key1, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key) + test_contract.functions.par_add(0,2).cfx_transact(priv_key = priv_key1, storage_limit = bytes_per_key, err_msg="VmError(ExceedStorageLimit)") assert_equal(client.get_collateral_for_storage(contract_addr), 0) assert_equal(client.get_collateral_for_storage(addr1), 0) assert_equal(client.get_balance(addr1), b1 - gas) # addr1 create 2 keys without privilege, and storage limit is 2, should succeed b1 = client.get_balance(addr1) - self.call_contract_function( - contract=test_contract, - name="par_add", - args=[0, 2], - sender_key=priv_key1, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key * 2) + test_contract.functions.par_add(0,2).cfx_transact(priv_key = priv_key1, storage_limit=bytes_per_key * 2) assert_equal(client.get_collateral_for_storage(contract_addr), 0) assert_equal(client.get_collateral_for_storage(addr1), collateral_per_storage_key * 2) assert_equal(client.get_balance(addr1), b1 - charged_of_huge_gas(gas) - collateral_per_storage_key * 2) # remove 1 key create by addr1 b1 = client.get_balance(addr1) - self.call_contract_function( - contract=test_contract, - name="par_del", - args=[0, 1], - sender_key=priv_key1, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key * 2) + test_contract.functions.par_del(0,1).cfx_transact(priv_key = priv_key1, storage_limit=bytes_per_key * 2) assert_equal(client.get_collateral_for_storage(contract_addr), 0) assert_equal(client.get_collateral_for_storage(addr1), collateral_per_storage_key) assert_equal(client.get_balance(addr1), b1 - charged_of_huge_gas(gas) + collateral_per_storage_key) @@ -488,14 +236,7 @@ def run_test(self): sbc = client.get_sponsor_balance_for_collateral(contract_addr) sbg = client.get_sponsor_balance_for_gas(contract_addr) b2 = client.get_balance(addr2) - self.call_contract_function( - contract=test_contract, - name="par_add", - args=[2, 4], - sender_key=priv_key2, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key) + test_contract.functions.par_add(2,4).cfx_transact(priv_key = priv_key2, storage_limit=bytes_per_key) assert_equal(client.get_collateral_for_storage(contract_addr), collateral_per_storage_key * 2) assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), sbc - collateral_per_storage_key * 2) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sbg - charged_of_huge_gas(gas)) @@ -506,14 +247,7 @@ def run_test(self): sbc = client.get_sponsor_balance_for_collateral(contract_addr) sbg = client.get_sponsor_balance_for_gas(contract_addr) b2 = client.get_balance(addr2) - self.call_contract_function( - contract=test_contract, - name="par_add", - args=[4, 17], - sender_key=priv_key2, - contract_addr=contract_addr, - wait=True, - storage_limit=0) + test_contract.functions.par_add(4,17).cfx_transact(priv_key=priv_key2, storage_limit=0) assert_equal(client.get_collateral_for_storage(contract_addr), collateral_per_storage_key * 15) assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), sbc - collateral_per_storage_key * 13) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sbg - charged_of_huge_gas(gas)) @@ -530,14 +264,7 @@ def run_test(self): sbc = client.get_sponsor_balance_for_collateral(contract_addr) sbg = client.get_sponsor_balance_for_gas(contract_addr) b2 = client.get_balance(addr2) - self.call_contract_function( - contract=test_contract, - name="par_add", - args=[17, 18], - sender_key=priv_key2, - contract_addr=contract_addr, - wait=True, - storage_limit=0) + test_contract.functions.par_add(17,18).cfx_transact(priv_key=priv_key2, storage_limit=0, err_msg = "VmError(NotEnoughBalanceForStorage { required: 62500000000000000, got: 62499999999999999 })") assert_equal(client.get_collateral_for_storage(contract_addr), collateral_per_storage_key * 15) assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), sbc) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sbg - gas) @@ -548,14 +275,7 @@ def run_test(self): sbc = client.get_sponsor_balance_for_collateral(contract_addr) sbg = client.get_sponsor_balance_for_gas(contract_addr) b2 = client.get_balance(addr2) - self.call_contract_function( - contract=test_contract, - name="par_add", - args=[17, 18], - sender_key=priv_key2, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key * 2) + test_contract.functions.par_add(17, 18).cfx_transact(priv_key = priv_key2, storage_limit=bytes_per_key * 2) assert_equal(client.get_collateral_for_storage(contract_addr), collateral_per_storage_key * 15) assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), sbc) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sbg - charged_of_huge_gas(gas)) @@ -566,14 +286,7 @@ def run_test(self): sbc = client.get_sponsor_balance_for_collateral(contract_addr) sbg = client.get_sponsor_balance_for_gas(contract_addr) b2 = client.get_balance(addr2) - self.call_contract_function( - contract=test_contract, - name="par_del", - args=[2, 12], - sender_key=priv_key2, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key) + test_contract.functions.par_del(2,12).cfx_transact(priv_key=priv_key2, storage_limit=bytes_per_key) assert_equal(client.get_collateral_for_storage(contract_addr), collateral_per_storage_key * 5) assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), sbc + collateral_per_storage_key * 10) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sbg - charged_of_huge_gas(gas)) @@ -583,31 +296,18 @@ def run_test(self): # addr3 sponsor more, treat as transfer b3 = client.get_balance(addr3) sb = client.get_sponsor_balance_for_collateral(contract_addr) - self.call_contract_function( - contract=control_contract, - name="setSponsorForCollateral", - args=[Web3.toChecksumAddress(contract_addr)], - value=sb, - sender_key=priv_key3, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + self.sponsorControl.functions.setSponsorForCollateral(contract_addr).cfx_transact(value = sb, decimals = 0, priv_key = priv_key3, storage_limit = 0) assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), sb * 2) - assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3) + assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3.lower()) assert_equal(client.get_balance(addr3), b3 - charged_of_huge_gas(gas) - sb) # genesis sponsor with sponsor balance, should failed b0 = client.get_balance(genesis_addr) sb = client.get_sponsor_balance_for_collateral(contract_addr) - self.call_contract_function( - contract=control_contract, - name="setSponsorForCollateral", - args=[Web3.toChecksumAddress(contract_addr)], - value=sb + 1, - sender_key=self.genesis_priv_key, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + err_msg = 'VmError(InternalContract("sponsor_balance is not enough to cover previous sponsor\'s sponsor_balance and collateral_for_storage"))' + self.sponsorControl.functions.setSponsorForCollateral(contract_addr).cfx_transact(value = sb +1, decimals= 0, err_msg = err_msg) assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), sb) - assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3) + assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3.lower()) assert_equal(client.get_balance(genesis_addr), b0 - gas) # genesis sponsor with sponsor balance and collateral_for_storage, should succeed @@ -615,97 +315,44 @@ def run_test(self): b3 = client.get_balance(addr3) cfs = client.get_collateral_for_storage(contract_addr) sb = client.get_sponsor_balance_for_collateral(contract_addr) - self.call_contract_function( - contract=control_contract, - name="setSponsorForCollateral", - args=[Web3.toChecksumAddress(contract_addr)], - value=sb + cfs + 1, - sender_key=self.genesis_priv_key, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + self.sponsorControl.functions.setSponsorForCollateral(contract_addr).cfx_transact(value = sb + cfs + 1, decimals = 0) assert_equal(client.get_collateral_for_storage(contract_addr), cfs) assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), sb + 1) assert_equal(client.get_sponsor_for_collateral(contract_addr), genesis_addr) assert_equal(client.get_balance(genesis_addr), b0 - charged_of_huge_gas(gas) - sb - cfs - 1) assert_equal(client.get_balance(addr3), b3 + sb + cfs) + # storage change test c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="par", - args=[10, 20, 30, 41], - sender_key=self.genesis_priv_key, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key * 30) + test_contract.functions.par(10,20,30,41).cfx_transact(storage_limit=bytes_per_key * 30) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + 11 * collateral_per_storage_key) + c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="par_add_del", - args=[110, 120, 110, 120], - sender_key=self.genesis_priv_key, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key * 30) + test_contract.functions.par_add_del(110,120,110,120).cfx_transact(storage_limit = bytes_per_key * 30) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + 10 * collateral_per_storage_key) + c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="par_add_del", - args=[210, 220, 215, 220], - sender_key=self.genesis_priv_key, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key * 30) + test_contract.functions.par_add_del(210,220,215,220).cfx_transact(storage_limit=bytes_per_key * 30) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + 5 * collateral_per_storage_key) c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="par_add_del", - args=[310, 320, 320, 330], - sender_key=self.genesis_priv_key, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key * 30) + test_contract.functions.par_add_del(310,320,320,330).cfx_transact(storage_limit = bytes_per_key * 30) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + 10 * collateral_per_storage_key) c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="par_add_del", - args=[410, 420, 409, 430], - sender_key=self.genesis_priv_key, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key * 300) + test_contract.functions.par_add_del(410, 420, 409, 430).cfx_transact(storage_limit = bytes_per_key * 300) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + 21 * collateral_per_storage_key) # test recurrence c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="rec", - args=[510, 520, 3], - sender_key=self.genesis_priv_key, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key * 30) + test_contract.functions.rec(510, 520, 3).cfx_transact(storage_limit = bytes_per_key * 30) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + 4 * collateral_per_storage_key) c0 = client.get_collateral_for_storage(genesis_addr) - self.call_contract_function( - contract=test_contract, - name="par_del", - args=[510, 520], - sender_key=self.genesis_priv_key, - contract_addr=contract_addr, - wait=True, - storage_limit=bytes_per_key * 30) + test_contract.functions.par_del(510, 520).cfx_transact(storage_limit = bytes_per_key * 30) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 - 4 * collateral_per_storage_key) self.log.info("Pass") diff --git a/tests/conflux/rpc.py b/tests/conflux/rpc.py index d30daddd5b..3fffd60342 100644 --- a/tests/conflux/rpc.py +++ b/tests/conflux/rpc.py @@ -1,6 +1,7 @@ import os import random from typing import Optional, Union +from web3 import Web3 import eth_utils import rlp @@ -78,7 +79,7 @@ def rand_addr(self) -> str: def rand_account(self) -> (str, bytes): priv_key = eth_utils.encode_hex(os.urandom(32)) addr = eth_utils.encode_hex(priv_to_addr(priv_key)) - return (addr, priv_key) + return (Web3.toChecksumAddress(addr), priv_key) def rand_hash(self, seed: bytes = None) -> str: if seed is None: diff --git a/tests/contracts/clear_admin_at_creation.bytecode b/tests/contracts/clear_admin_at_creation.bytecode deleted file mode 100644 index 5c19919b21..0000000000 --- a/tests/contracts/clear_admin_at_creation.bytecode +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b50600073088800000000000000000000000000000000000090506100386105f360201b60201c565b73100000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166364efb22b306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156100ca57600080fd5b505afa1580156100de573d6000803e3d6000fd5b505050506040513d60208110156100f457600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff16141561018f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f726571756972652061646d696e20213d206576696c000000000000000000000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff166040516024016040516020818303038152906040527f8b0b3140000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b6020831061025c5780518252602082019150602081019050602083039250610239565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146102be576040519150601f19603f3d011682016040523d82523d6000602084013e6102c3565b606091505b505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166364efb22b306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561034557600080fd5b505afa158015610359573d6000803e3d6000fd5b505050506040513d602081101561036f57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff16141561040a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f726571756972652061646d696e20213d206e756c6c000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663c55b6bb73060006040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b15801561049257600080fd5b505af11580156104a6573d6000803e3d6000fd5b50505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166364efb22b306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561052957600080fd5b505afa15801561053d573d6000803e3d6000fd5b505050506040513d602081101561055357600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff16146105ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f726571756972652061646d696e203d3d206e756c6c000000000000000000000081525060200191505060405180910390fd5b506106c2565b600073088800000000000000000000000000000000000090508073ffffffffffffffffffffffffffffffffffffffff1663c55b6bb7337310000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b1580156106a757600080fd5b505af11580156106bb573d6000803e3d6000fd5b5050505050565b610572806106d16000396000f3fe60806040526004361061003f5760003560e01c80638b0b3140146100445780638ef99ff51461005b578063b61b2fe914610140578063ce0a10db1461014a575b600080fd5b34801561005057600080fd5b5061005961018b565b005b6101146004803603602081101561007157600080fd5b810190808035906020019064010000000081111561008e57600080fd5b8201836020820111156100a057600080fd5b803590602001918460018302840111640100000000831117156100c257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610247565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610148610455565b005b34801561015657600080fd5b5061015f610524565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600073088800000000000000000000000000000000000090508073ffffffffffffffffffffffffffffffffffffffff1663c55b6bb73060006040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b15801561022c57600080fd5b505af1158015610240573d6000803e3d6000fd5b5050505050565b600080600060019050600034905084516020860182f09250823b61026a57600091505b816102dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f637265617465206661696c65640000000000000000000000000000000000000081525060200191505060405180910390fd5b600073088800000000000000000000000000000000000090508073ffffffffffffffffffffffffffffffffffffffff1663c55b6bb7857310000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b15801561039157600080fd5b505af11580156103a5573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff1663c55b6bb78560006040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b15801561043157600080fd5b505af1158015610445573d6000803e3d6000fd5b5050505083945050505050919050565b600073088800000000000000000000000000000000000090508073ffffffffffffffffffffffffffffffffffffffff1663c55b6bb7337310000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b15801561050957600080fd5b505af115801561051d573d6000803e3d6000fd5b5050505050565b7310000000000000000000000000000000000000008156fea26469706673582212202c31ce63532b9505d29a0bc966eaf60cdfb73b60450947848b68c1bee93fa30c64736f6c63430007010033 \ No newline at end of file diff --git a/tests/contracts/clear_admin_at_creation.json b/tests/contracts/clear_admin_at_creation.json deleted file mode 100644 index 58f26822f9..0000000000 --- a/tests/contracts/clear_admin_at_creation.json +++ /dev/null @@ -1,53 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EVIL_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "clearAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "code", - "type": "bytes" - } - ], - "name": "deployAndHijackAdmin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "hijackAdmin", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/tests/contracts/clear_admin_at_creation.sol b/tests/contracts/clear_admin_at_creation.sol deleted file mode 100644 index 94dc640f39..0000000000 --- a/tests/contracts/clear_admin_at_creation.sol +++ /dev/null @@ -1,52 +0,0 @@ -pragma solidity >=0.7.0; - -import "internal/AdminControl.sol"; - -contract AdminTestContract { - address public constant EVIL_ADDR = 0x1000000000000000000000000000000000000000; - address constant ADMIN_CONTROL_ADDR = 0x0888000000000000000000000000000000000000; - - constructor() { - AdminControl ac = AdminControl(ADMIN_CONTROL_ADDR); - // This should fail - hijackAdmin(); - require(ac.getAdmin(address(this)) != EVIL_ADDR, "require admin != evil"); - // This should fail - address(this).call(abi.encodeWithSignature("clearAdmin()")); - require(ac.getAdmin(address(this)) != address(0), "require admin != null"); - // This should succeed - ac.setAdmin(address(this), address(0)); - require(ac.getAdmin(address(this)) == address(0), "require admin == null"); - } - - function deployAndHijackAdmin(bytes memory code) external payable returns (address) { - address addr; - bool success = true; - uint value = msg.value; - assembly { - addr := create(value, add(code, 0x20), mload(code)) - if iszero(extcodesize(addr)) { - success := 0 - } - } - require(success, "create failed"); - - // Hijack the admin to an evil party. - AdminControl ac = AdminControl(ADMIN_CONTROL_ADDR); - ac.setAdmin(addr, EVIL_ADDR); - // Hijack the admin to null. - ac.setAdmin(addr, address(0)); - return addr; - } - - function clearAdmin() public { - AdminControl ac = AdminControl(ADMIN_CONTROL_ADDR); - ac.setAdmin(address(this), address(0)); - } - - function hijackAdmin() public payable { - // Hijack the admin to an evil party. - AdminControl ac = AdminControl(ADMIN_CONTROL_ADDR); - ac.setAdmin(msg.sender, EVIL_ADDR); - } -} diff --git a/tests/contracts/commission_privilege_control.sol b/tests/contracts/commission_privilege_control.sol deleted file mode 100644 index d012d5b7ed..0000000000 --- a/tests/contracts/commission_privilege_control.sol +++ /dev/null @@ -1,59 +0,0 @@ -pragma solidity >=0.4.15; - -import "internal/SponsorWhitelistControl.sol"; - -contract CommissionPrivilegeTest { - mapping(uint => uint) public ss; - - function add(address account) public payable { - SponsorWhitelistControl cpc = SponsorWhitelistControl(0x0888000000000000000000000000000000000001); - address[] memory a = new address[](1); - a[0] = account; - cpc.addPrivilege(a); - } - - function remove(address account) public payable { - SponsorWhitelistControl cpc = SponsorWhitelistControl(0x0888000000000000000000000000000000000001); - address[] memory a = new address[](1); - a[0] = account; - cpc.removePrivilege(a); - } - - function foo() public payable { - } - - function par_add(uint start, uint end) public { - for (uint i = start; i < end; i++) { - ss[i] = 1; - } - } - function par_del(uint start, uint end) public { - for (uint i = start; i < end; i++) { - ss[i] = 0; - } - } - function par(uint s1, uint e1, uint s2, uint e2) public { - this.par_add(s1, e1); - this.par_del(s1, e1); - this.par_del(s2, e2); - this.par_add(s2, e2); - } - function par_add_del(uint s1, uint e1, uint s2, uint e2) public { - this.par_add(s1, e1); - this.par_del(s2, e2); - this.par_del(s1, e1); - this.par_add(s2, e2); - } - function rec(uint l, uint r, uint d) public payable { - if (d == 0) { - for (uint i = l; i < r; i++) { - ss[i] = 0; - } - } else { - for (uint i = l; i < r; i++) { - ss[i] = d % 2; - } - rec(l + 1, r - 1, d - 1); - } - } -} diff --git a/tests/contracts/commission_privilege_test_abi.json b/tests/contracts/commission_privilege_test_abi.json deleted file mode 100644 index 4f4aab80dc..0000000000 --- a/tests/contracts/commission_privilege_test_abi.json +++ /dev/null @@ -1,169 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "add", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "foo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "s1", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "e1", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s2", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "e2", - "type": "uint256" - } - ], - "name": "par", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "start", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "end", - "type": "uint256" - } - ], - "name": "par_add", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "s1", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "e1", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s2", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "e2", - "type": "uint256" - } - ], - "name": "par_add_del", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "start", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "end", - "type": "uint256" - } - ], - "name": "par_del", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "l", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "r", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "d", - "type": "uint256" - } - ], - "name": "rec", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "remove", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "ss", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] \ No newline at end of file diff --git a/tests/contracts/commission_privilege_test_bytecode.dat b/tests/contracts/commission_privilege_test_bytecode.dat deleted file mode 100644 index fa38b90d86..0000000000 --- a/tests/contracts/commission_privilege_test_bytecode.dat +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b50610aa3806100206000396000f3fe6080604052600436106100865760003560e01c8063989d12b611610059578063989d12b6146101b1578063c298557814610200578063c2b114aa1461020a578063d626f8071461024c578063f3354720146102a557610086565b80630a3b0a4f1461008b57806329092d0e146100cf5780632b44ec00146101135780633ca87b6b14610158575b600080fd5b6100cd600480360360208110156100a157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506102ea565b005b610111600480360360208110156100e557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610448565b005b34801561011f57600080fd5b506101566004803603604081101561013657600080fd5b8101908080359060200190929190803590602001909291905050506105a6565b005b34801561016457600080fd5b506101af6004803603608081101561017b57600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291905050506105de565b005b3480156101bd57600080fd5b506101ea600480360360208110156101d457600080fd5b81019080803590602001909291905050506107b0565b6040518082815260200191505060405180910390f35b6102086107c8565b005b61024a6004803603606081101561022057600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506107ca565b005b34801561025857600080fd5b506102a36004803603608081101561026f57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190505050610863565b005b3480156102b157600080fd5b506102e8600480360360408110156102c857600080fd5b810190808035906020019092919080359060200190929190505050610a35565b005b600073088800000000000000000000000000000000000190506060600167ffffffffffffffff8111801561031d57600080fd5b5060405190808252806020026020018201604052801561034c5781602001602082028036833780820191505090505b509050828160008151811061035d57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff166310128d3e826040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b838110156104065780820151818401526020810190506103eb565b5050505090500192505050600060405180830381600087803b15801561042b57600080fd5b505af115801561043f573d6000803e3d6000fd5b50505050505050565b600073088800000000000000000000000000000000000190506060600167ffffffffffffffff8111801561047b57600080fd5b506040519080825280602002602001820160405280156104aa5781602001602082028036833780820191505090505b50905082816000815181106104bb57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1663d2932db6826040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b83811015610564578082015181840152602081019050610549565b5050505090500192505050600060405180830381600087803b15801561058957600080fd5b505af115801561059d573d6000803e3d6000fd5b50505050505050565b60008290505b818110156105d95760008060008381526020019081526020016000208190555080806001019150506105ac565b505050565b3073ffffffffffffffffffffffffffffffffffffffff1663f335472085856040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b15801561063957600080fd5b505af115801561064d573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff16632b44ec0083836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b1580156106ac57600080fd5b505af11580156106c0573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff16632b44ec0085856040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b15801561071f57600080fd5b505af1158015610733573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff1663f335472083836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b15801561079257600080fd5b505af11580156107a6573d6000803e3d6000fd5b5050505050505050565b60006020528060005260406000206000915090505481565b565b600081141561080c5760008390505b828110156108065760008060008381526020019081526020016000208190555080806001019150506107d9565b5061085e565b60008390505b82811015610848576002828161082457fe5b06600080838152602001908152602001600020819055508080600101915050610812565b5061085d6001840160018403600184036107ca565b5b505050565b3073ffffffffffffffffffffffffffffffffffffffff1663f335472085856040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b1580156108be57600080fd5b505af11580156108d2573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff16632b44ec0085856040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b15801561093157600080fd5b505af1158015610945573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff16632b44ec0083836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b1580156109a457600080fd5b505af11580156109b8573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff1663f335472083836040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b158015610a1757600080fd5b505af1158015610a2b573d6000803e3d6000fd5b5050505050505050565b60008290505b81811015610a68576001600080838152602001908152602001600020819055508080600101915050610a3b565b50505056fea264697066735822122016722fde05837bfc55e1d3d3a364c4ab29cc9e102ca078b319b5e4401883255a64736f6c63430006060033 \ No newline at end of file diff --git a/tests/contracts/storage_test_for_cip107.bytecode b/tests/contracts/storage_test_for_cip107.bytecode deleted file mode 100644 index f60ea19f7e..0000000000 --- a/tests/contracts/storage_test_for_cip107.bytecode +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b5061024e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806307c488ff146100465780631d8c311f14610062578063e365981c1461007e575b600080fd5b610060600480360381019061005b919061017e565b61009a565b005b61007c6004803603810190610077919061017e565b6100db565b005b6100986004803603810190610093919061017e565b61010a565b005b60016000808367ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008282546100d191906101e4565b9250508190555050565b60016000808367ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000208190555050565b60008060008367ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000208190555050565b600080fd5b600067ffffffffffffffff82169050919050565b61015b8161013e565b811461016657600080fd5b50565b60008135905061017881610152565b92915050565b60006020828403121561019457610193610139565b5b60006101a284828501610169565b91505092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006101ef826101ab565b91506101fa836101ab565b9250828201905080821115610212576102116101b5565b5b9291505056fea2646970667358221220fc602c14f5f955061aef7b13d3749727cb4eb8e98c8f379c862423a835d5072264736f6c63430008110033 \ No newline at end of file diff --git a/tests/contracts/storage_test_for_cip107.json b/tests/contracts/storage_test_for_cip107.json deleted file mode 100644 index 61a9d599cc..0000000000 --- a/tests/contracts/storage_test_for_cip107.json +++ /dev/null @@ -1,46 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "index", - "type": "uint64" - } - ], - "name": "change", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "index", - "type": "uint64" - } - ], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "index", - "type": "uint64" - } - ], - "name": "set", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] \ No newline at end of file diff --git a/tests/contracts/storage_test_for_cip107.sol b/tests/contracts/storage_test_for_cip107.sol deleted file mode 100644 index 993f8c4a81..0000000000 --- a/tests/contracts/storage_test_for_cip107.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.8; - -contract Storage { - mapping(uint64 => uint) data; - - constructor() {} - - function change(uint64 index) public { - data[index] += 1; - } - - function set(uint64 index) public { - data[index] = 1; - } - - function reset(uint64 index) public { - data[index] = 0; - } -} \ No newline at end of file diff --git a/tests/light/rpc_test.py b/tests/light/rpc_test.py index 9cec928c72..97da74c086 100755 --- a/tests/light/rpc_test.py +++ b/tests/light/rpc_test.py @@ -10,6 +10,7 @@ from conflux.rpc import RpcClient from test_framework.test_framework import ConfluxTestFramework from test_framework.util import assert_equal, assert_greater_than, assert_is_hex_string, assert_raises_rpc_error, connect_nodes, sync_blocks, get_contract_instance +from test_framework.contracts import cfx_contract from web3 import Web3 FULLNODE0 = 0 @@ -20,7 +21,6 @@ NUM_BLOCKS = 600 NUM_TXS = 10 BLAME_CHECK_OFFSET = 20 -CONTRACT_PATH = "../contracts/commission_privilege_test_bytecode.dat" class LightRPCTest(ConfluxTestFramework): def set_test_params(self): @@ -161,9 +161,7 @@ def setup_network(self): self.block_d = block_d # deploy contract - bytecode_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), CONTRACT_PATH) - assert(os.path.isfile(bytecode_file)) - bytecode = open(bytecode_file).read() + bytecode = cfx_contract("CommissionPrivilegeTest").bytecode.hex() receipt, contractAddr = self.deploy_contract(bytecode) self.log.info(f"contract deployed: {contractAddr}") self._setup_sponsor(contractAddr) diff --git a/tests/rpc/test_tx_by_hash.py b/tests/rpc/test_tx_by_hash.py index f217254d6f..6e0bff4ca2 100644 --- a/tests/rpc/test_tx_by_hash.py +++ b/tests/rpc/test_tx_by_hash.py @@ -46,7 +46,7 @@ def test_tx_stated(self): tx2 = self.get_tx(tx_hash) assert_equal(tx2["from"], self.GENESIS_ADDR) - assert_equal(tx2["to"], to) + assert_equal(tx2["to"], to.lower()) assert_equal(tx2["nonce"], hex(tx.nonce)) assert_equal(tx2["gas"], hex(tx.gas)) assert_equal(tx2["gasPrice"], hex(tx.gas_price)) diff --git a/tests/sponsored_tx_test.py b/tests/sponsored_tx_test.py index c7997fdf56..c8fcfa59c6 100755 --- a/tests/sponsored_tx_test.py +++ b/tests/sponsored_tx_test.py @@ -7,18 +7,13 @@ from conflux.utils import priv_to_addr from test_framework.block_gen_thread import BlockGenThread from test_framework.blocktools import create_transaction, encode_hex_0x, wait_for_initial_nonce_for_address -from test_framework.test_framework import ConfluxTestFramework +from test_framework.contracts import ConfluxTestFrameworkForContract from test_framework.mininode import * from test_framework.util import * from web3 import Web3 +from web3.contract import Contract -class SponsoredTxTest(ConfluxTestFramework): - REQUEST_BASE = { - 'gas': CONTRACT_DEFAULT_GAS, - 'gasPrice': 1, - 'chainId': 1, - } - +class SponsoredTxTest(ConfluxTestFrameworkForContract): def __init__(self): super().__init__() @@ -30,22 +25,6 @@ def __init__(self): def set_test_params(self): self.num_nodes = 1 - def setup_network(self): - self.setup_nodes() - sync_blocks(self.nodes) - - def get_nonce(self, sender, inc=True): - if sender not in self.nonce_map: - self.nonce_map[sender] = wait_for_initial_nonce_for_address(self.nodes[0], sender) - else: - self.nonce_map[sender] += 1 - return self.nonce_map[sender] - - def send_transaction(self, transaction, wait, check_status): - self.nodes[0].p2p.send_protocol_msg(Transactions(transactions=[transaction])) - if wait: - self.wait_for_tx([transaction], check_status) - def call_contract_function(self, contract, name, args, sender_key, value=None, contract_addr=None, wait=False, check_status=False, @@ -81,76 +60,37 @@ def call_contract_function(self, contract, name, args, sender_key, value=None, return transaction def run_test(self): - sponsor_whitelist_contract_addr = Web3.toChecksumAddress("0888000000000000000000000000000000000001") collateral_per_storage_key = COLLATERAL_UNIT_IN_DRIP * 64 upper_bound = 5 * 10 ** 7 + gas = CONTRACT_DEFAULT_GAS - file_dir = os.path.dirname(os.path.realpath(__file__)) + self.log.info("Initializing contract") - control_contract_file_path =os.path.join(file_dir, "..", "internal_contract", "metadata", "SponsorWhitelistControl.json") - control_contract_dict = json.loads(open(control_contract_file_path, "r").read()) + control_contract = self.internal_contract("SponsorWhitelistControl") + test_contract = self.cfx_contract("CommissionPrivilegeTest") - control_contract = get_contract_instance(contract_dict=control_contract_dict) + client = self.client + genesis_addr = self.genesis_addr - test_contract = get_contract_instance( - abi_file=os.path.join(file_dir, "contracts/commission_privilege_test_abi.json"), - bytecode_file=os.path.join(file_dir, "contracts/commission_privilege_test_bytecode.dat"), - ) - start_p2p_connection(self.nodes) - self.log.info("Initializing contract") - genesis_key = self.genesis_priv_key - genesis_addr = encode_hex_0x(self.genesis_addr) - self.log.info("genesis_addr={}".format(genesis_addr)) - nonce = 0 - gas_price = 1 - gas = CONTRACT_DEFAULT_GAS - block_gen_thread = BlockGenThread(self.nodes, self.log) - block_gen_thread.start() - self.tx_conf = { - "from": Web3.toChecksumAddress(genesis_addr), - "nonce": int_to_hex(nonce), - "gas": int_to_hex(gas), - "gasPrice": int_to_hex(gas_price), - "chainId": 0 - } # Setup balance for node 0 - node = self.nodes[0] - client = RpcClient(node) (addr1, priv_key1) = client.rand_account() self.log.info("addr1={}".format(addr1)) - tx = client.new_tx( - sender=genesis_addr, - priv_key=genesis_key, - value=10 ** 6, - nonce=self.get_nonce(self.genesis_addr), - receiver=addr1) - client.send_tx(tx, True) + self.cfx_transfer(addr1, 10 ** 6, decimals=0) assert_equal(client.get_balance(addr1), 10 ** 6) # setup contract - transaction = self.call_contract_function( - contract=test_contract, - name="constructor", - args=[], - sender_key=self.genesis_priv_key, - storage_limit=20000) - contract_addr = self.wait_for_tx([transaction], True)[0]['contractCreated'] - self.log.info("contract_addr={}".format(contract_addr)) + test_contract: Contract = test_contract.deploy() + contract_addr = test_contract.address + self.log.info("contract_addr={}".format(test_contract.address)) assert_equal(client.get_balance(contract_addr), 0) + # sponsor the contract succeed b0 = client.get_balance(genesis_addr) - self.call_contract_function( - contract=control_contract, - name="setSponsorForGas", - args=[Web3.toChecksumAddress(contract_addr), upper_bound], - value=10 ** 18, - sender_key=self.genesis_priv_key, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + control_contract.functions.setSponsorForGas(contract_addr, upper_bound).cfx_transact(value = 1, gas = gas) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 10 ** 18) assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr) assert_equal(client.get_sponsor_gas_bound(contract_addr), upper_bound) @@ -159,66 +99,39 @@ def run_test(self): # set privilege for addr1 b0 = client.get_balance(genesis_addr) c0 = client.get_collateral_for_storage(genesis_addr) - transaction = self.call_contract_function( - contract=test_contract, - name="add", - args=[Web3.toChecksumAddress(addr1)], - sender_key=genesis_key, - contract_addr=contract_addr, - wait=True, - check_status=True, - storage_limit=64) + receipt = test_contract.functions.add(addr1).cfx_transact(storage_limit = 64, gas = gas) assert_equal(client.get_balance(genesis_addr), b0 - charged_of_huge_gas(gas) - collateral_per_storage_key) assert_equal(client.get_collateral_for_storage(genesis_addr), c0 + collateral_per_storage_key) - assert_equal(self.wait_for_tx([transaction], True)[0]['gasCoveredBySponsor'], False) + assert_equal(receipt['gasCoveredBySponsor'], False) + # addr1 call contract with privilege without enough cfx for gas fee sb = client.get_sponsor_balance_for_gas(contract_addr) b1 = client.get_balance(addr1) - transaction = self.call_contract_function( - contract=test_contract, - name="foo", - args=[], - sender_key=priv_key1, - contract_addr=contract_addr, - wait=True, - check_status=True) + receipt = test_contract.functions.foo().cfx_transact(priv_key = priv_key1, storage_limit = 0, gas = gas) assert_equal(client.get_balance(addr1), b1) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb - charged_of_huge_gas(gas)) - assert_equal(self.wait_for_tx([transaction], True)[0]['gasCoveredBySponsor'], True) + assert_equal(receipt['gasCoveredBySponsor'], True) + # sponsor collateral for the contract succeed b0 = client.get_balance(genesis_addr) - self.call_contract_function( - contract=control_contract, - name="setSponsorForCollateral", - args=[Web3.toChecksumAddress(contract_addr)], - value=10 ** 18, # 1 CFX = 1KB - sender_key=self.genesis_priv_key, - contract_addr=sponsor_whitelist_contract_addr, - wait=True) + control_contract.functions.setSponsorForCollateral(contract_addr).cfx_transact(value = 1, gas = gas) assert_equal(client.get_sponsor_balance_for_collateral(contract_addr), 10 ** 18) assert_equal(client.get_sponsor_for_collateral(contract_addr), genesis_addr) assert_equal(client.get_balance(genesis_addr), b0 - 10 ** 18 - charged_of_huge_gas(gas)) + # addr1 call contract with privilege without enough cfx for storage sb = client.get_sponsor_balance_for_gas(contract_addr) b1 = client.get_balance(addr1) - transaction = self.call_contract_function( - contract=test_contract, - name="foo", - args=[], - sender_key=priv_key1, - contract_addr=contract_addr, - wait=True, - check_status=True, - storage_limit=1024) + receipt = test_contract.functions.foo().cfx_transact(priv_key = priv_key1, storage_limit = 1024, gas = gas) assert_equal(client.get_balance(addr1), b1) assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb - charged_of_huge_gas(gas)) - assert_equal(self.wait_for_tx([transaction], True)[0]['storageCoveredBySponsor'], True) + assert_equal(receipt['storageCoveredBySponsor'], True) # addr1 call with larger storage limit, should be rejected for not enough balance - data = get_contract_function_data(test_contract, "foo", []) + data = test_contract.functions.foo().data() transaction = client.new_contract_tx(receiver=contract_addr, data_hex=encode_hex(data), priv_key=priv_key1, storage_limit=1025) # rejected for not enough balance @@ -226,18 +139,13 @@ def run_test(self): tx_info = self.nodes[0].txpool_txWithPoolInfo(transaction.hash_hex()) assert_equal(tx_info['exist'], False) + # send 1025 * 10 ** 18 // 1024 CFX to addr1 - tx = client.new_tx( - sender=genesis_addr, - priv_key=genesis_key, - value=1025 * 10 ** 18 // 1024, - nonce=self.get_nonce(self.genesis_addr), - receiver=addr1) - client.send_tx(tx, True) + receipt = self.cfx_transfer(addr1, value = 1025 * 10 ** 18 // 1024, decimals = 0) assert_equal(client.get_balance(addr1), 10 ** 6 + 1025 * 10 ** 18 // 1024) client.send_tx(transaction, True) - assert_equal(self.wait_for_tx([transaction], True)[0]['storageCoveredBySponsor'], False) + assert_equal(receipt['storageCoveredBySponsor'], False) tx_info = self.nodes[0].txpool_txWithPoolInfo(transaction.hash_hex()) # Now addr1 pays for storage collateral by itself. assert_equal(int(tx_info['local_nonce'], 16), 3) diff --git a/tests/test_contracts b/tests/test_contracts new file mode 160000 index 0000000000..acdce12560 --- /dev/null +++ b/tests/test_contracts @@ -0,0 +1 @@ +Subproject commit acdce12560e9f92c9e6e6c186bd05dc7855154eb diff --git a/tests/test_framework/contracts.py b/tests/test_framework/contracts.py new file mode 100644 index 0000000000..af88e84e49 --- /dev/null +++ b/tests/test_framework/contracts.py @@ -0,0 +1,265 @@ +from os.path import dirname, join +from pathlib import Path +import json + +from typing import Literal, Dict +import types + +from web3 import Web3 +from web3.contract import ContractFunction, Contract, ContractConstructor, get_abi_output_types +from conflux.address import b32_address_to_hex +from conflux.config import default_config +from conflux.utils import priv_to_addr +from test_framework.blocktools import encode_hex_0x +from test_framework.test_framework import ConfluxTestFramework, RpcClient, start_p2p_connection +from test_framework.util import * +from eth_utils import decode_hex + + +BASE = int(1e18) +ZERO_ADDRESS = f"0x{'0'*40}" + +InternalContractName = Literal["AdminControl", "SponsorWhitelistControl", + "Staking", "ConfluxContext", "PoSRegister", "CrossSpaceCall", "ParamsControl"] + +INTERNAL_CONTRACT_MAP: Dict[InternalContractName, str] = { + "AdminControl": "0x0888000000000000000000000000000000000000", + "SponsorWhitelistControl": "0x0888000000000000000000000000000000000001", + "Staking": "0x0888000000000000000000000000000000000002", + "ConfluxContext": "0x0888000000000000000000000000000000000004", + "PoSRegister": "0x0888000000000000000000000000000000000005", + "CrossSpaceCall": "0x0888000000000000000000000000000000000006", + "ParamsControl": "0x0888000000000000000000000000000000000007", +} + + +def _load_contract_metadata(name: str): + path = Path(join(dirname(__file__), "..", "test_contracts", "artifacts")) + try: + found_file = next(path.rglob(f"{name}.json")) + return json.loads(open(found_file, "r").read()) + except StopIteration: + raise Exception(f"Cannot found contract {name}'s metadata") + + +def cfx_contract(name: str, framework: ConfluxTestFramework = None) -> Contract: + metadata = _load_contract_metadata(name) + w3 = Web3() + contract = w3.eth.contract( + abi=metadata["abi"], bytecode=metadata["bytecode"]) + + contract.framework = framework + _enact_contract(contract) + return contract + + +def cfx_internal_contract(name: InternalContractName, framework: ConfluxTestFramework = None) -> Contract: + contract_addr = INTERNAL_CONTRACT_MAP[name] + return cfx_contract(name, framework).at(contract_addr) + + +def _add_address(self: Contract, address: str) -> Contract: + w3 = Web3() + new_contract = w3.eth.contract( + abi=self.abi, bytecode=self.bytecode, address=Web3.toChecksumAddress(address)) + + new_contract.framework = self.framework + _enact_contract(new_contract) + return new_contract + + +def _deploy_contract(self: Contract, *args, **kwargs) -> Contract: + if not hasattr(self, "framework"): + raise Exception("Contract does not hold Conflux framework") + + receipt = _cfx_transact(self.constructor( + *args, **kwargs), framework=self.framework) + return _add_address(self, receipt["contractCreated"]) + + +def _deploy_create2_contract(self: Contract, seed, *args, **kwargs) -> Contract: + if not hasattr(self, "framework"): + raise Exception("Contract does not hold Conflux framework") + + if not hasattr(self.framework, "create2factory"): + raise Exception("Create2Factory is not deployed") + + deployCode = _cfx_data(self.constructor(*args, **kwargs)) + receipt = self.framework.create2factory.functions.callCreate2( + seed, deployCode).cfx_transact() + + trace = self.framework.rpc.trace_transaction(receipt["transactionHash"]) + deploy_item = [t for t in trace if t["type"] == "create_result"][0] + created_address = b32_address_to_hex(deploy_item["action"]["addr"]) + + return _add_address(self, created_address) + + +def _enact_contract(contract: Contract): + framework = contract.framework + + contract.at = types.MethodType(_add_address, contract) + contract.deploy = types.MethodType(_deploy_contract, contract) + contract.deploy2 = types.MethodType(_deploy_create2_contract, contract) + + for _, obj in contract.functions.__dict__.items(): + if isinstance(obj, ContractFunction): + obj.framework = framework + + +def _get_framework(fn: ContractFunction) -> ConfluxTestFramework: + if hasattr(fn, "framework") and isinstance(fn.framework, ConfluxTestFramework): + pass + else: + raise Exception( + f"Not bind test framework when making call for {fn.function_identifier}") + + return fn.framework + + +def _cfx_transact(self: ContractFunction, value=None, decimals: int = 18, gas=None, storage_limit=None, priv_key=None, err_msg = None, framework=None): + if framework is None: + framework = _get_framework(self) + + tx = self.build_transaction( + {"gas": 3000000, "gasPrice": 1, "chainId": 1}) + data = bytes.fromhex(tx["data"][2:]) + + if value is not None: + value = int(value * (10**decimals)) + else: + value = 0 + + if storage_limit is None: + if len(tx["to"]) == 0: + storage_limit = 30000 + else: + storage_limit = 1024 + + if gas is None: + if len(tx["to"]) == 0: + gas = 10_000_000 + else: + gas = 3_000_000 + + if len(tx["to"]) == 0: + receiver = None + else: + receiver = tx["to"] + + if gas is None: + if len(data) > 0: + gas = 3000000 + else: + gas = 21000 + + tx = framework.client.new_contract_tx( + receiver=receiver, value=value, data_hex=tx["data"], priv_key=priv_key, gas=gas, storage_limit=storage_limit) + framework.client.send_tx(tx, True) + framework.wait_for_tx([tx], err_msg is None) + receipt = framework.client.get_transaction_receipt(tx.hash_hex()) + if err_msg is not None: + assert_equal(receipt["txExecErrorMsg"], err_msg) + # self.log.info(receipt) + return receipt + + + +def _cfx_call(self: ContractFunction, framework=None, sender=None, raw_output=False): + if framework is None: + framework = _get_framework(self) + + tx = self.build_transaction( + {"gas": 3000000, "gasPrice": 1, "chainId": 1}) + result = framework.client.call(tx["to"], tx["data"], sender=sender) + + if not raw_output: + output_types = get_abi_output_types(self.abi) + ans = self.web3.codec.decode_abi(output_types, decode_hex(result)) + if len(ans) == 0: + return + elif len(ans) == 1: + return ans[0] + else: + return ans + else: + return result + + +def _cfx_data(self: ContractFunction): + tx = self.build_transaction( + {"gas": 3000000, "gasPrice": 1, "chainId": 1}) + return tx["data"] + + +setattr(ContractFunction, 'cfx_transact', _cfx_transact) +setattr(ContractFunction, 'cfx_call', _cfx_call) +setattr(ContractFunction, 'data', _cfx_data) + +setattr(ContractConstructor, 'cfx_transact', _cfx_transact) +setattr(ContractConstructor, 'cfx_call', _cfx_call) +setattr(ContractConstructor, 'data', _cfx_data) + + +class ConfluxTestFrameworkForContract(ConfluxTestFramework): + def __init__(self): + super().__init__() + self.conf_parameters["executive_trace"] = "true" + + def before_test(self): + if not bool(self.conf_parameters["executive_trace"]): + raise AssertionError( + "Trace should be enabled for contract toolkit") + super().before_test() + self.rpc = self.nodes[0].rpc + self.client = RpcClient(self.nodes[0]) + ip = self.nodes[0].ip + port = self.nodes[0].ethrpcport + self.w3 = Web3(Web3.HTTPProvider(f'http://{ip}:{port}/')) + start_p2p_connection(self.nodes) + self.deploy_create2() + + self.genesis_key = default_config["GENESIS_PRI_KEY"] + self.genesis_addr = encode_hex_0x(priv_to_addr(self.genesis_key)) + self.genesis_key2 = default_config["GENESIS_PRI_KEY_2"] + self.genesis_addr2 = encode_hex_0x(priv_to_addr(self.genesis_key2)) + + def cfx_contract(self, name): + return cfx_contract(name, self) + + def internal_contract(self, name: InternalContractName): + return cfx_internal_contract(name, self) + + def cfx_transfer(self, receiver, value=None, gas_price=1, priv_key=None, decimals: int = 18): + if value is not None: + value = int(value * (10**decimals)) + else: + value = 0 + + tx = self.client.new_tx( + receiver=receiver, gas_price=gas_price, priv_key=priv_key, value=value) + self.client.send_tx(tx, True) + self.wait_for_tx([tx], True) + receipt = self.client.get_transaction_receipt(tx.hash_hex()) + # self.log.info(receipt) + return receipt + + def initialize_accounts(self, number = 10, value = 100): + def initialize_new_account() -> (str, bytes): + (address, priv) = self.client.rand_account() + if value > 0: + self.cfx_transfer(address, value = value) + return (address, priv) + + return [initialize_new_account() for _ in range(number)] + + @property + def adminControl(self): + return self.internal_contract("AdminControl") + + @property + def sponsorControl(self): + return self.internal_contract("SponsorWhitelistControl") + + def deploy_create2(self): + self.create2factory: Contract = self.cfx_contract("Create2Factory").deploy() diff --git a/tests/test_framework/test_framework.py b/tests/test_framework/test_framework.py index 15d2850b7c..2abc46690c 100644 --- a/tests/test_framework/test_framework.py +++ b/tests/test_framework/test_framework.py @@ -43,7 +43,6 @@ wait_until, ) - class TestStatus(Enum): PASSED = 1 FAILED = 2 @@ -212,6 +211,7 @@ def main(self): "--usecli specified but test does not support using CLI") self.setup_chain() self.setup_network() + self.before_test() self.run_test() success = TestStatus.PASSED except JSONRPCException as e: @@ -457,6 +457,9 @@ def _initialize_chain_clean(self): for i in range(self.num_nodes): initialize_datadir(self.options.tmpdir, i, self.options.port_min, self.conf_parameters, self.extra_conf_files) + + def before_test(self): + pass def wait_for_tx(self, all_txs, check_status=False): for tx in all_txs: @@ -486,8 +489,7 @@ def wait_for_tx(self, all_txs, check_status=False): for i in receipts: if int(i["outcomeStatus"], 0) != 0: raise AssertionError("Receipt states the execution failes: {}".format(i)) - return receipts - + return receipts class SkipTest(Exception): """This exception is raised to skip a test""" diff --git a/tests/vote_token_test.py b/tests/vote_token_test.py index 560891d128..5c669a22f9 100755 --- a/tests/vote_token_test.py +++ b/tests/vote_token_test.py @@ -5,51 +5,50 @@ from conflux.rpc import RpcClient from conflux.transactions import CONTRACT_DEFAULT_GAS from test_framework.blocktools import create_transaction, encode_hex_0x -from test_framework.smart_contract_bench_base import SmartContractBenchBase +from test_framework.contracts import ConfluxTestFrameworkForContract +from test_framework.block_gen_thread import BlockGenThread from test_framework.mininode import * from test_framework.util import * from web3 import Web3 -import os +from web3.contract import Contract import random -class VoteTokenTest(SmartContractBenchBase): - +class VoteTokenTest(ConfluxTestFrameworkForContract): def __init__(self): super().__init__() self.vote_address = "" self.token_address = "" - self.token_contract = None - self.vote_contract = None + self.token_contract: Contract = None + self.vote_contract: Contract = None self.accounts = [] self.num_of_options = 5 self.gas_price = 1 self.gas = CONTRACT_DEFAULT_GAS self.tx_conf = {"gas":int_to_hex(self.gas), "gasPrice":int_to_hex(self.gas_price)} - def setup_contract(self): - file_dir = os.path.dirname(os.path.realpath(__file__)) + def set_test_params(self): + self.num_nodes = 1 - self.token_contract = get_contract_instance(source=os.path.join(file_dir, "contracts/vote.sol"), - contract_name="DummyErc20") - self.vote_contract = get_contract_instance(source=os.path.join(file_dir, "contracts/vote.sol"), - contract_name="AdvancedTokenVote1202") + def setup_contract(self): + self.token_contract = self.cfx_contract("DummyErc20").deploy() + self.vote_contract = self.cfx_contract("AdvancedTokenVote1202").deploy() self.log.info("Initializing contract") - transaction = self.call_contract_function(self.token_contract, "constructor", [], self.default_account_key, storage_limit=20000) - self.token_address = self.wait_for_tx([transaction], True)[0]['contractCreated'] - transaction = self.call_contract_function(self.vote_contract, "constructor", [], self.default_account_key, storage_limit=20000) - self.vote_address = self.wait_for_tx([transaction], True)[0]['contractCreated'] self.accounts = [a[0] for a in self.new_address_and_transfer(5)] - def generate_transactions(self, i): - self.call_contract_function(self.vote_contract, "createIssue", - [i, Web3.toChecksumAddress(self.token_address), [j for j in range(self.num_of_options)], - [Web3.toChecksumAddress(priv_to_addr(acc)) for acc in self.accounts], "v"], - self.default_account_key, self.vote_address, True, True, storage_limit=5120) - for _ in range(self.num_of_options): - self.call_contract_function(self.vote_contract, "vote", [i, random.randint(0, self.num_of_options-1)], - self.default_account_key, self.vote_address, True, True, storage_limit=5120) + def run_test(self): + self.token_contract = self.cfx_contract("DummyErc20").deploy() + self.vote_contract = self.cfx_contract("AdvancedTokenVote1202").deploy() + self.log.info("Initializing contract") + self.accounts = self.initialize_accounts(5) + + for i in range(1): + self.vote_contract.functions.createIssue(i, self.token_contract.address, list(range(self.num_of_options)), [acc[0] for acc in self.accounts], "v").cfx_transact(storage_limit = 5120) + for _ in range(self.num_of_options): + vote_choice = random.randint(0, self.num_of_options - 1) + self.vote_contract.functions.vote(i, vote_choice).cfx_transact(storage_limit = 5120) + if __name__ == "__main__":