diff --git a/neo3/contracts/applicationengine.py b/neo3/contracts/applicationengine.py index 2385d826..5a756b23 100644 --- a/neo3/contracts/applicationengine.py +++ b/neo3/contracts/applicationengine.py @@ -415,7 +415,7 @@ def _contract_call_internal2(self, has_return_value: bool, args: List[vm.StackItem]): if method_descriptor.safe: - flags &= ~contracts.CallFlags.WRITE_STATES + flags &= ~(contracts.CallFlags.WRITE_STATES | contracts.CallFlags.ALLOW_NOTIFY) else: current_contract = contracts.ManagementContract().get_contract(self.snapshot, self.current_scripthash) if current_contract and not current_contract.can_call(target_contract, method_descriptor.name): diff --git a/neo3/contracts/interop/contract.py b/neo3/contracts/interop/contract.py index fc677b57..bc69f8f9 100644 --- a/neo3/contracts/interop/contract.py +++ b/neo3/contracts/interop/contract.py @@ -64,7 +64,7 @@ def contract_create_multisigaccount(engine: contracts.ApplicationEngine, return to_script_hash(contracts.Contract.create_multisig_redeemscript(m, public_keys)) -@register("System.Contract.NativeOnPersist", 0, contracts.CallFlags.WRITE_STATES) +@register("System.Contract.NativeOnPersist", 0, contracts.CallFlags.STATES) def native_on_persist(engine: contracts.ApplicationEngine) -> None: if engine.trigger != contracts.TriggerType.ON_PERSIST: raise SystemError() @@ -77,7 +77,7 @@ def native_on_persist(engine: contracts.ApplicationEngine) -> None: contract.on_persist(engine) -@register("System.Contract.NativePostPersist", 0, contracts.CallFlags.WRITE_STATES) +@register("System.Contract.NativePostPersist", 0, contracts.CallFlags.STATES) def native_post_persist(engine: contracts.ApplicationEngine) -> None: if engine.trigger != contracts.TriggerType.POST_PERSIST: raise SystemError() diff --git a/neo3/contracts/interop/storage.py b/neo3/contracts/interop/storage.py index c785e93c..f297a836 100644 --- a/neo3/contracts/interop/storage.py +++ b/neo3/contracts/interop/storage.py @@ -101,7 +101,7 @@ def _storage_put_internal(engine: contracts.ApplicationEngine, item.is_constant = is_constant -@register("System.Storage.Put", 0, contracts.CallFlags.WRITE_STATES) +@register("System.Storage.Put", 0, contracts.CallFlags.STATES) def storage_put(engine: contracts.ApplicationEngine, context: storage.StorageContext, key: bytes, @@ -109,7 +109,7 @@ def storage_put(engine: contracts.ApplicationEngine, _storage_put_internal(engine, context, key, value, storage.StorageFlags.NONE) -@register("System.Storage.PutEx", 0, contracts.CallFlags.WRITE_STATES) +@register("System.Storage.PutEx", 0, contracts.CallFlags.STATES) def storage_put_ex(engine: contracts.ApplicationEngine, context: storage.StorageContext, key: bytes, @@ -118,7 +118,7 @@ def storage_put_ex(engine: contracts.ApplicationEngine, _storage_put_internal(engine, context, key, value, flags) -@register("System.Storage.Delete", 0, contracts.CallFlags.WRITE_STATES) +@register("System.Storage.Delete", 0, contracts.CallFlags.STATES) def storage_delete(engine: contracts.ApplicationEngine, context: storage.StorageContext, key: bytes) -> None: if context.is_read_only: raise ValueError("Cannot delete from read-only storage context") diff --git a/neo3/contracts/native/designate.py b/neo3/contracts/native/designate.py index 80f2e25f..0ee8f727 100644 --- a/neo3/contracts/native/designate.py +++ b/neo3/contracts/native/designate.py @@ -38,7 +38,7 @@ def get_designated_by_role(self, else: return [] - @register("designateAsRole", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("designateAsRole", contracts.CallFlags.STATES, cpu_price=1 << 15) def designate_as_role(self, engine: contracts.ApplicationEngine, role: DesignateRole, diff --git a/neo3/contracts/native/fungible.py b/neo3/contracts/native/fungible.py index 0bc31435..b4d6e668 100644 --- a/neo3/contracts/native/fungible.py +++ b/neo3/contracts/native/fungible.py @@ -207,7 +207,7 @@ def _post_transfer(self, engine.call_from_native(self.hash, account_to, "onNEP17Payment", [from_, vm.IntegerStackItem(amount), data]) @register("transfer", - (contracts.CallFlags.WRITE_STATES | contracts.CallFlags.ALLOW_CALL | contracts.CallFlags.ALLOW_NOTIFY), + (contracts.CallFlags.STATES | contracts.CallFlags.ALLOW_CALL | contracts.CallFlags.ALLOW_NOTIFY), cpu_price=1 << 17, storage_price=50) def transfer(self, engine: contracts.ApplicationEngine, @@ -631,7 +631,7 @@ def unclaimed_gas(self, snapshot: storage.Snapshot, account: types.UInt160, end: state = storage_item.get(self._state) return self._calculate_bonus(snapshot, state.vote_to, state.balance, state.balance_height, end) - @register("registerCandidate", contracts.CallFlags.WRITE_STATES) + @register("registerCandidate", contracts.CallFlags.STATES) def register_candidate(self, engine: contracts.ApplicationEngine, public_key: cryptography.ECPoint) -> bool: @@ -663,7 +663,7 @@ def register_candidate(self, self._candidates_dirty = True return True - @register("unregisterCandidate", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 16) + @register("unregisterCandidate", contracts.CallFlags.STATES, cpu_price=1 << 16) def unregister_candidate(self, engine: contracts.ApplicationEngine, public_key: cryptography.ECPoint) -> bool: @@ -694,7 +694,7 @@ def unregister_candidate(self, self._candidates_dirty = True return True - @register("vote", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 16) + @register("vote", contracts.CallFlags.STATES, cpu_price=1 << 16) def vote(self, engine: contracts.ApplicationEngine, account: types.UInt160, @@ -819,7 +819,7 @@ def _compute_committee_members(self, snapshot: storage.Snapshot) -> Dict[cryptog results.update({candidate[0]: candidate[1]}) return results - @register("setGasPerBlock", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("setGasPerBlock", contracts.CallFlags.STATES, cpu_price=1 << 15) def _set_gas_per_block(self, engine: contracts.ApplicationEngine, gas_per_block: vm.BigInteger) -> None: if gas_per_block > 0 or gas_per_block > 10 * self._gas.factor: raise ValueError("new gas per block value exceeds limits") @@ -844,7 +844,7 @@ def get_gas_per_block(self, snapshot: storage.Snapshot) -> vm.BigInteger: else: raise ValueError - @register("setRegisterPrice", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("setRegisterPrice", contracts.CallFlags.STATES, cpu_price=1 << 15) def set_register_price(self, engine: contracts.ApplicationEngine, register_price: int) -> None: if register_price <= 0: raise ValueError("Register price cannot be negative or zero") diff --git a/neo3/contracts/native/management.py b/neo3/contracts/native/management.py index 12e72bb7..a1a64fcb 100644 --- a/neo3/contracts/native/management.py +++ b/neo3/contracts/native/management.py @@ -67,14 +67,14 @@ def on_persist(self, engine: contracts.ApplicationEngine) -> None: def get_contract(self, snapshot: storage.Snapshot, hash_: types.UInt160) -> Optional[contracts.ContractState]: return snapshot.contracts.try_get(hash_, read_only=True) - @register("deploy", contracts.CallFlags.WRITE_STATES | contracts.CallFlags.ALLOW_NOTIFY) + @register("deploy", contracts.CallFlags.STATES | contracts.CallFlags.ALLOW_NOTIFY) def contract_create(self, engine: contracts.ApplicationEngine, nef_file: bytes, manifest: bytes) -> contracts.ContractState: return self.contract_create_with_data(engine, nef_file, manifest, vm.NullStackItem()) - @register("deploy", contracts.CallFlags.WRITE_STATES | contracts.CallFlags.ALLOW_NOTIFY) + @register("deploy", contracts.CallFlags.STATES | contracts.CallFlags.ALLOW_NOTIFY) def contract_create_with_data(self, engine: contracts.ApplicationEngine, nef_file: bytes, @@ -128,12 +128,19 @@ def contract_create_with_data(self, ) return contract - @register("update", contracts.CallFlags.WRITE_STATES | contracts.CallFlags.ALLOW_NOTIFY) + @register("update", contracts.CallFlags.STATES | contracts.CallFlags.ALLOW_NOTIFY) def contract_update(self, engine: contracts.ApplicationEngine, nef_file: bytes, - manifest: bytes, - data: vm.StackItem) -> None: + manifest: bytes) -> None: + self.contract_update_with_data(engine, nef_file, manifest, vm.NullStackItem()) + + @register("update", contracts.CallFlags.STATES | contracts.CallFlags.ALLOW_NOTIFY) + def contract_update_with_data(self, + engine: contracts.ApplicationEngine, + nef_file: bytes, + manifest: bytes, + data: vm.StackItem) -> None: nef_len = len(nef_file) manifest_len = len(manifest) @@ -178,7 +185,7 @@ def contract_update(self, ) ) - @register("destroy", contracts.CallFlags.WRITE_STATES | contracts.CallFlags.ALLOW_NOTIFY, cpu_price=1 << 15) + @register("destroy", contracts.CallFlags.STATES | contracts.CallFlags.ALLOW_NOTIFY, cpu_price=1 << 15) def contract_destroy(self, engine: contracts.ApplicationEngine) -> None: hash_ = engine.current_scripthash contract = engine.snapshot.contracts.try_get(hash_) @@ -202,7 +209,7 @@ def contract_destroy(self, engine: contracts.ApplicationEngine) -> None: def get_minimum_deployment_fee(self, snapshot: storage.Snapshot) -> int: return int.from_bytes(snapshot.storages[self.key_min_deploy_fee].value, 'little') - @register("setMinimumDeploymentFee", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("setMinimumDeploymentFee", contracts.CallFlags.STATES, cpu_price=1 << 15) def _set_minimum_deployment_fee(self, engine: contracts.ApplicationEngine, value: int) -> None: if value < 0: raise ValueError("Can't set deployment fee to a negative value") diff --git a/neo3/contracts/native/nameservice.py b/neo3/contracts/native/nameservice.py index f90c0479..d69903f8 100644 --- a/neo3/contracts/native/nameservice.py +++ b/neo3/contracts/native/nameservice.py @@ -95,7 +95,7 @@ def on_persist(self, engine: contracts.ApplicationEngine) -> None: def on_transferred(self, engine: contracts.ApplicationEngine, from_account: types.UInt160, token: NFTState) -> None: token.owner = types.UInt160.zero() - @register("addRoot", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("addRoot", contracts.CallFlags.STATES, cpu_price=1 << 15) def add_root(self, engine: contracts.ApplicationEngine, root: str) -> None: if not self.REGEX_ROOT.match(root): raise ValueError("Regex failure - root not found") @@ -107,7 +107,7 @@ def add_root(self, engine: contracts.ApplicationEngine, root: str) -> None: raise ValueError("The name already exists") roots.append(root) - @register("setPrice", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("setPrice", contracts.CallFlags.STATES, cpu_price=1 << 15) def set_price(self, engine: contracts.ApplicationEngine, price: int) -> None: if price <= 0 or price > 10000_00000000: raise ValueError(f"New price '{price}' exceeds limits") @@ -136,7 +136,7 @@ def is_available(self, snapshot: storage.Snapshot, name: str) -> bool: raise ValueError(f"'{names[1]}' is not a registered root") return True - @register("register", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("register", contracts.CallFlags.STATES, cpu_price=1 << 15) def do_register(self, engine: contracts.ApplicationEngine, name: str, owner: types.UInt160) -> bool: if not self.is_available(engine.snapshot, name): raise ValueError(f"Registration failure - '{name}' is not available") @@ -153,7 +153,7 @@ def do_register(self, engine: contracts.ApplicationEngine, name: str, owner: typ ) return True - @register("renew", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("renew", contracts.CallFlags.STATES, cpu_price=1 << 15) def renew(self, engine: contracts.ApplicationEngine, name: str) -> int: if not self.REGEX_NAME.match(name): raise ValueError("Regex failure - name is not valid") @@ -165,7 +165,7 @@ def renew(self, engine: contracts.ApplicationEngine, name: str) -> int: state.expiration += self.ONE_YEAR return state.expiration - @register("setAdmin", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15, storage_price=20) + @register("setAdmin", contracts.CallFlags.STATES, cpu_price=1 << 15, storage_price=20) def set_admin(self, engine: contracts.ApplicationEngine, name: str, admin: types.UInt160) -> None: if not self.REGEX_NAME.match(name): raise ValueError("Regex failure - name is not valid") @@ -184,7 +184,7 @@ def set_admin(self, engine: contracts.ApplicationEngine, name: str, admin: types state.admin = admin - @register("setRecord", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15, storage_price=200) + @register("setRecord", contracts.CallFlags.STATES, cpu_price=1 << 15, storage_price=200) def set_record(self, engine: contracts.ApplicationEngine, name: str, record_type: RecordType, data: str) -> None: if not self.REGEX_NAME.match(name): raise ValueError("Regex failure - name is not valid") @@ -231,7 +231,7 @@ def get_records(self, snapshot: storage.Snapshot, name: str) -> Iterator[Tuple[R record_type = RecordType(int.from_bytes(key.key[-1], 'little')) yield record_type, value.value.decode() - @register("deleteRecord", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("deleteRecord", contracts.CallFlags.STATES, cpu_price=1 << 15) def delete_record(self, engine: contracts.ApplicationEngine, name: str, record_type: RecordType) -> None: if not self.REGEX_NAME.match(name): raise ValueError("Regex failure - name is not valid") diff --git a/neo3/contracts/native/nonfungible.py b/neo3/contracts/native/nonfungible.py index ff74143c..d0dc6c21 100644 --- a/neo3/contracts/native/nonfungible.py +++ b/neo3/contracts/native/nonfungible.py @@ -161,7 +161,7 @@ def balance_of(self, snapshot: storage.Snapshot, owner: types.UInt160) -> vm.Big return NFTAccountState.deserialize_from_bytes(storage_item.value).balance @register("transfer", - contracts.CallFlags.WRITE_STATES | contracts.CallFlags.ALLOW_NOTIFY, + contracts.CallFlags.STATES | contracts.CallFlags.ALLOW_CALL | contracts.CallFlags.ALLOW_NOTIFY, cpu_price=1 << 17, storage_price=50) def transfer(self, engine: contracts.ApplicationEngine, account_to: types.UInt160, token_id: bytes) -> bool: diff --git a/neo3/contracts/native/oracle.py b/neo3/contracts/native/oracle.py index 57baf21f..da4ce402 100644 --- a/neo3/contracts/native/oracle.py +++ b/neo3/contracts/native/oracle.py @@ -87,7 +87,7 @@ def _initialize(self, engine: contracts.ApplicationEngine) -> None: engine.snapshot.storages.put(self.key_request_id, storage.StorageItem(vm.BigInteger.zero().to_array())) engine.snapshot.storages.put(self.key_price, storage.StorageItem(vm.BigInteger(50000000).to_array())) - @register("setPrice", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("setPrice", contracts.CallFlags.STATES, cpu_price=1 << 15) def set_price(self, engine: contracts.ApplicationEngine, price: int) -> None: if price <= 0: raise ValueError("Oracle->setPrice value cannot be negative or zero") @@ -101,7 +101,7 @@ def get_price(self, snapshot: storage.Snapshot) -> int: return int(vm.BigInteger(snapshot.storages.get(self.key_price).value)) @register("finish", - (contracts.CallFlags.WRITE_STATES | contracts.CallFlags.ALLOW_CALL | contracts.CallFlags.ALLOW_NOTIFY)) + (contracts.CallFlags.STATES | contracts.CallFlags.ALLOW_CALL | contracts.CallFlags.ALLOW_NOTIFY)) def finish(self, engine: contracts.ApplicationEngine) -> None: tx = engine.script_container tx = cast(payloads.Transaction, tx) @@ -153,7 +153,7 @@ def _get_original_txid(self, engine: contracts.ApplicationEngine) -> types.UInt2 raise ValueError # C# will throw null pointer access exception return request.original_tx_id - @register("request", contracts.CallFlags.WRITE_STATES | contracts.CallFlags.ALLOW_NOTIFY) + @register("request", contracts.CallFlags.STATES | contracts.CallFlags.ALLOW_NOTIFY) def _request(self, engine: contracts.ApplicationEngine, url: str, diff --git a/neo3/contracts/native/policy.py b/neo3/contracts/native/policy.py index 97872135..1ec03cbd 100644 --- a/neo3/contracts/native/policy.py +++ b/neo3/contracts/native/policy.py @@ -59,7 +59,7 @@ def is_blocked(self, snapshot: storage.Snapshot, account: types.UInt160) -> bool else: return True - @register("setFeePerByte", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("setFeePerByte", contracts.CallFlags.STATES, cpu_price=1 << 15) def _set_fee_per_byte(self, engine: contracts.ApplicationEngine, value: int) -> None: """ Should only be called through syscalls @@ -73,7 +73,7 @@ def _set_fee_per_byte(self, engine: contracts.ApplicationEngine, value: int) -> storage_item = engine.snapshot.storages.get(self.key_fee_per_byte, read_only=False) storage_item.value = self._int_to_bytes(value) - @register("blockAccount", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("blockAccount", contracts.CallFlags.STATES, cpu_price=1 << 15) def _block_account(self, engine: contracts.ApplicationEngine, account: types.UInt160) -> bool: """ Should only be called through syscalls @@ -90,7 +90,7 @@ def _block_account(self, engine: contracts.ApplicationEngine, account: types.UIn return True - @register("unblockAccount", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("unblockAccount", contracts.CallFlags.STATES, cpu_price=1 << 15) def _unblock_account(self, engine: contracts.ApplicationEngine, account: types.UInt160) -> bool: """ Should only be called through syscalls @@ -118,7 +118,7 @@ def get_storage_price(self, snapshot: storage.Snapshot) -> int: storage_item = snapshot.storages.get(self.key_storage_price, read_only=True) return int(vm.BigInteger(storage_item.value)) - @register("setExecFeeFactor", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("setExecFeeFactor", contracts.CallFlags.STATES, cpu_price=1 << 15) def _set_exec_fee_factor(self, engine: contracts.ApplicationEngine, value: int) -> None: if value == 0 or value > self.MAX_EXEC_FEE_FACTOR: raise ValueError("New exec fee value out of range") @@ -127,7 +127,7 @@ def _set_exec_fee_factor(self, engine: contracts.ApplicationEngine, value: int) storage_item = engine.snapshot.storages.get(self.key_exec_fee_factor, read_only=False) storage_item.value = vm.BigInteger(value).to_array() - @register("setStoragePrice", contracts.CallFlags.WRITE_STATES, cpu_price=1 << 15) + @register("setStoragePrice", contracts.CallFlags.STATES, cpu_price=1 << 15) def _set_storage_price(self, engine: contracts.ApplicationEngine, value: int) -> None: if value == 0 or value > self.MAX_STORAGE_PRICE: raise ValueError("New storage price value out of range")