diff --git a/tests/parser/features/test_logging.py b/tests/parser/features/test_logging.py index 0bc386b61c1..bcdeb163d3e 100644 --- a/tests/parser/features/test_logging.py +++ b/tests/parser/features/test_logging.py @@ -70,6 +70,34 @@ def foo(): assert c.translator.decode_event(logs.topics, logs.data) == {'arg1': b'bar', 'arg2': b'home', 'arg3': '0x'+c.address.hex(), '_event_type': b'MyLog'} +def test_logging_the_same_event_multiple_times_with_topics(): + loggy_code = """ +MyLog: __log__({arg1: indexed(num), arg2: indexed(address)}) + +def foo(): + log.MyLog(1, self) + log.MyLog(1, self) + +def bar(): + log.MyLog(1, self) + log.MyLog(1, self) + """ + + c = get_contract(loggy_code) + c.foo() + c.bar() + logs = s.head_state.receipts[-1].logs[-1] + event_id = u.bytes_to_int(u.sha3(bytes('MyLog(int128,address)', 'utf-8'))) + # Event id is always the first topic + assert logs.topics[0] == event_id + # Event id is calculated correctly + assert c.translator.event_data[event_id] + # Event abi is created correctly + assert c.translator.event_data[event_id] == {'types': ['int128','address'], 'name': 'MyLog', 'names': ['arg1','arg2'], 'indexed': [True,True], 'anonymous': False} + # Event is decoded correctly + assert c.translator.decode_event(logs.topics, logs.data) == {'_event_type': b'MyLog', 'arg1': 1, 'arg2': '0x' + c.address.hex()} + + def test_event_logging_cannot_have_more_than_three_topics(): loggy_code = """ MyLog: __log__({arg1: indexed(bytes <= 3), arg2: indexed(bytes <= 4), arg3: indexed(address), arg4: indexed(num)}) @@ -110,7 +138,8 @@ def test_event_loggging_with_fixed_array_data(): def foo(): log.MyLog([1,2], [block.timestamp, block.timestamp+1, block.timestamp+2], [[1,2],[1,2]]) -# """ + log.MyLog([1,2], [block.timestamp, block.timestamp+1, block.timestamp+2], [[1,2],[1,2]]) + """ c = get_contract(loggy_code) c.foo() diff --git a/viper/parser/parser.py b/viper/parser/parser.py index be687e3133c..c4a5408bdf6 100644 --- a/viper/parser/parser.py +++ b/viper/parser/parser.py @@ -954,23 +954,21 @@ def parse_stmt(stmt, context): return Stmt(stmt, context).lll_node -def pack_logging_topics(event, args, context): - topics = [event.event_id] - stored_topics = ['seq'] +def pack_logging_topics(event_id, args, topics_types, context): + topics = [event_id] topics_count = 1 - for pos, is_indexed in enumerate(event.indexed_list): - if is_indexed: - typ = event.args.pop(pos + 1 - topics_count).typ - arg = args.pop(pos + 1 - topics_count) - topics_count += 1 - if isinstance(arg, ast.Str): - stored_topics.append(parse_value_expr(arg, context)) - topics.append(['mload', stored_topics[-1].to_list()[-1][-1][-1] + 32]) - else: - input = parse_value_expr(arg, context) - input = base_type_conversion(input, input.typ, typ) - topics.append(input) - return topics, stored_topics, event, args + stored_topics = ['seq'] + for pos, typ in enumerate(topics_types): + arg = args[pos] + topics_count += 1 + if isinstance(arg, ast.Str): + stored_topics.append(parse_value_expr(arg, context)) + topics.append(['mload', stored_topics[-1].to_list()[-1][-1][-1] + 32]) + else: + input = parse_value_expr(arg, context) + input = base_type_conversion(input, input.typ, typ) + topics.append(input) + return topics, stored_topics def pack_args_by_32(holder, maxlen, arg, typ, context, placeholder): @@ -998,13 +996,13 @@ def pack_args_by_32(holder, maxlen, arg, typ, context, placeholder): # Pack logging data arguments -def pack_logging_data(signature, args, context): +def pack_logging_data(types, args, context): # Checks to see if there's any data if not args: return ['seq'], 0, 0 holder = ['seq'] maxlen = len(args) * 32 - for i, (arg, typ) in enumerate(zip(args, [arg.typ for arg in signature.args])): + for i, (arg, typ) in enumerate(zip(args, types)): holder, maxlen = pack_args_by_32(holder, maxlen, arg, typ, context, context.new_placeholder(BaseType(32))) return holder, maxlen, holder[1].to_list()[1][0]