class ClearAdminTest(ConfluxTestFramework): def set_test_params(self): self.num_nodes = 8 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'] # 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) 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) 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) # 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) 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) self.log.info("Pass") 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
def run_test(self): file_dir = os.path.dirname(os.path.realpath(__file__)) pay_contract = get_contract_instance( abi_file=os.path.join(file_dir, "contracts/pay_abi.json"), bytecode_file=os.path.join(file_dir, "contracts/pay_bytecode.dat"), ) 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) start_p2p_connection(self.nodes) self.log.info("Initializing contract") genesis_key = self.genesis_priv_key genesis_addr = self.genesis_addr self.log.info("genesis_addr={}".format(encode_hex_0x(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(encode_hex_0x(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) (addr, priv_key) = client.rand_account() self.log.info("addr=%s priv_key=%s", addr, priv_key) tx = client.new_tx(value=5 * 10 ** 18, receiver=addr, nonce=self.get_nonce(genesis_addr)) client.send_tx(tx, True) assert_equal(client.get_balance(addr), 5000000000000000000) (addr2, priv_key2) = client.rand_account() self.log.info("addr2=%s priv_key2=%s", addr2, priv_key2) tx = client.new_tx(value=5 * 10 ** 18, receiver=addr2, nonce=self.get_nonce(genesis_addr)) client.send_tx(tx, True) assert_equal(client.get_balance(addr2), 5000000000000000000) # deploy pay contract tx = self.call_contract_function( contract=pay_contract, name="constructor", args=[], sender_key=priv_key, storage_limit=512) contract_addr = self.wait_for_tx([tx], True)[0]['contractCreated'] self.log.info("contract_addr={}".format(contract_addr)) assert_equal(client.get_collateral_for_storage(addr), 512 * 976562500000000) assert_equal(client.get_balance(contract_addr), 0) # deposit 10**18 b0 = int(node.cfx_getBalance(addr), 16) tx = self.call_contract_function( contract=pay_contract, name="recharge", args=[], sender_key=priv_key, contract_addr=contract_addr, value=10 ** 18, wait=True, 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) # transfer admin (fail) tx = self.call_contract_function( contract=admin_control_contract, name="setAdmin", args=[Web3.toChecksumAddress(contract_addr), Web3.toChecksumAddress(addr2)], sender_key=priv_key2, contract_addr=Web3.toChecksumAddress("0x0888000000000000000000000000000000000000"), wait=True, check_status=True) assert_equal(client.get_admin(contract_addr), addr) assert_equal(client.get_balance(addr2), 5 * 10 ** 18 - charged_of_huge_gas(gas)) # transfer admin (success) tx = self.call_contract_function( contract=admin_control_contract, name="setAdmin", args=[Web3.toChecksumAddress(contract_addr), Web3.toChecksumAddress(addr2)], sender_key=priv_key, contract_addr=Web3.toChecksumAddress("0x0888000000000000000000000000000000000000"), wait=True, check_status=True) assert_equal(client.get_admin(contract_addr), addr2) # destroy b0 = client.get_balance(addr) tx = self.call_contract_function( contract=admin_control_contract, name="destroy", args=[Web3.toChecksumAddress(contract_addr)], sender_key=priv_key2, contract_addr=Web3.toChecksumAddress("0x0888000000000000000000000000000000000000"), wait=True, check_status=True) assert_equal(client.get_balance(contract_addr), 0) assert_equal(client.get_balance(addr2), 6 * 10 ** 18 - charged_of_huge_gas(gas) * 2) assert_equal(client.get_collateral_for_storage(addr), 0) assert_equal(client.get_balance(addr), b0 + 512 * 976562500000000) self.log.info("Pass")
def run_test(self): file_dir = os.path.dirname(os.path.realpath(__file__)) pay_contract = get_contract_instance( abi_file=os.path.join(file_dir, "contracts/pay_abi.json"), bytecode_file=os.path.join(file_dir, "contracts/pay_bytecode.dat"), ) admin_control_contract = get_contract_instance( abi_file=os.path.join(file_dir, "contracts/admin_control_abi.json"), bytecode_file=os.path.join(file_dir, "contracts/admin_control_bytecode.dat"), ) start_p2p_connection(self.nodes) self.log.info("Initializing contract") genesis_key = self.genesis_priv_key genesis_addr = self.genesis_addr self.log.info("genesis_addr={}".format(encode_hex_0x(genesis_addr))) nonce = 0 gas_price = 1 gas = 50000000 block_gen_thread = BlockGenThread(self.nodes, self.log) block_gen_thread.start() self.tx_conf = {"from":Web3.toChecksumAddress(encode_hex_0x(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) (addr, priv_key) = client.rand_account() self.log.info("addr=%s priv_key=%s", addr, priv_key) tx = client.new_tx(value=5 * 10 ** 18, receiver=addr, nonce=self.get_nonce(genesis_addr)) client.send_tx(tx, True) assert_equal(client.get_balance(addr), 5000000000000000000) (addr2, priv_key2) = client.rand_account() self.log.info("addr2=%s priv_key2=%s", addr2, priv_key2) tx = client.new_tx(value=5 * 10 ** 18, receiver=addr2, nonce=self.get_nonce(genesis_addr)) client.send_tx(tx, True) assert_equal(client.get_balance(addr2), 5000000000000000000) # deploy pay contract tx = self.call_contract_function( contract=pay_contract, name="constructor", args=[], sender_key=priv_key) contract_addr = self.wait_for_tx([tx], True)[0]['contractCreated'] self.log.info("contract_addr={}".format(contract_addr)) assert_equal(client.get_balance(contract_addr), 0) # deposit 10**18 b0 = int(node.cfx_getBalance(addr), 16) tx = self.call_contract_function( contract=pay_contract, name="recharge", args=[], sender_key=priv_key, contract_addr=contract_addr, value=10 ** 18, wait=True, check_status=True) assert_equal(client.get_balance(contract_addr), 10 ** 18) assert_equal(client.get_balance(addr), b0 - 10 ** 18 - gas + gas // 4) assert_equal(client.get_admin(contract_addr), addr) # transfer admin (fail) tx = self.call_contract_function( contract=admin_control_contract, name="set_admin", args=[Web3.toChecksumAddress(contract_addr), Web3.toChecksumAddress(addr2)], sender_key=priv_key2, contract_addr=Web3.toChecksumAddress("0x6060de9e1568e69811c4a398f92c3d10949dc891"), wait=True, check_status=True) assert_equal(client.get_admin(contract_addr), addr) # transfer admin (success) tx = self.call_contract_function( contract=admin_control_contract, name="set_admin", args=[Web3.toChecksumAddress(contract_addr), Web3.toChecksumAddress(addr2)], sender_key=priv_key, contract_addr=Web3.toChecksumAddress("0x6060de9e1568e69811c4a398f92c3d10949dc891"), wait=True, check_status=True) assert_equal(client.get_admin(contract_addr), addr2) # destroy tx = self.call_contract_function( contract=admin_control_contract, name="destroy", args=[Web3.toChecksumAddress(contract_addr)], sender_key=priv_key2, contract_addr=Web3.toChecksumAddress("0x6060de9e1568e69811c4a398f92c3d10949dc891"), wait=True, check_status=True) assert_equal(client.get_balance(contract_addr), 0) assert_equal(client.get_balance(addr2), 5999999999912500000 + gas // 4) self.log.info("Pass")