From 2a45b5b4fe83a1c31537cbb94a8b26d08f1b14e2 Mon Sep 17 00:00:00 2001 From: Mirella de Medeiros Date: Mon, 1 Apr 2024 20:45:22 -0300 Subject: [PATCH] CU-86drpncy1 - Add new methods on storage to get/put primitive values without the need of TypeHelper --- boa3/builtin/interop/storage/__init__.py | 263 +++++++++++++++++- boa3/builtin/type/__init__.py | 5 +- .../compiler/codegenerator/codegenerator.py | 7 +- .../codegenerator/engine/stackmemento.py | 18 +- .../internal/model/builtin/interop/interop.py | 30 +- .../model/builtin/interop/storage/__init__.py | 20 +- .../builtin/interop/storage/get/__init__.py | 7 + .../istoragegetmethod.py} | 35 ++- .../storage/get/storagegetboolmethod.py | 22 ++ .../storage/get/storagegetbytesmethod.py | 19 ++ .../storage/get/storagegetecpointmethod.py | 20 ++ .../storage/get/storagegetintmethod.py | 22 ++ .../storage/get/storagegetstrmethod.py | 22 ++ .../storage/get/storagegetuint160method.py | 20 ++ .../storage/get/storagegetuint256method.py | 20 ++ .../builtin/interop/storage/put/__init__.py | 7 + .../istorageputmethod.py} | 34 ++- .../storage/put/storageputboolmethod.py | 15 + .../storage/put/storageputbytesmethod.py | 15 + .../storage/put/storageputecpointmethod.py | 15 + .../storage/put/storageputintmethod.py | 15 + .../storage/put/storageputstrmethod.py | 15 + .../storage/put/storageputuint160method.py | 15 + .../storage/put/storageputuint256method.py | 15 + .../model/builtin/method/maxmethod.py | 2 +- .../model/builtin/method/minmethod.py | 2 +- .../type/collection/sequence/ecpointtype.py | 33 +++ .../type/collection/sequence/uint160type.py | 36 +++ .../type/collection/sequence/uint256type.py | 36 +++ boa3/internal/neo/vm/opcode/OpcodeInfo.py | 2 +- boa3_test/examples/amm.py | 74 ++--- .../auxiliary_contracts/update_contract.py | 14 +- boa3_test/examples/htlc.py | 98 +++---- boa3_test/examples/ico.py | 42 +-- boa3_test/examples/nep11_non_divisible.py | 101 +++---- boa3_test/examples/nep17.py | 26 +- boa3_test/examples/simple_nep17.py | 10 +- boa3_test/examples/update_contract.py | 14 +- boa3_test/examples/wrapped_gas.py | 40 +-- boa3_test/examples/wrapped_neo.py | 44 +-- .../class_test/UserClassWithDeployMethod.py | 2 +- .../ContractInterfaceCodeOptimization.py | 2 +- ...ContractManualInterfaceCodeOptimization.py | 2 +- .../contract_interface_test/Nep17Interface.py | 2 +- .../Nep17InterfaceWithDisplayName.py | 2 +- .../test_sc/for_test/IteratorCondition.py | 6 +- .../interop_test/contract/CallFlagsUsage.py | 7 +- .../interop_test/contract/NewContract.py | 7 +- .../interop_test/iterator/IteratorNext.py | 2 +- .../interop_test/iterator/IteratorValue.py | 2 +- .../runtime/ExecutingScriptHashOnDeploy.py | 2 +- .../storage/ImportInteropStorage.py | 5 +- .../interop_test/storage/ImportStorage.py | 5 +- .../interop_test/storage/StorageAsReadOnly.py | 11 +- .../interop_test/storage/StorageBoa2Test.py | 4 +- .../interop_test/storage/StorageCreateMap.py | 2 +- .../storage/StorageDeleteBytesKey.py | 2 +- .../storage/StorageDeleteWithContext.py | 2 +- .../storage/StorageFindBytesPrefix.py | 2 +- .../storage/StorageFindStrPrefix.py | 2 +- .../storage/StorageFindWithContext.py | 2 +- .../storage/StorageFindWithOptions.py | 2 +- .../interop_test/storage/StorageGetAndPut1.py | 7 +- .../interop_test/storage/StorageGetAndPut2.py | 7 +- .../storage/StorageGetWithContext.py | 4 +- .../storage/StoragePutBytesKeyIntValue.py | 4 +- .../storage/StoragePutBytesKeyStrValue.py | 4 +- .../storage/StoragePutStrKeyIntValue.py | 4 +- .../storage/StoragePutStrKeyStrValue.py | 4 +- .../native_test/oracle/OracleRequestCall.py | 8 +- .../compiler_tests/test_native/test_oracle.py | 6 +- .../test_nep11_non_divisible.py | 2 +- docs/source/getting-started.md | 10 +- 73 files changed, 1045 insertions(+), 340 deletions(-) create mode 100644 boa3/internal/model/builtin/interop/storage/get/__init__.py rename boa3/internal/model/builtin/interop/storage/{storagegetmethod.py => get/istoragegetmethod.py} (74%) create mode 100644 boa3/internal/model/builtin/interop/storage/get/storagegetboolmethod.py create mode 100644 boa3/internal/model/builtin/interop/storage/get/storagegetbytesmethod.py create mode 100644 boa3/internal/model/builtin/interop/storage/get/storagegetecpointmethod.py create mode 100644 boa3/internal/model/builtin/interop/storage/get/storagegetintmethod.py create mode 100644 boa3/internal/model/builtin/interop/storage/get/storagegetstrmethod.py create mode 100644 boa3/internal/model/builtin/interop/storage/get/storagegetuint160method.py create mode 100644 boa3/internal/model/builtin/interop/storage/get/storagegetuint256method.py create mode 100644 boa3/internal/model/builtin/interop/storage/put/__init__.py rename boa3/internal/model/builtin/interop/storage/{storageputmethod.py => put/istorageputmethod.py} (72%) create mode 100644 boa3/internal/model/builtin/interop/storage/put/storageputboolmethod.py create mode 100644 boa3/internal/model/builtin/interop/storage/put/storageputbytesmethod.py create mode 100644 boa3/internal/model/builtin/interop/storage/put/storageputecpointmethod.py create mode 100644 boa3/internal/model/builtin/interop/storage/put/storageputintmethod.py create mode 100644 boa3/internal/model/builtin/interop/storage/put/storageputstrmethod.py create mode 100644 boa3/internal/model/builtin/interop/storage/put/storageputuint160method.py create mode 100644 boa3/internal/model/builtin/interop/storage/put/storageputuint256method.py diff --git a/boa3/builtin/interop/storage/__init__.py b/boa3/builtin/interop/storage/__init__.py index 61e848315..56d0d592d 100644 --- a/boa3/builtin/interop/storage/__init__.py +++ b/boa3/builtin/interop/storage/__init__.py @@ -3,9 +3,21 @@ 'StorageContext', 'StorageMap', 'get', + 'get_int', + 'get_bool', + 'get_str', + 'get_uint160', + 'get_uint256', + 'get_ecpoint', 'get_context', 'get_read_only_context', 'put', + 'put_int', + 'put_bool', + 'put_str', + 'put_uint160', + 'put_uint256', + 'put_ecpoint', 'delete', 'find', ] @@ -14,6 +26,7 @@ from boa3.builtin.interop.storage.findoptions import FindOptions from boa3.builtin.interop.storage.storagecontext import StorageContext from boa3.builtin.interop.storage.storagemap import StorageMap +from boa3.builtin.type import UInt160, UInt256, ECPoint def get_context() -> StorageContext: @@ -35,7 +48,7 @@ def get(key: bytes, context: StorageContext = get_context()) -> bytes: >>> put(b'unit', 'test') ... get(b'unit') - 'test' + b'test' >>> get(b'fake_key') '' @@ -50,6 +63,138 @@ def get(key: bytes, context: StorageContext = get_context()) -> bytes: pass +def get_int(key: bytes, context: StorageContext = get_context()) -> int: + """ + Gets a value as integer from the persistent store based on the given key. + It's equivalent to boa3.builtin.type.helper.to_int(get(key, context)) + + >>> put_int(b'unit', 5) + ... get_int(b'unit') + 5 + + >>> get_int(b'fake_key') + '' + + :param key: value identifier in the store + :type key: bytes + :param context: storage context to be used + :type context: StorageContext + :return: the value corresponding to given key for current storage context + :rtype: int + """ + pass + + +def get_bool(key: bytes, context: StorageContext = get_context()) -> bool: + """ + Gets a value as boolean from the persistent store based on the given key. + It's equivalent to boa3.builtin.type.helper.to_bool(get(key, context)) + + >>> put_bool(b'unit', True) + ... get_bool(b'unit') + True + + >>> get_bool(b'fake_key') + '' + + :param key: value identifier in the store + :type key: bytes + :param context: storage context to be used + :type context: StorageContext + :return: the value corresponding to given key for current storage context + :rtype: bool + """ + pass + + +def get_str(key: bytes, context: StorageContext = get_context()) -> str: + """ + Gets a value as string from the persistent store based on the given key. + It's equivalent to boa3.builtin.type.helper.to_str(get(key, context)) + + >>> put_str(b'unit', 'test') + ... get_str(b'unit') + 'test' + + >>> get_str(b'fake_key') + '' + + :param key: value identifier in the store + :type key: bytes + :param context: storage context to be used + :type context: StorageContext + :return: the value corresponding to given key for current storage context + :rtype: str + """ + pass + + +def get_uint160(key: bytes, context: StorageContext = get_context()) -> UInt160: + """ + Gets a value as UInt160 from the persistent store based on the given key. + It's equivalent UInt160(get(key, context)) + + >>> put_uint160(b'unit', UInt160(b'0123456789ABCDEFGHIJ')) + ... get_uint160(b'unit') + UInt160(0x4a49484746454443424139383736353433323130) + + >>> get_uint160(b'fake_key') + '' + + :param key: value identifier in the store + :type key: bytes + :param context: storage context to be used + :type context: StorageContext + :return: the value corresponding to given key for current storage context + :rtype: UInt160 + """ + pass + + +def get_uint256(key: bytes, context: StorageContext = get_context()) -> UInt256: + """ + Gets a value as UInt256 from the persistent store based on the given key. + It's equivalent UInt256(get(key, context)) + + >>> put_uint256(b'unit', UInt256(b'0123456789ABCDEFGHIJKLMNOPQRSTUV')) + ... get_uint256(b'unit') + UInt256(0x565554535251504f4e4d4c4b4a49484746454443424139383736353433323130) + + >>> get_uint160(b'fake_key') + '' + + :param key: value identifier in the store + :type key: bytes + :param context: storage context to be used + :type context: StorageContext + :return: the value corresponding to given key for current storage context + :rtype: UInt256 + """ + pass + + +def get_ecpoint(key: bytes, context: StorageContext = get_context()) -> ECPoint: + """ + Gets a value as ECPoint from the persistent store based on the given key. + It's equivalent ECPoint(get(key, context)) + + >>> put_ecpoint(b'unit', ECPoint(b'0123456789ABCDEFGHIJKLMNOPQRSTUVW')) + ... get_ecpoint(b'unit') + ECPoint(0x57565554535251504f4e4d4c4b4a49484746454443424139383736353433323130) + + >>> get_ecpoint(b'fake_key') + '' + + :param key: value identifier in the store + :type key: bytes + :param context: storage context to be used + :type context: StorageContext + :return: the value corresponding to given key for current storage context + :rtype: ECPoint + """ + pass + + def get_read_only_context() -> StorageContext: """ Gets current read only storage context. @@ -63,17 +208,125 @@ def get_read_only_context() -> StorageContext: pass -def put(key: bytes, value: int | bytes | str, context: StorageContext = get_context()): +def put(key: bytes, value: bytes, context: StorageContext = get_context()): """ - Inserts a given value in the key-value format into the persistent storage. + Inserts a given bytes value in the key-value format into the persistent storage. - >>> put(b'unit', 'test') + >>> put(b'unit', b'test') + None + + :param key: the identifier in the store for the new value + :type key: bytes + :param value: value to be stored + :type value: bytes + :param context: storage context to be used + :type context: StorageContext + """ + pass + + +def put_int(key: bytes, value: int, context: StorageContext = get_context()): + """ + Inserts a given integer value in the key-value format into the persistent storage. + It's equivalent to put(key, boa3.builtin.type.helper.to_int(value), context) + + >>> put_int(b'unit', 5) + None + + :param key: the identifier in the store for the new value + :type key: bytes + :param value: value to be stored + :type value: int + :param context: storage context to be used + :type context: StorageContext + """ + pass + + +def put_bool(key: bytes, value: bool, context: StorageContext = get_context()): + """ + Inserts a given boolean value in the key-value format into the persistent storage. + It's equivalent to put(key, boa3.builtin.type.helper.to_bool(value), context) + + >>> put_bool(b'unit', True) + None + + :param key: the identifier in the store for the new value + :type key: bytes + :param value: value to be stored + :type value: bool + :param context: storage context to be used + :type context: StorageContext + """ + pass + + +def put_str(key: bytes, value: str, context: StorageContext = get_context()): + """ + Inserts a given str value in the key-value format into the persistent storage. + It's equivalent to put(key, boa3.builtin.type.helper.to_str(value), context) + + >>> put_str(b'unit', 'test') + None + + :param key: the identifier in the store for the new value + :type key: bytes + :param value: value to be stored + :type value: str + :param context: storage context to be used + :type context: StorageContext + """ + pass + + +def put_uint160(key: bytes, value: UInt160, context: StorageContext = get_context()): + """ + Inserts a given UInt160 value in the key-value format into the persistent storage. + It's equivalent to put(key, value, context) since UInt160 is a subclass of bytes + + >>> put_uint160(b'unit', UInt160(b'0123456789ABCDEFGHIJ')) + None + + :param key: the identifier in the store for the new value + :type key: bytes + :param value: value to be stored + :type value: UInt160 + :param context: storage context to be used + :type context: StorageContext + """ + pass + + +def put_uint256(key: bytes, value: UInt256, context: StorageContext = get_context()): + """ + Inserts a given UInt256 value in the key-value format into the persistent storage. + It's equivalent to put(key, value, context) since UInt256 is a subclass of bytes + + >>> put_uint256(b'unit', UInt256(b'0123456789ABCDEFGHIJKLMNOPQRSTUV')) + None + + :param key: the identifier in the store for the new value + :type key: bytes + :param value: value to be stored + :type value: UInt256 + :param context: storage context to be used + :type context: StorageContext + """ + pass + + +def put_ecpoint(key: bytes, value: ECPoint, context: StorageContext = get_context()): + """ + Inserts a given ECPoint value in the key-value format into the persistent storage. + It's equivalent to put(key, value, context) since ECPoint is a subclass of bytes + + >>> put_ecpoint(b'unit', ECPoint(b'0123456789ABCDEFGHIJKLMNOPQRSTUVW')) None :param key: the identifier in the store for the new value :type key: bytes :param value: value to be stored - :type value: int or str or bytes + :type value: ECPoint :param context: storage context to be used :type context: StorageContext """ diff --git a/boa3/builtin/type/__init__.py b/boa3/builtin/type/__init__.py index 5a9d6dc45..9407bb81d 100644 --- a/boa3/builtin/type/__init__.py +++ b/boa3/builtin/type/__init__.py @@ -40,6 +40,7 @@ class UInt160(bytes): """ Represents a 160-bit unsigned integer. """ + zero: UInt160 def __init__(self, arg: bytes | int = 0): super().__init__() @@ -50,6 +51,7 @@ class UInt256(bytes): """ Represents a 256-bit unsigned integer. """ + zero: UInt256 def __init__(self, arg: bytes | int = 0): super().__init__() @@ -60,12 +62,13 @@ class ECPoint(bytes): """ Represents a coordinate pair for elliptic curve cryptography (ECC) structures. """ + zero: ECPoint def __init__(self, arg: bytes): super().__init__() pass - def to_script_hash(self) -> bytes: + def to_script_hash(self) -> UInt160: """ Converts a data to a script hash. diff --git a/boa3/internal/compiler/codegenerator/codegenerator.py b/boa3/internal/compiler/codegenerator/codegenerator.py index 0baa41519..fb8105095 100644 --- a/boa3/internal/compiler/codegenerator/codegenerator.py +++ b/boa3/internal/compiler/codegenerator/codegenerator.py @@ -269,11 +269,14 @@ def stack_size(self) -> int: return len(self._stack) def _stack_append(self, value_type: IType): - self._stack_states.append(value_type, self.last_code) + self._stack_states.append(self.last_code, value_type) def _stack_pop(self, index: int = -1) -> IType: return self._stack_states.pop(self.last_code, index) + def _stack_reverse(self, start: int = 0, end: int = None, *, rotate: bool = False) -> IType: + return self._stack_states.reverse(self.last_code, start, end, rotate=rotate) + @property def last_code_start_address(self) -> int: """ @@ -2408,7 +2411,7 @@ def swap_reverse_stack_items(self, no_items: int = 0, rotate: bool = False): if opcode is Opcode.REVERSEN and no_items > 0: self._stack_pop() if no_items > 0: - self._stack.reverse(-no_items, rotate=rotate) + self._stack_reverse(-no_items, rotate=rotate) def convert_init_user_class(self, class_type: ClassType): if isinstance(class_type, UserClass): diff --git a/boa3/internal/compiler/codegenerator/engine/stackmemento.py b/boa3/internal/compiler/codegenerator/engine/stackmemento.py index e35d78a32..7e5d8b86a 100644 --- a/boa3/internal/compiler/codegenerator/engine/stackmemento.py +++ b/boa3/internal/compiler/codegenerator/engine/stackmemento.py @@ -57,7 +57,7 @@ def restore_state(self, code_address): if latest_stack is not None: self._current_stack = latest_stack - def append(self, value: IType, code: VMCode): + def append(self, code: VMCode, value: IType): states = self.stack_map index = VMCodeMapping.instance().get_start_address(code) if index in states: @@ -90,6 +90,22 @@ def pop(self, code: VMCode, index: int = -1): if len(stack) > 0: return stack.pop(index) + def reverse(self, code: VMCode, start: int = 0, end: int = None, *, rotate: bool = False): + states = self.stack_map + stack_index = VMCodeMapping.instance().get_start_address(code) + if stack_index in states: + stack = states[stack_index] + else: + if self._current_stack is not None: + stack = self._current_stack.copy() + else: + stack = NeoStack() + + self._stacks.append((code, stack)) + self._current_stack = stack + + return stack.reverse(start, end, rotate=rotate) + class NeoStack(IStack): def __init__(self): diff --git a/boa3/internal/model/builtin/interop/interop.py b/boa3/internal/model/builtin/interop/interop.py index 56b996608..046f00bd1 100644 --- a/boa3/internal/model/builtin/interop/interop.py +++ b/boa3/internal/model/builtin/interop/interop.py @@ -192,8 +192,20 @@ def interop_events(cls) -> list[Event]: StorageFind = StorageFindMethod(FindOptionsType) StorageGetContext = StorageGetContextMethod(StorageContextType) StorageGetReadOnlyContext = StorageGetReadOnlyContextMethod(StorageContextType) - StorageGet = StorageGetMethod() - StoragePut = StoragePutMethod() + StorageGet = StorageGetBytesMethod() + StorageGetInt = StorageGetIntMethod() + StorageGetBool = StorageGetBoolMethod() + StorageGetStr = StorageGetStrMethod() + StorageGetUInt160 = StorageGetUInt160Method() + StorageGetUInt256 = StorageGetUInt256Method() + StorageGetECPoint = StorageGetECPointMethod() + StoragePut = StoragePutBytesMethod() + StoragePutInt = StoragePutIntMethod() + StoragePutBool = StoragePutBoolMethod() + StoragePutStr = StoragePutStrMethod() + StoragePutUInt160 = StoragePutUInt160Method() + StoragePutUInt256 = StoragePutUInt256Method() + StoragePutECPoint = StoragePutECPointMethod() # endregion @@ -427,9 +439,21 @@ def interop_events(cls) -> list[Event]: methods=[StorageDelete, StorageFind, StorageGet, + StorageGetInt, + StorageGetBool, + StorageGetStr, + StorageGetUInt160, + StorageGetUInt256, + StorageGetECPoint, StorageGetContext, StorageGetReadOnlyContext, - StoragePut + StoragePut, + StoragePutInt, + StoragePutBool, + StoragePutStr, + StoragePutUInt160, + StoragePutUInt256, + StoragePutECPoint, ], packages=[FindOptionsModule, StorageContextModule, diff --git a/boa3/internal/model/builtin/interop/storage/__init__.py b/boa3/internal/model/builtin/interop/storage/__init__.py index 39dad5e3c..219390143 100644 --- a/boa3/internal/model/builtin/interop/storage/__init__.py +++ b/boa3/internal/model/builtin/interop/storage/__init__.py @@ -4,17 +4,29 @@ 'StorageFindMethod', 'StorageGetContextMethod', 'StorageGetReadOnlyContextMethod', - 'StorageGetMethod', + 'StorageGetBoolMethod', + 'StorageGetBytesMethod', + 'StorageGetECPointMethod', + 'StorageGetIntMethod', + 'StorageGetStrMethod', + 'StorageGetUInt160Method', + 'StorageGetUInt256Method', 'StorageMapType', - 'StoragePutMethod' + 'StoragePutBoolMethod', + 'StoragePutBytesMethod', + 'StoragePutECPointMethod', + 'StoragePutIntMethod', + 'StoragePutStrMethod', + 'StoragePutUInt160Method', + 'StoragePutUInt256Method' ] from boa3.internal.model.builtin.interop.storage.findoptionstype import FindOptionsType +from boa3.internal.model.builtin.interop.storage.get import * +from boa3.internal.model.builtin.interop.storage.put import * from boa3.internal.model.builtin.interop.storage.storagecontext import StorageContextType from boa3.internal.model.builtin.interop.storage.storagedeletemethod import StorageDeleteMethod from boa3.internal.model.builtin.interop.storage.storagefindmethod import StorageFindMethod from boa3.internal.model.builtin.interop.storage.storagegetcontextmethod import StorageGetContextMethod -from boa3.internal.model.builtin.interop.storage.storagegetmethod import StorageGetMethod from boa3.internal.model.builtin.interop.storage.storagegetreadonlycontextmethod import StorageGetReadOnlyContextMethod from boa3.internal.model.builtin.interop.storage.storagemap.storagemaptype import StorageMapType -from boa3.internal.model.builtin.interop.storage.storageputmethod import StoragePutMethod diff --git a/boa3/internal/model/builtin/interop/storage/get/__init__.py b/boa3/internal/model/builtin/interop/storage/get/__init__.py new file mode 100644 index 000000000..d93948138 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/get/__init__.py @@ -0,0 +1,7 @@ +from boa3.internal.model.builtin.interop.storage.get.storagegetboolmethod import StorageGetBoolMethod +from boa3.internal.model.builtin.interop.storage.get.storagegetbytesmethod import StorageGetBytesMethod +from boa3.internal.model.builtin.interop.storage.get.storagegetecpointmethod import StorageGetECPointMethod +from boa3.internal.model.builtin.interop.storage.get.storagegetintmethod import StorageGetIntMethod +from boa3.internal.model.builtin.interop.storage.get.storagegetstrmethod import StorageGetStrMethod +from boa3.internal.model.builtin.interop.storage.get.storagegetuint160method import StorageGetUInt160Method +from boa3.internal.model.builtin.interop.storage.get.storagegetuint256method import StorageGetUInt256Method diff --git a/boa3/internal/model/builtin/interop/storage/storagegetmethod.py b/boa3/internal/model/builtin/interop/storage/get/istoragegetmethod.py similarity index 74% rename from boa3/internal/model/builtin/interop/storage/storagegetmethod.py rename to boa3/internal/model/builtin/interop/storage/get/istoragegetmethod.py index e02c2e797..62a42c70d 100644 --- a/boa3/internal/model/builtin/interop/storage/storagegetmethod.py +++ b/boa3/internal/model/builtin/interop/storage/get/istoragegetmethod.py @@ -1,3 +1,4 @@ +import abc import ast from collections.abc import Iterable, Sized from typing import Any @@ -10,13 +11,12 @@ from boa3.internal.model.variable import Variable -class StorageGetMethod(InteropMethod): +class IStorageGetMethod(InteropMethod, abc.ABC): - def __init__(self): + def __init__(self, identifier: str, value_type: IType): from boa3.internal.model.type.type import Type from boa3.internal.model.builtin.interop.storage.storagecontext.storagecontexttype import StorageContextType - identifier = 'get' syscall = 'System.Storage.Get' context_type = StorageContextType.build() @@ -25,9 +25,17 @@ def __init__(self): from boa3.internal.model.builtin.interop.storage.storagegetcontextmethod import StorageGetContextMethod default_id = StorageGetContextMethod(context_type).identifier - context_default = set_internal_call(ast.parse("{0}()".format(default_id) + context_default = set_internal_call(ast.parse(f"{default_id}()" ).body[0].value) - super().__init__(identifier, syscall, args, defaults=[context_default], return_type=Type.bytes) + super().__init__(identifier, syscall, args, defaults=[context_default], return_type=value_type) + + @abc.abstractmethod + def generate_default_value_opcodes(self, code_generator): + pass + + @abc.abstractmethod + def generate_deserialize_value_opcodes(self, code_generator): + pass def generate_internal_opcodes(self, code_generator): super().generate_internal_opcodes(code_generator) @@ -36,9 +44,15 @@ def generate_internal_opcodes(self, code_generator): code_generator.insert_type_check(None) if_is_null = code_generator.convert_begin_if() - # result = b'' + # result = default_value code_generator.remove_stack_top_item() - code_generator.convert_literal(b'') + self.generate_default_value_opcodes(code_generator) + + else_is_null = code_generator.convert_begin_else(if_is_null, is_internal=True) + self.generate_deserialize_value_opcodes(code_generator) + + if else_is_null < code_generator.last_code_start_address: + if_is_null = else_is_null code_generator.convert_end_if(if_is_null, is_internal=True) @property @@ -81,7 +95,10 @@ def build(self, value: Any) -> IBuiltinMethod: method = self key_type: IType = exp[0].type - if not method.key_arg.type.is_type_of(key_type): - method = StorageGetMethod() + if method.key_arg.type.is_type_of(key_type): + return self + else: + from boa3.internal.model.builtin.interop.storage.get.storagegetbytesmethod import StorageGetBytesMethod + method = StorageGetBytesMethod() method.args['key'] = Variable(key_type) return method diff --git a/boa3/internal/model/builtin/interop/storage/get/storagegetboolmethod.py b/boa3/internal/model/builtin/interop/storage/get/storagegetboolmethod.py new file mode 100644 index 000000000..b14b3dcc9 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/get/storagegetboolmethod.py @@ -0,0 +1,22 @@ +from boa3.internal.model.builtin.interop.storage.get.istoragegetmethod import IStorageGetMethod + + +class StorageGetBoolMethod(IStorageGetMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + + identifier = 'get_bool' + value_type = Type.bool + + super().__init__(identifier, value_type=value_type) + + def generate_default_value_opcodes(self, code_generator): + # default_value = 0 + code_generator.convert_literal(0) + + def generate_deserialize_value_opcodes(self, code_generator): + from boa3.internal.model.builtin.method.toboolmethod import ToBool + from boa3.internal.model.type.type import Type + + converter = ToBool.build(Type.bytes) + code_generator.convert_builtin_method_call(converter) diff --git a/boa3/internal/model/builtin/interop/storage/get/storagegetbytesmethod.py b/boa3/internal/model/builtin/interop/storage/get/storagegetbytesmethod.py new file mode 100644 index 000000000..6df38c623 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/get/storagegetbytesmethod.py @@ -0,0 +1,19 @@ +from boa3.internal.model.builtin.interop.storage.get.istoragegetmethod import IStorageGetMethod + + +class StorageGetBytesMethod(IStorageGetMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + + identifier = 'get' + value_type = Type.bytes + + super().__init__(identifier, value_type=value_type) + + def generate_default_value_opcodes(self, code_generator): + # default_value = b'' + code_generator.convert_literal(b'') + + def generate_deserialize_value_opcodes(self, code_generator): + # it doesn't need to deserialize bytes values + return diff --git a/boa3/internal/model/builtin/interop/storage/get/storagegetecpointmethod.py b/boa3/internal/model/builtin/interop/storage/get/storagegetecpointmethod.py new file mode 100644 index 000000000..c262135c6 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/get/storagegetecpointmethod.py @@ -0,0 +1,20 @@ +from boa3.internal.model.builtin.interop.storage.get.istoragegetmethod import IStorageGetMethod + + +class StorageGetECPointMethod(IStorageGetMethod): + def __init__(self): + from boa3.internal.model.type.collection.sequence.ecpointtype import ECPointType + + identifier = 'get_ecpoint' + value_type = ECPointType.build() + + super().__init__(identifier, value_type=value_type) + + def generate_default_value_opcodes(self, code_generator): + from boa3.internal.model.builtin.builtin import Builtin + + code_generator.convert_literal(Builtin.ECPoint.default_value) + + def generate_deserialize_value_opcodes(self, code_generator): + # it doesn't need to deserialize bytes values + return diff --git a/boa3/internal/model/builtin/interop/storage/get/storagegetintmethod.py b/boa3/internal/model/builtin/interop/storage/get/storagegetintmethod.py new file mode 100644 index 000000000..49d0baa9d --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/get/storagegetintmethod.py @@ -0,0 +1,22 @@ +from boa3.internal.model.builtin.interop.storage.get.istoragegetmethod import IStorageGetMethod + + +class StorageGetIntMethod(IStorageGetMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + + identifier = 'get_int' + value_type = Type.int + + super().__init__(identifier, value_type=value_type) + + def generate_default_value_opcodes(self, code_generator): + # default_value = 0 + code_generator.convert_literal(0) + + def generate_deserialize_value_opcodes(self, code_generator): + from boa3.internal.model.builtin.method.tointmethod import ToInt + from boa3.internal.model.type.type import Type + + converter = ToInt.build(Type.bytes) + code_generator.convert_builtin_method_call(converter) diff --git a/boa3/internal/model/builtin/interop/storage/get/storagegetstrmethod.py b/boa3/internal/model/builtin/interop/storage/get/storagegetstrmethod.py new file mode 100644 index 000000000..f6ddd8c28 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/get/storagegetstrmethod.py @@ -0,0 +1,22 @@ +from boa3.internal.model.builtin.interop.storage.get.istoragegetmethod import IStorageGetMethod + + +class StorageGetStrMethod(IStorageGetMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + + identifier = 'get_str' + value_type = Type.str + + super().__init__(identifier, value_type=value_type) + + def generate_default_value_opcodes(self, code_generator): + # default_value = '' + code_generator.convert_literal('') + + def generate_deserialize_value_opcodes(self, code_generator): + from boa3.internal.model.builtin.method.tostrmethod import ToStr + from boa3.internal.model.type.type import Type + + converter = ToStr.build(Type.bytes) + code_generator.convert_builtin_method_call(converter) diff --git a/boa3/internal/model/builtin/interop/storage/get/storagegetuint160method.py b/boa3/internal/model/builtin/interop/storage/get/storagegetuint160method.py new file mode 100644 index 000000000..b1466ed3a --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/get/storagegetuint160method.py @@ -0,0 +1,20 @@ +from boa3.internal.model.builtin.interop.storage.get.istoragegetmethod import IStorageGetMethod + + +class StorageGetUInt160Method(IStorageGetMethod): + def __init__(self): + from boa3.internal.model.type.collection.sequence.uint160type import UInt160Type + + identifier = 'get_uint160' + value_type = UInt160Type.build() + + super().__init__(identifier, value_type=value_type) + + def generate_default_value_opcodes(self, code_generator): + from boa3.internal.model.builtin.builtin import Builtin + + code_generator.convert_literal(Builtin.UInt160.default_value) + + def generate_deserialize_value_opcodes(self, code_generator): + # it doesn't need to deserialize bytes values + return diff --git a/boa3/internal/model/builtin/interop/storage/get/storagegetuint256method.py b/boa3/internal/model/builtin/interop/storage/get/storagegetuint256method.py new file mode 100644 index 000000000..0e3624a36 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/get/storagegetuint256method.py @@ -0,0 +1,20 @@ +from boa3.internal.model.builtin.interop.storage.get.istoragegetmethod import IStorageGetMethod + + +class StorageGetUInt256Method(IStorageGetMethod): + def __init__(self): + from boa3.internal.model.type.collection.sequence.uint256type import UInt256Type + + identifier = 'get_uint256' + value_type = UInt256Type.build() + + super().__init__(identifier, value_type=value_type) + + def generate_default_value_opcodes(self, code_generator): + from boa3.internal.model.builtin.builtin import Builtin + + code_generator.convert_literal(Builtin.UInt256.default_value) + + def generate_deserialize_value_opcodes(self, code_generator): + # it doesn't need to deserialize bytes values + return diff --git a/boa3/internal/model/builtin/interop/storage/put/__init__.py b/boa3/internal/model/builtin/interop/storage/put/__init__.py new file mode 100644 index 000000000..fa6bb1ac3 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/put/__init__.py @@ -0,0 +1,7 @@ +from boa3.internal.model.builtin.interop.storage.put.storageputboolmethod import StoragePutBoolMethod +from boa3.internal.model.builtin.interop.storage.put.storageputbytesmethod import StoragePutBytesMethod +from boa3.internal.model.builtin.interop.storage.put.storageputecpointmethod import StoragePutECPointMethod +from boa3.internal.model.builtin.interop.storage.put.storageputintmethod import StoragePutIntMethod +from boa3.internal.model.builtin.interop.storage.put.storageputstrmethod import StoragePutStrMethod +from boa3.internal.model.builtin.interop.storage.put.storageputuint160method import StoragePutUInt160Method +from boa3.internal.model.builtin.interop.storage.put.storageputuint256method import StoragePutUInt256Method diff --git a/boa3/internal/model/builtin/interop/storage/storageputmethod.py b/boa3/internal/model/builtin/interop/storage/put/istorageputmethod.py similarity index 72% rename from boa3/internal/model/builtin/interop/storage/storageputmethod.py rename to boa3/internal/model/builtin/interop/storage/put/istorageputmethod.py index 46052ef2b..64ed0958a 100644 --- a/boa3/internal/model/builtin/interop/storage/storageputmethod.py +++ b/boa3/internal/model/builtin/interop/storage/put/istorageputmethod.py @@ -1,3 +1,4 @@ +import abc import ast from collections.abc import Iterable, Sized from typing import Any @@ -10,30 +11,42 @@ from boa3.internal.model.variable import Variable -class StoragePutMethod(InteropMethod): +class IStoragePutMethod(InteropMethod, abc.ABC): - def __init__(self): + def __init__(self, identifier: str, value_type: IType): from boa3.internal.model.type.type import Type from boa3.internal.model.builtin.interop.storage.storagecontext.storagecontexttype import StorageContextType - identifier = 'put' syscall = 'System.Storage.Put' context_type = StorageContextType.build() - storage_value_type = Type.union.build([Type.bytes, - Type.int, - Type.str, - ]) args: dict[str, Variable] = {'key': Variable(Type.bytes), - 'value': Variable(storage_value_type), + 'value': Variable(value_type), 'context': Variable(context_type)} from boa3.internal.model.builtin.interop.storage.storagegetcontextmethod import StorageGetContextMethod default_id = StorageGetContextMethod(context_type).identifier - context_default = set_internal_call(ast.parse("{0}()".format(default_id) + context_default = set_internal_call(ast.parse(f"{default_id}()" ).body[0].value) super().__init__(identifier, syscall, args, defaults=[context_default], return_type=Type.none) + @abc.abstractmethod + def generate_serialize_value_opcodes(self, code_generator): + pass + + def generate_internal_opcodes(self, code_generator): + start_address = code_generator.bytecode_size + code_generator.swap_reverse_stack_items(3) + self.generate_serialize_value_opcodes(code_generator) + end_address = code_generator.last_code_start_address + + if end_address > start_address: + code_generator.swap_reverse_stack_items(3) + else: + code_generator._remove_inserted_opcodes_since(start_address) + + super().generate_internal_opcodes(code_generator) + @property def generation_order(self) -> list[int]: """ @@ -76,7 +89,8 @@ def build(self, value: Any) -> IBuiltinMethod: if self.key_arg.type.is_type_of(key_type) and self.value_arg.type.is_type_of(value_type): return self - method: InteropMethod = StoragePutMethod() + from boa3.internal.model.builtin.interop.storage.put.storageputintmethod import StoragePutBytesMethod + method: InteropMethod = StoragePutBytesMethod() method.args['key'] = Variable(key_type) method.args['value'] = Variable(value_type) return method diff --git a/boa3/internal/model/builtin/interop/storage/put/storageputboolmethod.py b/boa3/internal/model/builtin/interop/storage/put/storageputboolmethod.py new file mode 100644 index 000000000..de397d410 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/put/storageputboolmethod.py @@ -0,0 +1,15 @@ +from boa3.internal.model.builtin.interop.storage.put.istorageputmethod import IStoragePutMethod + + +class StoragePutBoolMethod(IStoragePutMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + + identifier = 'put_bool' + value_type = Type.bool + + super().__init__(identifier, value_type=value_type) + + def generate_serialize_value_opcodes(self, code_generator): + # it doesn't need to serialize primitive types values on put + return diff --git a/boa3/internal/model/builtin/interop/storage/put/storageputbytesmethod.py b/boa3/internal/model/builtin/interop/storage/put/storageputbytesmethod.py new file mode 100644 index 000000000..bb77eb87d --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/put/storageputbytesmethod.py @@ -0,0 +1,15 @@ +from boa3.internal.model.builtin.interop.storage.put.istorageputmethod import IStoragePutMethod + + +class StoragePutBytesMethod(IStoragePutMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + + identifier = 'put' + value_type = Type.bytes + + super().__init__(identifier, value_type=value_type) + + def generate_serialize_value_opcodes(self, code_generator): + # it doesn't need to serialize bytes values + return diff --git a/boa3/internal/model/builtin/interop/storage/put/storageputecpointmethod.py b/boa3/internal/model/builtin/interop/storage/put/storageputecpointmethod.py new file mode 100644 index 000000000..60d0084f3 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/put/storageputecpointmethod.py @@ -0,0 +1,15 @@ +from boa3.internal.model.builtin.interop.storage.put.istorageputmethod import IStoragePutMethod + + +class StoragePutECPointMethod(IStoragePutMethod): + def __init__(self): + from boa3.internal.model.type.collection.sequence.ecpointtype import ECPointType + + identifier = 'put_ecpoint' + value_type = ECPointType.build() + + super().__init__(identifier, value_type=value_type) + + def generate_serialize_value_opcodes(self, code_generator): + # it doesn't need to serialize ECPoint because it is also bytes value + return diff --git a/boa3/internal/model/builtin/interop/storage/put/storageputintmethod.py b/boa3/internal/model/builtin/interop/storage/put/storageputintmethod.py new file mode 100644 index 000000000..6ed9352ef --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/put/storageputintmethod.py @@ -0,0 +1,15 @@ +from boa3.internal.model.builtin.interop.storage.put.istorageputmethod import IStoragePutMethod + + +class StoragePutIntMethod(IStoragePutMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + + identifier = 'put_int' + value_type = Type.int + + super().__init__(identifier, value_type=value_type) + + def generate_serialize_value_opcodes(self, code_generator): + # it doesn't need to serialize primitive types values on put + return diff --git a/boa3/internal/model/builtin/interop/storage/put/storageputstrmethod.py b/boa3/internal/model/builtin/interop/storage/put/storageputstrmethod.py new file mode 100644 index 000000000..dd99ef043 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/put/storageputstrmethod.py @@ -0,0 +1,15 @@ +from boa3.internal.model.builtin.interop.storage.put.istorageputmethod import IStoragePutMethod + + +class StoragePutStrMethod(IStoragePutMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + + identifier = 'put_str' + value_type = Type.str + + super().__init__(identifier, value_type=value_type) + + def generate_serialize_value_opcodes(self, code_generator): + # it doesn't need to serialize primitive types values on put + return diff --git a/boa3/internal/model/builtin/interop/storage/put/storageputuint160method.py b/boa3/internal/model/builtin/interop/storage/put/storageputuint160method.py new file mode 100644 index 000000000..86f264977 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/put/storageputuint160method.py @@ -0,0 +1,15 @@ +from boa3.internal.model.builtin.interop.storage.put.istorageputmethod import IStoragePutMethod + + +class StoragePutUInt160Method(IStoragePutMethod): + def __init__(self): + from boa3.internal.model.type.collection.sequence.uint160type import UInt160Type + + identifier = 'put_uint160' + value_type = UInt160Type.build() + + super().__init__(identifier, value_type=value_type) + + def generate_serialize_value_opcodes(self, code_generator): + # it doesn't need to serialize UInt160 because it is also bytes value + return diff --git a/boa3/internal/model/builtin/interop/storage/put/storageputuint256method.py b/boa3/internal/model/builtin/interop/storage/put/storageputuint256method.py new file mode 100644 index 000000000..b61ba0df8 --- /dev/null +++ b/boa3/internal/model/builtin/interop/storage/put/storageputuint256method.py @@ -0,0 +1,15 @@ +from boa3.internal.model.builtin.interop.storage.put.istorageputmethod import IStoragePutMethod + + +class StoragePutUInt256Method(IStoragePutMethod): + def __init__(self): + from boa3.internal.model.type.collection.sequence.uint256type import UInt256Type + + identifier = 'put_uint256' + value_type = UInt256Type.build() + + super().__init__(identifier, value_type=value_type) + + def generate_serialize_value_opcodes(self, code_generator): + # it doesn't need to serialize UInt256 because it is also bytes value + return diff --git a/boa3/internal/model/builtin/method/maxmethod.py b/boa3/internal/model/builtin/method/maxmethod.py index 9c0402e54..b7200ba63 100644 --- a/boa3/internal/model/builtin/method/maxmethod.py +++ b/boa3/internal/model/builtin/method/maxmethod.py @@ -73,7 +73,7 @@ def generate_opcodes(self, code_generator): code_generator.insert_opcode(Opcode.INC) code_generator.insert_opcode(Opcode.INC) code_generator.convert_end_if(else_stack_size_equals_3, is_internal=True) - code_generator.insert_opcode(Opcode.PACK) + code_generator.insert_opcode(Opcode.PACK, add_to_stack=[Type.list.build(self._arg_values.type)]) # index = len(aux_list) - 1 code_generator.duplicate_stack_top_item() diff --git a/boa3/internal/model/builtin/method/minmethod.py b/boa3/internal/model/builtin/method/minmethod.py index 17080c8fe..dbb75b0c9 100644 --- a/boa3/internal/model/builtin/method/minmethod.py +++ b/boa3/internal/model/builtin/method/minmethod.py @@ -73,7 +73,7 @@ def generate_opcodes(self, code_generator): code_generator.insert_opcode(Opcode.INC) code_generator.insert_opcode(Opcode.INC) code_generator.convert_end_if(else_stack_size_equals_3, is_internal=True) - code_generator.insert_opcode(Opcode.PACK) + code_generator.insert_opcode(Opcode.PACK, add_to_stack=[Type.list.build(self._arg_values.type)]) # index = len(aux_list) - 1 code_generator.duplicate_stack_top_item() diff --git a/boa3/internal/model/type/collection/sequence/ecpointtype.py b/boa3/internal/model/type/collection/sequence/ecpointtype.py index 330fba691..461eb7b47 100644 --- a/boa3/internal/model/type/collection/sequence/ecpointtype.py +++ b/boa3/internal/model/type/collection/sequence/ecpointtype.py @@ -1,6 +1,8 @@ from typing import Any from boa3.internal import constants +from boa3.internal.model.builtin.builtinproperty import IBuiltinProperty +from boa3.internal.model.builtin.method import IBuiltinMethod from boa3.internal.model.method import Method from boa3.internal.model.type.itype import IType from boa3.internal.model.type.primitive.bytestype import BytesType @@ -48,12 +50,17 @@ def _init_class_symbols(self): from boa3.internal.model.builtin.builtin import Builtin + properties = [ECPointZeroProperty() + ] instance_methods = [Builtin.ScriptHashMethod_, ] for instance_method in instance_methods: self._instance_methods[instance_method.raw_identifier] = instance_method.build(self) + for prop in properties: + self._properties[prop.identifier] = prop + def is_instance_opcodes(self) -> list[tuple[Opcode, bytes]]: from boa3.internal.model.type.classes.pythonclass import PythonClass return super(PythonClass, self).is_instance_opcodes() @@ -83,3 +90,29 @@ def _is_instance_inner_opcodes(self, jmp_to_if_false: int = 0) -> list[tuple[Opc _ECPoint = ECPointType() + + +class GetECPointZeroMethod(IBuiltinMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + identifier = '-ecpoint_get_zero' + args = {} + super().__init__(identifier, args, return_type=Type.int) + + def generate_internal_opcodes(self, code_generator): + code_generator.convert_literal(_ECPoint.default_value) + + @property + def _args_on_stack(self) -> int: + return len(self.args) + + @property + def _body(self) -> str | None: + return + + +class ECPointZeroProperty(IBuiltinProperty): + def __init__(self): + identifier = 'zero' + getter = GetECPointZeroMethod() + super().__init__(identifier, getter) diff --git a/boa3/internal/model/type/collection/sequence/uint160type.py b/boa3/internal/model/type/collection/sequence/uint160type.py index 0a9401dbc..f7ee95211 100644 --- a/boa3/internal/model/type/collection/sequence/uint160type.py +++ b/boa3/internal/model/type/collection/sequence/uint160type.py @@ -1,6 +1,8 @@ from typing import Any from boa3.internal import constants +from boa3.internal.model.builtin.builtinproperty import IBuiltinProperty +from boa3.internal.model.builtin.method import IBuiltinMethod from boa3.internal.model.method import Method from boa3.internal.model.type.itype import IType from boa3.internal.model.type.primitive.bytestype import BytesType @@ -43,6 +45,14 @@ def build(cls, value: Any = None) -> IType: def _is_type_of(cls, value: Any): return isinstance(value, UInt160Type) + def _init_class_symbols(self): + super()._init_class_symbols() + properties = [UInt160ZeroProperty() + ] + + for prop in properties: + self._properties[prop.identifier] = prop + def is_instance_opcodes(self) -> list[tuple[Opcode, bytes]]: from boa3.internal.model.type.classes.pythonclass import PythonClass return super(PythonClass, self).is_instance_opcodes() @@ -71,3 +81,29 @@ def _is_instance_inner_opcodes(self, jmp_to_if_false: int = 0) -> list[tuple[Opc _UInt160 = UInt160Type() + + +class GetUInt160ZeroMethod(IBuiltinMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + identifier = '-uint160_get_zero' + args = {} + super().__init__(identifier, args, return_type=Type.int) + + def generate_internal_opcodes(self, code_generator): + code_generator.convert_literal(_UInt160.default_value) + + @property + def _args_on_stack(self) -> int: + return len(self.args) + + @property + def _body(self) -> str | None: + return + + +class UInt160ZeroProperty(IBuiltinProperty): + def __init__(self): + identifier = 'zero' + getter = GetUInt160ZeroMethod() + super().__init__(identifier, getter) diff --git a/boa3/internal/model/type/collection/sequence/uint256type.py b/boa3/internal/model/type/collection/sequence/uint256type.py index 20557356d..28f2b4387 100644 --- a/boa3/internal/model/type/collection/sequence/uint256type.py +++ b/boa3/internal/model/type/collection/sequence/uint256type.py @@ -1,6 +1,8 @@ from typing import Any from boa3.internal import constants +from boa3.internal.model.builtin.builtinproperty import IBuiltinProperty +from boa3.internal.model.builtin.method import IBuiltinMethod from boa3.internal.model.method import Method from boa3.internal.model.type.classes.classtype import ClassType from boa3.internal.model.type.itype import IType @@ -44,6 +46,14 @@ def build(cls, value: Any = None) -> IType: def _is_type_of(cls, value: Any): return isinstance(value, UInt256Type) + def _init_class_symbols(self): + super()._init_class_symbols() + properties = [UInt256ZeroProperty() + ] + + for prop in properties: + self._properties[prop.identifier] = prop + def is_instance_opcodes(self) -> list[tuple[Opcode, bytes]]: from boa3.internal.model.type.classes.pythonclass import PythonClass return super(PythonClass, self).is_instance_opcodes() @@ -72,3 +82,29 @@ def _is_instance_inner_opcodes(self, jmp_to_if_false: int = 0) -> list[tuple[Opc _UInt256 = UInt256Type() + + +class GetUInt256ZeroMethod(IBuiltinMethod): + def __init__(self): + from boa3.internal.model.type.type import Type + identifier = '-uint160_get_zero' + args = {} + super().__init__(identifier, args, return_type=Type.int) + + def generate_internal_opcodes(self, code_generator): + code_generator.convert_literal(_UInt256.default_value) + + @property + def _args_on_stack(self) -> int: + return len(self.args) + + @property + def _body(self) -> str | None: + return + + +class UInt256ZeroProperty(IBuiltinProperty): + def __init__(self): + identifier = 'zero' + getter = GetUInt256ZeroMethod() + super().__init__(identifier, getter) diff --git a/boa3/internal/neo/vm/opcode/OpcodeInfo.py b/boa3/internal/neo/vm/opcode/OpcodeInfo.py index 20b5c4ea4..f429535a3 100644 --- a/boa3/internal/neo/vm/opcode/OpcodeInfo.py +++ b/boa3/internal/neo/vm/opcode/OpcodeInfo.py @@ -205,7 +205,7 @@ def get_info(cls, opcode: Opcode) -> OpcodeInformation | None: # The top three items on the stack are rotated to the left. ROT = OpcodeInformation(Opcode.ROT) # The item n back in the stack is moved to the top. - ROLL = OpcodeInformation(Opcode.ROLL) + ROLL = OpcodeInformation(Opcode.ROLL, stack_items=1) # Reverse the order of the top 3 items on the stack. REVERSE3 = OpcodeInformation(Opcode.REVERSE3) # Reverse the order of the top 4 items on the stack. diff --git a/boa3_test/examples/amm.py b/boa3_test/examples/amm.py index 2a766885c..be1f3eae5 100644 --- a/boa3_test/examples/amm.py +++ b/boa3_test/examples/amm.py @@ -6,7 +6,7 @@ from boa3.builtin.interop.contract import call_contract from boa3.builtin.math import sqrt from boa3.builtin.nativecontract.contractmanagement import ContractManagement -from boa3.builtin.type import UInt160, helper as type_helper +from boa3.builtin.type import UInt160 # ------------------------------------------- @@ -141,7 +141,7 @@ def total_supply() -> int: :return: the total token supply deployed in the system. """ - return type_helper.to_int(storage.get(SUPPLY_KEY)) + return storage.get_int(SUPPLY_KEY) @public(name='balanceOf', safe=True) @@ -155,7 +155,7 @@ def balance_of(account: UInt160) -> int: :type account: UInt160 """ assert len(account) == 20 - return type_helper.to_int(storage.get(account)) + return storage.get_int(account) @public @@ -184,7 +184,7 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) assert amount >= 0 # The function MUST return false if the from account balance does not have enough tokens to spend. - from_balance = type_helper.to_int(storage.get(from_address)) + from_balance = storage.get_int(from_address) if from_balance < amount: return False @@ -200,10 +200,10 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) if from_balance == amount: storage.delete(from_address) else: - storage.put(from_address, from_balance - amount) + storage.put_int(from_address, from_balance - amount) - to_balance = type_helper.to_int(storage.get(to_address)) - storage.put(to_address, to_balance + amount) + to_balance = storage.get_int(to_address) + storage.put_int(to_address, to_balance + amount) # if the method succeeds, it must fire the transfer event on_transfer(from_address, to_address, amount) @@ -241,13 +241,13 @@ def _deploy(data: Any, update: bool): """ if not update: container = runtime.script_container - storage.put(b'owner', container.sender) - storage.put(DEPLOYED, True) + storage.put_uint160(b'owner', container.sender) + storage.put_bool(DEPLOYED, True) @public def onNEP17Payment(from_address: UInt160, amount: int, data: Any): - if not runtime.calling_script_hash == storage.get(TOKEN_A) and not runtime.calling_script_hash == storage.get(TOKEN_B): + if not runtime.calling_script_hash == storage.get_uint160(TOKEN_A) and not runtime.calling_script_hash == storage.get_uint160(TOKEN_B): abort() @@ -257,7 +257,7 @@ def onNEP17Payment(from_address: UInt160, amount: int, data: Any): def get_owner() -> UInt160: - return UInt160(storage.get(b'owner')) + return storage.get_uint160(b'owner') @public @@ -275,26 +275,26 @@ def set_address(address_token_a: UInt160, address_token_b: UInt160) -> bool: if not runtime.check_witness(get_owner()): return False - if not type_helper.to_bool(storage.get(DEPLOYED)): + if not storage.get_bool(DEPLOYED): return False - if storage.get(TOKEN_A) != b'' or storage.get(TOKEN_B) != b'': + if storage.get_uint160(TOKEN_A) != UInt160.zero or storage.get_uint160(TOKEN_B) != UInt160.zero: return False - storage.put(TOKEN_A, address_token_a) - storage.put(TOKEN_B, address_token_b) + storage.put_uint160(TOKEN_A, address_token_a) + storage.put_uint160(TOKEN_B, address_token_b) return True @public def get_token_a() -> UInt160: - return UInt160(storage.get(TOKEN_A)) + return storage.get_uint160(TOKEN_A) @public def get_token_b() -> UInt160: - return UInt160(storage.get(TOKEN_B)) + return storage.get_uint160(TOKEN_B) @public @@ -304,8 +304,8 @@ def get_reserves() -> List[int]: :return: a list of 2 ints, the value in the first index is reserve of token_a and the second value is the reserve of token_b """ - return [type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_A)), - type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_B))] + return [storage.get_int(SUPPLY_KEY + TOKEN_A), + storage.get_int(SUPPLY_KEY + TOKEN_B)] @public @@ -333,8 +333,8 @@ def add_liquidity(amount_token_a_desired: int, amount_token_b_desired: int, amou """ assert runtime.check_witness(user_address) - reserve_token_a = type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_A)) - reserve_token_b = type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_B)) + reserve_token_a = storage.get_int(SUPPLY_KEY + TOKEN_A) + reserve_token_b = storage.get_int(SUPPLY_KEY + TOKEN_B) # If there is no liquidity pool, then the values that will be used to mint and create a pool are the desired ones if reserve_token_a == 0 and reserve_token_b == 0: amount_token_a = amount_token_a_desired @@ -390,8 +390,8 @@ def mint(user_address: UInt160) -> int: # reserve_token_a and reserve_token_b are the amount of token_a and token_b tokens that the smart contract has saved in the # storage, it's not the actual amount that is in the balance, because the amount is not updated after transferring # the token_a and token_b tokens, it will be update only after minting - reserve_token_a = type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_A)) - reserve_token_b = type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_B)) + reserve_token_a = storage.get_int(SUPPLY_KEY + TOKEN_A) + reserve_token_b = storage.get_int(SUPPLY_KEY + TOKEN_B) # balance_token_a and balance_token_b are the actual amount that are in the balance of this smart contract balance_token_a = call_contract(get_token_a(), 'balanceOf', [runtime.executing_script_hash]) @@ -404,7 +404,7 @@ def mint(user_address: UInt160) -> int: amount_token_a = balance_token_a - reserve_token_a amount_token_b = balance_token_b - reserve_token_b - total_supply = type_helper.to_int(storage.get(SUPPLY_KEY)) + total_supply = storage.get_int(SUPPLY_KEY) # if there are no AMM tokens, then the quantity of AMM tokens that will be minted are calculated multiplying # amount_token_a and amount_token_b if total_supply == 0: @@ -416,9 +416,9 @@ def mint(user_address: UInt160) -> int: assert liquidity > 0 # updates the total supply of AMM tokens - storage.put(SUPPLY_KEY, total_supply + liquidity) + storage.put_int(SUPPLY_KEY, total_supply + liquidity) # change the amount of liquidity the user has - storage.put(user_address, type_helper.to_int(storage.get(user_address)) + liquidity) + storage.put_int(user_address, storage.get_int(user_address) + liquidity) on_transfer(None, user_address, liquidity) update(balance_token_a, balance_token_b) @@ -509,7 +509,7 @@ def burn(liquidity: int, user_address: UInt160) -> List[int]: amount_token_b: int = 0 if isinstance(balance_token_a, int) and isinstance(balance_token_b, int): - total_supply = type_helper.to_int(storage.get(SUPPLY_KEY)) + total_supply = storage.get_int(SUPPLY_KEY) # amount_token_a and amount_token_b are the amount that will be transferred to the user after burning the liquidity amount_token_a = liquidity * balance_token_a // total_supply @@ -517,9 +517,9 @@ def burn(liquidity: int, user_address: UInt160) -> List[int]: assert amount_token_a > 0 and amount_token_b > 0 # changing the user balance after burning the liquidity - storage.put(user_address, balance_of(user_address) - liquidity) + storage.put_int(user_address, balance_of(user_address) - liquidity) # update the amount of AMM tokens in this smart contract - storage.put(SUPPLY_KEY, total_supply - liquidity) + storage.put_int(SUPPLY_KEY, total_supply - liquidity) on_transfer(user_address, None, liquidity) call_contract(token_a, 'transfer', [runtime.executing_script_hash, user_address, amount_token_a, None]) @@ -548,8 +548,8 @@ def update(balance_token_a: int, balance_token_b: int): :param balance_token_b: the amount of token_b tokens in the balance of this smart contract :type balance_token_b: int """ - storage.put(SUPPLY_KEY + TOKEN_A, balance_token_a) - storage.put(SUPPLY_KEY + TOKEN_B, balance_token_b) + storage.put_int(SUPPLY_KEY + TOKEN_A, balance_token_a) + storage.put_int(SUPPLY_KEY + TOKEN_B, balance_token_b) on_sync(balance_token_a, balance_token_b) @@ -574,8 +574,8 @@ def swap(amount_token_a_out: int, amount_token_b_out: int, user_address: UInt160 any token from the user, or if the constant k after the swap ends up being lower than the one at the beginning """ assert amount_token_a_out > 0 or amount_token_b_out > 0 - reserve_token_a = type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_A)) - reserve_token_b = type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_B)) + reserve_token_a = storage.get_int(SUPPLY_KEY + TOKEN_A) + reserve_token_b = storage.get_int(SUPPLY_KEY + TOKEN_B) assert amount_token_a_out < reserve_token_a and amount_token_b_out < reserve_token_b token_a = get_token_a() @@ -632,13 +632,13 @@ def swap_tokens(amount_in: int, amount_out_min: int, token_in: UInt160, user_add # Verifies if the user is trying to swap token_a or token_b and set the variables accordingly if token_in == token_a: - reserve_token_in = type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_A)) - reserve_token_out = type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_B)) + reserve_token_in = storage.get_int(SUPPLY_KEY + TOKEN_A) + reserve_token_out = storage.get_int(SUPPLY_KEY + TOKEN_B) amount_token_a_in = amount_in amount_token_b_in = 0 else: - reserve_token_in = type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_B)) - reserve_token_out = type_helper.to_int(storage.get(SUPPLY_KEY + TOKEN_A)) + reserve_token_in = storage.get_int(SUPPLY_KEY + TOKEN_B) + reserve_token_out = storage.get_int(SUPPLY_KEY + TOKEN_A) amount_token_a_in = 0 amount_token_b_in = amount_in diff --git a/boa3_test/examples/auxiliary_contracts/update_contract.py b/boa3_test/examples/auxiliary_contracts/update_contract.py index 8fa033f81..fce2bdf2f 100644 --- a/boa3_test/examples/auxiliary_contracts/update_contract.py +++ b/boa3_test/examples/auxiliary_contracts/update_contract.py @@ -4,7 +4,7 @@ from boa3.builtin.interop import storage, runtime from boa3.builtin.interop.runtime import check_witness from boa3.builtin.nativecontract.contractmanagement import ContractManagement -from boa3.builtin.type import UInt160, helper as type_helper +from boa3.builtin.type import UInt160 # ------------------------------------------- # TOKEN SETTINGS @@ -73,7 +73,7 @@ def method(account: UInt160): # now there is a verification to this method if check_witness(get_owner()): - storage.put(account, type_helper.to_int(storage.get(account)) + 2 * 10 ** 8) + storage.put_int(account, storage.get_int(account) + 2 * 10 ** 8) on_transfer(None, account, 2 * 10 ** 8) # more omitted code @@ -86,9 +86,9 @@ def _deploy(data: Any, update: bool): if not update: container = runtime.script_container - storage.put(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY) - storage.put(container.sender, TOKEN_TOTAL_SUPPLY) - storage.put(OWNER_KEY, container.sender) + storage.put_int(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY) + storage.put_int(container.sender, TOKEN_TOTAL_SUPPLY) + storage.put_uint160(OWNER_KEY, container.sender) on_transfer(None, container.sender, TOKEN_TOTAL_SUPPLY) @@ -98,7 +98,7 @@ def balance_of(account: UInt160) -> int: Get the current balance of an address. """ assert len(account) == 20 - return type_helper.to_int(storage.get(account)) + return storage.get_int(account) @public @@ -110,4 +110,4 @@ def get_owner() -> UInt160: """ Gets the script hash of the owner (the account that deployed this smart contract) """ - return UInt160(storage.get(OWNER_KEY)) + return storage.get_uint160(OWNER_KEY) diff --git a/boa3_test/examples/htlc.py b/boa3_test/examples/htlc.py index e31b23c75..ac3310c82 100644 --- a/boa3_test/examples/htlc.py +++ b/boa3_test/examples/htlc.py @@ -5,7 +5,7 @@ from boa3.builtin.interop import runtime, storage from boa3.builtin.interop.contract import GAS as GAS_SCRIPT, call_contract from boa3.builtin.interop.crypto import hash160 -from boa3.builtin.type import UInt160, helper as type_helper +from boa3.builtin.type import UInt160 # ------------------------------------------- @@ -69,8 +69,8 @@ def _deploy(data: Any, update: bool): if not update: container = runtime.script_container - storage.put(OWNER_KEY, container.sender) - storage.put(NOT_INITIALIZED, True) + storage.put_uint160(OWNER_KEY, container.sender) + storage.put_bool(NOT_INITIALIZED, True) @public @@ -105,16 +105,16 @@ def atomic_swap(person_a_address: UInt160, person_a_token: UInt160, person_a_amo # the parameter amount must be greater than 0. If not, this method should throw an exception. assert person_a_amount > 0 and person_b_amount > 0 - if type_helper.to_bool(storage.get(NOT_INITIALIZED)) and verify(): - storage.put(ADDRESS_PREFIX + PERSON_A, person_a_address) - storage.put(TOKEN_PREFIX + PERSON_A, person_a_token) - storage.put(AMOUNT_PREFIX + PERSON_A, person_a_amount) - storage.put(ADDRESS_PREFIX + PERSON_B, person_b_address) - storage.put(TOKEN_PREFIX + PERSON_B, person_b_token) - storage.put(AMOUNT_PREFIX + PERSON_B, person_b_amount) + if storage.get_bool(NOT_INITIALIZED) and verify(): + storage.put_uint160(ADDRESS_PREFIX + PERSON_A, person_a_address) + storage.put_uint160(TOKEN_PREFIX + PERSON_A, person_a_token) + storage.put_int(AMOUNT_PREFIX + PERSON_A, person_a_amount) + storage.put_uint160(ADDRESS_PREFIX + PERSON_B, person_b_address) + storage.put_uint160(TOKEN_PREFIX + PERSON_B, person_b_token) + storage.put_int(AMOUNT_PREFIX + PERSON_B, person_b_amount) storage.put(SECRET_HASH, secret_hash) - storage.put(NOT_INITIALIZED, False) - storage.put(START_TIME, runtime.time) + storage.put_bool(NOT_INITIALIZED, False) + storage.put_int(START_TIME, runtime.time) return True return False @@ -142,35 +142,35 @@ def onNEP17Payment(from_address: UInt160, amount: int, data: Any): if from_address is None and runtime.calling_script_hash == GAS_SCRIPT: return - if not type_helper.to_bool(storage.get(NOT_INITIALIZED)): + if not storage.get_bool(NOT_INITIALIZED): # Used to check if the one who's transferring to this contract is the PERSON_A - address = storage.get(ADDRESS_PREFIX + PERSON_A) + address = storage.get_uint160(ADDRESS_PREFIX + PERSON_A) # Used to check if PERSON_A has already transferred to this smart contract - funded_crypto = type_helper.to_int(storage.get(FUNDED_PREFIX + PERSON_A)) + funded_crypto = storage.get_int(FUNDED_PREFIX + PERSON_A) # Used to check if PERSON_A is transferring the correct amount - amount_crypto = type_helper.to_int(storage.get(AMOUNT_PREFIX + PERSON_A)) + amount_crypto = storage.get_int(AMOUNT_PREFIX + PERSON_A) # Used to check if PERSON_A is transferring the correct token - token_crypto = storage.get(TOKEN_PREFIX + PERSON_A) + token_crypto = storage.get_uint160(TOKEN_PREFIX + PERSON_A) if (from_address == address and funded_crypto == 0 and amount == amount_crypto and runtime.calling_script_hash == token_crypto): - storage.put(FUNDED_PREFIX + PERSON_A, amount) + storage.put_int(FUNDED_PREFIX + PERSON_A, amount) return else: # Used to check if the one who's transferring to this contract is the OTHER_PERSON - address = storage.get(ADDRESS_PREFIX + PERSON_B) + address = storage.get_uint160(ADDRESS_PREFIX + PERSON_B) # Used to check if PERSON_B already transfer to this smart contract - funded_crypto = type_helper.to_int(storage.get(FUNDED_PREFIX + PERSON_B)) + funded_crypto = storage.get_int(FUNDED_PREFIX + PERSON_B) # Used to check if PERSON_B is transferring the correct amount - amount_crypto = type_helper.to_int(storage.get(AMOUNT_PREFIX + PERSON_B)) + amount_crypto = storage.get_int(AMOUNT_PREFIX + PERSON_B) # Used to check if PERSON_B is transferring the correct token - token_crypto = storage.get(TOKEN_PREFIX + PERSON_B) + token_crypto = storage.get_uint160(TOKEN_PREFIX + PERSON_B) if (from_address == address and funded_crypto == 0 and amount == amount_crypto and runtime.calling_script_hash == token_crypto): - storage.put(FUNDED_PREFIX + PERSON_B, amount) + storage.put_int(FUNDED_PREFIX + PERSON_B, amount) return abort() @@ -188,19 +188,19 @@ def withdraw(secret: str) -> bool: :rtype: bool """ # Checking if PERSON_A and PERSON_B transferred to this smart contract - funded_person_a = type_helper.to_int(storage.get(FUNDED_PREFIX + PERSON_A)) - funded_person_b = type_helper.to_int(storage.get(FUNDED_PREFIX + PERSON_B)) + funded_person_a = storage.get_int(FUNDED_PREFIX + PERSON_A) + funded_person_b = storage.get_int(FUNDED_PREFIX + PERSON_B) if verify() and not refund() and hash160(secret) == storage.get(SECRET_HASH) and funded_person_a != 0 and funded_person_b != 0: - storage.put(FUNDED_PREFIX + PERSON_A, 0) - storage.put(FUNDED_PREFIX + PERSON_B, 0) - storage.put(NOT_INITIALIZED, True) - storage.put(START_TIME, 0) - call_contract(UInt160(storage.get(TOKEN_PREFIX + PERSON_B)), 'transfer', - [runtime.executing_script_hash, storage.get(ADDRESS_PREFIX + PERSON_A), - type_helper.to_int(storage.get(AMOUNT_PREFIX + PERSON_B)), None]) - call_contract(UInt160(storage.get(TOKEN_PREFIX + PERSON_A)), 'transfer', - [runtime.executing_script_hash, storage.get(ADDRESS_PREFIX + PERSON_B), - type_helper.to_int(storage.get(AMOUNT_PREFIX + PERSON_A)), None]) + storage.put_int(FUNDED_PREFIX + PERSON_A, 0) + storage.put_int(FUNDED_PREFIX + PERSON_B, 0) + storage.put_bool(NOT_INITIALIZED, True) + storage.put_int(START_TIME, 0) + call_contract(storage.get_uint160(TOKEN_PREFIX + PERSON_B), 'transfer', + [runtime.executing_script_hash, storage.get_uint160(ADDRESS_PREFIX + PERSON_A), + storage.get_int(AMOUNT_PREFIX + PERSON_B), None]) + call_contract(storage.get_uint160(TOKEN_PREFIX + PERSON_A), 'transfer', + [runtime.executing_script_hash, storage.get_uint160(ADDRESS_PREFIX + PERSON_B), + storage.get_int(AMOUNT_PREFIX + PERSON_A), None]) return True return False @@ -214,24 +214,24 @@ def refund() -> bool: :return: whether enough time has passed and the cryptocurrencies were refunded :rtype: bool """ - if runtime.time > type_helper.to_int(storage.get(START_TIME)) + LOCK_TIME: + if runtime.time > storage.get_int(START_TIME) + LOCK_TIME: # Checking if PERSON_A transferred to this smart contract - funded_crypto = type_helper.to_int(storage.get(FUNDED_PREFIX + PERSON_A)) + funded_crypto = storage.get_int(FUNDED_PREFIX + PERSON_A) if funded_crypto != 0: - call_contract(UInt160(storage.get(TOKEN_PREFIX + PERSON_A)), 'transfer', - [runtime.executing_script_hash, UInt160(storage.get(ADDRESS_PREFIX + PERSON_A)), - type_helper.to_int(storage.get(AMOUNT_PREFIX + PERSON_A)), None]) + call_contract(storage.get_uint160(TOKEN_PREFIX + PERSON_A), 'transfer', + [runtime.executing_script_hash, storage.get_uint160(ADDRESS_PREFIX + PERSON_A), + storage.get_int(AMOUNT_PREFIX + PERSON_A), None]) # Checking if PERSON_B transferred to this smart contract - funded_crypto = type_helper.to_int(storage.get(FUNDED_PREFIX + PERSON_B)) + funded_crypto = storage.get_int(FUNDED_PREFIX + PERSON_B) if funded_crypto != 0: - call_contract(UInt160(storage.get(TOKEN_PREFIX + PERSON_B)), 'transfer', - [runtime.executing_script_hash, storage.get(ADDRESS_PREFIX + PERSON_B), - type_helper.to_int(storage.get(AMOUNT_PREFIX + PERSON_B)), None]) - storage.put(FUNDED_PREFIX + PERSON_A, 0) - storage.put(FUNDED_PREFIX + PERSON_B, 0) - storage.put(NOT_INITIALIZED, True) - storage.put(START_TIME, 0) + call_contract(storage.get_uint160(TOKEN_PREFIX + PERSON_B), 'transfer', + [runtime.executing_script_hash, storage.get_uint160(ADDRESS_PREFIX + PERSON_B), + storage.get_int(AMOUNT_PREFIX + PERSON_B), None]) + storage.put_int(FUNDED_PREFIX + PERSON_A, 0) + storage.put_int(FUNDED_PREFIX + PERSON_B, 0) + storage.put_bool(NOT_INITIALIZED, True) + storage.put_int(START_TIME, 0) return True return False @@ -240,4 +240,4 @@ def get_owner() -> UInt160: """ Gets the script hash of the owner (the account that deployed this smart contract) """ - return UInt160(storage.get(OWNER_KEY)) + return storage.get_uint160(OWNER_KEY) diff --git a/boa3_test/examples/ico.py b/boa3_test/examples/ico.py index ce20266c1..564d113ef 100644 --- a/boa3_test/examples/ico.py +++ b/boa3_test/examples/ico.py @@ -7,7 +7,7 @@ from boa3.builtin.nativecontract.contractmanagement import ContractManagement from boa3.builtin.nativecontract.gas import GAS as GAS_TOKEN from boa3.builtin.nativecontract.neo import NEO as NEO_TOKEN -from boa3.builtin.type import UInt160, helper as type_helper +from boa3.builtin.type import UInt160 # ------------------------------------------- @@ -93,7 +93,7 @@ def is_valid_address(address: UInt160) -> bool: :return: whether the given address is validated by kyc """ - return type_helper.to_int(storage.get(KYC_WHITELIST_PREFIX + address)) > 0 + return storage.get_int(KYC_WHITELIST_PREFIX + address) > 0 @public @@ -106,16 +106,16 @@ def _deploy(data: Any, update: bool): if not update: container = runtime.script_container owner = container.sender - storage.put(TOKEN_OWNER_KEY, owner) + storage.put_uint160(TOKEN_OWNER_KEY, owner) - storage.put(TOKEN_TOTAL_SUPPLY_PREFIX, TOKEN_INITIAL_SUPPLY) - storage.put(owner, TOKEN_INITIAL_SUPPLY) + storage.put_int(TOKEN_TOTAL_SUPPLY_PREFIX, TOKEN_INITIAL_SUPPLY) + storage.put_int(owner, TOKEN_INITIAL_SUPPLY) on_transfer(None, owner, TOKEN_INITIAL_SUPPLY) def get_owner() -> UInt160: - return UInt160(storage.get(TOKEN_OWNER_KEY)) + return storage.get_uint160(TOKEN_OWNER_KEY) @public @@ -136,8 +136,8 @@ def mint(amount: int) -> bool: current_total_supply = total_supply() owner_balance = balance_of(token_owner) - storage.put(TOKEN_TOTAL_SUPPLY_PREFIX, current_total_supply + amount) - storage.put(token_owner, owner_balance + amount) + storage.put_int(TOKEN_TOTAL_SUPPLY_PREFIX, current_total_supply + amount) + storage.put_int(token_owner, owner_balance + amount) on_transfer(None, token_owner, amount) post_transfer(None, token_owner, amount, None) @@ -219,7 +219,7 @@ def total_supply() -> int: :return: the total token supply deployed in the system. """ - return type_helper.to_int(storage.get(TOKEN_TOTAL_SUPPLY_PREFIX)) + return storage.get_int(TOKEN_TOTAL_SUPPLY_PREFIX) @public(name='balanceOf', safe=True) @@ -236,7 +236,7 @@ def balance_of(account: UInt160) -> int: :raise AssertionError: raised if `account` length is not 20. """ assert len(account) == 20, 'invalid account length' - return type_helper.to_int(storage.get(account)) + return storage.get_int(account) @public @@ -265,7 +265,7 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) assert amount >= 0 # The function MUST return false if the from account balance does not have enough tokens to spend. - from_balance = type_helper.to_int(storage.get(from_address)) + from_balance = storage.get_int(from_address) if from_balance < amount: return False @@ -281,10 +281,10 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) if from_balance == amount: storage.delete(from_address) else: - storage.put(from_address, from_balance - amount) + storage.put_int(from_address, from_balance - amount) - to_balance = type_helper.to_int(storage.get(to_address)) - storage.put(to_address, to_balance + amount) + to_balance = storage.get_int(to_address) + storage.put_int(to_address, to_balance + amount) # if the method succeeds, it must fire the transfer event on_transfer(from_address, to_address, amount) @@ -356,7 +356,7 @@ def allowance(from_address: UInt160, to_address: UInt160) -> int: """ # the parameters from and to should be 20-byte addresses. If not, this method should throw an exception. assert len(from_address) == 20 and len(to_address) == 20 - return type_helper.to_int(storage.get(TRANSFER_ALLOWANCE_PREFIX + from_address + to_address)) + return storage.get_int(TRANSFER_ALLOWANCE_PREFIX + from_address + to_address) @public(name='transferFrom') @@ -403,7 +403,7 @@ def transfer_from(originator: UInt160, from_address: UInt160, to_address: UInt16 if approved_transfer_amount == amount: storage.delete(TRANSFER_ALLOWANCE_PREFIX + originator + from_address) else: - storage.put(TRANSFER_ALLOWANCE_PREFIX + originator + from_address, approved_transfer_amount - amount) + storage.put_int(TRANSFER_ALLOWANCE_PREFIX + originator + from_address, approved_transfer_amount - amount) # skip balance changes if transferring to yourself or transferring 0 cryptocurrency if amount != 0 and from_address != to_address: @@ -411,11 +411,11 @@ def transfer_from(originator: UInt160, from_address: UInt160, to_address: UInt16 if originator_balance == amount: storage.delete(originator) else: - storage.put(originator, originator_balance - amount) + storage.put_int(originator, originator_balance - amount) # updates to's balance - to_balance = type_helper.to_int(storage.get(to_address)) - storage.put(to_address, to_balance + amount) + to_balance = storage.get_int(to_address) + storage.put_int(to_address, to_balance + amount) # if the method succeeds, it must fire the transfer event on_transfer(from_address, to_address, amount) @@ -456,7 +456,7 @@ def approve(originator: UInt160, to_address: UInt160, amount: int) -> bool: if balance_of(originator) < amount: return False - storage.put(TRANSFER_ALLOWANCE_PREFIX + originator + to_address, amount) + storage.put_int(TRANSFER_ALLOWANCE_PREFIX + originator + to_address, amount) return True @@ -478,7 +478,7 @@ def kyc_register(addresses: List[UInt160]) -> int: for address in addresses: if len(address) == 20: kyc_key = KYC_WHITELIST_PREFIX + address - storage.put(kyc_key, True) + storage.put_bool(kyc_key, True) included_addresses += 1 return included_addresses diff --git a/boa3_test/examples/nep11_non_divisible.py b/boa3_test/examples/nep11_non_divisible.py index fb642bfec..d3fa367aa 100644 --- a/boa3_test/examples/nep11_non_divisible.py +++ b/boa3_test/examples/nep11_non_divisible.py @@ -13,7 +13,7 @@ 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.storage import delete, find, get, get_read_only_context, put +from boa3.builtin.interop import storage from boa3.builtin.interop.storage.findoptions import FindOptions from boa3.builtin.type import UInt160, helper as type_helper @@ -170,8 +170,8 @@ def totalSupply() -> int: :return: the total token supply deployed in the system. """ - debug(['totalSupply: ', type_helper.to_int(get(SUPPLY_PREFIX))]) - return type_helper.to_int(get(SUPPLY_PREFIX, get_read_only_context())) + debug(['totalSupply: ', storage.get_int(SUPPLY_PREFIX)]) + return storage.get_int(SUPPLY_PREFIX, storage.get_read_only_context()) @public(safe=True) @@ -187,8 +187,8 @@ def balanceOf(owner: UInt160) -> int: :raise AssertionError: raised if `owner` length is not 20. """ expect(validateAddress(owner), "Not a valid address") - debug(['balanceOf: ', type_helper.to_int(get(mk_balance_key(owner), get_read_only_context()))]) - return type_helper.to_int(get(mk_balance_key(owner), get_read_only_context())) + debug(['balanceOf: ', storage.get_int(mk_balance_key(owner), storage.get_read_only_context())]) + return storage.get_int(mk_balance_key(owner), storage.get_read_only_context()) @public(safe=True) @@ -205,8 +205,8 @@ def tokensOf(owner: UInt160) -> Iterator: """ expect(validateAddress(owner), "Not a valid address") flags = FindOptions.REMOVE_PREFIX | FindOptions.KEYS_ONLY - context = get_read_only_context() - return find(mk_account_key(owner), context, flags) + context = storage.get_read_only_context() + return storage.find(mk_account_key(owner), context, flags) @public @@ -237,6 +237,7 @@ def transfer(to: UInt160, tokenId: bytes, data: Any) -> bool: expect(validateAddress(to), "Not a valid address") expect(not isPaused(), "Contract is currently paused") token_owner = get_owner_of(tokenId) + expect(token_owner != UInt160.zero, "Token not found") if not check_witness(token_owner): return False @@ -299,8 +300,8 @@ def tokens() -> Iterator: :return: an iterator that contains all of the tokens minted by the contract. """ flags = FindOptions.REMOVE_PREFIX | FindOptions.KEYS_ONLY - context = get_read_only_context() - return find(TOKEN_PREFIX, context, flags) + context = storage.get_read_only_context() + return storage.find(TOKEN_PREFIX, context, flags) @public(safe=True) @@ -349,7 +350,7 @@ def _deploy(data: Any, upgrade: bool): if upgrade: return - if type_helper.to_bool(get(DEPLOYED, get_read_only_context())): + if storage.get_bool(DEPLOYED, storage.get_read_only_context()): return tx = script_container @@ -373,14 +374,14 @@ def _deploy(data: Any, upgrade: bool): def internal_deploy(owner: UInt160): debug(["internal: ", owner]) - put(DEPLOYED, True) - put(PAUSED, False) - put(TOKEN_COUNT, 0) + storage.put_bool(DEPLOYED, True) + storage.put_bool(PAUSED, False) + storage.put_int(TOKEN_COUNT, 0) auth: List[UInt160] = [] auth.append(owner) serialized = serialize(auth) - put(AUTH_ADDRESSES, serialized) + storage.put(AUTH_ADDRESSES, serialized) @public(name='onNEP11Payment') @@ -509,7 +510,7 @@ def getAuthorizedAddress() -> list[UInt160]: :return: whether the transaction signature is correct :raise AssertionError: raised if witness is not verified. """ - serialized = get(AUTH_ADDRESSES, get_read_only_context()) + serialized = storage.get(AUTH_ADDRESSES, storage.get_read_only_context()) auth = cast(list[UInt160], deserialize(serialized)) return auth @@ -535,7 +536,7 @@ def setAuthorizedAddress(address: UInt160, authorized: bool): expect(verified, '`account` is not allowed for setAuthorizedAddress') expect(validateAddress(address), "Not a valid address") expect(isinstance(authorized, bool), "authorized has to be of type bool") - serialized = get(AUTH_ADDRESSES, get_read_only_context()) + serialized = storage.get(AUTH_ADDRESSES, storage.get_read_only_context()) auth = cast(list[UInt160], deserialize(serialized)) if authorized: @@ -548,11 +549,11 @@ def setAuthorizedAddress(address: UInt160, authorized: bool): if not found: auth.append(address) - put(AUTH_ADDRESSES, serialize(auth)) + storage.put(AUTH_ADDRESSES, serialize(auth)) on_auth(address, 0, True) else: auth.remove(address) - put(AUTH_ADDRESSES, serialize(auth)) + storage.put(AUTH_ADDRESSES, serialize(auth)) on_auth(address, 0, False) @@ -569,9 +570,9 @@ def updatePause(status: bool) -> bool: verified: bool = verify() expect(verified, '`account` is not allowed for updatePause') expect(isinstance(status, bool), "status has to be of type bool") - put(PAUSED, status) - debug(['updatePause: ', type_helper.to_bool(get(PAUSED, get_read_only_context()))]) - return type_helper.to_bool(get(PAUSED, get_read_only_context())) + storage.put_bool(PAUSED, status) + debug(['updatePause: ', storage.get_bool(PAUSED, storage.get_read_only_context())]) + return storage.get_bool(PAUSED, storage.get_read_only_context()) @public(safe=True) @@ -583,8 +584,8 @@ def isPaused() -> bool: :return: whether the contract is paused """ - debug(['isPaused: ', type_helper.to_bool(get(PAUSED))]) - if type_helper.to_bool(get(PAUSED, get_read_only_context())): + debug(['isPaused: ', storage.get_bool(PAUSED)]) + if storage.get_bool(PAUSED, storage.get_read_only_context()): return True return False @@ -600,7 +601,7 @@ def verify() -> bool: :return: whether the transaction signature is correct """ - serialized = get(AUTH_ADDRESSES, get_read_only_context()) + serialized = storage.get(AUTH_ADDRESSES, storage.get_read_only_context()) auth = cast(list[UInt160], deserialize(serialized)) tx = script_container for addr in auth: @@ -685,8 +686,8 @@ def internal_mint(account: UInt160, meta: str, lockedContent: str, royalties: st """ expect(len(meta) != 0, '`meta` can not be empty') - tokenId = type_helper.to_int(get(TOKEN_COUNT, get_read_only_context())) + 1 - put(TOKEN_COUNT, tokenId) + tokenId = storage.get_int(TOKEN_COUNT, storage.get_read_only_context()) + 1 + storage.put_int(TOKEN_COUNT, tokenId) tokenIdBytes = type_helper.to_bytes(tokenId) set_owner_of(tokenIdBytes, account) @@ -712,38 +713,38 @@ def internal_mint(account: UInt160, meta: str, lockedContent: str, royalties: st def remove_token_account(holder: UInt160, tokenId: bytes): key = mk_account_key(holder) + tokenId debug(['add_token_account: ', key, tokenId]) - delete(key) + storage.delete(key) def add_token_account(holder: UInt160, tokenId: bytes): key = mk_account_key(holder) + tokenId debug(['add_token_account: ', key, tokenId]) - put(key, tokenId) + storage.put(key, tokenId) def get_owner_of(tokenId: bytes) -> UInt160: key = mk_token_key(tokenId) debug(['get_owner_of: ', key, tokenId]) - owner = get(key, get_read_only_context()) - return UInt160(owner) + owner = storage.get_uint160(key, storage.get_read_only_context()) + return owner def remove_owner_of(tokenId: bytes): key = mk_token_key(tokenId) debug(['remove_owner_of: ', key, tokenId]) - delete(key) + storage.delete(key) def set_owner_of(tokenId: bytes, owner: UInt160): key = mk_token_key(tokenId) debug(['set_owner_of: ', key, tokenId]) - put(key, owner) + storage.put_uint160(key, owner) def add_to_supply(amount: int): total = totalSupply() + amount debug(['add_to_supply: ', amount]) - put(SUPPLY_PREFIX, total) + storage.put_int(SUPPLY_PREFIX, total) def set_balance(owner: UInt160, amount: int): @@ -753,85 +754,85 @@ def set_balance(owner: UInt160, amount: int): key = mk_balance_key(owner) if (new > 0): - put(key, new) + storage.put_int(key, new) else: - delete(key) + storage.delete(key) def get_meta(tokenId: bytes) -> str: key = mk_meta_key(tokenId) debug(['get_meta: ', key, tokenId]) - val = get(key, get_read_only_context()) - return type_helper.to_str(val) + val = storage.get_str(key, storage.get_read_only_context()) + return val def remove_meta(tokenId: bytes): key = mk_meta_key(tokenId) debug(['remove_meta: ', key, tokenId]) - delete(key) + storage.delete(key) def add_meta(tokenId: bytes, meta: str): key = mk_meta_key(tokenId) debug(['add_meta: ', key, tokenId]) - put(key, meta) + storage.put_str(key, meta) def get_locked_content(tokenId: bytes) -> str: key = mk_locked_key(tokenId) debug(['get_locked_content: ', key, tokenId]) - val = type_helper.to_str(get(key, get_read_only_context())) + val = storage.get_str(key, storage.get_read_only_context()) return val def remove_locked_content(tokenId: bytes): key = mk_locked_key(tokenId) debug(['remove_locked_content: ', key, tokenId]) - delete(key) + storage.delete(key) def add_locked_content(tokenId: bytes, content: str): key = mk_locked_key(tokenId) debug(['add_locked_content: ', key, tokenId]) - put(key, content) + storage.put_str(key, content) def get_royalties(tokenId: bytes) -> str: key = mk_royalties_key(tokenId) debug(['get_royalties: ', key, tokenId]) - val = get(key, get_read_only_context()) - return type_helper.to_str(val) + val = storage.get_str(key, storage.get_read_only_context()) + return val def add_royalties(tokenId: bytes, royalties: str): key = mk_royalties_key(tokenId) debug(['add_royalties: ', key, tokenId]) - put(key, royalties) + storage.put_str(key, royalties) def remove_royalties(tokenId: bytes): key = mk_royalties_key(tokenId) debug(['remove_royalties: ', key, tokenId]) - delete(key) + storage.delete(key) def get_locked_view_counter(tokenId: bytes) -> int: key = mk_lv_key(tokenId) debug(['get_locked_view_counter: ', key, tokenId]) - return type_helper.to_int(get(key, get_read_only_context())) + return storage.get_int(key, storage.get_read_only_context()) def remove_locked_view_counter(tokenId: bytes): key = mk_lv_key(tokenId) debug(['remove_locked_view_counter: ', key, tokenId]) - delete(key) + storage.delete(key) def set_locked_view_counter(tokenId: bytes): key = mk_lv_key(tokenId) debug(['set_locked_view_counter: ', key, tokenId]) - count = type_helper.to_int(get(key, get_read_only_context())) + 1 - put(key, count) + count = storage.get_int(key, storage.get_read_only_context()) + 1 + storage.put_int(key, count) # helpers diff --git a/boa3_test/examples/nep17.py b/boa3_test/examples/nep17.py index 6a5b9a360..8aeee6a28 100644 --- a/boa3_test/examples/nep17.py +++ b/boa3_test/examples/nep17.py @@ -5,7 +5,7 @@ from boa3.builtin.interop import runtime, storage from boa3.builtin.interop.contract import GAS as GAS_SCRIPT, NEO as NEO_SCRIPT, call_contract from boa3.builtin.nativecontract.contractmanagement import ContractManagement -from boa3.builtin.type import UInt160, helper as type_helper +from boa3.builtin.type import UInt160 # ------------------------------------------- @@ -100,7 +100,7 @@ def total_supply() -> int: :return: the total token supply deployed in the system. """ - return type_helper.to_int(storage.get(SUPPLY_KEY)) + return storage.get_int(SUPPLY_KEY) @public(name='balanceOf', safe=True) @@ -114,7 +114,7 @@ def balance_of(account: UInt160) -> int: :type account: UInt160 """ assert len(account) == 20 - return type_helper.to_int(storage.get(account)) + return storage.get_int(account) @public @@ -143,7 +143,7 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) assert amount >= 0 # The function MUST return false if the from account balance does not have enough tokens to spend. - from_balance = type_helper.to_int(storage.get(from_address)) + from_balance = storage.get_int(from_address) if from_balance < amount: return False @@ -159,10 +159,10 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) if from_balance == amount: storage.delete(from_address) else: - storage.put(from_address, from_balance - amount) + storage.put_int(from_address, from_balance - amount) - to_balance = type_helper.to_int(storage.get(to_address)) - storage.put(to_address, to_balance + amount) + to_balance = storage.get_int(to_address) + storage.put_int(to_address, to_balance + amount) # if the method succeeds, it must fire the transfer event on_transfer(from_address, to_address, amount) @@ -206,8 +206,8 @@ def mint(account: UInt160, amount: int): current_total_supply = total_supply() account_balance = balance_of(account) - storage.put(SUPPLY_KEY, current_total_supply + amount) - storage.put(account, account_balance + amount) + storage.put_int(SUPPLY_KEY, current_total_supply + amount) + storage.put_int(account, account_balance + amount) on_transfer(None, account, amount) post_transfer(None, account, amount, None) @@ -233,9 +233,9 @@ def _deploy(data: Any, update: bool): if not update: container = runtime.script_container - storage.put(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY) - storage.put(OWNER_KEY, container.sender) - storage.put(container.sender, TOKEN_TOTAL_SUPPLY) + storage.put_int(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY) + storage.put_uint160(OWNER_KEY, container.sender) + storage.put_int(container.sender, TOKEN_TOTAL_SUPPLY) on_transfer(None, container.sender, TOKEN_TOTAL_SUPPLY) @@ -277,4 +277,4 @@ def get_owner() -> UInt160: """ Gets the script hash of the owner (the account that deployed this smart contract) """ - return UInt160(storage.get(OWNER_KEY)) + return storage.get_uint160(OWNER_KEY) diff --git a/boa3_test/examples/simple_nep17.py b/boa3_test/examples/simple_nep17.py index 5151ac6f0..7a3f6469f 100644 --- a/boa3_test/examples/simple_nep17.py +++ b/boa3_test/examples/simple_nep17.py @@ -5,7 +5,7 @@ from boa3.builtin.interop import runtime, storage from boa3.builtin.interop.contract import call_contract from boa3.builtin.nativecontract.contractmanagement import ContractManagement -from boa3.builtin.type import UInt160, helper as type_helper +from boa3.builtin.type import UInt160 # ------------------------------------------- @@ -108,7 +108,7 @@ def balance_of(account: UInt160) -> int: :type account: UInt160 """ assert len(account) == 20 - return type_helper.to_int(storage.get(account)) + return storage.get_int(account) @public @@ -150,9 +150,9 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) if from_balance == amount: storage.delete(from_address) else: - storage.put(from_address, from_balance - amount) + storage.put_int(from_address, from_balance - amount) - storage.put(to_address, to_balance + amount) + storage.put_int(to_address, to_balance + amount) # if the method succeeds, it must fire the transfer event on_transfer(from_address, to_address, amount) @@ -192,6 +192,6 @@ def _deploy(data: Any, update: bool): if not update: container = runtime.script_container - storage.put(container.sender, total_supply()) + storage.put_int(container.sender, total_supply()) on_transfer(None, container.sender, total_supply()) diff --git a/boa3_test/examples/update_contract.py b/boa3_test/examples/update_contract.py index c9fc43740..69624ab9b 100644 --- a/boa3_test/examples/update_contract.py +++ b/boa3_test/examples/update_contract.py @@ -4,7 +4,7 @@ from boa3.builtin.interop import storage, runtime from boa3.builtin.interop.runtime import check_witness from boa3.builtin.nativecontract.contractmanagement import ContractManagement -from boa3.builtin.type import UInt160, helper as type_helper +from boa3.builtin.type import UInt160 # ------------------------------------------- # TOKEN SETTINGS @@ -75,7 +75,7 @@ def method(account: UInt160): This method is not working as intended and ends up giving tokens to a user whenever he wants. """ # some omitted code - storage.put(account, type_helper.to_int(storage.get(account)) + 2 * 10 ** 8) + storage.put_int(account, storage.get_int(account) + 2 * 10 ** 8) on_transfer(None, account, 2 * 10 ** 8) # more omitted code @@ -88,9 +88,9 @@ def _deploy(data: Any, update: bool): if not update: container = runtime.script_container - storage.put(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY) - storage.put(container.sender, TOKEN_TOTAL_SUPPLY) - storage.put(OWNER_KEY, container.sender) + storage.put_int(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY) + storage.put_int(container.sender, TOKEN_TOTAL_SUPPLY) + storage.put_uint160(OWNER_KEY, container.sender) on_transfer(None, container.sender, TOKEN_TOTAL_SUPPLY) @@ -100,11 +100,11 @@ def balance_of(account: UInt160) -> int: Get the current balance of an address. """ assert len(account) == 20 - return type_helper.to_int(storage.get(account)) + return storage.get_int(account) def get_owner() -> UInt160: """ Gets the script hash of the owner (the account that deployed this smart contract) """ - return UInt160(storage.get(OWNER_KEY)) + return storage.get_uint160(OWNER_KEY) diff --git a/boa3_test/examples/wrapped_gas.py b/boa3_test/examples/wrapped_gas.py index f707c066e..299326abe 100644 --- a/boa3_test/examples/wrapped_gas.py +++ b/boa3_test/examples/wrapped_gas.py @@ -6,7 +6,7 @@ from boa3.builtin.interop.contract import GAS as GAS_SCRIPT, call_contract from boa3.builtin.nativecontract.contractmanagement import ContractManagement from boa3.builtin.nativecontract.gas import GAS as GAS_TOKEN -from boa3.builtin.type import UInt160, helper as type_helper +from boa3.builtin.type import UInt160 # ------------------------------------------- @@ -106,7 +106,7 @@ def total_supply() -> int: :return: the total token supply deployed in the system. """ - return type_helper.to_int(storage.get(SUPPLY_KEY)) + return storage.get_int(SUPPLY_KEY) @public(name='balanceOf', safe=True) @@ -120,7 +120,7 @@ def balance_of(account: UInt160) -> int: :type account: bytes """ assert len(account) == 20 - return type_helper.to_int(storage.get(account)) + return storage.get_int(account) @public @@ -149,7 +149,7 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) assert amount >= 0 # The function MUST return false if the from account balance does not have enough tokens to spend. - from_balance = type_helper.to_int(storage.get(from_address)) + from_balance = storage.get_int(from_address) if from_balance < amount: return False @@ -165,10 +165,10 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) if from_balance == amount: storage.delete(from_address) else: - storage.put(from_address, from_balance - amount) + storage.put_int(from_address, from_balance - amount) - to_balance = type_helper.to_int(storage.get(to_address)) - storage.put(to_address, to_balance + amount) + to_balance = storage.get_int(to_address) + storage.put_int(to_address, to_balance + amount) # if the method succeeds, it must fire the transfer event on_transfer(from_address, to_address, amount) @@ -207,7 +207,7 @@ def transfer_from(spender: UInt160, from_address: UInt160, to_address: UInt160, assert amount >= 0 # The function MUST return false if the from account balance does not have enough tokens to spend. - from_balance = type_helper.to_int(storage.get(from_address)) + from_balance = storage.get_int(from_address) if from_balance < amount: return False @@ -226,17 +226,17 @@ def transfer_from(spender: UInt160, from_address: UInt160, to_address: UInt160, if allowed == amount: storage.delete(ALLOWANCE_PREFIX + from_address + spender) else: - storage.put(ALLOWANCE_PREFIX + from_address + spender, allowed - amount) + storage.put_int(ALLOWANCE_PREFIX + from_address + spender, allowed - amount) # skip balance changes if transferring to yourself or transferring 0 cryptocurrency if from_address != to_address and amount != 0: if from_balance == amount: storage.delete(from_address) else: - storage.put(from_address, from_balance - amount) + storage.put_int(from_address, from_balance - amount) - to_balance = type_helper.to_int(storage.get(to_address)) - storage.put(to_address, to_balance + amount) + to_balance = storage.get_int(to_address) + storage.put_int(to_address, to_balance + amount) # if the method succeeds, it must fire the transfer event on_transfer(from_address, to_address, amount) @@ -268,7 +268,7 @@ def approve(owner: UInt160, spender: UInt160, amount: int) -> bool: return False if balance_of(owner) >= amount: - storage.put(ALLOWANCE_PREFIX + owner + spender, amount) + storage.put_int(ALLOWANCE_PREFIX + owner + spender, amount) on_approval(owner, spender, amount) return True return False @@ -284,7 +284,7 @@ def allowance(owner: UInt160, spender: UInt160) -> int: :param spender: the address that can spend zGAS from the owner's account :type spender: UInt160 """ - return type_helper.to_int(storage.get(ALLOWANCE_PREFIX + owner + spender)) + return storage.get_int(ALLOWANCE_PREFIX + owner + spender) def post_transfer(from_address: Union[UInt160, None], to_address: Union[UInt160, None], amount: int, data: Any, @@ -325,8 +325,8 @@ def mint(account: UInt160, amount: int): current_total_supply = total_supply() account_balance = balance_of(account) - storage.put(SUPPLY_KEY, current_total_supply + amount) - storage.put(account, account_balance + amount) + storage.put_int(SUPPLY_KEY, current_total_supply + amount) + storage.put_int(account, account_balance + amount) on_transfer(None, account, amount) post_transfer(None, account, amount, None, True) @@ -353,12 +353,12 @@ def burn(account: UInt160, amount: int): assert account_balance >= amount - storage.put(SUPPLY_KEY, current_total_supply - amount) + storage.put_int(SUPPLY_KEY, current_total_supply - amount) if account_balance == amount: storage.delete(account) else: - storage.put(account, account_balance - amount) + storage.put_int(account, account_balance - amount) on_transfer(account, None, amount) post_transfer(account, None, amount, None, False) @@ -386,8 +386,8 @@ def _deploy(data: Any, update: bool): :return: whether the deploy was successful. This method must return True only during the smart contract's deploy. """ if not update: - storage.put(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY) - storage.put(OWNER, TOKEN_TOTAL_SUPPLY) + storage.put_int(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY) + storage.put_int(OWNER, TOKEN_TOTAL_SUPPLY) on_transfer(None, OWNER, TOKEN_TOTAL_SUPPLY) diff --git a/boa3_test/examples/wrapped_neo.py b/boa3_test/examples/wrapped_neo.py index 937544881..e200f709f 100644 --- a/boa3_test/examples/wrapped_neo.py +++ b/boa3_test/examples/wrapped_neo.py @@ -6,7 +6,7 @@ from boa3.builtin.interop.contract import GAS as GAS_SCRIPT, NEO as NEO_SCRIPT, call_contract from boa3.builtin.nativecontract.contractmanagement import ContractManagement from boa3.builtin.nativecontract.neo import NEO as NEO_TOKEN -from boa3.builtin.type import UInt160, helper as type_helper +from boa3.builtin.type import UInt160 # ------------------------------------------- @@ -106,7 +106,7 @@ def total_supply() -> int: :return: the total token supply deployed in the system. """ - return type_helper.to_int(storage.get(SUPPLY_KEY)) + return storage.get_int(SUPPLY_KEY) @public(name='balanceOf', safe=True) @@ -120,7 +120,7 @@ def balance_of(account: UInt160) -> int: :type account: bytes """ assert len(account) == 20 - return type_helper.to_int(storage.get(account)) + return storage.get_int(account) @public @@ -149,7 +149,7 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) assert amount >= 0 # The function MUST return false if the from account balance does not have enough tokens to spend. - from_balance = type_helper.to_int(storage.get(from_address)) + from_balance = storage.get_int(from_address) if from_balance < amount: return False @@ -165,10 +165,10 @@ def transfer(from_address: UInt160, to_address: UInt160, amount: int, data: Any) if from_balance == amount: storage.delete(from_address) else: - storage.put(from_address, from_balance - amount) + storage.put_int(from_address, from_balance - amount) - to_balance = type_helper.to_int(storage.get(to_address)) - storage.put(to_address, to_balance + amount) + to_balance = storage.get_int(to_address) + storage.put_int(to_address, to_balance + amount) # if the method succeeds, it must fire the transfer event on_transfer(from_address, to_address, amount) @@ -207,7 +207,7 @@ def transfer_from(spender: UInt160, from_address: UInt160, to_address: UInt160, assert amount >= 0 # The function MUST return false if the from account balance does not have enough tokens to spend. - from_balance = type_helper.to_int(storage.get(from_address)) + from_balance = storage.get_int(from_address) if from_balance < amount: return False @@ -226,17 +226,17 @@ def transfer_from(spender: UInt160, from_address: UInt160, to_address: UInt160, if allowed == amount: storage.delete(ALLOWANCE_PREFIX + from_address + spender) else: - storage.put(ALLOWANCE_PREFIX + from_address + spender, allowed - amount) + storage.put_int(ALLOWANCE_PREFIX + from_address + spender, allowed - amount) # skip balance changes if transferring to yourself or transferring 0 cryptocurrency if from_address != to_address and amount != 0: if from_balance == amount: storage.delete(from_address) else: - storage.put(from_address, from_balance - amount) + storage.put_int(from_address, from_balance - amount) - to_balance = type_helper.to_int(storage.get(to_address)) - storage.put(to_address, to_balance + amount) + to_balance = storage.get_int(to_address) + storage.put_int(to_address, to_balance + amount) # if the method succeeds, it must fire the transfer event on_transfer(from_address, to_address, amount) @@ -268,7 +268,7 @@ def approve(owner: UInt160, spender: UInt160, amount: int) -> bool: return False if balance_of(owner) >= amount: - storage.put(ALLOWANCE_PREFIX + owner + spender, amount) + storage.put_int(ALLOWANCE_PREFIX + owner + spender, amount) on_approval(owner, spender, amount) return True return False @@ -284,7 +284,7 @@ def allowance(owner: UInt160, spender: UInt160) -> int: :param spender: the address that can spend zNEO from the owner's account :type spender: UInt160 """ - return type_helper.to_int(storage.get(ALLOWANCE_PREFIX + owner + spender)) + return storage.get_int(ALLOWANCE_PREFIX + owner + spender) def post_transfer(from_address: Union[UInt160, None], to_address: Union[UInt160, None], amount: int, data: Any, @@ -325,8 +325,8 @@ def mint(account: UInt160, amount: int): current_total_supply = total_supply() account_balance = balance_of(account) - storage.put(SUPPLY_KEY, current_total_supply + amount) - storage.put(account, account_balance + amount) + storage.put_int(SUPPLY_KEY, current_total_supply + amount) + storage.put_int(account, account_balance + amount) on_transfer(None, account, amount) post_transfer(None, account, amount, None, True) @@ -353,12 +353,12 @@ def burn(account: UInt160, amount: int): assert account_balance >= amount - storage.put(SUPPLY_KEY, current_total_supply - amount) + storage.put_int(SUPPLY_KEY, current_total_supply - amount) if account_balance == amount: storage.delete(account) else: - storage.put(account, account_balance - amount) + storage.put_int(account, account_balance - amount) on_transfer(account, None, amount) post_transfer(account, None, amount, None, False) @@ -388,9 +388,9 @@ def _deploy(data: Any, update: bool): if not update: container = runtime.script_container - storage.put(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY) - storage.put(container.sender, TOKEN_TOTAL_SUPPLY) - storage.put(OWNER_KEY, container.sender) + storage.put_int(SUPPLY_KEY, TOKEN_TOTAL_SUPPLY) + storage.put_int(container.sender, TOKEN_TOTAL_SUPPLY) + storage.put_uint160(OWNER_KEY, container.sender) on_transfer(None, container.sender, TOKEN_TOTAL_SUPPLY) @@ -421,4 +421,4 @@ def get_owner() -> UInt160: """ Gets the script hash of the owner (the account that deployed this smart contract) """ - return UInt160(storage.get(OWNER_KEY)) + return storage.get_uint160(OWNER_KEY) diff --git a/boa3_test/test_sc/class_test/UserClassWithDeployMethod.py b/boa3_test/test_sc/class_test/UserClassWithDeployMethod.py index 435b7b15c..8a6c34bdb 100644 --- a/boa3_test/test_sc/class_test/UserClassWithDeployMethod.py +++ b/boa3_test/test_sc/class_test/UserClassWithDeployMethod.py @@ -21,6 +21,6 @@ def _deploy(data: Any, update: bool): if not update: # setup instructions that will be executed when the smart contract is deployed container = runtime.script_container - storage.put(b'owner', container.sender) + storage.put_uint160(b'owner', container.sender) else: return diff --git a/boa3_test/test_sc/contract_interface_test/ContractInterfaceCodeOptimization.py b/boa3_test/test_sc/contract_interface_test/ContractInterfaceCodeOptimization.py index 5dcab5503..b19a5a33d 100644 --- a/boa3_test/test_sc/contract_interface_test/ContractInterfaceCodeOptimization.py +++ b/boa3_test/test_sc/contract_interface_test/ContractInterfaceCodeOptimization.py @@ -4,7 +4,7 @@ from boa3.builtin.type import UInt160 -@contract('0x9fe946187a660f01c50b2b6bca2781f94d93ceca') +@contract('0x327f3bb13088dbf9fb01b28b8b53a24e37ae9043') class Nep17: @staticmethod diff --git a/boa3_test/test_sc/contract_interface_test/ContractManualInterfaceCodeOptimization.py b/boa3_test/test_sc/contract_interface_test/ContractManualInterfaceCodeOptimization.py index a4b9943bb..0e4396c83 100644 --- a/boa3_test/test_sc/contract_interface_test/ContractManualInterfaceCodeOptimization.py +++ b/boa3_test/test_sc/contract_interface_test/ContractManualInterfaceCodeOptimization.py @@ -6,7 +6,7 @@ class Nep17: - _hash = UInt160(b'\xca\xce\x93\x4d\xf9\x81\x27\xca\x6b\x2b\x0b\xc5\x01\x0f\x66\x7a\x18\x46\xe9\x9f') + _hash = UInt160(b'\x43\x90\xae\x37\x4e\xa2\x53\x8b\x8b\xb2\x01\xfb\xf9\xdb\x88\x30\xb1\x3b\x7f\x32') @classmethod def symbol(cls) -> str: diff --git a/boa3_test/test_sc/contract_interface_test/Nep17Interface.py b/boa3_test/test_sc/contract_interface_test/Nep17Interface.py index f016ab0dd..bf0e1f9af 100644 --- a/boa3_test/test_sc/contract_interface_test/Nep17Interface.py +++ b/boa3_test/test_sc/contract_interface_test/Nep17Interface.py @@ -4,7 +4,7 @@ from boa3.builtin.type import UInt160 -@contract('0x9fe946187a660f01c50b2b6bca2781f94d93ceca') +@contract('0x327f3bb13088dbf9fb01b28b8b53a24e37ae9043') class Nep17: @staticmethod diff --git a/boa3_test/test_sc/contract_interface_test/Nep17InterfaceWithDisplayName.py b/boa3_test/test_sc/contract_interface_test/Nep17InterfaceWithDisplayName.py index 315a8ef05..3bd3985e4 100644 --- a/boa3_test/test_sc/contract_interface_test/Nep17InterfaceWithDisplayName.py +++ b/boa3_test/test_sc/contract_interface_test/Nep17InterfaceWithDisplayName.py @@ -4,7 +4,7 @@ from boa3.builtin.type import UInt160 -@contract('0x9fe946187a660f01c50b2b6bca2781f94d93ceca') +@contract('0x327f3bb13088dbf9fb01b28b8b53a24e37ae9043') class Nep17: @staticmethod diff --git a/boa3_test/test_sc/for_test/IteratorCondition.py b/boa3_test/test_sc/for_test/IteratorCondition.py index 2f86d582b..6219c2487 100644 --- a/boa3_test/test_sc/for_test/IteratorCondition.py +++ b/boa3_test/test_sc/for_test/IteratorCondition.py @@ -19,9 +19,9 @@ def Main() -> int: @public def _deploy(data: Any, update: bool): prefix = b'example' - storage.put(prefix + b'\x01', 1) - storage.put(prefix + b'\x02', 2) - storage.put(prefix + b'\x03', 3) + storage.put_int(prefix + b'\x01', 1) + storage.put_int(prefix + b'\x02', 2) + storage.put_int(prefix + b'\x03', 3) def get_iterator() -> Iterator: diff --git a/boa3_test/test_sc/interop_test/contract/CallFlagsUsage.py b/boa3_test/test_sc/interop_test/contract/CallFlagsUsage.py index 113969db3..9a0bf7608 100644 --- a/boa3_test/test_sc/interop_test/contract/CallFlagsUsage.py +++ b/boa3_test/test_sc/interop_test/contract/CallFlagsUsage.py @@ -3,8 +3,7 @@ from boa3.builtin.compile_time import public from boa3.builtin.interop.contract import NEO, call_contract from boa3.builtin.interop.runtime import executing_script_hash, notify -from boa3.builtin.interop.storage import get, put -from boa3.builtin.type.helper import to_int +from boa3.builtin.interop.storage import get_int, put_int @public @@ -19,9 +18,9 @@ def notify_user(): @public def put_value(key: bytes, value: int): - put(key, value) + put_int(key, value) @public def get_value(key: bytes) -> int: - return to_int(get(key)) + return get_int(key) diff --git a/boa3_test/test_sc/interop_test/contract/NewContract.py b/boa3_test/test_sc/interop_test/contract/NewContract.py index 3c3c1d175..cbdb299bc 100644 --- a/boa3_test/test_sc/interop_test/contract/NewContract.py +++ b/boa3_test/test_sc/interop_test/contract/NewContract.py @@ -2,13 +2,12 @@ from boa3.builtin.compile_time import public from boa3.builtin.interop.runtime import notify -from boa3.builtin.interop.storage import get, put -from boa3.builtin.type.helper import to_str +from boa3.builtin.interop.storage import get_str, put_str @public def main() -> str: - return to_str(get(b'storage')) + return get_str(b'storage') @public @@ -16,4 +15,4 @@ def _deploy(data: Any, update: bool): notify(update) notify(data) if isinstance(data, str): - put(b'storage', data) + put_str(b'storage', data) diff --git a/boa3_test/test_sc/interop_test/iterator/IteratorNext.py b/boa3_test/test_sc/interop_test/iterator/IteratorNext.py index d2f66066f..38c209a4f 100644 --- a/boa3_test/test_sc/interop_test/iterator/IteratorNext.py +++ b/boa3_test/test_sc/interop_test/iterator/IteratorNext.py @@ -9,4 +9,4 @@ def has_next(prefix: bytes) -> bool: @public def store_data(key: bytes, value: int): - storage.put(key, value) + storage.put_int(key, value) diff --git a/boa3_test/test_sc/interop_test/iterator/IteratorValue.py b/boa3_test/test_sc/interop_test/iterator/IteratorValue.py index fa69da87b..6532ce5fc 100644 --- a/boa3_test/test_sc/interop_test/iterator/IteratorValue.py +++ b/boa3_test/test_sc/interop_test/iterator/IteratorValue.py @@ -14,4 +14,4 @@ def test_iterator(prefix: bytes) -> Union[tuple, None]: @public def store_data(key: bytes, value: int): - storage.put(key, value) + storage.put_int(key, value) diff --git a/boa3_test/test_sc/interop_test/runtime/ExecutingScriptHashOnDeploy.py b/boa3_test/test_sc/interop_test/runtime/ExecutingScriptHashOnDeploy.py index 3ee01d573..f657fa034 100644 --- a/boa3_test/test_sc/interop_test/runtime/ExecutingScriptHashOnDeploy.py +++ b/boa3_test/test_sc/interop_test/runtime/ExecutingScriptHashOnDeploy.py @@ -7,7 +7,7 @@ @public def _deploy(data: Any, update: bool): if not update: - storage.put(b'testKey', runtime.executing_script_hash) + storage.put_uint160(b'testKey', runtime.executing_script_hash) @public diff --git a/boa3_test/test_sc/interop_test/storage/ImportInteropStorage.py b/boa3_test/test_sc/interop_test/storage/ImportInteropStorage.py index fc5b08ecc..61958b984 100644 --- a/boa3_test/test_sc/interop_test/storage/ImportInteropStorage.py +++ b/boa3_test/test_sc/interop_test/storage/ImportInteropStorage.py @@ -1,17 +1,16 @@ from boa3.builtin import interop from boa3.builtin.compile_time import public from boa3.builtin.interop.iterator import Iterator -from boa3.builtin.type.helper import to_int @public def put_value(key: bytes, value: int): - interop.storage.put(key, value) + interop.storage.put_int(key, value) @public def get_value(key: bytes) -> int: - return to_int(interop.storage.get(key)) + return interop.storage.get_int(key) @public diff --git a/boa3_test/test_sc/interop_test/storage/ImportStorage.py b/boa3_test/test_sc/interop_test/storage/ImportStorage.py index 9e6864539..e6957da9d 100644 --- a/boa3_test/test_sc/interop_test/storage/ImportStorage.py +++ b/boa3_test/test_sc/interop_test/storage/ImportStorage.py @@ -1,17 +1,16 @@ from boa3.builtin.compile_time import public from boa3.builtin.interop import storage from boa3.builtin.interop.iterator import Iterator -from boa3.builtin.type.helper import to_int @public def put_value(key: bytes, value: int): - storage.put(key, value) + storage.put_int(key, value) @public def get_value(key: bytes) -> int: - return to_int(storage.get(key)) + return storage.get_int(key) @public diff --git a/boa3_test/test_sc/interop_test/storage/StorageAsReadOnly.py b/boa3_test/test_sc/interop_test/storage/StorageAsReadOnly.py index 6fcdeccfe..3be0bac0b 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageAsReadOnly.py +++ b/boa3_test/test_sc/interop_test/storage/StorageAsReadOnly.py @@ -1,23 +1,22 @@ from boa3.builtin.compile_time import public -from boa3.builtin.interop.storage import get, get_context, put -from boa3.builtin.type.helper import to_str +from boa3.builtin.interop.storage import get_str, get_context, put_str @public def put_value_in_storage(key: bytes, value: str): - put(key, value) + put_str(key, value) @public def get_value_in_storage(key: bytes) -> str: - return to_str(get(key)) + return get_str(key) @public def put_value_in_storage_read_only(key: bytes, value: str): - put(key, value, get_context().as_read_only()) + put_str(key, value, get_context().as_read_only()) @public def get_value_in_storage_read_only(key: bytes) -> str: - return to_str(get(key, get_context().as_read_only())) + return get_str(key, get_context().as_read_only()) diff --git a/boa3_test/test_sc/interop_test/storage/StorageBoa2Test.py b/boa3_test/test_sc/interop_test/storage/StorageBoa2Test.py index 6c8e20f82..9bdfe43bb 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageBoa2Test.py +++ b/boa3_test/test_sc/interop_test/storage/StorageBoa2Test.py @@ -1,7 +1,7 @@ from typing import Any from boa3.builtin.compile_time import public -from boa3.builtin.interop.storage import delete, get, get_context, put +from boa3.builtin.interop.storage import delete, get, get_context, put_str @public @@ -16,7 +16,7 @@ def main(operation: str, arg: bytes, val: str) -> Any: elif operation == 'sput': - put(arg, val, storage_context) + put_str(arg, val, storage_context) return True elif operation == 'sdel': diff --git a/boa3_test/test_sc/interop_test/storage/StorageCreateMap.py b/boa3_test/test_sc/interop_test/storage/StorageCreateMap.py index 9f60e5f8c..36f9e5e84 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageCreateMap.py +++ b/boa3_test/test_sc/interop_test/storage/StorageCreateMap.py @@ -9,7 +9,7 @@ def get_from_map(key: bytes) -> bytes: @public -def insert_to_map(key: bytes, value: str): +def insert_to_map(key: bytes, value: bytes): context = create_map() context.put(key, value) diff --git a/boa3_test/test_sc/interop_test/storage/StorageDeleteBytesKey.py b/boa3_test/test_sc/interop_test/storage/StorageDeleteBytesKey.py index adc06d772..cd5a87770 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageDeleteBytesKey.py +++ b/boa3_test/test_sc/interop_test/storage/StorageDeleteBytesKey.py @@ -18,4 +18,4 @@ def has_key(key: bytes) -> bool: @public def _deploy(data: Any, update: bool): # test data to test in unit tests - storage.put(b'example', 23) + storage.put_int(b'example', 23) diff --git a/boa3_test/test_sc/interop_test/storage/StorageDeleteWithContext.py b/boa3_test/test_sc/interop_test/storage/StorageDeleteWithContext.py index 90dd13b2b..4267a549d 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageDeleteWithContext.py +++ b/boa3_test/test_sc/interop_test/storage/StorageDeleteWithContext.py @@ -21,4 +21,4 @@ def has_key(key: bytes) -> bool: def _deploy(data: Any, update: bool): # test data to test in unit tests context = get_context() - storage.put(b'example', 23, context) + storage.put_int(b'example', 23, context) diff --git a/boa3_test/test_sc/interop_test/storage/StorageFindBytesPrefix.py b/boa3_test/test_sc/interop_test/storage/StorageFindBytesPrefix.py index 1bb52e4af..62c61b90b 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageFindBytesPrefix.py +++ b/boa3_test/test_sc/interop_test/storage/StorageFindBytesPrefix.py @@ -11,5 +11,5 @@ def find_by_prefix(prefix: bytes) -> Iterator: @public -def put_on_storage(key: bytes, value: Union[bytes, int, str]): +def put_on_storage(key: bytes, value: bytes): put(key, value) diff --git a/boa3_test/test_sc/interop_test/storage/StorageFindStrPrefix.py b/boa3_test/test_sc/interop_test/storage/StorageFindStrPrefix.py index df2a56a0c..8f0608357 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageFindStrPrefix.py +++ b/boa3_test/test_sc/interop_test/storage/StorageFindStrPrefix.py @@ -8,5 +8,5 @@ def find_by_prefix(prefix: str) -> Iterator: return find(prefix) -def put_on_storage(key: bytes, value: Union[bytes, int, str]): +def put_on_storage(key: bytes, value: bytes): put(key, value) diff --git a/boa3_test/test_sc/interop_test/storage/StorageFindWithContext.py b/boa3_test/test_sc/interop_test/storage/StorageFindWithContext.py index 3403fdb8b..48ac1c0ba 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageFindWithContext.py +++ b/boa3_test/test_sc/interop_test/storage/StorageFindWithContext.py @@ -12,5 +12,5 @@ def find_by_prefix(prefix: bytes) -> Iterator: @public -def put_on_storage(key: bytes, value: Union[bytes, int, str]): +def put_on_storage(key: bytes, value: bytes): put(key, value) diff --git a/boa3_test/test_sc/interop_test/storage/StorageFindWithOptions.py b/boa3_test/test_sc/interop_test/storage/StorageFindWithOptions.py index 94c1523db..3819fbbb7 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageFindWithOptions.py +++ b/boa3_test/test_sc/interop_test/storage/StorageFindWithOptions.py @@ -13,5 +13,5 @@ def find_by_prefix(prefix: bytes) -> Iterator: @public -def put_on_storage(key: bytes, value: Union[bytes, int, str]): +def put_on_storage(key: bytes, value: bytes): put(key, value) diff --git a/boa3_test/test_sc/interop_test/storage/StorageGetAndPut1.py b/boa3_test/test_sc/interop_test/storage/StorageGetAndPut1.py index c57d5c239..55a00d2f7 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageGetAndPut1.py +++ b/boa3_test/test_sc/interop_test/storage/StorageGetAndPut1.py @@ -1,13 +1,12 @@ from boa3.builtin.compile_time import public -from boa3.builtin.interop.storage import get, put -from boa3.builtin.type.helper import to_int +from boa3.builtin.interop.storage import get_int, put_int @public def put_value(key: bytes, value: int): - put(key, value) + put_int(key, value) @public def get_value(key: bytes) -> int: - return to_int(get(key)) + return get_int(key) diff --git a/boa3_test/test_sc/interop_test/storage/StorageGetAndPut2.py b/boa3_test/test_sc/interop_test/storage/StorageGetAndPut2.py index c85e6cfe3..57df43236 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageGetAndPut2.py +++ b/boa3_test/test_sc/interop_test/storage/StorageGetAndPut2.py @@ -1,13 +1,12 @@ from boa3.builtin.compile_time import public -from boa3.builtin.interop.storage import get, put -from boa3.builtin.type.helper import to_int +from boa3.builtin.interop.storage import get_int, put_int @public def get_value(key: bytes) -> int: - return to_int(get(key)) + return get_int(key) @public def put_value(key: bytes, value: int): - put(key, value) + put_int(key, value) diff --git a/boa3_test/test_sc/interop_test/storage/StorageGetWithContext.py b/boa3_test/test_sc/interop_test/storage/StorageGetWithContext.py index 8f986f1a9..52786c9ec 100644 --- a/boa3_test/test_sc/interop_test/storage/StorageGetWithContext.py +++ b/boa3_test/test_sc/interop_test/storage/StorageGetWithContext.py @@ -15,5 +15,5 @@ def Main(key: bytes) -> bytes: def _deploy(data: Any, update: bool): # test data to test in unit tests context = get_context() - storage.put(b'example', 23, context) - storage.put(b'test', 42, context) + storage.put_int(b'example', 23, context) + storage.put_int(b'test', 42, context) diff --git a/boa3_test/test_sc/interop_test/storage/StoragePutBytesKeyIntValue.py b/boa3_test/test_sc/interop_test/storage/StoragePutBytesKeyIntValue.py index 69301cc45..4e7269469 100644 --- a/boa3_test/test_sc/interop_test/storage/StoragePutBytesKeyIntValue.py +++ b/boa3_test/test_sc/interop_test/storage/StoragePutBytesKeyIntValue.py @@ -1,8 +1,8 @@ from boa3.builtin.compile_time import public -from boa3.builtin.interop.storage import put +from boa3.builtin.interop.storage import put_int @public def Main(key: bytes): value: int = 123 - put(key, value) + put_int(key, value) diff --git a/boa3_test/test_sc/interop_test/storage/StoragePutBytesKeyStrValue.py b/boa3_test/test_sc/interop_test/storage/StoragePutBytesKeyStrValue.py index 7a758896d..0b401a563 100644 --- a/boa3_test/test_sc/interop_test/storage/StoragePutBytesKeyStrValue.py +++ b/boa3_test/test_sc/interop_test/storage/StoragePutBytesKeyStrValue.py @@ -1,8 +1,8 @@ from boa3.builtin.compile_time import public -from boa3.builtin.interop.storage import put +from boa3.builtin.interop.storage import put_str @public def Main(key: bytes): value: str = '123' - put(key, value) + put_str(key, value) diff --git a/boa3_test/test_sc/interop_test/storage/StoragePutStrKeyIntValue.py b/boa3_test/test_sc/interop_test/storage/StoragePutStrKeyIntValue.py index 8c2026784..92bb855b4 100644 --- a/boa3_test/test_sc/interop_test/storage/StoragePutStrKeyIntValue.py +++ b/boa3_test/test_sc/interop_test/storage/StoragePutStrKeyIntValue.py @@ -1,6 +1,6 @@ -from boa3.builtin.interop.storage import put +from boa3.builtin.interop.storage import put_int def Main(key: str): value: int = 123 - put(key, value) + put_int(key, value) diff --git a/boa3_test/test_sc/interop_test/storage/StoragePutStrKeyStrValue.py b/boa3_test/test_sc/interop_test/storage/StoragePutStrKeyStrValue.py index 566459862..8421c5fa1 100644 --- a/boa3_test/test_sc/interop_test/storage/StoragePutStrKeyStrValue.py +++ b/boa3_test/test_sc/interop_test/storage/StoragePutStrKeyStrValue.py @@ -1,6 +1,6 @@ -from boa3.builtin.interop.storage import put +from boa3.builtin.interop.storage import put_str def Main(key: str): value: str = '123' - put(key, value) + put_str(key, value) diff --git a/boa3_test/test_sc/native_test/oracle/OracleRequestCall.py b/boa3_test/test_sc/native_test/oracle/OracleRequestCall.py index 479dc758c..056a02e35 100644 --- a/boa3_test/test_sc/native_test/oracle/OracleRequestCall.py +++ b/boa3_test/test_sc/native_test/oracle/OracleRequestCall.py @@ -16,17 +16,17 @@ def oracle_call(url: str, request_filter: str, callback: str, user_data: Any, ga @public def callback_method(requested_url: str, user_data: bytes, code: OracleResponseCode, request_result: bytes): - storage.put(b'pUrl', requested_url) + storage.put_str(b'pUrl', requested_url) storage.put(b'pUser', serialize(user_data)) - storage.put(b'pCode', type_helper.to_bytes(code)) + storage.put_int(b'pCode', code) storage.put(b'pRes', request_result) @public def get_storage() -> List[Any]: - a = storage.get(b'pUrl') + a = storage.get_str(b'pUrl') b = storage.get(b'pUser') - c = storage.get(b'pCode') + c = storage.get_int(b'pCode') d = storage.get(b'pRes') return [a, b, c, d] diff --git a/boa3_test/tests/compiler_tests/test_native/test_oracle.py b/boa3_test/tests/compiler_tests/test_native/test_oracle.py index 9584f9728..561e65a8f 100644 --- a/boa3_test/tests/compiler_tests/test_native/test_oracle.py +++ b/boa3_test/tests/compiler_tests/test_native/test_oracle.py @@ -138,7 +138,7 @@ def test_oracle_response(self): from boa3_test.tests.test_drive import neoxp from boa3_test.tests.test_drive.testrunner.boa_test_runner import BoaTestRunner - path, _ = self.get_deploy_file_paths('OracleRequestCall.py') + path, _ = self.get_deploy_file_paths('OracleRequestCall.py', compile_if_found=True) runner = BoaTestRunner(runner_id=self.method_name()) invokes = [] @@ -159,7 +159,7 @@ def test_oracle_response(self): expected_results.append(True) invokes.append(runner.call_contract(path, 'get_storage')) - expected_results.append(['', '', '', '']) + expected_results.append(['', '', 0, '']) runner.execute(account=OWNER, add_invokes_to_batch=True) self.assertEqual(VMState.HALT, runner.vm_state, msg=runner.error) @@ -185,7 +185,7 @@ def test_oracle_response(self): self.assertEqual(test_url, storage.result[0]) self.assertEqual(f"{(StackItemType.ByteString + len(user_data).to_bytes(1,'little')).decode()}{user_data}", storage.result[1]) - self.assertEqual(OracleResponseCode.Success.to_bytes(1, 'little').decode(), storage.result[2]) + self.assertEqual(OracleResponseCode.Success, storage.result[2]) self.assertEqual(json_data, json.loads(storage.result[3])) self.assertEqual(1, len(response_tx_ids)) diff --git a/boa3_test/tests/examples_tests/test_nep11_non_divisible.py b/boa3_test/tests/examples_tests/test_nep11_non_divisible.py index 618fc2d00..6e00c2cc0 100644 --- a/boa3_test/tests/examples_tests/test_nep11_non_divisible.py +++ b/boa3_test/tests/examples_tests/test_nep11_non_divisible.py @@ -249,7 +249,7 @@ async def test_transfer_fail_non_existing_token(self): [self.account2.script_hash, token, None], return_type=bool ) - self.assertIsNone(*context.exception.args) + self.assertEqual(str(context.exception), 'Token not found') async def test_transfer_fail_bad_account(self): token = self.TEST_TOKEN_ID diff --git a/docs/source/getting-started.md b/docs/source/getting-started.md index 71db000f7..2f9b3a6d5 100644 --- a/docs/source/getting-started.md +++ b/docs/source/getting-started.md @@ -51,12 +51,12 @@ from boa3.builtin.interop import storage @public # the public decorator will make this method callable def save_hello_world(): # an empty return type indicates that the return is None - storage.put(b"first script", "Hello World") # the put method will store the "Hello World" value with the "first script" key + storage.put_str(b"first script", "Hello World") # the put method will store the "Hello World" value with the "first script" key @public # the public decorator will make this method callable too def get_hello_world() -> str: # this method will return a string, so it needs to specify it - return str(storage.get(b"first script")) # the get method will return the value associated with "first script" key + return storage.get_str(b"first script") # the get method will return the value associated with "first script" key ``` ### Neo Methods @@ -98,17 +98,17 @@ from boa3.builtin.interop import storage @public def _deploy(data: Any, update: bool): # the _deploy function needs to have this signature - storage.put(b"second script", "Hello World") # "Hello World" will be stored when this smart contract is deployed + storage.put_str(b"second script", "Hello World") # "Hello World" will be stored when this smart contract is deployed @public def get_message() -> str: # this method will still try to get the value saved on the blockchain - return str(storage.get(b"second script")) + return storage.get_str(b"second script") @public def set_message(new_message: str): # now this method will overwrite a new string on the blockchain - storage.put(b"second script", new_message) + storage.put_str(b"second script", new_message) ``` ## Compiling your Smart Contract