Skip to content

Commit

Permalink
fix[codegen]: fix raw_log() when topics are non-literals (#3977)
Browse files Browse the repository at this point in the history
this commit fixes codegen for the `raw_log()` builtin when the topics
are non-literals. `unwrap_location()` was not being called, so when the
topic expression is not a literal, the pointer to the variable was being
returned instead of the value of the variable.
  • Loading branch information
cyberthirst committed May 13, 2024
1 parent dea5d2b commit 120b7d5
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 6 deletions.
75 changes: 75 additions & 0 deletions tests/functional/codegen/features/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,81 @@ def ioo(inp: Bytes[100]):
print("Passed raw log tests")


def test_raw_log_topic_double_eval(get_contract, get_logs):
t1 = "0x1111111111111111111111111111111111111111111111111111111111111111"
code = f"""
x: bytes32
c: public(uint256)
@internal
def bar() -> bytes32:
self.c += 1
return {t1}
@external
def foo():
self.x = {t1}
raw_log([self.bar(), self.bar()], b"")
"""

c = get_contract(code)
c.foo()

assert c.c() == 2


def test_raw_log_with_topics_in_storage_locs(get_contract, get_logs):
t1 = "0x1111111111111111111111111111111111111111111111111111111111111111"
t2 = "0x2222222222222222222222222222222222222222222222222222222222222222"
code = f"""
x: bytes32
@external
def foo():
self.x = {t1}
raw_log([self.x], b"")
y: bytes32 = {t2}
raw_log([y], b"")
"""

c = get_contract(code)
c.foo()
logs = get_logs(c, raw=True)

assert len(logs) == 2
assert logs[0][0][0] == int(t1, 16).to_bytes(32, "big")
assert logs[1][0][0] == int(t2, 16).to_bytes(32, "big")


def test_raw_log_with_topics_in_storage_locs2(get_contract, get_logs):
t1 = "0x1111111111111111111111111111111111111111111111111111111111111111"
t2 = "0x2222222222222222222222222222222222222222222222222222222222222222"
t3 = "0x3333333333333333333333333333333333333333333333333333333333333333"
t4 = "0x4444444444444444444444444444444444444444444444444444444444444444"
code = f"""
x: bytes32
x2: bytes32
@external
def foo():
self.x = {t1}
self.x2 = {t2}
y: bytes32 = {t3}
y2: bytes32 = {t4}
raw_log([self.x, y, self.x2, y2], b"")
raw_log([y, self.x], b"")
"""

c = get_contract(code)
c.foo()
logs = get_logs(c, raw=True)

assert len(logs) == 2
assert logs[0][0] == [int(t, 16).to_bytes(32, "big") for t in [t1, t3, t2, t4]]
assert logs[1][0] == [int(t, 16).to_bytes(32, "big") for t in [t3, t1]]


def test_raw_call_bytes32_data(get_logs, get_contract):
code = """
b: uint256
Expand Down
8 changes: 2 additions & 6 deletions vyper/builtins/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,7 @@ def infer_arg_types(self, node, expected_return_typ=None):
def build_IR(self, expr, args, kwargs, context):
topics_length = len(expr.args[0].elements)
topics = args[0].args
topics = [unwrap_location(topic) for topic in topics]

# sanity check topics is a literal list
assert args[0].value in ("~empty", "multi")
Expand All @@ -1283,12 +1284,7 @@ def build_IR(self, expr, args, kwargs, context):
placeholder = context.new_internal_variable(BYTES32_T)
log_ir = [log_op, placeholder, 32] + topics
return IRnode.from_list(
[
"seq",
# TODO use make_setter
["mstore", placeholder, unwrap_location(data)],
ensure_eval_once("raw_log", log_ir),
]
["seq", make_setter(placeholder, data), ensure_eval_once("raw_log", log_ir)]
)

input_buf = ensure_in_memory(data, context)
Expand Down

0 comments on commit 120b7d5

Please sign in to comment.