def test_convert_for_internal(self): min_return = 10 amount_to_convert = 5 convert_result_amount = 10 for_address = Address.from_string("hx" + "a" * 40) icx_token_score_interface = \ self.network_score.create_interface_score(self.icx_token, ProxyScore(ABCIcxToken)) icx_token_score_interface.withdrawTo = PropertyMock() irc_token_score_interface = \ self.network_score.create_interface_score(self.connector_token_list[0], ProxyScore(ABCIRCToken)) irc_token_score_interface.transfer = PropertyMock() # success case: finally converted token is Icx token ( Icx token SCORE's 'withdrawTo' method should be called ) converted_path = [ self.connector_token_list[0], self.flexible_token_address_list[0], self.icx_token ] # '_convert_by_path' method returns 'to' token Address, and converted amount with MultiPatch([ patch_property(IconScoreBase, 'msg', Message(self.network_owner)), patch.object(Network, '_convert_by_path', return_value=(self.icx_token, convert_result_amount)), patch.object(Network, 'create_interface_score', return_value=icx_token_score_interface) ]): # register icx_token self.network_score._icx_tokens[self.icx_token] = True self.network_score._convert_for_internal(converted_path, amount_to_convert, min_return, for_address) icx_token_score_interface.withdrawTo.assert_called_with( convert_result_amount, for_address) # success case: finally converted token is irc token ( token SCORE's 'transfer' method should be called ) converted_path = [ self.icx_token, self.flexible_token_address_list[0], self.connector_token_list[1] ] # '_convert_by_path' method returns 'to' token Address, and converted amount with MultiPatch([ patch_property(IconScoreBase, 'msg', Message(self.network_owner)), patch.object(Network, '_convert_by_path', return_value=(self.connector_token_list[1], convert_result_amount)), patch.object(Network, 'create_interface_score', return_value=irc_token_score_interface) ]): self.network_score._convert_for_internal(converted_path, amount_to_convert, min_return, for_address) irc_token_score_interface.transfer.assert_called_with( for_address, convert_result_amount, b'None')
def test_check_valid_path(self): # success case: input the valid path path = [ self.connector_token_list[0], self.flexible_token_address_list[0], self.connector_token_list[1] ] self.network_score._require_valid_path(path) # failure case: input path whose length under 3 invalid_path = [ self.connector_token_list[0], self.flexible_token_address_list[0] ] self.assertRaises(RevertException, self.network_score._require_valid_path, invalid_path) # failure case: input path whose length is more than 21 random = SystemRandom() # use random data to avoid same address is made invalid_path = [ Address.from_string("cx" + str(random.randrange(10)) + str(random.randrange(10)) * 39) in range(0, 22) ] self.assertRaises(RevertException, self.network_score._require_valid_path, invalid_path) # failure case: input path whose length is even invalid_path = [ self.connector_token_list[0], self.flexible_token_address_list[0], self.connector_token_list[1], self.flexible_token_address_list[1] ] self.assertRaises(RevertException, self.network_score._require_valid_path, invalid_path) # failure case: input path which has the same flexible token address in it invalid_path = [ self.connector_token_list[0], self.flexible_token_address_list[0], self.connector_token_list[1], self.flexible_token_address_list[0], self.connector_token_list[1] ] self.assertRaises(RevertException, self.network_score._require_valid_path, invalid_path) # success case: input path which has the same flexible token address in the 'from' or 'to' position in it # path: [connector0 - flexible token0 - flexible token1 - flexible token2, flexible token0] path = [ self.connector_token_list[0], self.flexible_token_address_list[0], self.flexible_token_address_list[1], self.flexible_token_address_list[2], self.flexible_token_address_list[0] ] self.network_score._require_valid_path(path) # success case: input path which has the same flexible tokens that only exist in 'from' or 'to' in it path = [ self.flexible_token_address_list[0], self.flexible_token_address_list[1], self.connector_token_list[0], self.flexible_token_address_list[2], self.flexible_token_address_list[0] ] self.network_score._require_valid_path(path)
class TestIconScoreDatabase: @classmethod def _init_context(cls, context, address: 'Address'): context.current_address = address context._inv_container = Mock() @classmethod def _set_revision(cls, context, revision: int): context._inv_container.revision_code = revision @pytest.mark.parametrize( "values,value_type", [ ((0, 100, 200, 300), int), (("aa", "b", "ccc", "dddd"), str), ((b"aa", b"b", b"ccc", b"dddd"), bytes), ((True, False, True, False), bool), ([Address(AddressPrefix.EOA, os.urandom(20)) for _ in range(4)], Address), ] ) def test_array_db(self, context, key_value_db, values, value_type): context_db = ContextDatabase(key_value_db, is_shared=False) address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(address, context_db) self._init_context(context, score_db.address) self._set_revision(context, Revision.USE_RLP.value - 1) name = "array_db" array_db = ArrayDB(name, score_db, value_type) for i in range(2): array_db.put(values[i]) assert len(array_db) == 2 self._set_revision(context, Revision.USE_RLP.value) array_db.put(values[2]) array_db.put(values[3]) assert len(array_db) == 4 for i, value in enumerate(array_db): assert value == values[i] final_key: bytes = _get_final_key(address, ContainerTag.ARRAY, name.encode(), use_rlp=True) assert key_value_db.get(final_key) == int_to_bytes(len(array_db)) for i, use_rlp in enumerate((False, False, True, True)): key = _get_final_key( address.to_bytes(), ContainerTag.ARRAY.value, name.encode(), int_to_bytes(i), use_rlp=use_rlp, ) assert key_value_db.get(key) == ContainerUtil.encode_value(values[i]) for v in reversed(values): assert v == array_db.pop() assert len(array_db) == 0 # 2 values for array_db size still remain # even though all items in array_db have been popped. assert len(key_value_db) == 2 @pytest.mark.parametrize( "old_value,new_value,value_type", [ (300, 500, int), ("old string", "new string", str), (b"old", b"new", bytes), (False, True, bool), ( Address(AddressPrefix.EOA, os.urandom(20)), Address(AddressPrefix.CONTRACT, os.urandom(20)), Address, ), ] ) def test_var_db(self, context, key_value_db, old_value, new_value, value_type): context_db = ContextDatabase(key_value_db, is_shared=False) address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(address, context_db) self._init_context(context, address) self._set_revision(context, Revision.USE_RLP.value - 1) name = "var_db" var_db = VarDB(name, score_db, value_type) var_db.set(old_value) assert var_db.get() == old_value key = _get_final_key(address, ContainerTag.VAR, name.encode(), use_rlp=False) assert key_value_db.get(key) == ContainerUtil.encode_value(old_value) self._set_revision(context, Revision.USE_RLP.value) assert key_value_db.get(key) == ContainerUtil.encode_value(old_value) var_db.set(new_value) assert var_db.get() == new_value assert var_db.get() != old_value key = _get_final_key(address, ContainerTag.VAR, name.encode(), use_rlp=True) assert key_value_db.get(key) == ContainerUtil.encode_value(new_value) var_db.remove() assert var_db.get() == get_default_value(value_type) assert len(key_value_db) == 0 @pytest.mark.parametrize( "keys", [ (b"hello", 1234, "world", Address(AddressPrefix.EOA, os.urandom(20))), ] ) @pytest.mark.parametrize( "old_values, new_values, value_type", [ ((False, True, False, True), (True, False, True, False), bool), ((b"a", b"b", b"c", b"d"), (b"A", b"B", b"C", b"D"), bytes), ((10, 20, 30, 40), (100, 200, 300, 400), int), (("aa", "bb", "cc", "dd"), ("AA", "BB", "CC", "DD"), str), ( [Address(AddressPrefix.EOA, os.urandom(20)) for _ in range(4)], [Address(AddressPrefix.CONTRACT, os.urandom(20)) for _ in range(4)], Address ), ] ) def test_1_depth_dict_db(self, context, key_value_db, keys, old_values, new_values, value_type): context_db = ContextDatabase(key_value_db, is_shared=False) score_address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(score_address, context_db) self._init_context(context, score_address) self._set_revision(context, Revision.USE_RLP.value - 1) name = "dict_db_depth_1" dict_db = DictDB(name, score_db, depth=1, value_type=value_type) # Put two items to dict_db for i in range(2): k, v = keys[i], old_values[i] dict_db[k] = v assert dict_db[k] == v key = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerUtil.encode_key(k), use_rlp=False ) assert key_value_db.get(key) == ContainerUtil.encode_value(v) self._set_revision(context, Revision.USE_RLP.value) # Read old-formatted data on Revision.USE_RLP for i in range(2): k, v = keys[i], old_values[i] assert dict_db[k] == v key = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerUtil.encode_key(k), use_rlp=False ) assert key_value_db.get(key) == ContainerUtil.encode_value(v) # Put 4 items to dict_db for i, k in enumerate(keys): old_v = old_values[i] new_v = new_values[i] dict_db[k] = new_v assert dict_db[k] == new_v assert dict_db[k] != old_v key = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerUtil.encode_key(k), use_rlp=True ) assert key_value_db.get(key) == ContainerUtil.encode_value(new_v) # If there is no value for a given key, default value is returned for k in keys: del dict_db[k] assert dict_db[k] == get_default_value(value_type) assert len(key_value_db) == 0 @pytest.mark.parametrize( "keys1", [ (b"hello", 1234, "world", Address(AddressPrefix.EOA, os.urandom(20))), ] ) @pytest.mark.parametrize( "keys2", [ (b"hello2", 12345, "world2", Address(AddressPrefix.CONTRACT, os.urandom(20))), ] ) @pytest.mark.parametrize( "old_values, new_values, value_type", [ ((False, True, False, True), (True, False, True, False), bool), ((b"a", b"b", b"c", b"d"), (b"A", b"B", b"C", b"D"), bytes), ((10, 20, 30, 40), (100, 200, 300, 400), int), (("aa", "bb", "cc", "dd"), ("AA", "BB", "CC", "DD"), str), ( [Address(AddressPrefix.EOA, os.urandom(20)) for _ in range(4)], [Address(AddressPrefix.CONTRACT, os.urandom(20)) for _ in range(4)], Address ), ] ) def test_2_depth_dict_db(self, context, key_value_db, keys1, keys2, old_values, new_values, value_type): context_db = ContextDatabase(key_value_db, is_shared=False) score_address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(score_address, context_db) self._init_context(context, score_address) self._set_revision(context, Revision.USE_RLP.value - 1) name = "dict_db_depth_2" dict_db = DictDB(name, score_db, depth=2, value_type=value_type) # To assign a value to middle-layer dict_db is forbidden for k1, v in zip(keys1, old_values): with pytest.raises(InvalidContainerAccessException): dict_db[k1] = v # Assign values to dict_db on Revision.USE_RLP - 1 for k1 in keys1: for k2, v in zip(keys2, old_values): dict_db[k1][k2] = v assert len(key_value_db) == len(keys1) * len(keys2) for k1 in keys1: for k2, v in zip(keys2, old_values): assert dict_db[k1][k2] == v key: bytes = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerTag.DICT, ContainerUtil.encode_key(k1), ContainerUtil.encode_key(k2), use_rlp=False ) assert key_value_db.get(key) == ContainerUtil.encode_value(v) self._set_revision(context, Revision.USE_RLP.value) # Check if reading old-formatted key:value data works on Revision.USE_RLP for k1 in keys1: for k2, v in zip(keys2, old_values): assert dict_db[k1][k2] == v # Replace all old_values with new_values on Revision.USE_RLP for k1 in keys1: for k2, v in zip(keys2, new_values): dict_db[k1][k2] = v # old_values + new_values assert len(key_value_db) == len(keys1) * len(keys2) * 2 for k1 in keys1: for k2, v in zip(keys2, new_values): assert dict_db[k1][k2] == v key: bytes = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerUtil.encode_key(k1), ContainerUtil.encode_key(k2), use_rlp=True ) assert key_value_db.get(key) == ContainerUtil.encode_value(v) for k1 in keys1: for k2 in keys2: del dict_db[k1][k2] assert dict_db[k1][k2] == get_default_value(value_type) assert len(key_value_db) == 0 @pytest.mark.parametrize( "prefixes", [ (), (b"prefix0",), (b"prefix0", b"prefix1"), (b"prefix0", b"prefix1", b"prefix2"), ] ) @pytest.mark.parametrize( "old_values,new_values", [ ( (True, b"hello", 100, "world", Address(AddressPrefix.EOA, os.urandom(20))), (False, b"world", 1234, "helloworld", Address(AddressPrefix.CONTRACT, os.urandom(20))), ) ], ) def test_score_db(self, context, key_value_db, prefixes, old_values, new_values): context_db = ContextDatabase(key_value_db, is_shared=False) score_address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(score_address, context_db) args = [score_address] self._init_context(context, score_address) self._set_revision(context, Revision.USE_RLP.value - 1) for prefix in prefixes: score_db = score_db.get_sub_db(prefix) args.append(prefix) for i, value in enumerate(old_values): key: bytes = f"key{i}".encode() encoded_value: bytes = ContainerUtil.encode_value(value) score_db.put(key, encoded_value) assert score_db.get(key) == encoded_value final_key: bytes = _get_final_key(*args, key, use_rlp=False) assert key_value_db.get(final_key) == encoded_value self._set_revision(context, Revision.USE_RLP.value) for i, value in enumerate(old_values): key: bytes = f"key{i}".encode() encoded_value: bytes = ContainerUtil.encode_value(value) assert score_db.get(key) == encoded_value final_key: bytes = _get_final_key(*args, key, use_rlp=False) assert key_value_db.get(final_key) == encoded_value for i, value in enumerate(new_values): key: bytes = f"key{i}".encode() encoded_value: bytes = ContainerUtil.encode_value(value) score_db.put(key, encoded_value) assert score_db.get(key) == encoded_value final_key: bytes = _get_final_key(*args, key, use_rlp=True) assert key_value_db.get(final_key) == encoded_value score_db.delete(key) assert score_db.get(key) is None assert key_value_db.get(final_key) is None
def test_tokenFallback(self): # success case: input 'conversionResult' to _data ( convert_for_internal should not be called ) from_address = Address.from_string("hx" + "a" * 40) for_address = Address.from_string("hx" + "b" * 40) value = 10 min_return = 5 path = "{0},{1},{2}".format(str(self.connector_token_list[0]), str(self.flexible_token_address_list[0]), str(self.connector_token_list[1])) converted_path = [ Address.from_string(address) for address in path.split(",") ] data = dict() data["path"] = path data["minReturn"] = min_return data["for"] = str(for_address) stringed_data = json.dumps(data) decoded_data = stringed_data.encode(encoding='utf-8') with MultiPatch([ patch_property(IconScoreBase, 'msg', Message(self.connector_token_list[0])), patch.object(Network, '_convert_for_internal') ]): self.network_score.tokenFallback(from_address, value, b'conversionResult') self.network_score._convert_for_internal.assert_not_called() # failure case: input None data to the _data with MultiPatch([ patch_property(IconScoreBase, 'msg', Message(self.connector_token_list[0])), patch.object(Network, '_convert_for_internal') ]): self.assertRaises(RevertException, self.network_score.tokenFallback, from_address, value, b'None') self.assertRaises(RevertException, self.network_score.tokenFallback, from_address, value, None) # failure case: msg.sender is not equal to path[0] ( should be equal ) msg_sender = Address.from_string("cx" + "c" * 40) with MultiPatch([ patch_property(IconScoreBase, 'msg', Message(msg_sender)), patch.object(Network, '_convert_for_internal') ]): self.assertRaises(RevertException, self.network_score.tokenFallback, from_address, value, decoded_data) # success case: input valid data with MultiPatch([ patch_property(IconScoreBase, 'msg', Message(self.connector_token_list[0])), patch.object(Network, '_convert_for_internal'), patch.object(Network, '_require_valid_path'), patch('contracts.network.network.require_positive_value'), patch('contracts.network.network.require_valid_address'), ]) as mocks: self.network_score.tokenFallback(from_address, value, decoded_data) mocks[3].assert_called() # patched mock of require_positive_value mocks[4].assert_called() # patched mock of require_valid_address self.network_score._require_valid_path.assert_called_with( converted_path) self.network_score._convert_for_internal. \ assert_called_with(converted_path, value, min_return, for_address)
def test_address_from_to_bytes_EOA(self): addr1 = create_address() buf = addr1.to_bytes() addr2 = Address.from_bytes(buf) self.assertEqual(addr1, addr2)
def test_address_from_to_string_EOA(self): addr1 = create_address() buf = str(addr1) addr2 = Address.from_string(buf) self.assertEqual(addr1, addr2)
def test_from_string_invalid(self, address): with pytest.raises(BaseException) as e: Address.from_string(address) assert e.value.code == ExceptionCode.INVALID_PARAMETER assert e.value.message == "Invalid address"
def test_address_from_to_string_CONTRACT(self): addr1 = create_address(prefix=1) buf = str(addr1) addr2 = Address.from_string(buf) self.assertEqual(addr1, addr2)
def test_address_from_to_bytes(self, prefix): addr1 = create_address(prefix) buf = addr1.to_bytes() addr2 = Address.from_bytes(buf) assert addr1 == addr2
def test_address_from_to_string(self, prefix): addr1 = create_address(prefix=prefix) buf = str(addr1) addr2 = Address.from_string(buf) assert addr1 == addr2
def test_prefix_and_int(self): assert Address.from_prefix_and_int(AddressPrefix.CONTRACT, 0) == ZERO_SCORE_ADDRESS assert Address.from_prefix_and_int(AddressPrefix.CONTRACT, 1) == GOVERNANCE_SCORE_ADDRESS assert str(Address.from_prefix_and_int(AddressPrefix.EOA, 10)) == "hx000000000000000000000000000000000000000a" assert str(Address.from_prefix_and_int(AddressPrefix.CONTRACT, 1024)) == \ "cx0000000000000000000000000000000000000400"
def test_install_step(self): # Ignores deploy deploy_engine_invoke = Mock() IconScoreContext.engine.deploy.invoke = deploy_engine_invoke tx_hash1: str = bytes.hex(create_tx_hash()) from_ = create_address(AddressPrefix.EOA) to_ = Address.from_string('cx0000000000000000000000000000000000000000') content_type = 'application/zip' data = { 'contentType': content_type, 'content': '0x1867291283973610982301923812873419826abcdef9182731', } request1 = create_request([ ReqData(tx_hash1, from_, to_, 0, 'deploy', data), ]) # for StepType.CONTRACT_CREATE result = self._inner_task_invoke(request1) self.assertEqual(result['txResults'][tx_hash1]['status'], '0x1') # for StepType.CONTRACT_UPDATE to_ = result['txResults'][tx_hash1]['scoreAddress'] tx_hash2: str = bytes.hex(create_tx_hash()) request2 = create_request([ ReqData(tx_hash2, from_, to_, 0, 'deploy', data), ]) result = self._inner_task_invoke(request2) self.assertEqual(result['txResults'][tx_hash2]['status'], '0x1') deploy_engine_invoke.assert_called() input_length = (len(content_type.encode('utf-8')) + 25) call_args_for_apply_step = self.step_counter.apply_step.call_args_list self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[0][0]) self.assertEqual((StepType.INPUT, input_length), call_args_for_apply_step[1][0]) self.assertEqual((StepType.CONTRACT_CREATE, 1), call_args_for_apply_step[2][0]) self.assertEqual((StepType.CONTRACT_SET, 25), call_args_for_apply_step[3][0]) self.assertEqual((StepType.DEFAULT, 1), call_args_for_apply_step[4][0]) self.assertEqual((StepType.INPUT, input_length), call_args_for_apply_step[5][0]) self.assertEqual((StepType.CONTRACT_UPDATE, 1), call_args_for_apply_step[6][0]) self.assertEqual((StepType.CONTRACT_SET, 25), call_args_for_apply_step[7][0]) self.assertEqual(8, len(call_args_for_apply_step)) step_used_create = self._calc_step_used(0, 4) step_used_update = self._calc_step_used(4, 4) # check SCORE install stepUsed value self._assert_step_used(step_used_create, request1, tx_hash1) # check SCORE update stepUsed value self._assert_step_used(step_used_update, request2, tx_hash2)
def test_2_depth_dict_db(self, context, key_value_db, keys1, keys2, old_values, new_values, value_type): context_db = ContextDatabase(key_value_db, is_shared=False) score_address = Address(AddressPrefix.CONTRACT, os.urandom(20)) score_db = IconScoreDatabase(score_address, context_db) self._init_context(context, score_address) self._set_revision(context, Revision.USE_RLP.value - 1) name = "dict_db_depth_2" dict_db = DictDB(name, score_db, depth=2, value_type=value_type) # To assign a value to middle-layer dict_db is forbidden for k1, v in zip(keys1, old_values): with pytest.raises(InvalidContainerAccessException): dict_db[k1] = v # Assign values to dict_db on Revision.USE_RLP - 1 for k1 in keys1: for k2, v in zip(keys2, old_values): dict_db[k1][k2] = v assert len(key_value_db) == len(keys1) * len(keys2) for k1 in keys1: for k2, v in zip(keys2, old_values): assert dict_db[k1][k2] == v key: bytes = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerTag.DICT, ContainerUtil.encode_key(k1), ContainerUtil.encode_key(k2), use_rlp=False ) assert key_value_db.get(key) == ContainerUtil.encode_value(v) self._set_revision(context, Revision.USE_RLP.value) # Check if reading old-formatted key:value data works on Revision.USE_RLP for k1 in keys1: for k2, v in zip(keys2, old_values): assert dict_db[k1][k2] == v # Replace all old_values with new_values on Revision.USE_RLP for k1 in keys1: for k2, v in zip(keys2, new_values): dict_db[k1][k2] = v # old_values + new_values assert len(key_value_db) == len(keys1) * len(keys2) * 2 for k1 in keys1: for k2, v in zip(keys2, new_values): assert dict_db[k1][k2] == v key: bytes = _get_final_key( score_address, ContainerTag.DICT, name.encode(), ContainerUtil.encode_key(k1), ContainerUtil.encode_key(k2), use_rlp=True ) assert key_value_db.get(key) == ContainerUtil.encode_value(v) for k1 in keys1: for k2 in keys2: del dict_db[k1][k2] assert dict_db[k1][k2] == get_default_value(value_type) assert len(key_value_db) == 0
def test_handle_get_prep_term_with_penalized_preps(self): block_height = 200 sequence = 78 period = 43120 start_block_height = 200 end_block_height = 200 + period - 1 irep = icx_to_loop(40000) total_supply = icx_to_loop(800_460_000) total_delegated = icx_to_loop(1000) params = {} context = Mock() context.block.height = block_height main_prep_count = 22 elected_prep_count = 100 total_prep_count = 106 term = Term(sequence=sequence, start_block_height=start_block_height, period=period, irep=irep, total_supply=total_supply, total_delegated=total_delegated) preps = PRepContainer() for i in range(total_prep_count): address = Address.from_prefix_and_int(AddressPrefix.EOA, i) delegated = icx_to_loop(1000 - i) penalty = PenaltyReason.NONE status = PRepStatus.ACTIVE if 0 <= i <= 4: # block validation penalty preps: 5 penalty: 'PenaltyReason' = PenaltyReason.BLOCK_VALIDATION elif i == 5: # unregistered preps: 1 status = PRepStatus.UNREGISTERED elif 6 <= i <= 7: # low productivity preps: 2 status = PRepStatus.DISQUALIFIED penalty = PenaltyReason.LOW_PRODUCTIVITY elif 8 <= i <= 10: # disqualified preps: 3 status = PRepStatus.DISQUALIFIED penalty = PenaltyReason.PREP_DISQUALIFICATION prep = PRep(address, block_height=i, delegated=delegated, penalty=penalty, status=status) prep.freeze() preps.add(prep) preps.freeze() assert preps.size(active_prep_only=False) == total_prep_count electable_preps = filter(lambda x: x.is_electable(), preps) term.set_preps(electable_preps, main_prep_count=main_prep_count, elected_prep_count=elected_prep_count) engine = PRepEngine() engine.term = term engine.preps = preps ret: dict = engine.handle_get_prep_term(context, params) assert ret["blockHeight"] == block_height assert ret["sequence"] == sequence assert ret["startBlockHeight"] == start_block_height assert ret["endBlockHeight"] == end_block_height assert ret["totalSupply"] == total_supply assert ret["totalDelegated"] == total_delegated assert ret["irep"] == irep prep_list: List[Dict[str, Union[int, str, 'Address']]] = ret["preps"] assert len(prep_list) == elected_prep_count for i, prep_snapshot in enumerate(term.preps): prep_item: Dict[str, Union[int, str, 'Address']] = prep_list[i] assert prep_item["address"] == prep_snapshot.address assert prep_item["status"] == PRepStatus.ACTIVE.value assert prep_item["penalty"] == PenaltyReason.NONE.value # The P-Reps which got penalized for consecutive 660 block validation failure # are located at the end of the P-Rep list prev_delegated = -1 for i, prep_item in enumerate(prep_list[-5:]): assert prep_item["address"] == Address.from_prefix_and_int( AddressPrefix.EOA, i) assert prep_item["status"] == PRepStatus.ACTIVE.value assert prep_item["penalty"] == PenaltyReason.BLOCK_VALIDATION.value delegated: int = prep_item["delegated"] if prev_delegated >= 0: assert prev_delegated >= delegated prev_delegated = delegated
def create_address(prefix: AddressPrefix = AddressPrefix.EOA) -> 'Address': return Address.from_bytes(prefix.to_bytes(1, 'big') + os.urandom(20))
def create_address(prefix: int = 0, data: bytes=None) -> 'Address': if data is None: data = create_tx_hash() hash_value = hashlib.sha3_256(data).digest() return Address(AddressPrefix(prefix), hash_value[-20:])
def __init__(self, wallet: 'KeyWallet', balance: int = 0): self._wallet: 'KeyWallet' = wallet self.balance: int = balance self._address: 'Address' = Address.from_string(self._wallet.get_address())
def test_invalid_address(self): address: str = "hx123456" with self.assertRaises(BaseException) as e: Address.from_string(address) self.assertEqual(e.exception.code, ExceptionCode.INVALID_PARAMETER) self.assertEqual(e.exception.message, "Invalid address")
def test_check_and_convert_bytes_data(self): # failure case: input invalid JSON format data invalid_json_format = dict() invalid_json_format["path"] = "{0},{1},{2}".format( str(self.connector_token_list[0]), str(self.flexible_token_address_list[0]), str(self.connector_token_list[1])) invalid_json_format["for"] = str(self.network_owner) invalid_json_format["minReturn"] = 10 stringed_invalid_json_format = "[" + json.dumps( invalid_json_format) + "}" encoded_invalid_json_format = stringed_invalid_json_format.encode( encoding="utf-8") self.assertRaises(RevertException, self.network_score._convert_bytes_data, encoded_invalid_json_format, self.network_owner) # failure case: input data which is not decoded to utf-8 valid_json_format = dict() valid_json_format["path"] = "{0},{1},{2}".format( str(self.connector_token_list[0]), str(self.flexible_token_address_list[0]), str(self.connector_token_list[1])) valid_json_format["for"] = str(self.network_owner) valid_json_format["minReturn"] = 10 stringed_valid_json_format = json.dumps(valid_json_format) cp037_encoded_valid_json_format = stringed_valid_json_format.encode( encoding='cp037') self.assertRaises(RevertException, self.network_score._convert_bytes_data, cp037_encoded_valid_json_format, self.network_owner) # failure case: input invalid path data (associated with '/') json_format = dict() json_format["path"] = "{0}/{1}/{2}".format( str(self.connector_token_list[0]), str(self.flexible_token_address_list[0]), str(self.connector_token_list[1])) json_format["for"] = str(self.network_owner) json_format["minReturn"] = 10 stringed_valid_json_format = json.dumps(json_format) encoded_valid_json_format = stringed_valid_json_format.encode( encoding='utf-8') self.assertRaises(InvalidParamsException, self.network_score._convert_bytes_data, encoded_valid_json_format, self.network_owner) # failure case: input invalid path data ( has an invalid address as an element ) json_format = dict() json_format["path"] = "{0},{1},{2}".format( str(self.connector_token_list[0]), str("invalid_address"), str(self.connector_token_list[1])) json_format["for"] = str(self.network_owner) json_format["minReturn"] = 10 stringed_valid_json_format = json.dumps(json_format) encoded_valid_json_format = stringed_valid_json_format.encode( encoding='utf-8') self.assertRaises(InvalidParamsException, self.network_score._convert_bytes_data, encoded_valid_json_format, self.network_owner) # failure case: input string type minReturn json_format = dict() json_format["path"] = "{0},{1},{2}".format( str(self.connector_token_list[0]), str(self.flexible_token_address_list[0]), str(self.connector_token_list[1])) json_format["for"] = str(self.network_owner) json_format["minReturn"] = "10" stringed_valid_json_format = json.dumps(json_format) encoded_valid_json_format = stringed_valid_json_format.encode( encoding='utf-8') self.assertRaises(RevertException, self.network_score._convert_bytes_data, encoded_valid_json_format, self.network_owner) # success case: "for" key is not in the data # ( returned data should have token sender address as a "for" key's value ) token_sender = Address.from_string("hx" + "a" * 40) json_format = dict() json_format["path"] = "{0},{1},{2}".format( str(self.connector_token_list[0]), str(self.flexible_token_address_list[0]), str(self.connector_token_list[1])) json_format["minReturn"] = 10 stringed_valid_json_format = json.dumps(json_format) encoded_valid_json_format = stringed_valid_json_format.encode( encoding='utf-8') result_data = self.network_score._convert_bytes_data( encoded_valid_json_format, token_sender) self.assertEqual(token_sender, result_data["for"]) # success case: "for" key is exist but value is None # ( returned dict data should have token sender address as a "for" key's value ) json_format["for"] = None stringed_valid_json_format = json.dumps(json_format) encoded_valid_json_format = stringed_valid_json_format.encode( encoding='utf-8') result_data = self.network_score._convert_bytes_data( encoded_valid_json_format, token_sender) self.assertEqual(token_sender, result_data["for"]) # success case: input data which has "for" key and it's value for_address = Address.from_string("hx" + "b" * 40) json_format["for"] = str(for_address) stringed_valid_json_format = json.dumps(json_format) encoded_valid_json_format = stringed_valid_json_format.encode( encoding='utf-8') result_data = self.network_score._convert_bytes_data( encoded_valid_json_format, token_sender) self.assertEqual(for_address, result_data["for"])
def test_address_from_to_bytes_CONTRACT(self): addr1 = create_address(prefix=1) buf = addr1.to_bytes() addr2 = Address.from_bytes(buf) self.assertEqual(addr1, addr2)
def test_convertFor(self): icx_amount = 10 # failure case: input wrong path format min_return = 10 for_address = Address.from_string("hx" + "a" * 40) invalid_path = "{0}/{1}/{2}".format( str(self.icx_token), str(self.flexible_token_address_list[0]), str(self.connector_token_list[0])) with patch_property(IconScoreBase, 'msg', Message(self.network_owner, value=icx_amount)): self.assertRaises(InvalidParamsException, self.network_score.convertFor, invalid_path, min_return, for_address) # failure case: input path whose has invalid address as an element min_return = 10 for_address = Address.from_string("hx" + "a" * 40) invalid_path = "{0},{1},{2}".format(str(self.icx_token), str("invalid_address"), str(self.connector_token_list[1])) with patch_property(IconScoreBase, 'msg', Message(self.network_owner, value=icx_amount)): self.assertRaises(InvalidParamsException, self.network_score.convertFor, invalid_path, min_return, for_address) # failure case: input min return less than 0 invalid_min_return = -1 for_address = Address.from_string("hx" + "a" * 40) path = "{0},{1},{2}".format(str(self.icx_token), str(self.flexible_token_address_list[0]), str(self.connector_token_list[0])) with patch_property(IconScoreBase, 'msg', Message(self.network_owner, value=icx_amount)): self.assertRaises(RevertException, self.network_score.convertFor, path, invalid_min_return, for_address) # failure case: input path whose first address is not Icx token address min_return = 10 for_address = Address.from_string("hx" + "a" * 40) invalid_path = "{0},{1},{2}".format( str(self.connector_token_list[0]), str(self.flexible_token_address_list[0]), str(self.connector_token_list[1])) with patch_property(IconScoreBase, 'msg', Message(self.network_owner, value=icx_amount)): self.assertRaises(RevertException, self.network_score.convertFor, invalid_path, min_return, for_address) # success case: input valid path min_return = 10 for_address = Address.from_string("hx" + "a" * 40) path = "{0},{1},{2}".format(str(self.icx_token), str(self.flexible_token_address_list[0]), str(self.connector_token_list[1])) self.network_score._icx_tokens[self.icx_token] = True with MultiPatch([ patch_property(IconScoreBase, 'msg', Message(self.network_owner, value=icx_amount)), patch.object(Network, '_convert_for_internal') ]): self.network_score.convertFor(path, min_return, for_address) self.network_score.icx.transfer.assert_called_with( self.icx_token, icx_amount) converted_path = [ self.icx_token, self.flexible_token_address_list[0], self.connector_token_list[1] ] self.network_score._convert_for_internal.assert_called_with( converted_path, icx_amount, min_return, for_address)
335020, 327218, 319680, 312407, 305398, 298653, 292173, 285958, 280007, 274320, 268898, 263740, 258847, 254219, 249855, 245755, 241920, 238349, 235043, 232002, 229224, 226712, 224464, 222480, 220761, 219306, 218116, 217190, 216529, 216132, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000 ] SENDER_ADDRESS = Address.from_prefix_and_int(AddressPrefix.EOA, 0) def create_account( address: 'Address', balance: int, stake: int, unstake: int, unstake_block_height: int, delegated_amount: int, delegations: List[Tuple[Address, int]]) -> 'Account': coin_part = CoinPart(balance=balance) stake_part = StakePart(stake, unstake, unstake_block_height) delegation_part = DelegationPart(delegated_amount, delegations) return Account( address, 1024, coin_part=coin_part, stake_part=stake_part, delegation_part=delegation_part)
class TestEventLog: def test_parse_signature(self): signature = "Transfer(Address,Address,int)" name, types = EventLog.parse_signature(signature) assert name == "Transfer" assert types == ["Address", "Address", "int"] def test_from_dict_with_transfer_event_log(self): signature = "Transfer(Address,Address,int)" score_address = Address.from_string( "cx4d6f646441a3f9c9b91019c9b98e3c342cceb114" ) indexed_address_0 = Address.from_data(AddressPrefix.EOA, b"address0") indexed_address_1 = Address.from_data(AddressPrefix.EOA, b"address1") value = 0x8AC7230489E80000 event_log_data = { "scoreAddress": str(score_address), "indexed": [ signature, str(indexed_address_0), str(indexed_address_1), hex(value), ], "data": [], } event_log = EventLog.from_dict(event_log_data) assert event_log.signature == signature assert event_log.score_address == score_address assert event_log.indexed[0] == signature assert len(event_log.indexed) == 4 assert event_log.indexed[1] == indexed_address_0 assert event_log.indexed[2] == indexed_address_1 assert event_log.indexed[3] == value assert len(event_log.data) == 0 def test_from_dict_with_iscore_claimed_log(self): signature = "IScoreClaimed(int,int)" score_address = Address.from_string( "cx0000000000000000000000000000000000000000" ) iscore = 0x186A0 # unit: iscore icx = 0x64 # unit: loop event_log_data = { "scoreAddress": str(score_address), "indexed": [signature], "data": [hex(iscore), hex(icx)], } event_log = EventLog.from_dict(event_log_data) assert event_log.signature == signature assert event_log.score_address == score_address assert len(event_log.indexed) == 1 assert event_log.indexed[0] == signature assert len(event_log.data) == 2 assert event_log.data[0] == iscore assert event_log.data[1] == icx @pytest.mark.parametrize( "indexed,data", [ ( [ "Transfer(Address,Address,int)", Address.from_prefix_and_int(AddressPrefix.EOA, 0), Address.from_prefix_and_int(AddressPrefix.EOA, 1), ], [random.randint(0, 99999)], ), (["IScoreClaimed(int,int)"], [10_000, 10],), ], ) def test_serializable(self, indexed, data): score_address = Address(AddressPrefix.CONTRACT, os.urandom(20)) expected = EventLog(score_address, indexed, data) event_log = EventLog.from_bytes(expected.to_bytes()) assert event_log == expected assert event_log.indexed == indexed assert event_log.data == data