From 351a2635b61f65e8763981761831136828ffba97 Mon Sep 17 00:00:00 2001 From: Tim Zakian <2895723+tzakian@users.noreply.github.com> Date: Fri, 22 Sep 2023 14:56:19 -0700 Subject: [PATCH] [0/n][transfer-to-object] Transfer to Object Implementation (#12611) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description This PR implements the core transfer-to-object functionality. In particular it implements the ability to "receive" an object that was sent to the address (object ID) of another object using one of the `transfer` or `transfer_public` functions in the `transfer` module. More detail is given on the programming model in the attached issue so I will not go into that. SDK support for receiving objects has been added in the two PRs stacked on this one: * #12987 Adds the `Receiving` type to the json-rpc types, and adds support receiving objects in the Typescript SDK. * #12988 Adds support for receiving objects in the Rust SDK * #13420 Adds pruning of the `per_epoch_object_marker` table at epoch boundaries ## Test Plan I've written a number of tests for this that I believe cover things: * Execution-correctness tests for this in the transactional tests * Tests for effect computation in the new sui-core `transfer_to_object.rs` tests (e.g., receive-then-unwrap, receive-unwrap-wrap, etc). * Tests for lock-freeness of receiving arguments (i.e., that the object identified by the `Receiving` argument is not locked at signing) in the sui-core `transfer_to_object.rs` tests * Tests that dependencies are correctly registered, and notified in the transaction manager for `Receiving` arguments to transactions (see new tests in the `transaction_manager_tests.rs` file). A more detailed listing of the tests: * PTBs - Receive object and return to PTB - Do not do anything with the returned (non-drop) value [`receive_return_object_dont_touch.move`] - Call transfer object on it [`receive_return_object_then_transfer.move`] - Basic "can receive and then do something in the function" [`basic_receive.move`] - Duplicate "Receive" arguments to the PTB [`duplicate_receive_argument.move`] - Pass but don't use `Receiving` argument, then later use it in PTB. - By immut ref [`pass_receiver_immut_then_reuse.move`] - By mut ref [`pass_receiver_mut_then_reuse.move`] - By value and returning it [`pass_through_then_receive.move`] - Various combinations of receivership being passed [`receive_by_ref.move`] (checking borrow/borrow_mut, and restore rules for PTB execution) - Receive object of different type [`receive_invalid_type.move`] - Receive object with non-address owner ownership [`receive_object_owner.move`] - Reuse of input receiving argument [`take_receiver_then_try_to_reuse.move`] * Type malleability [`receive_invalid_param_ty.move`] - Pass receiver into a non-receiver type - primitive type - struct type with same layout - struct type with different layout - Pass non-receiver into a receiver type - primitive type - struct type with same layout - struct type with different layout * Resource conservation/Effects calculation (both transactional tests and sui-core tests for explicit effects checks) - Do various things with object after receiving it: - Immediately place it as a dynamic field [`receive_dof_and_mutate.move`] - Immediately add a dynamic field to it [`receive_add_dof_and_mutate.move`] - Immediately add a dynamic field to it, add as a dynamic field to parent object, then mutate both [`receive_add_dof_and_mutate.move`] - Immediately transfer it [`receive_and_send_back.move`] - Immediately delete it [`receive_and_deleted.move`] - Immediately wrap it [`receive_and_wrap.move`] - Immediately abort [`receive_and_abort.move`] - Don't use it [`receive_by_value_flow_through.move`] - Receive multiple times in a row making sure effects stay in-sync as expected [`receive_multiple_times_in_row.move`] - Shared objects - Make sure we can receive if object is transferred to an object which is already shared [`shared_parent/basic_receive.move`] - Make sure we can receive if object is transferred to an object which is then shared [`shared_parent/transfer_then_share.move`] - Non-usage of receiving object argument off a shared parent object [`shared_parent/drop_receiving.move`] - Receive object off of shared parent, add as dynamic field of shared parent and then mutate through the parent [`shared_parent/receive_dof_and_mutate.move`] - Send and receive the same object to the same shared parent multiple times [`shared_parent/receive_multiple_times_in_row.move`] - MVCC -- Test that we calculate contained UIDs correctly when we receive an object. This is tested in [`mvcc/receive_object_dof.move`] and [`mvcc/receive_object_split_changes_dof.move`] - Sui core tests checking explicit parts of the calculated effects to make sure they match what we expect: - Immediately unwrap then transfer inner object [`transfer_to_object_tests.rs/test_tto_unwrap_transfer`] - Immediately unwrap then delete inner object as well [`transfer_to_object_tests.rs/test_tto_unwrap_delete`] - Immediately unwrap then add inner object as dynamic field [`transfer_to_object_tests.rs/test_tto_unwrap_add_as_dynamic_field`] - Immediately unwrap, then wrap again -- this is part of the above since adding a dynamic field wraps the object - Basic object receive [`transfer_to_object_tests/test_tto_transfer`] - Pass but don't ise Receiving argument [`transfer_to_object_tests/test_tto_unused_receiver`] - Pass by different references [`transfer_to_object_tests/test_tto_pass_receiving_by_refs`] - Receive and immediately delete [`transfer_to_object_tests/test_tto_delete`] - Receive, wrap, and then transfer wrapped object [`transfer_to_object_tests/test_tto_wrap`] * Sui Core for object locking and transaction dependendency calculation in effects - Test that receiving object arguments are not locked, and that different orders of execution for two certs that want to receive the same argument (but only one is valid) can both be run in either order, and both return the same execution effects in either order [`transfer_to_object_tests/test_tt_not_locked`] - Test that transaction dependencies are added correctly: - Basic test that we add transaction dependendency if we execute successfully and receive the object [`transfer_to_object_tests/test_tto_valid_dependencies`] - Similar case for if we delete the object immediately [`transfer_to_object_tests/test_tto_valid_dependencies_delete_on_receive`] - That we don't register the transaction dependendency if we don't receive the object [`transfer_to_object_tests/test_tto_dependencies_dont_receive`] - That we don't register the transaction dependendency if we don't receive the object and we abort [`transfer_to_object_tests/test_tto_dependencies_dont_receive_but_abort`] - That we register the dependendency if we received the object, even if we then went on to abort in the transaction [`transfer_to_object_tests/test_tto_dependencies_receive_and_abort`] - Dynamic object field spoofing: make sure we don't accidentally register a dynamic object field load of an object that we want to receive at a different version as a receivership of that object (i.e., don't register the transaction dependendency) [`transfer_to_object_tests/receive_and_dof_interleave`] ## Additional tests - PTBs - `MakeMoveVec`: - create but don't use [receive_many_move_vec.move] - pass vec by value but don't receive [receive_many_move_vec.move] - pass vec by ref then use value to receive in later command [receive_many_move_vec.move] - Pass vec by mut ref and pop/receive some, then receive rest in other call [receive_many_move_vec.move] - Pass vec by mut ref, only receive some [receive_many_move_vec.move] - Pass vec by value, only receive some [receive_many_move_vec.move] - Pass vec by value, receive all [receive_many_move_vec.move] - Pack receiving tickets into a struct (some/all) then receive transitively [receive_duo_struct.move] - Type mismatches: - Receiving and phony struct with same struct layout and right type args ([receive_invalid_param_ty.move]) - Receiving with mismatched type args [move_vec_receiving_types.move] - Receiving with multiple different type args [move_vec_receiving_types.move] - `TransferObjects` - Try to transfer receiving ticket [receive_ticket_coin_operations.move] - `SplitCoins` - Try to split a receiving ticket [receive_ticket_coin_operations.move] - `MergeCoins` - Try to merge a receiving ticket [receive_ticket_coin_operations.move] - MVCC [`receive_object_access_through_parent[dof/df].move`] - Transaction input checks (in sui-core tests) - Delete between cert and execution [tests in `test_tto_not_locked`in the sui-core tests - Cert denial if sending a transaction where `input_objects \intersect receiving_object != {}` [`test_tto_intersection_input_and_receiving_objects`] - Type-fixing for receiving arguments [pt_receive_type_fixing.move] --- If your changes are not user-facing and not a breaking change, you can skip the following section. Otherwise, please indicate what changed, and then add to the Release Notes section as highlighted during the release process. ### Type of Change (Check all that apply) - [X] protocol change - [X] user-visible impact - [ ] breaking change for a client SDKs - [X] breaking change for FNs (FN binary must upgrade) - [X] breaking change for validators or node operators (must upgrade binaries) - [ ] breaking change for on-chain data layout - [ ] necessitate either a data wipe or data migration ### Release notes Added the ability to receive objects off of another object. This is currently only turned on in devnet. More information on transfer-to-object, receiving objects off of other objects, and current SDK support can be found in the GitHub issue which can be found here: https://github.com/MystenLabs/sui/issues/12658 --- move-compiler/src/sui_mode/mod.rs | 1 + move-compiler/src/sui_mode/typing.rs | 22 +++++++++++++++++-- .../generic_obj_mut_ref_vector.exp | 2 +- .../entry_points/generic_obj_ref_vector.exp | 2 +- .../entry_points/generic_with_key_invalid.exp | 4 ++-- .../entry_points/immut_receiving_ref.move | 22 +++++++++++++++++++ .../entry_points/mut_receiving_ref.move | 22 +++++++++++++++++++ .../nested_key_generic_vector_param.exp | 2 +- .../sui_mode/entry_points/non_key_struct.exp | 2 +- .../entry_points/non_key_struct_generic.exp | 4 ++-- .../entry_points/non_key_struct_vector.exp | 2 +- .../entry_points/obj_mut_ref_vector.exp | 2 +- .../sui_mode/entry_points/obj_ref_vector.exp | 2 +- .../receiving_non_object_type.exp | 12 ++++++++++ .../receiving_non_object_type.move | 13 +++++++++++ .../receiving_with_object_type.move | 22 +++++++++++++++++++ move-symbol-pool/src/lib.rs | 1 + 17 files changed, 124 insertions(+), 13 deletions(-) create mode 100644 move-compiler/tests/sui_mode/entry_points/immut_receiving_ref.move create mode 100644 move-compiler/tests/sui_mode/entry_points/mut_receiving_ref.move create mode 100644 move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.exp create mode 100644 move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.move create mode 100644 move-compiler/tests/sui_mode/entry_points/receiving_with_object_type.move diff --git a/move-compiler/src/sui_mode/mod.rs b/move-compiler/src/sui_mode/mod.rs index e0ffbc469a..8a7b257697 100644 --- a/move-compiler/src/sui_mode/mod.rs +++ b/move-compiler/src/sui_mode/mod.rs @@ -49,6 +49,7 @@ pub const TRANSFER_MODULE_NAME: Symbol = symbol!("transfer"); pub const TRANSFER_FUNCTION_NAME: Symbol = symbol!("transfer"); pub const FREEZE_FUNCTION_NAME: Symbol = symbol!("freeze_object"); pub const SHARE_FUNCTION_NAME: Symbol = symbol!("share_object"); +pub const RECEIVING_TYPE_NAME: Symbol = symbol!("Receiving"); pub const PRIVATE_TRANSFER_FUNCTIONS: &[Symbol] = &[ TRANSFER_FUNCTION_NAME, diff --git a/move-compiler/src/sui_mode/typing.rs b/move-compiler/src/sui_mode/typing.rs index 5a056a0acb..746884fc7b 100644 --- a/move-compiler/src/sui_mode/typing.rs +++ b/move-compiler/src/sui_mode/typing.rs @@ -641,7 +641,9 @@ fn entry_param_ty( // which should give a contextual error about `MyObject` having `key`, but the instantiation // `MyObject` not having `key` due to `InnerTypeWithoutStore` not having // `store` - let is_valid = is_entry_primitive_ty(param_ty) || is_entry_object_ty(param_ty); + let is_valid = is_entry_primitive_ty(param_ty) + || is_entry_object_ty(param_ty) + || is_entry_receiving_ty(param_ty); if is_mut_clock || !is_valid { let pmsg = format!( "Invalid 'entry' parameter type for parameter '{}'", @@ -656,7 +658,7 @@ fn entry_param_ty( ) } else { "'entry' parameters must be primitives (by-value), vectors of primitives, objects \ - (by-reference or by-value), or vectors of objects" + (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value)" .to_owned() }; let emsg = format!("'{name}' was declared 'entry' here"); @@ -682,6 +684,22 @@ fn is_mut_clock(param_ty: &Type) -> bool { } } +fn is_entry_receiving_ty(param_ty: &Type) -> bool { + match ¶m_ty.value { + Type_::Ref(_, t) => is_entry_receiving_ty(t), + Type_::Apply(_, sp!(_, n), targs) + if n.is(SUI_ADDR_NAME, TRANSFER_MODULE_NAME, RECEIVING_TYPE_NAME) => + { + debug_assert!(targs.len() == 1); + // Don't care about the type parameter, just that it's a receiving type -- since it has + // a `key` requirement on the type parameter it must be an object or type checking will + // fail. + true + } + _ => false, + } +} + fn is_entry_primitive_ty(param_ty: &Type) -> bool { use BuiltinTypeName_ as B; use TypeName_ as N; diff --git a/move-compiler/tests/sui_mode/entry_points/generic_obj_mut_ref_vector.exp b/move-compiler/tests/sui_mode/entry_points/generic_obj_mut_ref_vector.exp index 2905c590e4..606e3b0305 100644 --- a/move-compiler/tests/sui_mode/entry_points/generic_obj_mut_ref_vector.exp +++ b/move-compiler/tests/sui_mode/entry_points/generic_obj_mut_ref_vector.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/generic_obj_mut_ref_vector.move:5:32 │ 5 │ public entry fun no(_: &mut vector) { - │ ----- ^ -------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ -------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/generic_obj_ref_vector.exp b/move-compiler/tests/sui_mode/entry_points/generic_obj_ref_vector.exp index 38fee9c595..323d92010f 100644 --- a/move-compiler/tests/sui_mode/entry_points/generic_obj_ref_vector.exp +++ b/move-compiler/tests/sui_mode/entry_points/generic_obj_ref_vector.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/generic_obj_ref_vector.move:4:32 │ 4 │ public entry fun no(_: &vector) { - │ ----- ^ ---------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ---------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/generic_with_key_invalid.exp b/move-compiler/tests/sui_mode/entry_points/generic_with_key_invalid.exp index 91443f5c8c..5e9ceb81a4 100644 --- a/move-compiler/tests/sui_mode/entry_points/generic_with_key_invalid.exp +++ b/move-compiler/tests/sui_mode/entry_points/generic_with_key_invalid.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/generic_with_key_invalid.move:6:31 │ 6 │ public entry fun t(_: option::Option) { - │ ----- ^ ----------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ----------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 't' was declared 'entry' here @@ -11,7 +11,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/generic_with_key_invalid.move:10:32 │ 10 │ public entry fun t2(_: vector>) { - │ ----- ^ ------------------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ------------------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 't2' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/immut_receiving_ref.move b/move-compiler/tests/sui_mode/entry_points/immut_receiving_ref.move new file mode 100644 index 0000000000..3af390d56a --- /dev/null +++ b/move-compiler/tests/sui_mode/entry_points/immut_receiving_ref.move @@ -0,0 +1,22 @@ +// valid, Receiving type by immut ref with object type param + +module a::m { + use sui::object; + use sui::transfer::Receiving; + + struct S has key { id: object::UID } + + public entry fun yes(_: &Receiving) { } +} + +module sui::object { + struct UID has store { + id: address, + } +} + +module sui::transfer { + struct Receiving has drop { + id: address + } +} diff --git a/move-compiler/tests/sui_mode/entry_points/mut_receiving_ref.move b/move-compiler/tests/sui_mode/entry_points/mut_receiving_ref.move new file mode 100644 index 0000000000..fbaead9a07 --- /dev/null +++ b/move-compiler/tests/sui_mode/entry_points/mut_receiving_ref.move @@ -0,0 +1,22 @@ +// valid, Receiving type by mut ref with object type param + +module a::m { + use sui::object; + use sui::transfer::Receiving; + + struct S has key { id: object::UID } + + public entry fun yes(_: &mut Receiving) { } +} + +module sui::object { + struct UID has store { + id: address, + } +} + +module sui::transfer { + struct Receiving has drop { + id: address + } +} diff --git a/move-compiler/tests/sui_mode/entry_points/nested_key_generic_vector_param.exp b/move-compiler/tests/sui_mode/entry_points/nested_key_generic_vector_param.exp index 53cc2246ed..5600e180cd 100644 --- a/move-compiler/tests/sui_mode/entry_points/nested_key_generic_vector_param.exp +++ b/move-compiler/tests/sui_mode/entry_points/nested_key_generic_vector_param.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/nested_key_generic_vector_param.move:3:34 │ 3 │ public entry fun foo(_: vector>) { - │ ----- ^ ----------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ----------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'foo' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/non_key_struct.exp b/move-compiler/tests/sui_mode/entry_points/non_key_struct.exp index e5a5dc3124..9c37637512 100644 --- a/move-compiler/tests/sui_mode/entry_points/non_key_struct.exp +++ b/move-compiler/tests/sui_mode/entry_points/non_key_struct.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/non_key_struct.move:6:25 │ 6 │ public entry fun no(_: S) { - │ ----- ^ - 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ - 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/non_key_struct_generic.exp b/move-compiler/tests/sui_mode/entry_points/non_key_struct_generic.exp index 7199dc2e4a..8b4c4a45d2 100644 --- a/move-compiler/tests/sui_mode/entry_points/non_key_struct_generic.exp +++ b/move-compiler/tests/sui_mode/entry_points/non_key_struct_generic.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/non_key_struct_generic.move:9:25 │ 9 │ public entry fun t1(_: Obj) { - │ ----- ^ ------------ 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ------------ 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 't1' was declared 'entry' here @@ -11,7 +11,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/non_key_struct_generic.move:14:28 │ 14 │ public entry fun t2(_: Obj) { - │ ----- ^ ------ 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ------ 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 't2' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/non_key_struct_vector.exp b/move-compiler/tests/sui_mode/entry_points/non_key_struct_vector.exp index 824114c7ed..f3d21d93e4 100644 --- a/move-compiler/tests/sui_mode/entry_points/non_key_struct_vector.exp +++ b/move-compiler/tests/sui_mode/entry_points/non_key_struct_vector.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/non_key_struct_vector.move:6:25 │ 6 │ public entry fun no(_: vector) { - │ ----- ^ --------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ --------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/obj_mut_ref_vector.exp b/move-compiler/tests/sui_mode/entry_points/obj_mut_ref_vector.exp index 135d377806..8a7d091e35 100644 --- a/move-compiler/tests/sui_mode/entry_points/obj_mut_ref_vector.exp +++ b/move-compiler/tests/sui_mode/entry_points/obj_mut_ref_vector.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/obj_mut_ref_vector.move:8:25 │ 8 │ public entry fun no(_: &mut vector) { - │ ----- ^ -------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ -------------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/obj_ref_vector.exp b/move-compiler/tests/sui_mode/entry_points/obj_ref_vector.exp index 8f6e4cff22..8f772bd613 100644 --- a/move-compiler/tests/sui_mode/entry_points/obj_ref_vector.exp +++ b/move-compiler/tests/sui_mode/entry_points/obj_ref_vector.exp @@ -2,7 +2,7 @@ error[Sui E02002]: invalid 'entry' function signature ┌─ tests/sui_mode/entry_points/obj_ref_vector.move:8:25 │ 8 │ public entry fun no(_: &vector) { - │ ----- ^ ---------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), or vectors of objects + │ ----- ^ ---------- 'entry' parameters must be primitives (by-value), vectors of primitives, objects (by-reference or by-value), vectors of objects, or 'Receiving' arguments (by-reference or by-value) │ │ │ │ │ Invalid 'entry' parameter type for parameter '_' │ 'no' was declared 'entry' here diff --git a/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.exp b/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.exp new file mode 100644 index 0000000000..3422c96ab4 --- /dev/null +++ b/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.exp @@ -0,0 +1,12 @@ +error[E05001]: ability constraint not satisfied + ┌─ tests/sui_mode/entry_points/receiving_non_object_type.move:6:28 + │ + 6 │ public entry fun no(_: Receiving) { abort 0 } + │ ^^^^^^^^^^^^^^ + │ │ │ + │ │ The type 'u64' does not have the ability 'key' + │ 'key' constraint not satisifed + · +10 │ struct Receiving has drop { + │ --- 'key' constraint declared here + diff --git a/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.move b/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.move new file mode 100644 index 0000000000..56aad03267 --- /dev/null +++ b/move-compiler/tests/sui_mode/entry_points/receiving_non_object_type.move @@ -0,0 +1,13 @@ +// invalid, Receiving type with non-object type param + +module a::m { + use sui::transfer::Receiving; + + public entry fun no(_: Receiving) { abort 0 } +} + +module sui::transfer { + struct Receiving has drop { + id: address + } +} diff --git a/move-compiler/tests/sui_mode/entry_points/receiving_with_object_type.move b/move-compiler/tests/sui_mode/entry_points/receiving_with_object_type.move new file mode 100644 index 0000000000..9979bdc607 --- /dev/null +++ b/move-compiler/tests/sui_mode/entry_points/receiving_with_object_type.move @@ -0,0 +1,22 @@ +// valid, Receiving type with object type param + +module a::m { + use sui::object; + use sui::transfer::Receiving; + + struct S has key { id: object::UID } + + public entry fun yes(_: Receiving) { } +} + +module sui::object { + struct UID has store { + id: address, + } +} + +module sui::transfer { + struct Receiving has drop { + id: address + } +} diff --git a/move-symbol-pool/src/lib.rs b/move-symbol-pool/src/lib.rs index ea7749f17c..688e1a8d9a 100644 --- a/move-symbol-pool/src/lib.rs +++ b/move-symbol-pool/src/lib.rs @@ -78,6 +78,7 @@ static_symbols!( "share_object", "event", "emit", + "Receiving", ); /// The global, unique cache of strings.