Skip to content

Commit

Permalink
Merge pull request #1233 from CityOfZion/CU-86dt50abt
Browse files Browse the repository at this point in the history
CU-86dt50abt - Error when compiling using union type notation with | (bitwise or) in Event argument type
  • Loading branch information
luc10921 authored Apr 10, 2024
2 parents 9d1b679 + 446f3ad commit 01b259b
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 74 deletions.
12 changes: 6 additions & 6 deletions boa3/builtin/contract/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
'to_script_hash',
]

from typing import Any, Union
from typing import Any

from boa3.builtin.compile_time import CreateNewEvent
from boa3.builtin.contract.Nep17Contract import Nep17Contract
from boa3.builtin.type import ECPoint, UInt160, Event

Nep11TransferEvent: Event = CreateNewEvent(
[
('from', Union[UInt160, None]),
('to', Union[UInt160, None]),
('from', UInt160 | None),
('to', UInt160 | None),
('amount', int),
('tokenId', Union[str, bytes])
('tokenId', str | bytes)
],
'Transfer'
)
Expand Down Expand Up @@ -49,8 +49,8 @@

Nep17TransferEvent: Event = CreateNewEvent(
[
('from', Union[UInt160, None]),
('to', Union[UInt160, None]),
('from', UInt160 | None),
('to', UInt160 | None),
('amount', int)
],
'Transfer'
Expand Down
40 changes: 29 additions & 11 deletions boa3/internal/analyser/moduleanalyser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,25 @@ def get_values_type(self, value: ast.AST) -> Iterable[IType | None]:

return types

def visit_BinOp(self, bin_op: ast.BinOp) -> IType | None:
left = self.visit(bin_op.left)
if isinstance(left, str):
left = self.get_symbol(left)
elif isinstance(bin_op.left, ast.Constant) and left is None:
left = self.get_type(left)

right = self.visit(bin_op.right)
if isinstance(right, str):
right = self.get_symbol(right)
elif isinstance(bin_op.right, ast.Constant) and right is None:
right = self.get_type(right)

# only validate type1 | type2, other binary operations are evaluated on TypeAnalyser
if isinstance(bin_op.op, ast.BitOr) and isinstance(left, IType) and isinstance(right, IType):
return left.union_type(right)

return self.generic_visit(bin_op)

def visit_Call(self, call: ast.Call) -> IType | None:
"""
Visitor of a function call node
Expand Down Expand Up @@ -1319,25 +1338,24 @@ def create_new_event(self, create_call: ast.Call) -> Event:
)
elif len(event_args) > 0:
args_type = self.get_type(event_args[0])
expected_type = Builtin.NewEvent.arguments_type
if not Type.list.is_type_of(args_type):
self._log_error(
CompilerError.MismatchedTypes(line=event_args[0].lineno,
col=event_args[0].col_offset,
expected_type_id=Type.list.identifier,
expected_type_id=expected_type.identifier,
actual_type_id=args_type.identifier)
)
else:
expected_type = expected_type.value_type
for value in event_args[0].elts:
if not isinstance(value, ast.Tuple):
CompilerError.MismatchedTypes(line=value.lineno,
col=value.col_offset,
expected_type_id=Type.tuple.identifier,
actual_type_id=self.get_type(value).identifier)
elif len(value.elts) < 2:
if not isinstance(value, ast.Tuple) or len(value.elts) < 2:
actual_type = self.get_type(value)
self._log_error(
CompilerError.UnfilledArgument(line=value.lineno,
col=value.col_offset,
param=list(Builtin.NewEvent.args)[0])
CompilerError.MismatchedTypes(line=value.lineno,
col=value.col_offset,
expected_type_id=expected_type.identifier,
actual_type_id=actual_type.identifier)
)
else:
event_arg_name, event_arg_type = value.elts
Expand Down Expand Up @@ -1365,7 +1383,7 @@ def create_new_event(self, create_call: ast.Call) -> Event:
self._log_error(
CompilerError.MismatchedTypes(line=value.lineno,
col=value.col_offset,
expected_type_id=Type.tuple.identifier,
expected_type_id=expected_type.identifier,
actual_type_id=self.get_type(value).identifier)
)
else:
Expand Down
10 changes: 9 additions & 1 deletion boa3/internal/model/builtin/method/createeventmethod.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from boa3.internal.model.builtin.method.builtinmethod import IBuiltinMethod
from boa3.internal.model.expression import IExpression
from boa3.internal.model.type.collection.sequence.mutable.listtype import ListType
from boa3.internal.model.type.itype import IType
from boa3.internal.model.variable import Variable
from boa3.internal.neo.vm.type.AbiType import AbiType
Expand All @@ -11,15 +12,22 @@ class CreateEventMethod(IBuiltinMethod):
def __init__(self):
import ast
from boa3.internal.model.type.type import Type
from boa3.internal.model.type.typeutils import TypeUtils
identifier = 'CreateNewEvent'
args = {
'arguments': Variable(Type.list.build(Type.tuple)),
'arguments': Variable(Type.list.build(
Type.tuple.build_collection((Type.str, TypeUtils.type))
)),
'event_name': Variable(Type.str)
}
event_name_default = ast.parse("'{0}'".format(Type.str.default_value)
).body[0].value
super().__init__(identifier, args, defaults=[event_name_default], return_type=EventType)

@property
def arguments_type(self) -> ListType:
return self.args['arguments'].type

def validate_parameters(self, *params: IExpression) -> bool:
return len(params) == len(self.args)

Expand Down
6 changes: 3 additions & 3 deletions boa3_test/examples/auxiliary_contracts/update_contract.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Union
from typing import Any

from boa3.builtin.compile_time import CreateNewEvent, NeoMetadata, public
from boa3.builtin.interop import storage, runtime
Expand Down Expand Up @@ -42,8 +42,8 @@ def manifest_metadata() -> NeoMetadata:

on_transfer = CreateNewEvent(
[
('from_addr', Union[UInt160, None]),
('to_addr', Union[UInt160, None]),
('from_addr', UInt160 | None),
('to_addr', UInt160 | None),
('amount', int)
],
'Transfer'
Expand Down
6 changes: 3 additions & 3 deletions boa3_test/examples/nep11_non_divisible.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

from boa3.builtin.compile_time import CreateNewEvent, NeoMetadata, public
from boa3.builtin.contract import abort
from boa3.builtin.interop import storage
from boa3.builtin.interop.blockchain import get_contract
from boa3.builtin.interop.contract import CallFlags, call_contract, destroy_contract, get_call_flags, update_contract
from boa3.builtin.interop.iterator import Iterator
from boa3.builtin.interop.json import json_deserialize
from boa3.builtin.interop.runtime import check_witness, get_network, script_container
from boa3.builtin.interop.stdlib import deserialize, serialize
from boa3.builtin.interop import storage
from boa3.builtin.interop.storage.findoptions import FindOptions
from boa3.builtin.type import UInt160, helper as type_helper

Expand Down Expand Up @@ -80,8 +80,8 @@ def gm_manifest() -> NeoMetadata:
on_transfer = CreateNewEvent(
# trigger when tokens are transferred, including zero value transfers.
[
('from_addr', Union[UInt160, None]),
('to_addr', Union[UInt160, None]),
('from_addr', UInt160 | None),
('to_addr', UInt160 | None),
('amount', int),
('tokenId', bytes)
],
Expand Down
6 changes: 3 additions & 3 deletions boa3_test/examples/update_contract.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Union
from typing import Any

from boa3.builtin.compile_time import CreateNewEvent, NeoMetadata, public
from boa3.builtin.interop import storage, runtime
Expand Down Expand Up @@ -46,8 +46,8 @@ def manifest_metadata() -> NeoMetadata:

on_transfer = CreateNewEvent(
[
('from_addr', Union[UInt160, None]),
('to_addr', Union[UInt160, None]),
('from_addr', UInt160 | None),
('to_addr', UInt160 | None),
('amount', int)
],
'Transfer'
Expand Down
6 changes: 2 additions & 4 deletions boa3_test/test_sc/event_test/EventNep17TransferBuilt.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
from typing import Union

from boa3.builtin.compile_time import public, CreateNewEvent
from boa3.builtin.type import UInt160

transfer = CreateNewEvent(
[
('from', Union[UInt160, None]),
('to', Union[UInt160, None]),
('from', UInt160 | None),
('to', UInt160 | None),
('amount', int)
],
'Transfer'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
[
('optional', Optional[str]),
('union', Union[int, None]),
('union2', bool | None)
],
'event'
)


@public
def main():
event('foo', 1)
event('foo', 1, True)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, Union
from typing import Any, Dict

from boa3.builtin.compile_time import CreateNewEvent, NeoMetadata, public
from boa3.builtin.interop.iterator import Iterator
Expand All @@ -7,8 +7,8 @@
on_transfer = CreateNewEvent(
# trigger when tokens are transferred, including zero value transfers.
[
('from_addr', Union[UInt160, None]),
('to_addr', Union[UInt160, None]),
('from_addr', UInt160 | None),
('to_addr', UInt160 | None),
('amount', int),
('tokenId', bytes)
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, Union
from typing import Any, Dict

from boa3.builtin.compile_time import CreateNewEvent, NeoMetadata, public
from boa3.builtin.interop.iterator import Iterator
Expand All @@ -7,8 +7,8 @@
on_transfer = CreateNewEvent(
# trigger when tokens are transferred, including zero value transfers.
[
('from_addr', Union[UInt160, None]),
('to_addr', Union[UInt160, None]),
('from_addr', UInt160 | None),
('to_addr', UInt160 | None),
('amount', int),
('tokenId', str)
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from boa3.builtin.compile_time import CreateNewEvent

from typing import Union

from boa3.builtin.compile_time import CreateNewEvent
from boa3.builtin.type import UInt160

on_transfer = CreateNewEvent(
[
('from_addr', Union[UInt160, None]),
('to_addr', Union[UInt160, None]),
('from_addr', UInt160 | None),
('to_addr', UInt160 | None),
('amount', int),
],
'Transfer'
Expand Down
4 changes: 2 additions & 2 deletions boa3_test/tests/compiler_tests/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ async def test_event_nep11_transfer_run(self):
event = boatestcase.BoaTestEvent.from_notification(events[0], bytes, bytes, int, bytes)
self.assertEqual(transfer_args, event.state)

def test_event_with_return(self):
def test_event_without_types(self):
path = self.get_contract_path('EventWithoutTypes.py')
self.assertCompilerLogs(CompilerError.UnfilledArgument, path)
self.assertCompilerLogs(CompilerError.MismatchedTypes, path)

async def test_event_with_duplicated_name(self):
await self.set_up_contract('EventWithDuplicatedName.py')
Expand Down
Loading

0 comments on commit 01b259b

Please sign in to comment.