From 4d3b15d2313d6a98c82c89a69ba26ace37992b90 Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Sun, 21 Aug 2022 09:39:33 -0700 Subject: [PATCH] [move] sui framework cleanup - Moving `collection`, `bag`, `object_basics` to examples - Deleting redundant implementations of `transfer` on types with `store` - Fixing the numerous tests that expect object_basics to be part of the framework :/ --- .../tests/sui/coin_transfer.exp | 3 +- .../tests/sui/coin_transfer.move | 2 +- .../tests/sui/freeze.exp | 16 +- .../tests/sui/freeze.move | 74 +++++++- .../sui/move_call_incorrect_function.exp | 14 +- .../sui/move_call_incorrect_function.move | 17 +- .../tests/sui/object_basics.exp | 38 ++-- .../tests/sui/object_basics.move | 80 +++++++- .../tests/sui/unwrap.exp | 30 +-- .../tests/sui/unwrap.move | 76 +++++++- ...tests__empty_genesis_snapshot_matches.snap | 2 +- crates/sui-core/src/authority.rs | 7 +- .../execution_driver/tests.rs | 5 +- .../src/epoch/tests/reconfiguration_tests.rs | 4 +- .../unit_tests/authority_aggregator_tests.rs | 69 ++++--- .../src/unit_tests/authority_tests.rs | 174 +++++++++++------- crates/sui-core/src/unit_tests/batch_tests.rs | 8 +- .../src/unit_tests/batch_transaction_tests.rs | 25 +-- .../unit_tests/data/hero/sources/hero.move | 2 +- .../data/hero/sources/trusted_coin.move | 6 +- .../unit_tests/data/object_basics/Move.toml | 9 + .../object_basics/sources/object_basics.move | 65 +++++++ crates/sui-core/src/unit_tests/gas_tests.rs | 6 +- .../src/unit_tests/gateway_state_tests.rs | 28 +-- .../sources/trusted_coin.move | 2 +- .../snapshot_tests__good_snapshot.snap | 20 +- crates/sui-framework/sources/coin.move | 12 +- crates/sui-framework/sources/devnet_nft.move | 10 +- .../sources/governance/delegation.move | 6 +- crates/sui-framework/sources/sui.move | 6 +- .../src/unit_tests/rpc_server_tests.rs | 20 +- crates/sui-json/src/lib.rs | 4 + crates/sui-json/src/tests.rs | 16 +- crates/sui/src/unit_tests/cli_tests.rs | 40 +++- .../sources/trusted_coin.move | 4 +- .../data/move_call_args_linter/Move.toml | 9 + .../sources/object_basics.move | 65 +++++++ crates/test-utils/src/messages.rs | 20 +- .../ch2-using-objects.md | 2 +- doc/src/contribute/cli-client.md | 114 ++++++------ .../basics}/sources/object_basics.move | 2 +- .../fungible_tokens/sources/managed.move | 5 - .../examples/games/sources/sea_hero.move | 7 - .../games/sources/sea_hero_helper.move | 2 +- .../examples/nfts}/sources/bag.move | 2 +- .../examples/nfts}/sources/collection.move | 7 +- .../nfts/sources/discount_coupon.move | 6 +- .../examples/nfts/sources/geniteam.move | 4 +- .../examples/nfts/sources/marketplace.move | 4 +- .../examples/nfts/tests/auction_tests.move | 5 +- .../examples/nfts}/tests/bag_tests.move | 4 +- .../nfts}/tests/collection_tests.move | 13 +- .../nfts/tests/discount_coupon_tests.move | 5 +- .../nfts/tests/shared_auction_tests.move | 5 +- .../sources/color_object.move | 7 +- .../sources/trusted_swap.move | 4 - 56 files changed, 786 insertions(+), 406 deletions(-) create mode 100644 crates/sui-core/src/unit_tests/data/object_basics/Move.toml create mode 100644 crates/sui-core/src/unit_tests/data/object_basics/sources/object_basics.move create mode 100644 crates/sui/src/unit_tests/data/move_call_args_linter/Move.toml create mode 100644 crates/sui/src/unit_tests/data/move_call_args_linter/sources/object_basics.move rename {crates/sui-framework => sui_programmability/examples/basics}/sources/object_basics.move (98%) rename {crates/sui-framework => sui_programmability/examples/nfts}/sources/bag.move (99%) rename {crates/sui-framework => sui_programmability/examples/nfts}/sources/collection.move (95%) rename {crates/sui-framework => sui_programmability/examples/nfts}/tests/bag_tests.move (97%) rename {crates/sui-framework => sui_programmability/examples/nfts}/tests/collection_tests.move (93%) diff --git a/crates/sui-adapter-transactional-tests/tests/sui/coin_transfer.exp b/crates/sui-adapter-transactional-tests/tests/sui/coin_transfer.exp index 6f0f8bf723d6a..1105eda9ef06a 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/coin_transfer.exp +++ b/crates/sui-adapter-transactional-tests/tests/sui/coin_transfer.exp @@ -26,10 +26,11 @@ Child Count: None Contents: sui::coin::Coin {id: sui::object::UID {id: sui::object::ID {bytes: fake(106)}}, balance: sui::balance::Balance {value: 10u64}} task 5 'run'. lines 16-16: +created: object(108) written: object(100), object(107) task 6 'view-object'. lines 18-18: -Owner: Account Address ( C ) +Owner: Account Address ( A ) Version: 2 Child Count: None Contents: sui::coin::Coin {id: sui::object::UID {id: sui::object::ID {bytes: fake(100)}}, balance: sui::balance::Balance {value: 99990u64}} diff --git a/crates/sui-adapter-transactional-tests/tests/sui/coin_transfer.move b/crates/sui-adapter-transactional-tests/tests/sui/coin_transfer.move index 90d23c70b136f..40a275e09fb8b 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/coin_transfer.move +++ b/crates/sui-adapter-transactional-tests/tests/sui/coin_transfer.move @@ -13,6 +13,6 @@ //# view-object 106 -//# run sui::coin::transfer --type-args sui::sui::SUI --args object(100) @C --sender B +//# run sui::coin::split_and_transfer --type-args sui::sui::SUI --args object(100) 0 @C --sender B //# view-object 100 diff --git a/crates/sui-adapter-transactional-tests/tests/sui/freeze.exp b/crates/sui-adapter-transactional-tests/tests/sui/freeze.exp index 27368cb7eff5a..75f5b7c7b615c 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/freeze.exp +++ b/crates/sui-adapter-transactional-tests/tests/sui/freeze.exp @@ -1,19 +1,23 @@ -processed 5 tasks +processed 6 tasks init: A: object(100) -task 1 'run'. lines 8-8: +task 1 'publish'. lines 8-70: created: object(104) written: object(103) -task 2 'run'. lines 10-10: -written: object(104), object(105) +task 2 'run'. lines 72-72: +created: object(106) +written: object(105) -task 3 'run'. lines 12-12: +task 3 'run'. lines 74-74: +written: object(106), object(107) + +task 4 'run'. lines 76-76: Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Immutable and shared objects cannot be passed by-value. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: InvalidObjectByValue }), source: Some("Immutable and shared objects cannot be passed by-value, violation found in argument 0") } } -task 4 'run'. lines 14-14: +task 5 'run'. lines 78-78: Error: Transaction Effects Status: Entry Argument Type Error. Error for argument at index 0: Immutable objects cannot be passed by mutable reference, &mut. Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: EntryArgumentError(EntryArgumentError { argument_idx: 0, kind: InvalidObjectByMuteRef }), source: Some("Argument 0 is expected to be mutable, immutable object found") } } diff --git a/crates/sui-adapter-transactional-tests/tests/sui/freeze.move b/crates/sui-adapter-transactional-tests/tests/sui/freeze.move index 106b0c5543c4b..baf0fc26966d4 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/freeze.move +++ b/crates/sui-adapter-transactional-tests/tests/sui/freeze.move @@ -3,12 +3,76 @@ // test that freezing prevents transfers/mutations -//# init --accounts A +//# init --addresses test=0x0 --accounts A -//# run sui::object_basics::create --args 10 @A +//# publish -//# run sui::object_basics::freeze_object --args object(104) +module test::object_basics { + use sui::event; + use sui::object::{Self, UID}; + use sui::tx_context::{Self, TxContext}; + use sui::transfer; -//# run sui::object_basics::transfer --args object(104) @A + struct Object has key, store { + id: UID, + value: u64, + } -//# run sui::object_basics::set_value --args object(104) 1 + struct Wrapper has key { + id: UID, + o: Object + } + + struct NewValueEvent has copy, drop { + new_value: u64 + } + + public entry fun create(value: u64, recipient: address, ctx: &mut TxContext) { + transfer::transfer( + Object { id: object::new(ctx), value }, + recipient + ) + } + + public entry fun transfer(o: Object, recipient: address) { + transfer::transfer(o, recipient) + } + + public entry fun freeze_object(o: Object) { + transfer::freeze_object(o) + } + + public entry fun set_value(o: &mut Object, value: u64) { + o.value = value; + } + + // test that reading o2 and updating o1 works + public entry fun update(o1: &mut Object, o2: &Object) { + o1.value = o2.value; + // emit an event so the world can see the new value + event::emit(NewValueEvent { new_value: o2.value }) + } + + public entry fun delete(o: Object) { + let Object { id, value: _ } = o; + object::delete(id); + } + + public entry fun wrap(o: Object, ctx: &mut TxContext) { + transfer::transfer(Wrapper { id: object::new(ctx), o }, tx_context::sender(ctx)) + } + + public entry fun unwrap(w: Wrapper, ctx: &mut TxContext) { + let Wrapper { id, o } = w; + object::delete(id); + transfer::transfer(o, tx_context::sender(ctx)) + } +} + +//# run test::object_basics::create --args 10 @A + +//# run test::object_basics::freeze_object --args object(106) + +//# run test::object_basics::transfer --args object(106) @A + +//# run test::object_basics::set_value --args object(106) 1 diff --git a/crates/sui-adapter-transactional-tests/tests/sui/move_call_incorrect_function.exp b/crates/sui-adapter-transactional-tests/tests/sui/move_call_incorrect_function.exp index 930c1e3ab13c6..d0557ae68c3a9 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/move_call_incorrect_function.exp +++ b/crates/sui-adapter-transactional-tests/tests/sui/move_call_incorrect_function.exp @@ -1,9 +1,13 @@ -processed 2 tasks +processed 4 tasks -task 0 'run'. lines 7-9: +task 1 'publish'. lines 8-15: +created: object(103) +written: object(102) + +task 2 'run'. lines 16-18: Error: Transaction Effects Status: Move Bytecode Verification Error. Please run the Bytecode Verifier for more information. -Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: VMVerificationOrDeserializationError, source: Some(VMError { major_status: LINKER_ERROR, sub_status: None, message: Some("Cannot find ModuleId { address: _, name: Identifier(\"object_basics\") } in data cache"), exec_state: None, location: Undefined, indices: [], offsets: [] }) } } +Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: VMVerificationOrDeserializationError, source: Some(VMError { major_status: LINKER_ERROR, sub_status: None, message: Some("Cannot find ModuleId { address: _, name: Identifier(\"M\") } in data cache"), exec_state: None, location: Undefined, indices: [], offsets: [] }) } } -task 1 'run'. lines 10-10: +task 3 'run'. lines 19-19: Error: Transaction Effects Status: Function Not Found. -Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: FunctionNotFound, source: Some("Could not resolve function 'foo' in module sui::object_basics") } } +Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: FunctionNotFound, source: Some("Could not resolve function 'foo' in module Test::M") } } diff --git a/crates/sui-adapter-transactional-tests/tests/sui/move_call_incorrect_function.move b/crates/sui-adapter-transactional-tests/tests/sui/move_call_incorrect_function.move index cef5db9ea3959..3f0e0b60d73cc 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/move_call_incorrect_function.move +++ b/crates/sui-adapter-transactional-tests/tests/sui/move_call_incorrect_function.move @@ -3,8 +3,17 @@ // These functions do not exist -// Instead of calling on the Sui package, we are calling a non-existant package -//# run 0x242::object_basics::create +//# init --addresses Test=0x0 -// Calling a non-existant function. -//# run sui::object_basics::foo +//# publish + +module Test::M { + public entry fun create(_value: u64, _recipient: address) {} + +} + +// Instead of calling on the Test package, we are calling a non-existant package +//# run 0x242::M::create + +// Calling a non-existent function. +//# run Test::M::foo diff --git a/crates/sui-adapter-transactional-tests/tests/sui/object_basics.exp b/crates/sui-adapter-transactional-tests/tests/sui/object_basics.exp index 01dd4c2b7809e..7fa0a64a731c5 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/object_basics.exp +++ b/crates/sui-adapter-transactional-tests/tests/sui/object_basics.exp @@ -1,35 +1,39 @@ -processed 8 tasks +processed 9 tasks init: A: object(100), B: object(101) -task 1 'run'. lines 8-8: +task 1 'publish'. lines 8-70: created: object(105) written: object(104) -task 2 'view-object'. lines 10-10: +task 2 'run'. lines 72-72: +created: object(107) +written: object(106) + +task 3 'view-object'. lines 74-74: Owner: Account Address ( A ) Version: 1 Child Count: None -Contents: sui::object_basics::Object {id: sui::object::UID {id: sui::object::ID {bytes: fake(105)}}, value: 10u64} +Contents: test::object_basics::Object {id: sui::object::UID {id: sui::object::ID {bytes: fake(107)}}, value: 10u64} -task 3 'run'. lines 12-12: -written: object(105), object(106) +task 4 'run'. lines 76-76: +written: object(107), object(108) -task 4 'view-object'. lines 14-14: +task 5 'view-object'. lines 78-78: Owner: Account Address ( B ) Version: 2 Child Count: None -Contents: sui::object_basics::Object {id: sui::object::UID {id: sui::object::ID {bytes: fake(105)}}, value: 10u64} +Contents: test::object_basics::Object {id: sui::object::UID {id: sui::object::ID {bytes: fake(107)}}, value: 10u64} -task 5 'run'. lines 16-16: -created: object(108) -written: object(107) +task 6 'run'. lines 80-80: +created: object(110) +written: object(109) -task 6 'run'. lines 18-18: -events: MoveEvent { package_id: sui, transaction_module: Identifier("object_basics"), sender: B, type_: StructTag { address: sui, module: Identifier("object_basics"), name: Identifier("NewValueEvent"), type_params: [] }, contents: [20, 0, 0, 0, 0, 0, 0, 0] } -written: object(105), object(108), object(109) +task 7 'run'. lines 82-82: +events: MoveEvent { package_id: test, transaction_module: Identifier("object_basics"), sender: B, type_: StructTag { address: test, module: Identifier("object_basics"), name: Identifier("NewValueEvent"), type_params: [] }, contents: [20, 0, 0, 0, 0, 0, 0, 0] } +written: object(107), object(110), object(111) -task 7 'run'. lines 20-20: -written: object(110) -deleted: object(105) +task 8 'run'. lines 84-84: +written: object(112) +deleted: object(107) diff --git a/crates/sui-adapter-transactional-tests/tests/sui/object_basics.move b/crates/sui-adapter-transactional-tests/tests/sui/object_basics.move index 8e4366ef6342d..47fa3a8a3fd5c 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/object_basics.move +++ b/crates/sui-adapter-transactional-tests/tests/sui/object_basics.move @@ -3,18 +3,82 @@ // Exercise test functions that create, transfer, read, update, and delete objects -//# init --accounts A B +//# init --addresses test=0x0 --accounts A B -//# run sui::object_basics::create --sender A --args 10 @A +//# publish -//# view-object 105 +module test::object_basics { + use sui::event; + use sui::object::{Self, UID}; + use sui::tx_context::{Self, TxContext}; + use sui::transfer; -//# run sui::object_basics::transfer --sender A --args object(105) @B + struct Object has key, store { + id: UID, + value: u64, + } -//# view-object 105 + struct Wrapper has key { + id: UID, + o: Object + } -//# run sui::object_basics::create --sender B --args 20 @B + struct NewValueEvent has copy, drop { + new_value: u64 + } -//# run sui::object_basics::update --sender B --args object(105) object(108) --view-events + public entry fun create(value: u64, recipient: address, ctx: &mut TxContext) { + transfer::transfer( + Object { id: object::new(ctx), value }, + recipient + ) + } -//# run sui::object_basics::delete --sender B --args object(105) + public entry fun transfer(o: Object, recipient: address) { + transfer::transfer(o, recipient) + } + + public entry fun freeze_object(o: Object) { + transfer::freeze_object(o) + } + + public entry fun set_value(o: &mut Object, value: u64) { + o.value = value; + } + + // test that reading o2 and updating o1 works + public entry fun update(o1: &mut Object, o2: &Object) { + o1.value = o2.value; + // emit an event so the world can see the new value + event::emit(NewValueEvent { new_value: o2.value }) + } + + public entry fun delete(o: Object) { + let Object { id, value: _ } = o; + object::delete(id); + } + + public entry fun wrap(o: Object, ctx: &mut TxContext) { + transfer::transfer(Wrapper { id: object::new(ctx), o }, tx_context::sender(ctx)) + } + + public entry fun unwrap(w: Wrapper, ctx: &mut TxContext) { + let Wrapper { id, o } = w; + object::delete(id); + transfer::transfer(o, tx_context::sender(ctx)) + } +} + +//# run test::object_basics::create --sender A --args 10 @A + +//# view-object 107 + +//# run test::object_basics::transfer --sender A --args object(107) @B + +//# view-object 107 + +//# run test::object_basics::create --sender B --args 20 @B + +//# run test::object_basics::update --sender B --args object(107) object(110) --view-events + +//# run test::object_basics::delete --sender B --args object(107) diff --git a/crates/sui-adapter-transactional-tests/tests/sui/unwrap.exp b/crates/sui-adapter-transactional-tests/tests/sui/unwrap.exp index 6cb20a8e61037..57624c18ad08c 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/unwrap.exp +++ b/crates/sui-adapter-transactional-tests/tests/sui/unwrap.exp @@ -1,29 +1,33 @@ -processed 6 tasks +processed 7 tasks init: A: object(100) -task 1 'run'. lines 9-9: +task 1 'publish'. lines 9-71: created: object(104) written: object(103) -task 2 'view-object'. lines 11-11: +task 2 'run'. lines 73-73: +created: object(106) +written: object(105) + +task 3 'view-object'. lines 75-75: Owner: Account Address ( A ) Version: 1 Child Count: None -Contents: sui::object_basics::Object {id: sui::object::UID {id: sui::object::ID {bytes: fake(104)}}, value: 10u64} +Contents: test::object_basics::Object {id: sui::object::UID {id: sui::object::ID {bytes: fake(106)}}, value: 10u64} -task 3 'run'. lines 13-13: -created: object(106) -written: object(105) -deleted: object(104) - -task 4 'run'. lines 15-15: -written: object(104), object(107) +task 4 'run'. lines 77-77: +created: object(108) +written: object(107) deleted: object(106) -task 5 'view-object'. lines 17-17: +task 5 'run'. lines 79-79: +written: object(106), object(109) +deleted: object(108) + +task 6 'view-object'. lines 81-81: Owner: Account Address ( A ) Version: 2 Child Count: None -Contents: sui::object_basics::Object {id: sui::object::UID {id: sui::object::ID {bytes: fake(104)}}, value: 10u64} +Contents: test::object_basics::Object {id: sui::object::UID {id: sui::object::ID {bytes: fake(106)}}, value: 10u64} diff --git a/crates/sui-adapter-transactional-tests/tests/sui/unwrap.move b/crates/sui-adapter-transactional-tests/tests/sui/unwrap.move index ed845dd19b2e1..d410f07ef4ff0 100644 --- a/crates/sui-adapter-transactional-tests/tests/sui/unwrap.move +++ b/crates/sui-adapter-transactional-tests/tests/sui/unwrap.move @@ -4,14 +4,78 @@ // Exercise test functions that wrap and object and subsequently unwrap it // Ensure that the object's version is consistent -//# init --accounts A +//# init --addresses test=0x0 --accounts A -//# run sui::object_basics::create --args 10 @A +//# publish -//# view-object 104 +module test::object_basics { + use sui::event; + use sui::object::{Self, UID}; + use sui::tx_context::{Self, TxContext}; + use sui::transfer; -//# run sui::object_basics::wrap --args object(104) --sender A + struct Object has key, store { + id: UID, + value: u64, + } -//# run sui::object_basics::unwrap --args object(106) --sender A + struct Wrapper has key { + id: UID, + o: Object + } -//# view-object 104 + struct NewValueEvent has copy, drop { + new_value: u64 + } + + public entry fun create(value: u64, recipient: address, ctx: &mut TxContext) { + transfer::transfer( + Object { id: object::new(ctx), value }, + recipient + ) + } + + public entry fun transfer(o: Object, recipient: address) { + transfer::transfer(o, recipient) + } + + public entry fun freeze_object(o: Object) { + transfer::freeze_object(o) + } + + public entry fun set_value(o: &mut Object, value: u64) { + o.value = value; + } + + // test that reading o2 and updating o1 works + public entry fun update(o1: &mut Object, o2: &Object) { + o1.value = o2.value; + // emit an event so the world can see the new value + event::emit(NewValueEvent { new_value: o2.value }) + } + + public entry fun delete(o: Object) { + let Object { id, value: _ } = o; + object::delete(id); + } + + public entry fun wrap(o: Object, ctx: &mut TxContext) { + transfer::transfer(Wrapper { id: object::new(ctx), o }, tx_context::sender(ctx)) + } + + public entry fun unwrap(w: Wrapper, ctx: &mut TxContext) { + let Wrapper { id, o } = w; + object::delete(id); + transfer::transfer(o, tx_context::sender(ctx)) + } +} + +//# run test::object_basics::create --args 10 @A + +//# view-object 106 + +//# run test::object_basics::wrap --args object(106) --sender A + +//# run test::object_basics::unwrap --args object(108) --sender A + +//# view-object 106 diff --git a/crates/sui-config/tests/snapshots/snapshot_tests__empty_genesis_snapshot_matches.snap b/crates/sui-config/tests/snapshots/snapshot_tests__empty_genesis_snapshot_matches.snap index fc5617ef8ee95..3c03b485863f1 100644 --- a/crates/sui-config/tests/snapshots/snapshot_tests__empty_genesis_snapshot_matches.snap +++ b/crates/sui-config/tests/snapshots/snapshot_tests__empty_genesis_snapshot_matches.snap @@ -2,5 +2,5 @@ source: crates/sui-config/tests/snapshot_tests.rs expression: genesis --- -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ZGF0b3IFYXNjaWkGb3B0aW9uB2JhbGFuY2UPZXBvY2hfdGltZV9sb2NrBXN0YWtlA3N1aQp0eF9jb250ZXh0CVZhbGlkYXRvchFWYWxpZGF0b3JNZXRhZGF0YRphZGp1c3Rfc3Rha2VfYW5kX2dhc19wcmljZQ9kZWxlZ2F0ZV9hbW91bnQPZGVsZWdhdG9yX2NvdW50B2Rlc3Ryb3kJZ2FzX3ByaWNlDGlzX2R1cGxpY2F0ZQhtZXRhZGF0YQdCYWxhbmNlA1NVSQZPcHRpb24NRXBvY2hUaW1lTG9jawlUeENvbnRleHQDbmV3FHBlbmRpbmdfc3Rha2VfYW1vdW50EHBlbmRpbmdfd2l0aGRyYXcWcmVxdWVzdF9hZGRfZGVsZWdhdGlvbhFyZXF1ZXN0X2FkZF9zdGFrZRlyZXF1ZXN0X3JlbW92ZV9kZWxlZ2F0aW9uFXJlcXVlc3Rfc2V0X2dhc19wcmljZQVTdGFrZRZyZXF1ZXN0X3dpdGhkcmF3X3N0YWtlDHN0YWtlX2Ftb3VudAtzdWlfYWRkcmVzcwpkZWxlZ2F0aW9uDXBlbmRpbmdfc3Rha2UScGVuZGluZ19kZWxlZ2F0aW9uG3BlbmRpbmdfZGVsZWdhdGlvbl93aXRoZHJhdxdwZW5kaW5nX2RlbGVnYXRvcl9jb3VudCBwZW5kaW5nX2RlbGVnYXRvcl93aXRoZHJhd19jb3VudAxwdWJrZXlfYnl0ZXMEbmFtZQtuZXRfYWRkcmVzcxBuZXh0X2Vwb2NoX3N0YWtlFW5leHRfZXBvY2hfZGVsZWdhdGlvbhRuZXh0X2Vwb2NoX2dhc19wcmljZQZTdHJpbmcGc3RyaW5nBXZhbHVlBmNyZWF0ZQ53aXRoZHJhd19zdGFrZQAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAEAAgsTCAEiAyQDJQMbAyYDJwMPAygDKQMRAwECByMFKgoCKwoCLAoCLQMuAy8DAAMAAAFkCgAQABQKABABFBYKABACFBcKAA8AFQYAAAAAAAAAAAoADwEVBgAAAAAAAAAACgAPAhUKABAAFAoAEAMQBBQhAyMLAAEGAAAAAAAAAAAnCgAQBRQKABAGFBYKABAHFBcKAA8FFQYAAAAAAAAAAAoADwYVBgAAAAAAAAAACgAPBxUK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AwcIAwsIAQgHBwgCAwMIAAgNAQoIBQEIDQEIDAEIAAEJAAIDAwEGCwkBCQADBwgNBQMEAwULCQEIBwcIAgEGCwoBCQAEAwULCgEIBwcIAgELCQEJAAEIDgELDwEJAAQHCA0LCAEIBwsPAQgOBwgCAgsIAQgHCA4BCwoBCQACCwgBCQAIDgIDCAUIBQoCCgIKAgsIAQgHCw8BCA4DBwgCAQgFAgcIDQgFAwcIAwMHCAICBwgNBwgCAgcIDQYIAgMHCA0DBwgCAgMFAwcIAwUHCAIFBwgNBwgLAwMHCAICBggNBQdnZW5lc2lzCnN1aV9zeXN0ZW0Gb3B0aW9uB2JhbGFuY2UEY29pbgpkZWxlZ2F0aW9uE2Vwb2NoX3Jld2FyZF9yZWNvcmQPZXBvY2hfdGltZV9sb2NrC2xvY2tlZF9jb2luBm9iamVjdAVzdGFrZQNzdWkIdHJhbnNmZXIKdHhfY29udGV4dAl2YWxpZGF0b3INdmFsaWRhdG9yX3NldA5TdWlTeXN0ZW1TdGF0ZRBTeXN0ZW1QYXJhbWV0ZXJzCVR4Q29udGV4dA1hZHZhbmNlX2Vwb2NoCkRlbGVnYXRpb24RRXBvY2hSZXdhcmRSZWNvcmQXY2xhaW1fZGVsZWdhdGlvbl9yZXdhcmQJVmFsaWRhdG9yBlN1cHBseQNTVUkHQmFsYW5jZQZjcmVhdGUFZXBvY2gEQ29pbhZyZXF1ZXN0X2FkZF9kZWxlZ2F0aW9uCkxvY2tlZENvaW4ncmVxdWVzdF9hZGRfZGVsZWdhdGlvbl93aXRoX2xvY2tlZF9jb2luEXJlcXVlc3RfYWRkX3N0YWtlInJlcXVlc3RfYWRkX3N0YWtlX3dpdGhfbG9ja2VkX2NvaW4VcmVxdWVzdF9hZGRfdmFsaWRhdG9yGXJlcXVlc3RfcmVtb3ZlX2RlbGVnYXRpb24YcmVxdWVzdF9yZW1vdmVfdmFsaWRhdG9yFXJlcXVlc3Rfc2V0X2dhc19wcmljZRlyZXF1ZXN0X3N3aXRjaF9kZWxlZ2F0aW9uBVN0YWtlFnJlcXVlc3Rfd2l0aGRyYXdfc3Rha2UZdmFsaWRhdG9yX2RlbGVnYXRlX2Ftb3VudBl2YWxpZGF0b3JfZGVsZWdhdG9yX2NvdW50AmlkA1VJRAp2YWxpZGF0b3JzDFZhbGlkYXRvclNl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YWxjdWxhdGVfdG90YWxfc3Rha2VfYW5kX3F1b3J1bV90aHJlc2hvbGQbY29tcHV0ZV9yZXdhcmRfZGlzdHJpYnV0aW9uHGNvbnRhaW5zX2R1cGxpY2F0ZV92YWxpZGF0b3IUY3JlYXRlX2Vwb2NoX3JlY29yZHMRVmFsaWRhdG9yTWV0YWRhdGEcZGVyaXZlX25leHRfZXBvY2hfdmFsaWRhdG9ycxpkZXJpdmVfcmVmZXJlbmNlX2dhc19wcmljZRFkaXN0cmlidXRlX3Jld2FyZAZPcHRpb24OZmluZF92YWxpZGF0b3IRZ2V0X3ZhbGlkYXRvcl9tdXQRZ2V0X3ZhbGlkYXRvcl9yZWYTaXNfYWN0aXZlX3ZhbGlkYXRvcgNuZXcabmV4dF9lcG9jaF92YWxpZGF0b3JfY291bnQYcHJvY2Vzc19wZW5kaW5nX3JlbW92YWxzGnByb2Nlc3NfcGVuZGluZ192YWxpZGF0b3JzFnJlcXVlc3RfYWRkX2RlbGVnYXRpb24NRXBvY2hUaW1lTG9jaxFyZXF1ZXN0X2FkZF9zdGFrZRVyZXF1ZXN0X2FkZF92YWxpZGF0b3IZcmVxdWVzdF9yZW1vdmVfZGVsZWdhdGlvbhhyZXF1ZXN0X3JlbW92ZV92YWxpZGF0b3IVcmVxdWVzdF9zZXRfZ2FzX3ByaWNlBVN0YWtlFnJlcXVlc3Rfd2l0aGRyYXdfc3Rha2URc29ydF9yZW1vdmFsX2xpc3QWdG90YWxfZGVsZWdhdGlvbl9zdGFrZRV0b3RhbF92YWxpZGF0b3Jfc3Rha2UZdmFsaWRhdG9yX2RlbGVnYXRlX2Ftb3VudBl2YWxpZGF0b3JfZGVsZWdhdG9yX2NvdW50FnZhbGlkYXRvcl9zdGFrZV9hbW91bnQWcXVvcnVtX3N0YWtlX3RocmVzaG9sZBFhY3RpdmVfdmFsaWRhdG9ycxJwZW5kaW5nX3ZhbGlkYXRvcnMQcGVuZGluZ19yZW1vdmFscxVuZXh0X2Vwb2NoX3ZhbGlkYXRvcnMFdmFsdWUMc3Rha2VfYW1vdW50D2RlbGVnYXRlX2Ftb3VudAxpc19kdXBsaWNhdGUPZGVsZWdhdG9yX2NvdW50C3N1aV9hZGRyZXNzBmNyZWF0ZQhtZXRhZGF0YQVFbnRyeQ1Qcmlvcml0eVF1ZXVl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QHBUBCAAAAwYIAAMFAQEDBwgACwEBCAIHCAMEAwULBAEIAgcIAwQDBQsFAQgCBwgDAQYIAAEDAwcIAAUHCAMDBwgAAwcIAwEFBgsHAQsBAQgCCwcBCAgLBwEDAwgGAwEIBgELAQEIAgELBwEJAAEICAEGCwcBCQABBgkAAgEDAQYIAwEIAgILAQEJAAcIAwELBAEJAAELBAEIAgIJAAUCAwgAAQYLBAEJAAEHCAMBCwEBCQABCQAECwEBCAIDCAAICAEGCwUBCQABCwUBCQACCwEBCQAICAYLBwEICAsBAQgCAwMIAAsHAQgIAQcLBwEJAAEGCwEBCQADCAgFCwEBCAIECwEBCQAICAUHCAMKc3VpX3N5c3RlbQpkZWxlZ2F0aW9uBm9wdGlvbgdiYWxhbmNlBGNvaW4PZXBvY2hfdGltZV9sb2NrC2xvY2tlZF9jb2luBm9iamVjdANzdWkIdHJhbnNmZXIKdHhfY29udGV4dApEZWxlZ2F0aW9uBGJ1cm4QY2FuX2NsYWltX3Jld2FyZAdCYWxhbmNlA1NVSQlUeENvbnRleHQMY2xhaW1fcmV3YXJkBENvaW4GY3JlYXRlCkxvY2tlZENvaW4XY3JlYXRlX2Zyb21fbG9ja2VkX2NvaW4PZGVsZWdhdGVfYW1vdW50CWlzX2FjdGl2ZRFzd2l0Y2hfZGVsZWdhdGlvbgp1bmRlbGVnYXRlCXZhbGlkYXRvcgJpZANVSUQRYWN0aXZlX2RlbGVnYXRpb24GT3B0aW9uDGVuZGluZ19lcG9jaBtuZXh0X3Jld2FyZF91bmNsYWltZWRfZXBvY2gXY29pbl9sb2NrZWRfdW50aWxfZXBvY2gNRXBvY2hUaW1lTG9jaxF2YWxpZGF0b3JfYWRkcmVzcwZkZWxldGUMZGVzdHJveV9ub25lBmJvcnJvdwZzZW5kZXIMZnJvbV9iYWxhbmNlBXZhbHVlA25ldwxpbnRvX2JhbGFuY2UEc29tZQRub25lB2lzX3NvbWUHaXNfbm9uZQVlcG9jaAdleHRyYWN0EG5ld19mcm9tX2JhbGFuY2UAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAABAAIHGwgGHQsHAQsBAQgCHwsHAQMWAyADIQsHAQgIIwUAAQQADCAOABEGIAMGBgAAAAAAAAA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HCAQHCAIGCggFCwYBCAcLCAEIBwMDAwEGCAABAwQHCAALCQEIBwUHCAIEBwgACwoBCAcFBwgCAwcIAAsJAQgHBwgCAwcIAAsKAQgHBwgCBwcIAAoCCgIKAgsJAQgHAwcIAgMHCAAHCAMHCAICBwgABwgCAwcIAAMHCAIEBwgABwgDBQcIAgQHCAAHCAsDBwgCAgYIAAUICwgBCAcDCwgBCAcDAwsIAQgHAwMBBggCAQUBCAcCBwsGAQkAAwELCAEJAAEGCA0BBgsIAQkAAgcLCAEJAAMCBwsIAQkACwgBCQAFBggNAwMDBwgCAwcIDQcLCAEIBwcIAgcHCAMDBQMLCAEIBwMFAQYIBAMGCAMDBQEBAQYIAwIHCAQDAwcIAwsIAQgHBwgCAwMIAAgNAQoIBQEIDQEIDAEIAAEJAAIDAwEGCwkBCQADBwgNBQMEAwULCQEIBwcIAgEGCwoBCQAEAwULCgEIBwcIAgELCQEJAAEIDgELDwEJAAQHCA0LCAEIBwsPAQgOBwgCAgsIAQgHCA4BCwoBCQACCwgBCQAIDgIDCAUIBQoCCgIKAgsIAQgHCw8BCA4DBwgCAQgFAgcIDQgFAwcIAwMHCAICBwgNBwgCAgcIDQYIAgMHCA0DBwgCAgMFAwcIAwUHCAIFBwgNBwgLAwMHCAICBggNBQdnZW5lc2lzCnN1aV9zeXN0ZW0Gb3B0aW9uB2JhbGFuY2UEY29pbgpkZWxlZ2F0aW9uE2Vwb2NoX3Jld2FyZF9yZWNvcmQPZXBvY2hfdGltZV9sb2NrC2xvY2tlZF9jb2luBm9iamVjdAVzdGFrZQNzdWkIdHJhbnNmZXIKdHhfY29udGV4dAl2YWxpZGF0b3INdmFsaWRhdG9yX3NldA5TdWlTeXN0ZW1TdGF0ZRBTeXN0ZW1QYXJhbWV0ZXJzCVR4Q29udGV4dA1hZHZhbmNlX2Vwb2NoCkRlbGVnYXRpb24RRXBvY2hSZXdhcmRSZWNvcmQXY2xhaW1fZGVsZWdhdGlvbl9yZXdhcmQJVmFsaWRhdG9yBlN1cHBseQNTVUkHQmFsYW5jZQZjcmVhdGUFZXBvY2gEQ29pbhZyZXF1ZXN0X2FkZF9kZWxlZ2F0aW9uCkxvY2tlZENvaW4ncmVxdWVzdF9hZGRfZGVsZWdhdGlvbl93aXRoX2xvY2tlZF9jb2luEXJlcXVlc3RfYWRkX3N0YWtlInJlcXVlc3RfYWRkX3N0YWtlX3dpdGhfbG9ja2VkX2NvaW4VcmVxdWVzdF9hZGRfdmFsaWRhdG9yGXJlcXVlc3RfcmVtb3ZlX2RlbGVnYXRpb24YcmVxdWVzdF9yZW1vdmVfdmFsaWRhdG9yFXJlcXVlc3Rfc2V0X2dhc19wcmljZRlyZXF1ZXN0X3N3aXRjaF9kZWxlZ2F0aW9uBVN0YWtlFnJlcXVlc3Rfd2l0aGRyYXdfc3Rha2UZdmFsaWRhdG9yX2RlbGVnYXRlX2Ftb3VudBl2YWxpZGF0b3JfZGVsZWdhdG9yX2NvdW50AmlkA1VJRAp2YWxpZGF0b3JzDFZhbGlkYXRvclNldApzdWlfc3VwcGx5DHN0b3JhZ2VfZnVuZApwYXJhbWV0ZXJzEWRlbGVnYXRpb25fcmV3YXJkE3JlZmVyZW5jZV9nYXNfcHJpY2UTbWluX3ZhbGlkYXRvcl9zdGFrZR1tYXhfdmFsaWRhdG9yX2NhbmRpZGF0ZV9jb3VudBFzdG9yYWdlX2dhc19wcmljZQZzZW5kZXIPaW5jcmVhc2Vfc3VwcGx5FnRvdGFsX2RlbGVnYXRpb25fc3Rha2UVdG90YWxfdmFsaWRhdG9yX3N0YWtlBXZhbHVlBXNwbGl0BGpvaW4UY3JlYXRlX2Vwb2NoX3JlY29yZHMaZGVyaXZlX3JlZmVyZW5jZV9nYXNfcHJpY2UQY2FuX2NsYWltX3Jld2FyZA9kZWxlZ2F0ZV9hbW91bnQMY2xhaW1fcmV3YXJkA25ldxBzdWlfc3lzdGVtX3N0YXRlBHplcm8Mc2hhcmVfb2JqZWN0F2NyZWF0ZV9mcm9tX2xvY2tlZF9jb2luDGludG9fYmFsYW5jZQ1FcG9jaFRpbWVMb2NrBk9wdGlvbgRub25lBHNvbWUabmV4dF9lcG9jaF92YWxpZGF0b3JfY291bnQKdW5kZWxlZ2F0ZRFzd2l0Y2hfZGVsZWdhdGlvbgAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAEFFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIILAgMHAMuCA0wCwYBCAcxCwgBCAcyCAEzCwgBCAc0AwECAzUDNgM3AwABBAARagoELhEQBwAhAwwLAAELBAEGAAAAAAA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BAQgBBAMDCgMDAQgDAQYLAgEJAAIDAwYDAwMDBggBAwYDAwoDBAQGCAEDAwMGCAECBggBBggBAQUGAwMDAwUHCAQIAwMGCAUGCAUDAwMKCAUBCAUBBggFCwoLCQEDAwMDCwoBAwMDAwMGCAEGCggBAQsJAQMCAwkAAQsJAQkAAQoLCQEJAAELCgEJAAEHCwoBCQAFAwMLAgEIAwMHCAECBwsCAQkAAwELAgEJAAEIBwELBgEJAAQHCAELAgEIAwsGAQgHBwgEAQkABAcKCAEFAwsGAQMBBgsGAQkAAQcLBgEJAAIDCwYBAwQDAwMIAAIDCAEBBgoJAAIHCgkAAwIHCAEDAgcIAQUBBggEAwcIAQMLBgEDAwUDCwYBAwIGCgkABgkABQcIAQcICAMDBwgECAcKAwMHCgMDAwMDAwpzdWlfc3lzdGVtDXZhbGlkYXRvcl9zZXQGb3B0aW9uBnZlY3RvcgdiYWxhbmNlE2Vwb2NoX3Jld2FyZF9yZWNvcmQPZXBvY2hfdGltZV9sb2NrDnByaW9yaXR5X3F1ZXVlBXN0YWtlA3N1aQp0eF9jb250ZXh0CXZhbGlkYXRvcgxWYWxpZGF0b3JTZXQJVmFsaWRhdG9yGmFkanVzdF9zdGFrZV9hbmRfZ2FzX3ByaWNlB0JhbGFuY2UDU1VJCVR4Q29udGV4dA1hZHZhbmNlX2Vwb2NoGmNhbGN1bGF0ZV9xdW9ydW1fdGhyZXNob2xkKmNhbGN1bGF0ZV90b3RhbF9zdGFrZV9hbmRfcXVvcnVtX3RocmVzaG9sZBtjb21wdXRlX3Jld2FyZF9kaXN0cmlidXRpb24cY29udGFpbnNfZHVwbGljYXRlX3ZhbGlkYXRvchRjcmVhdGVfZXBvY2hfcmVjb3JkcxFWYWxpZGF0b3JNZXRhZGF0YRxkZXJpdmVfbmV4dF9lcG9jaF92YWxpZGF0b3JzGmRlcml2ZV9yZWZlcmVuY2VfZ2FzX3ByaWNlEWRpc3RyaWJ1dGVfcmV3YXJkBk9wdGlvbg5maW5kX3ZhbGlkYXRvchFnZXRfdmFsaWRhdG9yX211dBFnZXRfdmFsaWRhdG9yX3JlZhNpc19hY3RpdmVfdmFsaWRhdG9yA25ldxpuZXh0X2Vwb2NoX3ZhbGlkYXRvcl9jb3VudBhwcm9jZXNzX3BlbmRpbmdfcmVtb3ZhbHMacHJvY2Vzc19wZW5kaW5nX3ZhbGlkYXRvcnMWcmVxdWVzdF9hZGRfZGVsZWdhdGlvbg1FcG9jaFRpbWVMb2NrEXJlcXVlc3RfYWRkX3N0YWtlFXJlcXVlc3RfYWRkX3ZhbGlkYXRvchlyZXF1ZXN0X3JlbW92ZV9kZWxlZ2F0aW9uGHJlcXVlc3RfcmVtb3ZlX3ZhbGlkYXRvchVyZXF1ZXN0X3NldF9nYXNfcHJpY2UFU3Rha2UWcmVxdWVzdF93aXRoZHJhd19zdGFrZRFzb3J0X3JlbW92YWxfbGlzdBZ0b3RhbF9kZWxlZ2F0aW9uX3N0YWtlFXRvdGFsX3ZhbGlkYXRvcl9zdGFrZRl2YWxpZGF0b3JfZGVsZWdhdGVfYW1vdW50GXZhbGlkYXRvcl9kZWxlZ2F0b3JfY291bnQWdmFsaWRhdG9yX3N0YWtlX2Ftb3VudBZxdW9ydW1fc3Rha2VfdGhyZXNob2xkEWFjdGl2ZV92YWxpZGF0b3JzEnBlbmRpbmdfdmFsaWRhdG9ycxBwZW5kaW5nX3JlbW92YWxzFW5leHRfZXBvY2hfdmFsaWRhdG9ycwV2YWx1ZQxzdGFrZV9hbW91bnQPZGVsZWdhdGVfYW1vdW50DGlzX2R1cGxpY2F0ZQ9kZWxlZ2F0b3JfY291bnQLc3VpX2FkZHJlc3MGY3JlYXRlCG1ldGFkYXRhBUVudHJ5DVByaW9yaXR5UXVldWUJZ2FzX3ByaWNlCW5ld19lbnRyeQdwb3BfbWF4BXNwbGl0BG5vbmUEc29tZQdpc19zb21lB2V4dHJhY3QIaXNfZW1wdHkGcmVtb3ZlB2Rlc3Ryb3kGc2VuZGVyCGNvbnRhaW5zAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAQACBzADLwM0AzUKCAE2CggBNwoDOAoIBQAAAAAgGQoALkEhDAIGAAAAAAAAAAAMAQoBCgIjAwsFFgoACgFDIQwDCwMRHwsBBgEAAAAAAAAAFgwBBQYLAAECAQMAACI2CgAQAAoAEAEUCgEuOAARBAwFCgAPABEACgAPAA4FCwELAhEJCgAPAAoADwIREQoADwAKAA8DERAKAC4RBwoADwQVCgAQABEDDAQMAwwGCwYKAA8BFQsDCgAPBRULBAsADwYVAgIAAAAlEgsAQSEMAQYCAAAAAAAAAAoBGAYDAAAAAAAAABoGAQAAAAAAAAAWBmQAAAAAAAAAGAsBGgwCCwIzAgMAAAAmMQYAAAAAAAAAAAwGBgAAAAAAAAAADAEKAEEhDAMGAAAAAAAAAAAMAgoCCgMjAw4FIQoACgJCIQwFCwYKBREhFgwGCwELBREiFgwBCwIGAQAAAAAAAAAWDAIFCQsAAQoGCgEWDAQLBgsBCwQGAQAAAAAAAAAWBgIAAAAAAAAAGAYDAAAAAAAAABoCBAAAACcpQA0AAAAAAAAAAAwFCgBBIQwEBgAAAAAAAAAADAMKAwoEIwMMBSUKAAoDQiEMCAsIESE1DAcLBwoCNRgKATUaDAYNBQsGNEQNCwMGAQAAAAAAAAAWDAMFBwsAAQsFAgUAAAAoJAoAQSEMAwYAAAAAAAAAAAwCCgIKAyMDCgUeCgAKAkIhDAQLBAoBESMDEwUZCwABCwEBCAILAgYBAAAAAAAAABYMAgUFCwABCwEBCQIGAwAAKCMKABAAQSEMBgYAAAAAAAAAAAwFCgUKBiMDCwUeCgAQAAoFQiEMBwoBCgIKAwoHESQLBxElCgQRJgsFBgEAAAAAAAAAFgwFBQYLAAELBAECBwAAACxbCgAQAEEhDAEKABADQQ0MBkAtAAAAAAAAAAAMCAoBBgAAAAAAAAAAJAMPBT0KBgYAAAAAAAAAACQDFAUsCgAQAwoGBgEAAAAAAAAAF0INFAwHCwcKAQYBAAAAAAAAABchAyMFLAsGBgEAAAAAAAAAFwwGCwEGAQAAAAAAAAAXDAEFCgoAEAAKAQYBAAAAAAAAABdCIREnDAMNCAsDFEQtCwEGAQAAAAAAAAAXDAEFCgYAAAAAAAAAAAwCCgAQAkEhDAUKAgoFIwNIBVcKABACCgJCIREnDAQNCAsEFEQtCwIGAQAAAAAAAAAWDAIFQwsAAQsIAggBAAAvRQoAEAAMCwoLQSEMBEAwAAAAAAAAAAAMAQYAAAAAAAAAAAwDCgMKBCMDDwUiCgsKA0IhDAoNAQoKESgKChEhCwoRIhY4AUQwCwMGAQAAAAAAAAAWDAMFCgsLAQsBOAIMBQYAAAAAAAAAAAwICgARGwsAERoWBgMAAAAAAAAAGgwJBgAAAAAAAAAADAYKCAoJIwM4BUMNBTgDDAcMAgsCDAYLCAsHFgwIBTMLBgIJAAAANisKAC5BIQwFBgAAAAAAAAAADAQKBAoFIwMLBSIKAAoEQyEMCAoBCgRCDRQMBwoCCwc4BAwGCwgLBjgFCgMRLgsEBgEAAAAAAAAAFgwEBQYLAAELAQELAgELAwECCgAAACgiCgBBIQwDBgAAAAAAAAAADAIKAgoDIwMKBR4KAAoCQiEMBAsEESUKASEDFAUZCwABCwI4BgILAgYBAAAAAAAAABYMAgUFCwABOAcCCwAAAD0XCgALAQwDDAILAi4LAxEKDAUOBTgIAxALAAEGAAAAAAAAAAAnDQU4CQwECwALBEMhAgwAAABAEgoACwERCgwDDgM4CAMLCwABBgAAAAAAAAAAJw0DOAkMAgsACwJCIQINAwAAEAgLABAACwERCgwCDgI4CAIOAwAAQRUOABEDDAEMAgwDCwMLAgsBCwBAIQAAAAAAAAAAQA0AAAAAAAAAAEAtAAAAAAAAAAASAAwEDgQRBw0EDwQVCwQCDwMAAAEECwAQBEEtAhAAAABCFwoBERkKAS44CiADCAUSCgFFDQwCCgALAjgLDAMLAxE0BQILAQELAAECEQAAACESCgEuOAwgAwYFDQoBRSEMAgoACwJEIQUACwABCwEBAhIDAAASDwoADwALARELDAMLAwsCETUKAC4RBwsADwQVAhMDAABGFQoDLhE2DAUKAA8ACwURCwwECwQLAQsCCwMRLgoALhEHCwAPBBUCFAMAAAkhCgAQAA4BEQUgAwcFDgoAEAIOAREFIAwCBRAJDAILAgMWCwABBgAAAAAAAAAAJwoADwILAUQhCgAuEQcLAA8EFQIVAwAASB4KABAACwERCgwFDgU4CAMMCwABBgAAAAAAAAAAJw0FOAkMBAoADwALBEMhDAMLAwsCETcKAC4RBwsADwQVAhYDAABJJwsBETYMAgoAEAALAhEKDAQOBDgIAw8LAAEGAAAAAAAAAAAnDQQ4CQwDCgAQAw4DOA0gAxwLAAEGAAAAAAAAAAAnCgAPAwsDRA0KAC4RBwsADwQVAhcDAABGDQsCLhE2DAQLAA8ACwQRCwwDCwMLARE5AhgDAABGFgoELhE2DAYKAA8ACwYRCwwFCwULAQsCCwMLBBE6CgAuEQcLAA8EFQIZAAAATDwKAC5BDQwIBgEAAAAAAAAADAYKBgoIIwMLBTkKAAoGDAIMAQsBLgsCQg0UDAUKBgwHCgcGAAAAAAAAAAAkAxwFNAsHBgEAAAAAAAAAFwwHCgAKBwwEDAMLAy4LBEINFAoFJAMtBTQKAAoHCgcGAQAAAAAAAAAWRw0FFwsGBgEAAAAAAAAAFgwGBQYLAAECGgEAAAEECwAQBRQCGwEAAAEECwAQARQCHAEAABMICwAQAAsBEQwMAgsCESICHQEAABMICwAQAAsBEQwMAgsCESQCHgEAABMICwAQAAsBEQwMAgsCESECAAMAAAAEAAUABgABAAIAAAAOZWxsaXB0aWNfY3VydmWXBaEc6wsFAAAACQEAAgICCAMKQQVLJwdyrAIIngMUCrIDDAy+A6oBDegEBAAAAAEHAAACBwAAAwABAAAEAgMAAAUEAQAABgUDAAAHBQMAAAgDAwAACQYDAAAKBQMAAAsDAQAADAMHAAANBgcAAA4IAwAADwABAAIGCAAGCAABCAABBggAAQoCAggBCAECCgIKAgEDAQgBAQYIAQABAg5lbGxpcHRpY19jdXJ2ZQ5SaXN0cmV0dG9Qb2ludAZTY2FsYXIDYWRkBWJ5dGVzGmNyZWF0ZV9wZWRlcnNlbl9jb21taXRtZW50Gm5hdGl2ZV9hZGRfcmlzdHJldHRvX3BvaW50IW5hdGl2ZV9jcmVhdGVfcGVkZXJzZW5fY29tbWl0bWVudBhuYXRpdmVfc2NhbGFyX2Zyb21fYnl0ZXMWbmF0aXZlX3NjYWxhcl9mcm9tX3U2NB9uYXRpdmVfc3VidHJhY3RfcmlzdHJldHRvX3BvaW50Dm5ld19mcm9tX2J5dGVzFW5ld19zY2FsYXJfZnJvbV9ieXRlcxNuZXdfc2NhbGFyX2Zyb21fdTY0DHNjYWxhcl9ieXRlcwhzdWJ0cmFjdAV2YWx1ZQAAAAAAAAAAAAAAAAAAAAAAAAACAAIBEAoCAQIBEAoCAAEAAAkJCwAQABQLARAAFBEDEgACAQEAAAkECwAQABQCAgEAAAkJDgAQARQOARABFBEEEgACAwACAAQAAgAFAAIABgACAAcAAgAIAQAACQoOAEEKBiAAAAAAAAAAIQMHBgEAAAAAAAAAJwsAEgACCQEAAAkECwARBRIBAgoBAAAJBAsAEQYSAQILAQAACQQLABABFAIMAQAACQkLABAAFAsBEAAUEQcSAAIAAAEAAA5wcmlvcml0eV9xdWV1ZcYJoRzrCwUAAAANAQAEAgQMAxAwBEAKBUqZAQfjAaEBCIQDKAasAwoKtgMSC8gDBAzMA7YFDYIJBA6GCQQAAAEBAAIGAQIAAAMGAQIAAAQAAQECAAUCAwECAAYEAwECAAcBBQECAAgGBwECAAkIBgECAAoJAwECAQ4NDAEABwsHDAYMAgwHBwIKAwoJAAEKCwABCQADBwsBAQkAAwkAAAMHCgsAAQkAAwMBCwEBCQACAwkAAQsAAQkAAQcLAQEJAAIHCgsAAQkAAwUDAwMKCwABCQAJAAEDAQkAAgcKCQADDQcKCwABCQABAwcKCwABCQADAQcKCwABCQADBwoLAAEJAAMDAwMCAwMDAwMJAAUHCgsAAQkAAwcKCwABCQADAw5wcmlvcml0eV9xdWV1ZQZ2ZWN0b3IFRW50cnkNUHJpb3JpdHlRdWV1ZQ5jcmVhdGVfZW50cmllcwZpbnNlcnQVbWF4X2hlYXBpZnlfcmVjdXJzaXZlA25ldwluZXdfZW50cnkHcG9wX21heBZyZXN0b3JlX2hlYXBfcmVjdXJzaXZlCHByaW9yaXR5BXZhbHVlB2VudHJpZXMGcmVtb3ZlAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAQMIAAAAAAAAAAAAAgILAwwJAAECAQ0KCwABCQAADAEMAAEAAAonDgBBCwwDDgFBDAoDIQMKBgAAAAAAAAAAJ0AHAAAAAAAAAAAMBQYAAAAAAAAAAAwCCgIKAyMDEwUlDQAGAAAAAAAAAAA4AAwEDQEGAAAAAAAAAAA4AQwGDQULBAsGOQBEBwsCBgEAAAAAAAAAFgwCBQ4LBQIBAQAACxEKADYACwELAjkARAcKADcAQQcGAQAAAAAAAAAXDAMLADYACwM4AgICAAAADnMKAQYAAAAAAAAAACEDBQUICwABAgoCCgEjAxALAAEGAQAAAAAAAAAnCgIGAgAAAAAAAAAYBgEAAAAAAAAAFgwNCg0GAQAAAAAAAAAWDA8KAgwOCg0KASMDIQU4CgAKDQwFDAMKAAoODAcMBgsDLgsFQgc3ARQLBi4LB0IHNwEUJAwIBToJDAgLCAM9BT8LDQwOCg8KASMDRAVbCgAKDwwKDAkKAAoODAwMCwsJLgsKQgc3ARQLCy4LDEIHNwEUJAwEBV0JDAQLBANgBWILDwwOCg4KAiIDZwVwCgAKDgsCRwcLAAsBCw44AwVyCwABAgMBAAAPGA4AQQcMAgoCBgIAAAAAAAAAGgwBCgEGAAAAAAAAAAAkAwwFFQsBBgEAAAAAAAAAFwwBDQAKAgoBOAMFBwsAOQECBAEAAAMECwALATkAAgUBAAAQHQoANwBBBwwBCgEGAAAAAAAAAAAkAwwLAAEHACcKADYABgAAAAAAAAAAOAQ6AAwDDAILADYACwEGAQAAAAAAAAAXBgAAAAAAAAAAOAMLAgsDAgYAAAARMAoBBgAAAAAAAAAAIQMFBQgLAAECCgEGAQAAAAAAAAAXBgIAAAAAAAAAGgwGCgAKAQwDDAIKAAoGDAUMBAsCLgsDQgc3ARQLBC4LBUIHNwEUJAMlBS0KAAsBCgZHBwsACwY4AgUvCwABAgEAAAAADAEMAA9lcG9jaF90aW1lX2xvY2uXAqEc6wsFAAAACgEABAIECAMMFAUgGQc5RQh+FAaSARQKpgEFDKsBPg3pAQIAAAABAAIEAAEDAgAABAABAAAFAgMAAAYEBQABBQYDAAIIAAcIAQABBggAAQMCAwcIAQEIAAEGCAEPZXBvY2hfdGltZV9sb2NrCnR4X2NvbnRleHQNRXBvY2hUaW1lTG9jawlUeENvbnRleHQHZGVzdHJveQVlcG9jaANuZXcAAAAAAAAAAAAAAAAAAAAAAAAAAgMIAAAAAAAAAAADCAEAAAAAAAAAAAIBBQMAAQAAAwwLABMADAILAS4RAwsCJgMLBwEnAgEBAAABBAsAEAAUAgIBAAABCwsBLhEDCgAjAwgHACcLABIAAgAAAA9lcmM3MjFfbWV0YWRhdGGrA6Ec6wsFAAAACQEACAIIFAMcKAVELAdwjQEI/QEoCqUCEQy2AkUN+wIGAAABAQACAAMABAQAAAUFAAMGBwACCwcAAQYHAAAHAAEAAAgCAwAACQQFAAAKAAYAAAwABwABDgoJAAMPCgsAAhAJDAABBggAAQYIAgMIAQoCCgIBCAABAwEIAQEGCAEBBggDAAEIBAEKAgEIAgEIAw9lcmM3MjFfbWV0YWRhdGEFYXNjaWkDdXJsBHV0ZjgORVJDNzIxTWV0YWRhdGEHVG9rZW5JRAZTdHJpbmcEbmFtZQNuZXcMbmV3X3Rva2VuX2lkCHRva2VuX2lkA1VybAl0b2tlbl91cmkCaWQGc3RyaW5nDXN0cmluZ191bnNhZmUKbmV3X3Vuc2FmZQAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAEAAgMKCAEHCAIMCAMBAgENAwABAAAIAwsAEAACAQEAAAkKCwIRBQwDCwALAREGCwMRBxIAAgIBAAAIAwsAEgECAwEAAAgDCwAQAQIEAQAACAMLABACAgABAAAAAgATZXBvY2hfcmV3YXJkX3JlY29yZOUDoRzrCwUAAAALAQAIAggMAxQfBDMCBTUkB1nPAQioAhQKvAIQDMwCWg2mAwoPsAMEAAIAAwAEAAUABggAAwgCAAENBAAABwABAAAJAgMAAAoEAQAACwQFAAERBgcAAhIJAwEIBQgCBwgAAwEDBgMDAwMFBwgBAAEGCAABBQEHCAEBCAIBCAABCQAKc3VpX3N5c3RlbQ12YWxpZGF0b3Jfc2V0E2Vwb2NoX3Jld2FyZF9yZWNvcmQGb2JqZWN0CHRyYW5zZmVyCnR4X2NvbnRleHQRRXBvY2hSZXdhcmRSZWNvcmQMY2xhaW1fcmV3YXJkCVR4Q29udGV4dAZjcmVhdGUFZXBvY2gJdmFsaWRhdG9yAmlkA1VJRBJjb21wdXRhdGlvbl9jaGFyZ2ULdG90YWxfc3Rha2UPZGVsZWdhdG9yX2NvdW50A25ldwxzaGFyZV9vYmplY3QAAAAAAAAAAAAAAAAAAAAAAAAAAgACBgwIAgoDDgMPAxADCwUAAwAAAxIKABAAFAYBAAAAAAAAABcKAA8AFQsBCgAQARQYCwAQAhQaAgEDAAADCgsFEQQLAAsBCwILAwsEEgA4AAICAQAAAwQLABADFAIDAQAAAwQLABAEFAIABAACAAMAAQAFAAAAAQADIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIKc3VpX3N5c3RlbQ5TdWlTeXN0ZW1TdGF0ZQAAAQAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEB6EPNaAAAAQHoQ81oAAABAehDzWgAAZAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs index a208fd0d6e288..7c8a1c2c4162b 100644 --- a/crates/sui-core/src/authority.rs +++ b/crates/sui-core/src/authority.rs @@ -1181,7 +1181,7 @@ impl AuthorityState { None, )); - AuthorityState::new( + let state = AuthorityState::new( secret.public().into(), secret.clone(), store, @@ -1192,7 +1192,10 @@ impl AuthorityState { genesis, &prometheus::Registry::new(), ) - .await + .await; + + // add the object_basics module + state } // Continually pop in-progress txes from the WAL and try to drive them to completion. diff --git a/crates/sui-core/src/authority_active/execution_driver/tests.rs b/crates/sui-core/src/authority_active/execution_driver/tests.rs index c5a0ae51b4c49..5cefeacab3274 100644 --- a/crates/sui-core/src/authority_active/execution_driver/tests.rs +++ b/crates/sui-core/src/authority_active/execution_driver/tests.rs @@ -7,7 +7,6 @@ use crate::authority_active::checkpoint_driver::CheckpointMetrics; use std::sync::Arc; use std::time::Duration; -use sui_adapter::genesis; use sui_types::crypto::AccountKeyPair; use sui_types::{crypto::get_key_pair, messages::ExecutionStatus, object::Object}; @@ -203,15 +202,13 @@ async fn test_parent_cert_exec() { let (addr1, key1): (_, AccountKeyPair) = get_key_pair(); let gas_object1 = Object::with_owner_for_testing(addr1); let gas_object2 = Object::with_owner_for_testing(addr1); - let (aggregator, authorities) = + let (aggregator, authorities, framework_obj_ref) = init_local_authorities(4, vec![gas_object1.clone(), gas_object2.clone()]).await; let authority_clients: Vec<_> = authorities .iter() .map(|a| &aggregator.authority_clients[&a.name]) .collect(); - let framework_obj_ref = genesis::get_framework_object_ref(); - // Make a schedule of transactions let gas_ref_1 = get_latest_ref(authority_clients[0], gas_object1.id()).await; let tx1 = crate_object_move_transaction(addr1, &key1, addr1, 100, framework_obj_ref, gas_ref_1); diff --git a/crates/sui-core/src/epoch/tests/reconfiguration_tests.rs b/crates/sui-core/src/epoch/tests/reconfiguration_tests.rs index 0b6fe710366d8..76ccb95f21bd3 100644 --- a/crates/sui-core/src/epoch/tests/reconfiguration_tests.rs +++ b/crates/sui-core/src/epoch/tests/reconfiguration_tests.rs @@ -38,7 +38,7 @@ async fn test_start_epoch_change() { let gas_object = Object::with_id_owner_for_testing(ObjectID::random(), sender); let genesis_objects = vec![object.clone(), gas_object.clone()]; // Create authority_aggregator and authority states. - let (net, states) = init_local_authorities(4, genesis_objects.clone()).await; + let (net, states, _) = init_local_authorities(4, genesis_objects.clone()).await; let state = states[0].clone(); // Check that we initialized the genesis epoch. @@ -170,7 +170,7 @@ async fn test_start_epoch_change() { async fn test_finish_epoch_change() { // Create authority_aggregator and authority states. let genesis_objects = vec![]; - let (net, states) = init_local_authorities(4, genesis_objects.clone()).await; + let (net, states, _) = init_local_authorities(4, genesis_objects.clone()).await; let actives: Vec<_> = states .iter() .map(|state| { diff --git a/crates/sui-core/src/unit_tests/authority_aggregator_tests.rs b/crates/sui-core/src/unit_tests/authority_aggregator_tests.rs index c8547c82c2e2b..a5f0e76fc7e74 100644 --- a/crates/sui-core/src/unit_tests/authority_aggregator_tests.rs +++ b/crates/sui-core/src/unit_tests/authority_aggregator_tests.rs @@ -1,12 +1,13 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 use std::collections::BTreeMap; +use std::path::PathBuf; use std::sync::{Arc, Mutex}; use move_core_types::{account_address::AccountAddress, ident_str}; +use move_package::BuildConfig; use signature::Signer; -use sui_adapter::genesis; use sui_config::genesis::Genesis; use sui_config::ValidatorInfo; use sui_types::crypto::{get_key_pair, AccountKeyPair, AuthorityKeyPair, AuthorityPublicKeyBytes}; @@ -26,11 +27,21 @@ use tokio::time::Instant; pub async fn init_local_authorities( committee_size: usize, - genesis_objects: Vec, + mut genesis_objects: Vec, ) -> ( AuthorityAggregator, Vec>, + ObjectRef, ) { + // add object_basics package object to genesis + let build_config = BuildConfig::default(); + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("src/unit_tests/data/object_basics"); + let modules = sui_framework::build_move_package(&path, build_config).unwrap(); + let pkg = Object::new_package(modules, TransactionDigest::genesis()); + let pkg_ref = pkg.compute_object_reference(); + genesis_objects.push(pkg); + let mut builder = sui_config::genesis::Builder::new().add_objects(genesis_objects); let mut key_pairs = Vec::new(); for i in 0..committee_size { @@ -53,7 +64,8 @@ pub async fn init_local_authorities( key_pairs.push((authority_name, key_pair)); } let genesis = builder.build(); - init_local_authorities_with_genesis(&genesis, key_pairs).await + let (aggregator, authorities) = init_local_authorities_with_genesis(&genesis, key_pairs).await; + (aggregator, authorities, pkg_ref) } pub async fn init_local_authorities_with_genesis( @@ -377,7 +389,7 @@ async fn execute_transaction_with_fault_configs( #[tokio::test] async fn test_map_reducer() { - let (authorities, _) = init_local_authorities(4, vec![]).await; + let (authorities, _, _) = init_local_authorities(4, vec![]).await; // Test: reducer errors get propagated up let res = authorities @@ -514,14 +526,13 @@ async fn test_get_all_owned_objects() { let gas_object1 = Object::with_owner_for_testing(addr1); let gas_ref_1 = gas_object1.compute_object_reference(); let gas_object2 = Object::with_owner_for_testing(addr2); - let (authorities, _) = + + let (authorities, _, pkg_ref) = init_local_authorities(4, vec![gas_object1.clone(), gas_object2.clone()]).await; let authority_clients: Vec<_> = authorities.authority_clients.values().collect(); // Make a schedule of transactions - let framework_obj_ref = genesis::get_framework_object_ref(); - let create1 = - crate_object_move_transaction(addr1, &key1, addr1, 100, framework_obj_ref, gas_ref_1); + let create1 = crate_object_move_transaction(addr1, &key1, addr1, 100, pkg_ref, gas_ref_1); // Submit to 3 authorities, but not 4th do_transaction(authority_clients[0], &create1).await; @@ -561,8 +572,7 @@ async fn test_get_all_owned_objects() { // Make a delete transaction let gas_ref_del = get_latest_ref(authority_clients[0], gas_object1.id()).await; - let delete1 = - delete_object_move_transaction(addr1, &key1, created_ref, framework_obj_ref, gas_ref_del); + let delete1 = delete_object_move_transaction(addr1, &key1, created_ref, pkg_ref, gas_ref_del); // Get cert for delete transaction, and submit to first authority do_transaction(authority_clients[0], &delete1).await; @@ -601,19 +611,16 @@ async fn test_sync_all_owned_objects() { let (addr2, _): (_, AccountKeyPair) = get_key_pair(); let gas_object1 = Object::with_owner_for_testing(addr1); let gas_object2 = Object::with_owner_for_testing(addr1); - let (authorities, _) = + let (authorities, _, pkg_ref) = init_local_authorities(4, vec![gas_object1.clone(), gas_object2.clone()]).await; let authority_clients: Vec<_> = authorities.authority_clients.values().collect(); - let framework_obj_ref = genesis::get_framework_object_ref(); // Make a schedule of transactions let gas_ref_1 = get_latest_ref(authority_clients[0], gas_object1.id()).await; - let create1 = - crate_object_move_transaction(addr1, &key1, addr1, 100, framework_obj_ref, gas_ref_1); + let create1 = crate_object_move_transaction(addr1, &key1, addr1, 100, pkg_ref, gas_ref_1); let gas_ref_2 = get_latest_ref(authority_clients[0], gas_object2.id()).await; - let create2 = - crate_object_move_transaction(addr1, &key1, addr1, 101, framework_obj_ref, gas_ref_2); + let create2 = crate_object_move_transaction(addr1, &key1, addr1, 101, pkg_ref, gas_ref_2); // Submit to 3 authorities, but not 4th do_transaction(authority_clients[0], &create1).await; @@ -651,19 +658,12 @@ async fn test_sync_all_owned_objects() { // Make a delete transaction let gas_ref_del = get_latest_ref(authority_clients[0], gas_object1.id()).await; - let delete1 = - delete_object_move_transaction(addr1, &key1, new_ref_1, framework_obj_ref, gas_ref_del); + let delete1 = delete_object_move_transaction(addr1, &key1, new_ref_1, pkg_ref, gas_ref_del); // Make a transfer transaction let gas_ref_trans = get_latest_ref(authority_clients[0], gas_object2.id()).await; - let transfer1 = transfer_object_move_transaction( - addr1, - &key1, - addr2, - new_ref_2, - framework_obj_ref, - gas_ref_trans, - ); + let transfer1 = + transfer_object_move_transaction(addr1, &key1, addr2, new_ref_2, pkg_ref, gas_ref_trans); do_transaction(authority_clients[0], &delete1).await; do_transaction(authority_clients[1], &delete1).await; @@ -725,16 +725,13 @@ async fn test_process_certificate() { let (addr1, key1): (_, AccountKeyPair) = get_key_pair(); let gas_object1 = Object::with_owner_for_testing(addr1); let gas_object2 = Object::with_owner_for_testing(addr1); - let (authorities, _) = + let (authorities, _, pkg_ref) = init_local_authorities(4, vec![gas_object1.clone(), gas_object2.clone()]).await; let authority_clients: Vec<_> = authorities.authority_clients.values().collect(); - let framework_obj_ref = genesis::get_framework_object_ref(); - // Make a schedule of transactions let gas_ref_1 = get_latest_ref(authority_clients[0], gas_object1.id()).await; - let create1 = - crate_object_move_transaction(addr1, &key1, addr1, 100, framework_obj_ref, gas_ref_1); + let create1 = crate_object_move_transaction(addr1, &key1, addr1, 100, pkg_ref, gas_ref_1); do_transaction(authority_clients[0], &create1).await; do_transaction(authority_clients[1], &create1).await; @@ -755,8 +752,7 @@ async fn test_process_certificate() { // Make a schedule of transactions let gas_ref_set = get_latest_ref(authority_clients[0], gas_object1.id()).await; - let create2 = - set_object_move_transaction(addr1, &key1, new_ref_1, 100, framework_obj_ref, gas_ref_set); + let create2 = set_object_move_transaction(addr1, &key1, new_ref_1, 100, pkg_ref, gas_ref_set); do_transaction(authority_clients[0], &create2).await; do_transaction(authority_clients[1], &create2).await; @@ -782,16 +778,13 @@ async fn test_execute_cert_to_true_effects() { let (addr1, key1): (_, AccountKeyPair) = get_key_pair(); let gas_object1 = Object::with_owner_for_testing(addr1); let gas_object2 = Object::with_owner_for_testing(addr1); - let (authorities, _) = + let (authorities, _, pkg_ref) = init_local_authorities(4, vec![gas_object1.clone(), gas_object2.clone()]).await; let authority_clients: Vec<_> = authorities.authority_clients.values().collect(); - let framework_obj_ref = genesis::get_framework_object_ref(); - // Make a schedule of transactions let gas_ref_1 = get_latest_ref(authority_clients[0], gas_object1.id()).await; - let create1 = - crate_object_move_transaction(addr1, &key1, addr1, 100, framework_obj_ref, gas_ref_1); + let create1 = crate_object_move_transaction(addr1, &key1, addr1, 100, pkg_ref, gas_ref_1); do_transaction(authority_clients[0], &create1).await; do_transaction(authority_clients[1], &create1).await; diff --git a/crates/sui-core/src/unit_tests/authority_tests.rs b/crates/sui-core/src/unit_tests/authority_tests.rs index 869808d93df6d..01a8f9fc72081 100644 --- a/crates/sui-core/src/unit_tests/authority_tests.rs +++ b/crates/sui-core/src/unit_tests/authority_tests.rs @@ -677,10 +677,11 @@ async fn test_publish_non_existing_dependent_module() { async fn test_handle_move_transaction() { let (sender, sender_key): (_, AccountKeyPair) = get_key_pair(); let gas_payment_object_id = ObjectID::random(); - let gas_payment_object = Object::with_id_owner_for_testing(gas_payment_object_id, sender); - let authority_state = init_state_with_objects(vec![gas_payment_object]).await; + let (authority_state, pkg_ref) = + init_state_with_ids_and_object_basics(vec![(sender, gas_payment_object_id)]).await; let effects = create_move_object( + &pkg_ref, &authority_state, &gas_payment_object_id, &sender, @@ -1191,27 +1192,41 @@ async fn test_handle_confirmation_transaction_idempotent() { async fn test_move_call_mutable_object_not_mutated() { let (sender, sender_key): (_, AccountKeyPair) = get_key_pair(); let gas_object_id = ObjectID::random(); - let authority_state = init_state_with_ids(vec![(sender, gas_object_id)]).await; + let (authority_state, pkg_ref) = + init_state_with_ids_and_object_basics(vec![(sender, gas_object_id)]).await; - let effects = create_move_object(&authority_state, &gas_object_id, &sender, &sender_key) - .await - .unwrap(); + let effects = create_move_object( + &pkg_ref, + &authority_state, + &gas_object_id, + &sender, + &sender_key, + ) + .await + .unwrap(); assert!(effects.status.is_ok()); assert_eq!((effects.created.len(), effects.mutated.len()), (1, 1)); let (new_object_id1, seq1, _) = effects.created[0].0; - let effects = create_move_object(&authority_state, &gas_object_id, &sender, &sender_key) - .await - .unwrap(); + let effects = create_move_object( + &pkg_ref, + &authority_state, + &gas_object_id, + &sender, + &sender_key, + ) + .await + .unwrap(); assert!(effects.status.is_ok()); assert_eq!((effects.created.len(), effects.mutated.len()), (1, 1)); let (new_object_id2, seq2, _) = effects.created[0].0; - let effects = call_framework_code( + let effects = call_move( &authority_state, &gas_object_id, &sender, &sender_key, + &pkg_ref, "object_basics", "update", vec![], @@ -1335,27 +1350,41 @@ async fn test_move_call_insufficient_gas() { async fn test_move_call_delete() { let (sender, sender_key): (_, AccountKeyPair) = get_key_pair(); let gas_object_id = ObjectID::random(); - let authority_state = init_state_with_ids(vec![(sender, gas_object_id)]).await; + let (authority_state, pkg_ref) = + init_state_with_ids_and_object_basics(vec![(sender, gas_object_id)]).await; - let effects = create_move_object(&authority_state, &gas_object_id, &sender, &sender_key) - .await - .unwrap(); + let effects = create_move_object( + &pkg_ref, + &authority_state, + &gas_object_id, + &sender, + &sender_key, + ) + .await + .unwrap(); assert!(effects.status.is_ok()); assert_eq!((effects.created.len(), effects.mutated.len()), (1, 1)); let (new_object_id1, _seq1, _) = effects.created[0].0; - let effects = create_move_object(&authority_state, &gas_object_id, &sender, &sender_key) - .await - .unwrap(); + let effects = create_move_object( + &pkg_ref, + &authority_state, + &gas_object_id, + &sender, + &sender_key, + ) + .await + .unwrap(); assert!(effects.status.is_ok()); assert_eq!((effects.created.len(), effects.mutated.len()), (1, 1)); let (new_object_id2, _seq2, _) = effects.created[0].0; - let effects = call_framework_code( + let effects = call_move( &authority_state, &gas_object_id, &sender, &sender_key, + &pkg_ref, "object_basics", "update", vec![], @@ -1371,11 +1400,12 @@ async fn test_move_call_delete() { // obj1, obj2 and gas are all mutated here. assert_eq!((effects.created.len(), effects.mutated.len()), (0, 3)); - let effects = call_framework_code( + let effects = call_move( &authority_state, &gas_object_id, &sender, &sender_key, + &pkg_ref, "object_basics", "delete", vec![], @@ -1387,27 +1417,52 @@ async fn test_move_call_delete() { assert_eq!((effects.deleted.len(), effects.mutated.len()), (1, 1)); } +#[tokio::test] +async fn test_get_latest_parent_entry_genesis() { + let authority_state = init_state().await; + // There should not be any object with ID zero + assert!(authority_state + .get_latest_parent_entry(ObjectID::ZERO) + .await + .unwrap() + .is_none()); +} + #[tokio::test] async fn test_get_latest_parent_entry() { let (sender, sender_key): (_, AccountKeyPair) = get_key_pair(); let gas_object_id = ObjectID::random(); - let authority_state = init_state_with_ids(vec![(sender, gas_object_id)]).await; + let (authority_state, pkg_ref) = + init_state_with_ids_and_object_basics(vec![(sender, gas_object_id)]).await; - let effects = create_move_object(&authority_state, &gas_object_id, &sender, &sender_key) - .await - .unwrap(); + let effects = create_move_object( + &pkg_ref, + &authority_state, + &gas_object_id, + &sender, + &sender_key, + ) + .await + .unwrap(); let (new_object_id1, _seq1, _) = effects.created[0].0; - let effects = create_move_object(&authority_state, &gas_object_id, &sender, &sender_key) - .await - .unwrap(); + let effects = create_move_object( + &pkg_ref, + &authority_state, + &gas_object_id, + &sender, + &sender_key, + ) + .await + .unwrap(); let (new_object_id2, _seq2, _) = effects.created[0].0; - let effects = call_framework_code( + let effects = call_move( &authority_state, &gas_object_id, &sender, &sender_key, + &pkg_ref, "object_basics", "update", vec![], @@ -1429,11 +1484,12 @@ async fn test_get_latest_parent_entry() { assert_eq!(obj_ref.1, SequenceNumber::from(2)); assert_eq!(effects.transaction_digest, tx); - let effects = call_framework_code( + let effects = call_move( &authority_state, &gas_object_id, &sender, &sender_key, + &pkg_ref, "object_basics", "delete", vec![], @@ -1444,13 +1500,6 @@ async fn test_get_latest_parent_entry() { // Test get_latest_parent_entry function - // The very first object returns None - assert!(authority_state - .get_latest_parent_entry(ObjectID::ZERO) - .await - .unwrap() - .is_none()); - // The objects just after the gas object also returns None let mut x = gas_object_id.to_vec(); let last_index = x.len() - 1; @@ -1857,6 +1906,31 @@ pub async fn init_state_with_ids> state } +#[cfg(test)] +pub async fn init_state_with_ids_and_object_basics< + I: IntoIterator, +>( + objects: I, +) -> (AuthorityState, ObjectRef) { + use move_package::BuildConfig; + + let state = init_state().await; + for (address, object_id) in objects { + let obj = Object::with_id_owner_for_testing(object_id, address); + state.insert_genesis_object(obj).await; + } + + // add object_basics package object to genesis, since lots of test use it + let build_config = BuildConfig::default(); + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("src/unit_tests/data/object_basics"); + let modules = sui_framework::build_move_package(&path, build_config).unwrap(); + let pkg = Object::new_package(modules, TransactionDigest::genesis()); + let pkg_ref = pkg.compute_object_reference(); + state.insert_genesis_object(pkg).await; + (state, pkg_ref) +} + #[cfg(test)] pub async fn init_state_with_ids_and_versions< I: IntoIterator, @@ -1984,43 +2058,19 @@ pub async fn call_move( Ok(response.signed_effects.unwrap().effects) } -async fn call_framework_code( - authority: &AuthorityState, - gas_object_id: &ObjectID, - sender: &SuiAddress, - sender_key: &AccountKeyPair, - module: &'_ str, - function: &'_ str, - type_args: Vec, - args: Vec, -) -> SuiResult { - let package_object_ref = authority.get_framework_object_ref().await?; - - call_move( - authority, - gas_object_id, - sender, - sender_key, - &package_object_ref, - module, - function, - type_args, - args, - ) - .await -} - pub async fn create_move_object( + package_ref: &ObjectRef, authority: &AuthorityState, gas_object_id: &ObjectID, sender: &SuiAddress, sender_key: &AccountKeyPair, ) -> SuiResult { - call_framework_code( + call_move( authority, gas_object_id, sender, sender_key, + package_ref, "object_basics", "create", vec![], diff --git a/crates/sui-core/src/unit_tests/batch_tests.rs b/crates/sui-core/src/unit_tests/batch_tests.rs index aa3df7643a2bf..13bf6831f18a3 100644 --- a/crates/sui-core/src/unit_tests/batch_tests.rs +++ b/crates/sui-core/src/unit_tests/batch_tests.rs @@ -32,7 +32,6 @@ use sui_types::messages::{ CertifiedTransaction, EpochRequest, EpochResponse, ObjectInfoRequest, ObjectInfoResponse, Transaction, TransactionInfoRequest, TransactionInfoResponse, }; -use sui_types::object::Object; pub(crate) fn init_state_parameters_from_rng( rng: &mut R, @@ -354,9 +353,9 @@ async fn test_batch_manager_drop_out_of_order() { async fn test_handle_move_order_with_batch() { let (sender, sender_key): (_, AccountKeyPair) = get_key_pair(); let gas_payment_object_id = ObjectID::random(); - let gas_payment_object = Object::with_id_owner_for_testing(gas_payment_object_id, sender); - let authority_state = Arc::new(init_state_with_objects(vec![gas_payment_object]).await); - + let (authority_state_, pkg_ref) = + init_state_with_ids_and_object_basics(vec![(sender, gas_payment_object_id)]).await; + let authority_state = Arc::new(authority_state_); let inner_state = authority_state.clone(); let _join = tokio::task::spawn(async move { inner_state @@ -369,6 +368,7 @@ async fn test_handle_move_order_with_batch() { tokio::task::yield_now().await; let effects = create_move_object( + &pkg_ref, &authority_state, &gas_payment_object_id, &sender, diff --git a/crates/sui-core/src/unit_tests/batch_transaction_tests.rs b/crates/sui-core/src/unit_tests/batch_transaction_tests.rs index 0089e9b6f7445..120cd7fbff3d2 100644 --- a/crates/sui-core/src/unit_tests/batch_transaction_tests.rs +++ b/crates/sui-core/src/unit_tests/batch_transaction_tests.rs @@ -1,6 +1,8 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 +use crate::authority::authority_tests::init_state_with_ids_and_object_basics; + use super::*; use bcs; @@ -22,8 +24,10 @@ async fn test_batch_transaction_ok() -> anyhow::Result<()> { const N: usize = 100; const TOTAL: usize = N + 1; let all_ids = (0..TOTAL).map(|_| ObjectID::random()).collect::>(); - let authority_state = - init_state_with_ids([sender; TOTAL].into_iter().zip(all_ids.clone().into_iter())).await; + let (authority_state, package) = init_state_with_ids_and_object_basics( + [sender; TOTAL].into_iter().zip(all_ids.clone().into_iter()), + ) + .await; let mut transactions = vec![]; for obj_id in all_ids.iter().take(N) { transactions.push(SingleTransactionKind::TransferObject(TransferObject { @@ -35,10 +39,9 @@ async fn test_batch_transaction_ok() -> anyhow::Result<()> { .compute_object_reference(), })); } - let package_object_ref = authority_state.get_framework_object_ref().await?; for _ in 0..N { transactions.push(SingleTransactionKind::Call(MoveCall { - package: package_object_ref, + package, module: ident_str!("object_basics").to_owned(), function: ident_str!("create").to_owned(), type_arguments: vec![], @@ -90,8 +93,10 @@ async fn test_batch_transaction_last_one_fail() -> anyhow::Result<()> { const N: usize = 100; const TOTAL: usize = N + 1; let all_ids = (0..TOTAL).map(|_| ObjectID::random()).collect::>(); - let authority_state = - init_state_with_ids([sender; TOTAL].into_iter().zip(all_ids.clone().into_iter())).await; + let (authority_state, package) = init_state_with_ids_and_object_basics( + [sender; TOTAL].into_iter().zip(all_ids.clone().into_iter()), + ) + .await; let mut transactions = vec![]; for obj_id in all_ids.iter().take(N) { transactions.push(SingleTransactionKind::TransferObject(TransferObject { @@ -103,9 +108,8 @@ async fn test_batch_transaction_last_one_fail() -> anyhow::Result<()> { .compute_object_reference(), })); } - let package_object_ref = authority_state.get_framework_object_ref().await?; transactions.push(SingleTransactionKind::Call(MoveCall { - package: package_object_ref, + package, module: ident_str!("object_basics").to_owned(), function: ident_str!("create").to_owned(), type_arguments: vec![], @@ -169,7 +173,7 @@ async fn test_batch_insufficient_gas_balance() -> anyhow::Result<()> { // This test creates 100 Move call transactions batch, each with a budget of 5000. // However we provide a gas coin with only 49999 balance. let (sender, sender_key): (_, AccountKeyPair) = get_key_pair(); - let authority_state = init_state_with_ids([]).await; + let (authority_state, package) = init_state_with_ids_and_object_basics([]).await; let gas_object_id = ObjectID::random(); let gas_object = Object::with_id_owner_gas_for_testing( gas_object_id, @@ -180,12 +184,11 @@ async fn test_batch_insufficient_gas_balance() -> anyhow::Result<()> { .insert_genesis_object(gas_object.clone()) .await; - let package_object_ref = authority_state.get_framework_object_ref().await?; const N: usize = 100; let mut transactions = vec![]; for _ in 0..N { transactions.push(SingleTransactionKind::Call(MoveCall { - package: package_object_ref, + package, module: ident_str!("object_basics").to_owned(), function: ident_str!("create").to_owned(), type_arguments: vec![], diff --git a/crates/sui-core/src/unit_tests/data/hero/sources/hero.move b/crates/sui-core/src/unit_tests/data/hero/sources/hero.move index 7a0a033e92847..3956e2bf503e0 100644 --- a/crates/sui-core/src/unit_tests/data/hero/sources/hero.move +++ b/crates/sui-core/src/unit_tests/data/hero/sources/hero.move @@ -316,7 +316,7 @@ module examples::hero { let treasury_cap = test_scenario::take_owned>(scenario); let ctx = test_scenario::ctx(scenario); let coins = coin::mint(&mut treasury_cap, 500, ctx); - coin::transfer(coins, copy player); + transfer::transfer(coins, copy player); test_scenario::return_owned(scenario, treasury_cap); }; // Player purchases a hero with the coins diff --git a/crates/sui-core/src/unit_tests/data/hero/sources/trusted_coin.move b/crates/sui-core/src/unit_tests/data/hero/sources/trusted_coin.move index 363e2d6001a25..4b1f3ede74bba 100644 --- a/crates/sui-core/src/unit_tests/data/hero/sources/trusted_coin.move +++ b/crates/sui-core/src/unit_tests/data/hero/sources/trusted_coin.move @@ -22,11 +22,7 @@ module examples::trusted_coin { public entry fun mint(treasury_cap: &mut TreasuryCap, amount: u64, ctx: &mut TxContext) { let coin = coin::mint(amount, treasury_cap, ctx); - coin::transfer(coin, tx_context::sender(ctx)); - } - - public entry fun transfer(treasury_cap: TreasuryCap, recipient: address) { - coin::transfer_cap(treasury_cap, recipient); + transfer::transfer(coin, tx_context::sender(ctx)); } #[test_only] diff --git a/crates/sui-core/src/unit_tests/data/object_basics/Move.toml b/crates/sui-core/src/unit_tests/data/object_basics/Move.toml new file mode 100644 index 0000000000000..e6b34720bf6d4 --- /dev/null +++ b/crates/sui-core/src/unit_tests/data/object_basics/Move.toml @@ -0,0 +1,9 @@ +[package] +name = "Examples" +version = "0.0.1" + +[dependencies] +Sui = { local = "../../../../../sui-framework" } + +[addresses] +examples = "0x0" diff --git a/crates/sui-core/src/unit_tests/data/object_basics/sources/object_basics.move b/crates/sui-core/src/unit_tests/data/object_basics/sources/object_basics.move new file mode 100644 index 0000000000000..aa09eb547486a --- /dev/null +++ b/crates/sui-core/src/unit_tests/data/object_basics/sources/object_basics.move @@ -0,0 +1,65 @@ +// Copyright (c) 2022, Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +/// Test CTURD object basics (create, transfer, update, read, delete) +module examples::object_basics { + use sui::event; + use sui::object::{Self, UID}; + use sui::tx_context::{Self, TxContext}; + use sui::transfer; + + struct Object has key, store { + id: UID, + value: u64, + } + + struct Wrapper has key { + id: UID, + o: Object + } + + struct NewValueEvent has copy, drop { + new_value: u64 + } + + public entry fun create(value: u64, recipient: address, ctx: &mut TxContext) { + transfer::transfer( + Object { id: object::new(ctx), value }, + recipient + ) + } + + public entry fun transfer(o: Object, recipient: address) { + transfer::transfer(o, recipient) + } + + public entry fun freeze_object(o: Object) { + transfer::freeze_object(o) + } + + public entry fun set_value(o: &mut Object, value: u64) { + o.value = value; + } + + // test that reading o2 and updating o1 works + public entry fun update(o1: &mut Object, o2: &Object) { + o1.value = o2.value; + // emit an event so the world can see the new value + event::emit(NewValueEvent { new_value: o2.value }) + } + + public entry fun delete(o: Object) { + let Object { id, value: _ } = o; + object::delete(id); + } + + public entry fun wrap(o: Object, ctx: &mut TxContext) { + transfer::transfer(Wrapper { id: object::new(ctx), o }, tx_context::sender(ctx)) + } + + public entry fun unwrap(w: Wrapper, ctx: &mut TxContext) { + let Wrapper { id, o } = w; + object::delete(id); + transfer::transfer(o, tx_context::sender(ctx)) + } +} diff --git a/crates/sui-core/src/unit_tests/gas_tests.rs b/crates/sui-core/src/unit_tests/gas_tests.rs index 3d5e7c6bcefb3..479b85844b4bc 100644 --- a/crates/sui-core/src/unit_tests/gas_tests.rs +++ b/crates/sui-core/src/unit_tests/gas_tests.rs @@ -5,7 +5,7 @@ use super::*; use super::authority_tests::{init_state_with_ids, send_and_confirm_transaction}; use super::move_integration_tests::build_and_try_publish_test_package; -use crate::authority::authority_tests::init_state; +use crate::authority::authority_tests::{init_state, init_state_with_ids_and_object_basics}; use move_core_types::account_address::AccountAddress; use move_core_types::ident_str; use sui_adapter::genesis; @@ -371,8 +371,8 @@ async fn test_publish_gas() -> anyhow::Result<()> { async fn test_move_call_gas() -> SuiResult { let (sender, sender_key): (_, AccountKeyPair) = get_key_pair(); let gas_object_id = ObjectID::random(); - let authority_state = init_state_with_ids(vec![(sender, gas_object_id)]).await; - let package_object_ref = authority_state.get_framework_object_ref().await?; + let (authority_state, package_object_ref) = + init_state_with_ids_and_object_basics(vec![(sender, gas_object_id)]).await; let gas_object = authority_state.get_object(&gas_object_id).await?.unwrap(); let module = ident_str!("object_basics").to_owned(); diff --git a/crates/sui-core/src/unit_tests/gateway_state_tests.rs b/crates/sui-core/src/unit_tests/gateway_state_tests.rs index 04ac5adc74547..01c4c811cdef3 100644 --- a/crates/sui-core/src/unit_tests/gateway_state_tests.rs +++ b/crates/sui-core/src/unit_tests/gateway_state_tests.rs @@ -24,12 +24,14 @@ use crate::gateway_state::{GatewayAPI, GatewayState}; use super::*; -async fn create_gateway_state(genesis_objects: Vec) -> GatewayState { +async fn create_gateway_state_with_object_basics_ref( + genesis_objects: Vec, +) -> (GatewayState, ObjectRef) { let all_owners: HashSet<_> = genesis_objects .iter() .map(|o| o.get_single_owner().unwrap()) .collect(); - let (authorities, _) = init_local_authorities(4, genesis_objects).await; + let (authorities, _, pkg_ref) = init_local_authorities(4, genesis_objects).await; let path = tempfile::tempdir().unwrap().into_path(); let gateway_store = Arc::new(GatewayStore::open(&path, None)); let gateway = GatewayState::new_with_authorities( @@ -41,7 +43,13 @@ async fn create_gateway_state(genesis_objects: Vec) -> GatewayState) -> GatewayState { + create_gateway_state_with_object_basics_ref(genesis_objects) + .await + .0 } async fn public_transfer_object( @@ -104,15 +112,14 @@ async fn test_move_call() { let (addr1, key1): (_, AccountKeyPair) = get_key_pair(); let gas_object = Object::with_owner_for_testing(addr1); let genesis_objects = vec![gas_object.clone()]; - let gateway = create_gateway_state(genesis_objects).await; + let (gateway, pkg_ref) = create_gateway_state_with_object_basics_ref(genesis_objects).await; - let framework_obj_ref = gateway.get_framework_object_ref().await.unwrap(); let tx = crate_object_move_transaction( addr1, &key1, addr1, 100, - framework_obj_ref, + pkg_ref, gas_object.compute_object_reference(), ); @@ -697,13 +704,6 @@ async fn test_batch_transaction() { object_id: coin_object2.id(), recipient: addr2, }), - RPCTransactionRequestParams::MoveCallRequestParams(MoveCallParams { - package_object_id: gateway.get_framework_object_ref().await.unwrap().0, - module: "bag".to_string(), - function: "create".to_string(), - type_arguments: vec![], - arguments: vec![], - }), ]; // Gateway should be able to figure out the only usable gas object. let data = gateway @@ -716,6 +716,6 @@ async fn test_batch_transaction() { .await .unwrap() .effects; - assert_eq!(effects.created.len(), 1); + assert!(effects.created.is_empty()); assert_eq!(effects.mutated.len(), 3); } diff --git a/crates/sui-cost/tests/data/dummy_modules_publish/sources/trusted_coin.move b/crates/sui-cost/tests/data/dummy_modules_publish/sources/trusted_coin.move index d1eca5b353640..62b490a94f9ed 100644 --- a/crates/sui-cost/tests/data/dummy_modules_publish/sources/trusted_coin.move +++ b/crates/sui-cost/tests/data/dummy_modules_publish/sources/trusted_coin.move @@ -22,6 +22,6 @@ module examples::trusted_coin { public entry fun mint(treasury_cap: &mut TreasuryCap, amount: u64, ctx: &mut TxContext) { let coin = coin::mint(treasury_cap, amount, ctx); - coin::transfer(coin, tx_context::sender(ctx)); + transfer::transfer(coin, tx_context::sender(ctx)); } } diff --git a/crates/sui-cost/tests/snapshots/snapshot_tests__good_snapshot.snap b/crates/sui-cost/tests/snapshots/snapshot_tests__good_snapshot.snap index 1554da156275d..0a646d7199a9c 100644 --- a/crates/sui-cost/tests/snapshots/snapshot_tests__good_snapshot.snap +++ b/crates/sui-cost/tests/snapshots/snapshot_tests__good_snapshot.snap @@ -3,27 +3,27 @@ source: crates/sui-cost/tests/snapshot_tests.rs expression: common_costs --- Publish: - computationCost: 566 - storageCost: 84 + computationCost: 519 + storageCost: 83 storageRebate: 16 MergeCoin: - computationCost: 506 + computationCost: 461 storageCost: 32 storageRebate: 0 ? SplitCoin: 0 -: computationCost: 489 +: computationCost: 444 storageCost: 32 storageRebate: 0 ? SplitCoin: 1 -: computationCost: 532 +: computationCost: 486 storageCost: 48 storageRebate: 0 ? SplitCoin: 2 -: computationCost: 574 +: computationCost: 529 storageCost: 64 storageRebate: 0 ? SplitCoin: 3 -: computationCost: 617 +: computationCost: 571 storageCost: 80 storageRebate: 0 TransferWholeCoin: @@ -43,15 +43,15 @@ TransferPortionSuiCoin: storageCost: 48 storageRebate: 0 SharedCounterCreate: - computationCost: 99 + computationCost: 109 storageCost: 31 storageRebate: 0 SharedCounterAssertValue: - computationCost: 188 + computationCost: 198 storageCost: 31 storageRebate: 15 SharedCounterIncrement: - computationCost: 188 + computationCost: 197 storageCost: 31 storageRebate: 15 diff --git a/crates/sui-framework/sources/coin.move b/crates/sui-framework/sources/coin.move index 5ed9823b95b49..3eeedd496c0e1 100644 --- a/crates/sui-framework/sources/coin.move +++ b/crates/sui-framework/sources/coin.move @@ -101,14 +101,9 @@ module sui::coin { // === Functionality for Coin holders === - /// Send `c` to `recipient` - public entry fun transfer(c: Coin, recipient: address) { - transfer::transfer(c, recipient) - } - /// Transfer `c` to the sender of the current transaction public fun keep(c: Coin, ctx: &TxContext) { - transfer(c, tx_context::sender(ctx)) + transfer::transfer(c, tx_context::sender(ctx)) } /// Consume the coin `c` and add its value to `self`. @@ -194,11 +189,6 @@ module sui::coin { balance::decrease_supply(&mut cap.total_supply, balance) } - /// Give away the treasury cap to `recipient` - public fun transfer_cap(c: TreasuryCap, recipient: address) { - transfer::transfer(c, recipient) - } - // === Entrypoints === /// Mint `amount` of `Coin` and send it to `recipient`. Invokes `mint()`. diff --git a/crates/sui-framework/sources/devnet_nft.move b/crates/sui-framework/sources/devnet_nft.move index db70d06e0a445..90a74e6a664cd 100644 --- a/crates/sui-framework/sources/devnet_nft.move +++ b/crates/sui-framework/sources/devnet_nft.move @@ -56,13 +56,6 @@ module sui::devnet_nft { transfer::transfer(nft, sender); } - /// Transfer `nft` to `recipient` - public entry fun transfer( - nft: DevNetNFT, recipient: address, _: &mut TxContext - ) { - transfer::transfer(nft, recipient) - } - /// Update the `description` of `nft` to `new_description` public entry fun update_description( nft: &mut DevNetNFT, @@ -98,6 +91,7 @@ module sui::devnet_nft { module sui::devnet_nftTests { use sui::devnet_nft::{Self, DevNetNFT}; use sui::test_scenario; + use sui::transfer; use sui::utf8; #[test] @@ -113,7 +107,7 @@ module sui::devnet_nftTests { test_scenario::next_tx(&mut scenario, &addr1); { let nft = test_scenario::take_owned(&mut scenario); - devnet_nft::transfer(nft, addr2, test_scenario::ctx(&mut scenario)); + transfer::transfer(nft, addr2); }; // update its description test_scenario::next_tx(&mut scenario, &addr2); diff --git a/crates/sui-framework/sources/governance/delegation.move b/crates/sui-framework/sources/governance/delegation.move index cac4ffafa8498..66d98917ffe8a 100644 --- a/crates/sui-framework/sources/governance/delegation.move +++ b/crates/sui-framework/sources/governance/delegation.move @@ -148,7 +148,7 @@ module sui::delegation { ctx: &mut TxContext, ) { let sender = tx_context::sender(ctx); - coin::transfer(coin::from_balance(reward, ctx), sender); + transfer::transfer(coin::from_balance(reward, ctx), sender); self.next_reward_unclaimed_epoch = self.next_reward_unclaimed_epoch + 1; } @@ -174,10 +174,6 @@ module sui::delegation { assert!(next_reward_unclaimed_epoch == ending_epoch, 0); } - public entry fun transfer(self: Delegation, recipient: address) { - transfer::transfer(self, recipient) - } - /// Checks whether the delegation object is eligible to claim the reward /// given the epoch to claim and the validator address. public fun can_claim_reward( diff --git a/crates/sui-framework/sources/sui.move b/crates/sui-framework/sources/sui.move index 4472f1c3bf675..ac8e56ac5188a 100644 --- a/crates/sui-framework/sources/sui.move +++ b/crates/sui-framework/sources/sui.move @@ -3,8 +3,9 @@ /// Coin is the token used to pay for gas in Sui module sui::sui { - use sui::coin; use sui::balance::{Self, Supply}; + use sui::coin; + use sui::transfer; friend sui::genesis; @@ -17,8 +18,7 @@ module sui::sui { balance::create_supply(SUI {}) } - /// Transfer to a recipient public entry fun transfer(c: coin::Coin, recipient: address) { - coin::transfer(c, recipient) + transfer::transfer(c, recipient) } } diff --git a/crates/sui-gateway/src/unit_tests/rpc_server_tests.rs b/crates/sui-gateway/src/unit_tests/rpc_server_tests.rs index 32007dba5484c..0045395b31473 100644 --- a/crates/sui-gateway/src/unit_tests/rpc_server_tests.rs +++ b/crates/sui-gateway/src/unit_tests/rpc_server_tests.rs @@ -12,12 +12,12 @@ use sui_json_rpc::api::{ }; use sui_json_rpc_types::{GetObjectDataResponse, SuiTransactionResponse, TransactionBytes}; use sui_sdk::crypto::KeystoreType; +use sui_types::base_types::ObjectID; +use sui_types::base_types::TransactionDigest; +use sui_types::gas_coin::GAS; use sui_types::messages::Transaction; use sui_types::sui_serde::Base64; -use sui_types::{ - base_types::{ObjectID, TransactionDigest}, - SUI_FRAMEWORK_ADDRESS, -}; +use sui_types::SUI_FRAMEWORK_ADDRESS; use test_utils::network::start_rpc_test_network; @@ -113,14 +113,16 @@ async fn test_move_call() -> Result<(), anyhow::Error> { http_client.sync_account_state(*address).await?; let objects = http_client.get_objects_owned_by_address(*address).await?; let gas = objects.first().unwrap(); + let coin = &objects[1]; + // now do the call let package_id = ObjectID::new(SUI_FRAMEWORK_ADDRESS.into_bytes()); - let module = "object_basics".to_string(); - let function = "create".to_string(); + let module = "coin".to_string(); + let function = "split".to_string(); let json_args = vec![ - SuiJsonValue::from_str("10000")?, - SuiJsonValue::from_str(&format!("{:#x}", address))?, + SuiJsonValue::from_object_id(coin.object_id), + SuiJsonValue::from_str("10")?, ]; let transaction_bytes: TransactionBytes = http_client @@ -129,7 +131,7 @@ async fn test_move_call() -> Result<(), anyhow::Error> { package_id, module, function, - vec![], + vec![GAS::type_tag().into()], json_args, Some(gas.object_id), 1000, diff --git a/crates/sui-json/src/lib.rs b/crates/sui-json/src/lib.rs index 6479540088766..cc5419389cca8 100644 --- a/crates/sui-json/src/lib.rs +++ b/crates/sui-json/src/lib.rs @@ -57,6 +57,10 @@ impl SuiJsonValue { Ok(Self(json_value)) } + pub fn from_object_id(id: ObjectID) -> SuiJsonValue { + Self(JsonValue::String(id.to_hex_literal())) + } + pub fn to_bcs_bytes(&self, ty: &MoveTypeLayout) -> Result, anyhow::Error> { let move_value = Self::to_move_value(&self.0, ty)?; MoveValue::simple_serialize(&move_value) diff --git a/crates/sui-json/src/tests.rs b/crates/sui-json/src/tests.rs index 6b95467b73e89..731f290ccc58a 100644 --- a/crates/sui-json/src/tests.rs +++ b/crates/sui-json/src/tests.rs @@ -12,7 +12,6 @@ use test_fuzz::runtime::num_traits::ToPrimitive; use sui_types::base_types::{ObjectID, SuiAddress, TransactionDigest}; use sui_types::object::Object; -use sui_types::SUI_FRAMEWORK_ADDRESS; use super::{is_homogeneous, HEX_PREFIX}; use super::{resolve_move_function_args, SuiJsonCallArg, SuiJsonValue}; @@ -397,14 +396,13 @@ fn test_basic_args_linter_top_level() { assert!(resolve_move_function_args(example_package, module, function, args).is_err()); // Test with vecu8 as address - let genesis_objs = sui_adapter::genesis::clone_genesis_packages(); - let framework_pkg = genesis_objs - .iter() - .find(|q| q.id() == ObjectID::from(SUI_FRAMEWORK_ADDRESS)) - .expect("Unable to find framework object") - .data - .try_as_package() - .unwrap(); + let path = + Path::new(env!("CARGO_MANIFEST_DIR")).join("../../sui_programmability/examples/basics"); + let compiled_modules = + sui_framework::build_and_verify_package(&path, move_package::BuildConfig::default()) + .unwrap(); + let example_package = Object::new_package(compiled_modules, TransactionDigest::genesis()); + let framework_pkg = example_package.data.try_as_package().unwrap(); let module = Identifier::new("object_basics").unwrap(); let function = Identifier::new("create").unwrap(); diff --git a/crates/sui/src/unit_tests/cli_tests.rs b/crates/sui/src/unit_tests/cli_tests.rs index 964b67a7b0ce1..3847ea3bbff27 100644 --- a/crates/sui/src/unit_tests/cli_tests.rs +++ b/crates/sui/src/unit_tests/cli_tests.rs @@ -25,7 +25,7 @@ use sui_sdk::crypto::KeystoreType; use sui_sdk::ClientType; use sui_types::crypto::{AuthorityKeyPair, KeypairTraits, SuiKeyPair}; use sui_types::{base_types::ObjectID, crypto::get_key_pair, gas_coin::GasCoin}; -use sui_types::{sui_framework_address_concat_string, SUI_FRAMEWORK_OBJECT_ID}; +use sui_types::{sui_framework_address_concat_string, SUI_FRAMEWORK_ADDRESS}; use test_utils::network::{setup_network_and_wallet, start_test_network}; @@ -316,6 +316,31 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { let (_network, mut context, address1) = setup_network_and_wallet().await?; let address2 = context.keystore.addresses().get(1).cloned().unwrap(); + // publish the object basics package + let object_refs = context + .gateway + .read_api() + .get_objects_owned_by_address(address1) + .await?; + let gas_obj_id = object_refs.first().unwrap().object_id; + let mut package_path = PathBuf::from(TEST_DATA_DIR); + package_path.push("move_call_args_linter"); + let build_config = BuildConfig::default(); + let resp = SuiClientCommands::Publish { + package_path, + build_config, + gas: Some(gas_obj_id), + gas_budget: 1000, + } + .execute(&mut context) + .await?; + let package = if let SuiClientCommandResult::Publish(response) = resp { + let publish_resp = response.parsed_data.unwrap().to_publish_response().unwrap(); + publish_resp.package.object_id + } else { + unreachable!("Invalid response"); + }; + // Sync client to retrieve objects from the network. SuiClientCommands::SyncClientState { address: Some(address2), @@ -354,7 +379,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { // Test case with no gas specified let resp = SuiClientCommands::Call { - package: SUI_FRAMEWORK_OBJECT_ID, + package, module: "object_basics".to_string(), function: "create".to_string(), type_args: vec![], @@ -394,7 +419,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { } let resp = SuiClientCommands::Call { - package: SUI_FRAMEWORK_OBJECT_ID, + package, module: "object_basics".to_string(), function: "create".to_string(), type_args: vec![], @@ -418,7 +443,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { ]; let resp = SuiClientCommands::Call { - package: SUI_FRAMEWORK_OBJECT_ID, + package, module: "object_basics".to_string(), function: "transfer".to_string(), type_args: vec![], @@ -432,8 +457,9 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { assert!(resp.is_err()); let err_string = format!("{} ", resp.err().unwrap()); - let framework_addr = sui_framework_address_concat_string(""); - assert!(err_string.contains(&format!("Expected argument of type {framework_addr}::object_basics::Object, but found type {framework_addr}::coin::Coin<{framework_addr}::sui::SUI>"))); + let framework_addr = SUI_FRAMEWORK_ADDRESS.to_hex_literal(); + let package_addr = package.to_hex_literal(); + assert!(err_string.contains(&format!("Expected argument of type {package_addr}::object_basics::Object, but found type {framework_addr}::coin::Coin<{framework_addr}::sui::SUI>"))); // Try a proper transfer let args = vec![ @@ -442,7 +468,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { ]; SuiClientCommands::Call { - package: SUI_FRAMEWORK_OBJECT_ID, + package, module: "object_basics".to_string(), function: "transfer".to_string(), type_args: vec![], diff --git a/crates/sui/src/unit_tests/data/dummy_modules_publish/sources/trusted_coin.move b/crates/sui/src/unit_tests/data/dummy_modules_publish/sources/trusted_coin.move index 637127919778b..7bcd6fccd592b 100644 --- a/crates/sui/src/unit_tests/data/dummy_modules_publish/sources/trusted_coin.move +++ b/crates/sui/src/unit_tests/data/dummy_modules_publish/sources/trusted_coin.move @@ -22,11 +22,11 @@ module examples::trusted_coin { public entry fun mint(treasury_cap: &mut TreasuryCap, amount: u64, ctx: &mut TxContext) { let coin = coin::mint(treasury_cap, amount, ctx); - coin::transfer(coin, tx_context::sender(ctx)); + transfer::transfer(coin, tx_context::sender(ctx)); } public entry fun transfer(treasury_cap: TreasuryCap, recipient: address) { - coin::transfer_cap(treasury_cap, recipient); + transfer::transfer(treasury_cap, recipient); } #[test_only] diff --git a/crates/sui/src/unit_tests/data/move_call_args_linter/Move.toml b/crates/sui/src/unit_tests/data/move_call_args_linter/Move.toml new file mode 100644 index 0000000000000..e6b34720bf6d4 --- /dev/null +++ b/crates/sui/src/unit_tests/data/move_call_args_linter/Move.toml @@ -0,0 +1,9 @@ +[package] +name = "Examples" +version = "0.0.1" + +[dependencies] +Sui = { local = "../../../../../sui-framework" } + +[addresses] +examples = "0x0" diff --git a/crates/sui/src/unit_tests/data/move_call_args_linter/sources/object_basics.move b/crates/sui/src/unit_tests/data/move_call_args_linter/sources/object_basics.move new file mode 100644 index 0000000000000..aa09eb547486a --- /dev/null +++ b/crates/sui/src/unit_tests/data/move_call_args_linter/sources/object_basics.move @@ -0,0 +1,65 @@ +// Copyright (c) 2022, Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +/// Test CTURD object basics (create, transfer, update, read, delete) +module examples::object_basics { + use sui::event; + use sui::object::{Self, UID}; + use sui::tx_context::{Self, TxContext}; + use sui::transfer; + + struct Object has key, store { + id: UID, + value: u64, + } + + struct Wrapper has key { + id: UID, + o: Object + } + + struct NewValueEvent has copy, drop { + new_value: u64 + } + + public entry fun create(value: u64, recipient: address, ctx: &mut TxContext) { + transfer::transfer( + Object { id: object::new(ctx), value }, + recipient + ) + } + + public entry fun transfer(o: Object, recipient: address) { + transfer::transfer(o, recipient) + } + + public entry fun freeze_object(o: Object) { + transfer::freeze_object(o) + } + + public entry fun set_value(o: &mut Object, value: u64) { + o.value = value; + } + + // test that reading o2 and updating o1 works + public entry fun update(o1: &mut Object, o2: &Object) { + o1.value = o2.value; + // emit an event so the world can see the new value + event::emit(NewValueEvent { new_value: o2.value }) + } + + public entry fun delete(o: Object) { + let Object { id, value: _ } = o; + object::delete(id); + } + + public entry fun wrap(o: Object, ctx: &mut TxContext) { + transfer::transfer(Wrapper { id: object::new(ctx), o }, tx_context::sender(ctx)) + } + + public entry fun unwrap(w: Wrapper, ctx: &mut TxContext) { + let Wrapper { id, o } = w; + object::delete(id); + transfer::transfer(o, tx_context::sender(ctx)) + } +} diff --git a/crates/test-utils/src/messages.rs b/crates/test-utils/src/messages.rs index 8c2ad6dec20cf..c54c17dc0ec87 100644 --- a/crates/test-utils/src/messages.rs +++ b/crates/test-utils/src/messages.rs @@ -164,23 +164,6 @@ pub fn make_transactions_with_pre_genesis_objects( /// Make a few different test transaction containing the same shared object. pub fn test_shared_object_transactions() -> Vec { - // Helper function to load genesis packages. - fn get_genesis_package_by_module(genesis_objects: &[Object], module: &str) -> ObjectRef { - genesis_objects - .iter() - .find_map(|o| match o.data.try_as_package() { - Some(p) => { - if p.serialized_module_map().keys().any(|name| name == module) { - Some(o.compute_object_reference()) - } else { - None - } - } - None => None, - }) - .unwrap() - } - // The key pair of the sender of the transaction. let (sender, keypair) = test_account_keys().pop().unwrap(); @@ -190,8 +173,7 @@ pub fn test_shared_object_transactions() -> Vec { for gas_object in test_gas_objects() { let module = "object_basics"; let function = "create"; - let genesis_package_objects = genesis::clone_genesis_packages(); - let package_object_ref = get_genesis_package_by_module(&genesis_package_objects, module); + let package_object_ref = genesis::get_framework_object_ref(); let data = TransactionData::new_move_call( sender, diff --git a/doc/src/build/programming-with-objects/ch2-using-objects.md b/doc/src/build/programming-with-objects/ch2-using-objects.md index 0ec46dfe2f7c6..21710075714fc 100644 --- a/doc/src/build/programming-with-objects/ch2-using-objects.md +++ b/doc/src/build/programming-with-objects/ch2-using-objects.md @@ -145,7 +145,7 @@ test_scenario::next_tx(scenario, &owner); { let object = test_scenario::take_owned(scenario); let ctx = test_scenario::ctx(scenario); - color_object::transfer(object, recipient, ctx); + transfer::transfer(object, recipient, ctx); }; ``` Note that in the second transaction, the sender of the transaction should still be `owner`, because only the `owner` can transfer the object that it owns. After the tranfser, we can verify that `owner` no longer owns the object, while `recipient` now owns it: diff --git a/doc/src/contribute/cli-client.md b/doc/src/contribute/cli-client.md index 07ed574ca532f..0b1c3d0607edd 100644 --- a/doc/src/contribute/cli-client.md +++ b/doc/src/contribute/cli-client.md @@ -236,7 +236,7 @@ terminal window than one used to execute `sui start`). Assuming you accepted the default location for configuration: ```shell -$ sui console +$ sui console ``` This command will look for the client configuration file @@ -337,15 +337,15 @@ When not specified, the active address is used. ```shell $ sui client objects - Object ID | Version | Digest | Owner Type | Object Type + Object ID | Version | Digest | Owner Type | Object Type --------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 0 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 0 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> ``` ```shell $ sui client objects --address 0x913cf36f370613ed131868ac6f9da2420166062e - Object ID | Version | Digest | Owner Type | Object Type + Object ID | Version | Digest | Owner Type | Object Type --------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 0 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 0 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> ``` All commands where `address` is omitted will now use the newly specified active address: @@ -434,7 +434,7 @@ You can use the `objects` command to view the objects owned by the address. `objects` command usage: ```shell -sui-client-objects +sui-client-objects Obtain all objects owned by the address USAGE: @@ -455,13 +455,13 @@ $ sui client objects --address 0x66af3898e7558b79e115ab61184a958497d1905a The result should resemble the following. ```shell - Object ID | Version | Digest | Owner Type | Object Type + Object ID | Version | Digest | Owner Type | Object Type --------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 0 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xc8add7b4073900ffb0a8b4fe7d70a7db454c2e19 | 0 | uCZNPmDWOksKhCKwEaMtST5T4HbTjcgXGHRXP4qTLC8= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xd1949864f94d87cf25e1fd7b1c8ab4bf685f7801 | 0 | OsTryyECAPW9mnSbWlYWELX+QlRg5er7s/DlkgqhDww= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xddb6119c320f52f3fef9fbc272af305d985b6883 | 0 | gBCDdel7iJZnXpuf4g9dqIPT4XjaAY/4knNcDxbTons= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xe1fe79ac8d900342e617e0986f54ff64e4e323de | 0 | qjsWIzAaomo0eqFwQt99EkARsiC/aw2hPDH8quM6pYg= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 0 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xc8add7b4073900ffb0a8b4fe7d70a7db454c2e19 | 0 | uCZNPmDWOksKhCKwEaMtST5T4HbTjcgXGHRXP4qTLC8= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xd1949864f94d87cf25e1fd7b1c8ab4bf685f7801 | 0 | OsTryyECAPW9mnSbWlYWELX+QlRg5er7s/DlkgqhDww= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xddb6119c320f52f3fef9fbc272af305d985b6883 | 0 | gBCDdel7iJZnXpuf4g9dqIPT4XjaAY/4knNcDxbTons= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xe1fe79ac8d900342e617e0986f54ff64e4e323de | 0 | qjsWIzAaomo0eqFwQt99EkARsiC/aw2hPDH8quM6pYg= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> Showing 5 results. ``` @@ -470,7 +470,7 @@ If you want to view more information about the objects, you can use the `object` Usage of `object` command : ```shell -sui-client-object +sui-client-object Get object info USAGE: @@ -558,7 +558,7 @@ We will explore how to transfer coins using the Sui CLI client in this section. `transfer-coin` command usage: ```shell -sui-client-transfer-coin +sui-client-transfer-coin Transfer coin object USAGE: @@ -622,9 +622,9 @@ The account will now have one object: ```shell $ sui client objects --address 0xc72cf3adcc4d11c03079cef2c8992aea5268677a - Object ID | Version | Digest | Owner Type | Object Type + Object ID | Version | Digest | Owner Type | Object Type --------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 1 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 1 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> ``` ## Creating example NFTs @@ -659,7 +659,7 @@ The command will invoke the `mint` function in the `devnet_nft` module, which mi `create-example-nft` command usage: ```shell -sui-client-create-example-nft +sui-client-create-example-nft Create an example NFT USAGE: @@ -692,7 +692,7 @@ We can use the `merge-coin` command and `split-coin` command to consolidate or s Usage of `merge-coin`: ```shell -sui-client-merge-coin +sui-client-merge-coin Merge two coin objects into one coin USAGE: @@ -732,13 +732,13 @@ $ sui client objects --address 0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75 And its output: ``` - Object ID | Version | Digest | Owner Type | Object Type + Object ID | Version | Digest | Owner Type | Object Type --------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 0x1e90389f5d70d7fa6ce973155460e1c04deae194 | 0 | BC5O8Bf6Uw8S1LV1y4RCI6+kz1KhZG/aOpeqq9kTAvs= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x351f08f03709cebea85dcd20e24b00fbc1851c92 | 0 | 9aYvavAzY6chYbOUtMtJj0g/5GNc+KBsqptCX5pmQ2Y= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x3c720502f9eabb17a52a999859fbbaeb408b1d14 | 0 | WUPT6P40veMZ/C7GiQpv92I4EH+hvh5BbkBt+7p9yH0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x7438af4677b9cea2094848f611143346183c11d1 | 0 | 55B56RG/kCeHrN6GXdIq0IvnyYD/hng9J7I7FNRykQ4= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x9d5f2b2564ad2255c24a03556785bddc85381508 | 0 | rmyYjq/UEED0xR0hE3Da8OYgBAu3MYxKQ3v76pGTDek= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x1e90389f5d70d7fa6ce973155460e1c04deae194 | 0 | BC5O8Bf6Uw8S1LV1y4RCI6+kz1KhZG/aOpeqq9kTAvs= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x351f08f03709cebea85dcd20e24b00fbc1851c92 | 0 | 9aYvavAzY6chYbOUtMtJj0g/5GNc+KBsqptCX5pmQ2Y= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x3c720502f9eabb17a52a999859fbbaeb408b1d14 | 0 | WUPT6P40veMZ/C7GiQpv92I4EH+hvh5BbkBt+7p9yH0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x7438af4677b9cea2094848f611143346183c11d1 | 0 | 55B56RG/kCeHrN6GXdIq0IvnyYD/hng9J7I7FNRykQ4= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x9d5f2b2564ad2255c24a03556785bddc85381508 | 0 | rmyYjq/UEED0xR0hE3Da8OYgBAu3MYxKQ3v76pGTDek= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> Showing 5 results. ``` @@ -770,7 +770,7 @@ Updated Gas : Coin { id: 0x3c720502f9eabb17a52a999859fbbaeb408b1d14, value: 9944 Usage of `split-coin`: ```shell -sui-client-split-coin +sui-client-split-coin Split a coin object into multiple coins USAGE: @@ -799,13 +799,13 @@ $ sui client objects --address 0x08da15bee6a3f5b01edbbd402654a75421d81397 With output resembling: ```shell - Object ID | Version | Digest | Owner Type | Object Type + Object ID | Version | Digest | Owner Type | Object Type --------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 0x4a2853304fd2c243dae7d1ba58260bb7c40724e1 | 0 | uNcjv6KP8AXgQHTFmiEPV3tpWZcYHb1HmBR0B2pMsAo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x692c179dc434ceb0eaa51cdd198bb905b5ab27c4 | 0 | /ug6IGGld90PqnmL9qijciCqn25V11nn5/PAsKjxMY0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x7f7b7c1589aceb073a7c8740b1d47d05e4d89e3c | 0 | N5+qKRenKWqb7Y6WKZuFD+fRDB6pj/OtIyri+FSQ3Q0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xe42558e82e315c9c81ee5b9f1ac3db819ece5c1d | 0 | toHeih0DeFrqxQhGzVUi9EkVwAZSbLx6hv2gpMgNBbs= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xfa322fee6a7f4c266ad4840e85bf3d87689b6de0 | 0 | DxjnkJTSl0o6HlzeOX5K/If61bbFwvRDydjzd2bq8ho= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x4a2853304fd2c243dae7d1ba58260bb7c40724e1 | 0 | uNcjv6KP8AXgQHTFmiEPV3tpWZcYHb1HmBR0B2pMsAo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x692c179dc434ceb0eaa51cdd198bb905b5ab27c4 | 0 | /ug6IGGld90PqnmL9qijciCqn25V11nn5/PAsKjxMY0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x7f7b7c1589aceb073a7c8740b1d47d05e4d89e3c | 0 | N5+qKRenKWqb7Y6WKZuFD+fRDB6pj/OtIyri+FSQ3Q0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xe42558e82e315c9c81ee5b9f1ac3db819ece5c1d | 0 | toHeih0DeFrqxQhGzVUi9EkVwAZSbLx6hv2gpMgNBbs= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xfa322fee6a7f4c266ad4840e85bf3d87689b6de0 | 0 | DxjnkJTSl0o6HlzeOX5K/If61bbFwvRDydjzd2bq8ho= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> Showing 5 results. ``` @@ -840,16 +840,16 @@ Updated Gas : Coin { id: 0x692c179dc434ceb0eaa51cdd198bb905b5ab27c4, value: 9938 ``` $ sui client objects --address 0x08da15bee6a3f5b01edbbd402654a75421d81397 - Object ID | Version | Digest | Owner Type | Object Type + Object ID | Version | Digest | Owner Type | Object Type --------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 0x1da8193ac29f94f8207b0222bd5941b7814c1668 | 1 | nAMEV3NZ0zscjO10QQUt1drLvhNXTk4MVLAg1FXTQxw= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x3653bae7851c36e0e5e827b7c1a2978ef78efd7e | 1 | blMuVATrI89PRvqA4Kuv6rNkbuAb+bYhmkMocY7pavw= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x4a2853304fd2c243dae7d1ba58260bb7c40724e1 | 1 | uhfauig0guMidpxFyCO6FzhzDfucss+eA6xWzAVF3sU= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x692c179dc434ceb0eaa51cdd198bb905b5ab27c4 | 1 | sWTy2PUbt3UFEKx1Km32dEG7cQscSK+eVc3ChaZCkkA= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x7f7b7c1589aceb073a7c8740b1d47d05e4d89e3c | 0 | N5+qKRenKWqb7Y6WKZuFD+fRDB6pj/OtIyri+FSQ3Q0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xd5b694f67410d5b6cd293128cd48953aaa0a3dce | 1 | 4V0BC6eopxkN6wIOdm2FVgwN3psNbPvLKQ9/zrYtsDM= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xe42558e82e315c9c81ee5b9f1ac3db819ece5c1d | 0 | toHeih0DeFrqxQhGzVUi9EkVwAZSbLx6hv2gpMgNBbs= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xfa322fee6a7f4c266ad4840e85bf3d87689b6de0 | 0 | DxjnkJTSl0o6HlzeOX5K/If61bbFwvRDydjzd2bq8ho= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x1da8193ac29f94f8207b0222bd5941b7814c1668 | 1 | nAMEV3NZ0zscjO10QQUt1drLvhNXTk4MVLAg1FXTQxw= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x3653bae7851c36e0e5e827b7c1a2978ef78efd7e | 1 | blMuVATrI89PRvqA4Kuv6rNkbuAb+bYhmkMocY7pavw= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x4a2853304fd2c243dae7d1ba58260bb7c40724e1 | 1 | uhfauig0guMidpxFyCO6FzhzDfucss+eA6xWzAVF3sU= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x692c179dc434ceb0eaa51cdd198bb905b5ab27c4 | 1 | sWTy2PUbt3UFEKx1Km32dEG7cQscSK+eVc3ChaZCkkA= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x7f7b7c1589aceb073a7c8740b1d47d05e4d89e3c | 0 | N5+qKRenKWqb7Y6WKZuFD+fRDB6pj/OtIyri+FSQ3Q0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xd5b694f67410d5b6cd293128cd48953aaa0a3dce | 1 | 4V0BC6eopxkN6wIOdm2FVgwN3psNbPvLKQ9/zrYtsDM= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xe42558e82e315c9c81ee5b9f1ac3db819ece5c1d | 0 | toHeih0DeFrqxQhGzVUi9EkVwAZSbLx6hv2gpMgNBbs= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xfa322fee6a7f4c266ad4840e85bf3d87689b6de0 | 0 | DxjnkJTSl0o6HlzeOX5K/If61bbFwvRDydjzd2bq8ho= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> Showing 8 results. ``` @@ -865,7 +865,7 @@ following function we will be calling in this tutorial: ```rust public entry fun transfer(c: coin::Coin, recipient: address) { - coin::transfer(c, Address::new(recipient)) + transfer::transfer(c, Address::new(recipient)) } ``` @@ -878,13 +878,13 @@ Let us examine objects owned by address `0x48ff0a932b12976caec91d521265b009ad5b2 ```shell $ sui client objects --address 0x48ff0a932b12976caec91d521265b009ad5b2225 - Object ID | Version | Digest | Owner Type | Object Type + Object ID | Version | Digest | Owner Type | Object Type --------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 0x471c8e241d0473c34753461529b70f9c4ed3151b | 0 | MCQIALghS9kQUWMclChmsd6jCuLiUxNjEn9VRV+AhSA= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x53b50e3020a01e1fd6acf832a871feee240183f0 | 0 | VIbuA4fcsitOUmJLQ+FugZWIn7bg6LnVO8eTIAUDzkg= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x5c846224b8704683a1c576aec7c8d9c3413d87c1 | 0 | KO0Fr9uCPnT3KxOEishyzas33le4J9fAGg7iEOOzo7A= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x6fe4cf8d2c21f23f2aacf60f30c98ff9e2c78226 | 0 | p2evKbTirwEoF1PxGIu5USAsSdkxzh1sUD/OxBfpdNE= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xa28dd252ab5b984a8c1da699bbe10e7f09947a12 | 0 | 6VT+8479aijA8tYmab7YatVgjXm1TWy5jItooC416YQ= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x471c8e241d0473c34753461529b70f9c4ed3151b | 0 | MCQIALghS9kQUWMclChmsd6jCuLiUxNjEn9VRV+AhSA= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x53b50e3020a01e1fd6acf832a871feee240183f0 | 0 | VIbuA4fcsitOUmJLQ+FugZWIn7bg6LnVO8eTIAUDzkg= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x5c846224b8704683a1c576aec7c8d9c3413d87c1 | 0 | KO0Fr9uCPnT3KxOEishyzas33le4J9fAGg7iEOOzo7A= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x6fe4cf8d2c21f23f2aacf60f30c98ff9e2c78226 | 0 | p2evKbTirwEoF1PxGIu5USAsSdkxzh1sUD/OxBfpdNE= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xa28dd252ab5b984a8c1da699bbe10e7f09947a12 | 0 | 6VT+8479aijA8tYmab7YatVgjXm1TWy5jItooC416YQ= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> Showing 5 results. ``` @@ -959,12 +959,12 @@ the sender: ```shell $ sui client objects --address 0x48ff0a932b12976caec91d521265b009ad5b2225 - Object ID | Version | Digest | Owner Type | Object Type + Object ID | Version | Digest | Owner Type | Object Type --------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 0x53b50e3020a01e1fd6acf832a871feee240183f0 | 1 | st6KVE+nTPsQgtEtxSbgJZCzSSuSB2ZsJAMbXFNLw/k= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x5c846224b8704683a1c576aec7c8d9c3413d87c1 | 0 | KO0Fr9uCPnT3KxOEishyzas33le4J9fAGg7iEOOzo7A= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x6fe4cf8d2c21f23f2aacf60f30c98ff9e2c78226 | 0 | p2evKbTirwEoF1PxGIu5USAsSdkxzh1sUD/OxBfpdNE= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xa28dd252ab5b984a8c1da699bbe10e7f09947a12 | 0 | 6VT+8479aijA8tYmab7YatVgjXm1TWy5jItooC416YQ= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x53b50e3020a01e1fd6acf832a871feee240183f0 | 1 | st6KVE+nTPsQgtEtxSbgJZCzSSuSB2ZsJAMbXFNLw/k= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x5c846224b8704683a1c576aec7c8d9c3413d87c1 | 0 | KO0Fr9uCPnT3KxOEishyzas33le4J9fAGg7iEOOzo7A= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x6fe4cf8d2c21f23f2aacf60f30c98ff9e2c78226 | 0 | p2evKbTirwEoF1PxGIu5USAsSdkxzh1sUD/OxBfpdNE= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xa28dd252ab5b984a8c1da699bbe10e7f09947a12 | 0 | 6VT+8479aijA8tYmab7YatVgjXm1TWy5jItooC416YQ= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> Showing 4 results. ``` @@ -1019,12 +1019,12 @@ $ sui client objects --address 0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75 Outputting: ``` - Object ID | Version | Digest | Owner Type | Object Type + Object ID | Version | Digest | Owner Type | Object Type --------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 0x53b50e3020a01e1fd6acf832a871feee240183f0 | 1 | st6KVE+nTPsQgtEtxSbgJZCzSSuSB2ZsJAMbXFNLw/k= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x5c846224b8704683a1c576aec7c8d9c3413d87c1 | 0 | KO0Fr9uCPnT3KxOEishyzas33le4J9fAGg7iEOOzo7A= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0x6fe4cf8d2c21f23f2aacf60f30c98ff9e2c78226 | 0 | p2evKbTirwEoF1PxGIu5USAsSdkxzh1sUD/OxBfpdNE= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> - 0xa28dd252ab5b984a8c1da699bbe10e7f09947a12 | 0 | 6VT+8479aijA8tYmab7YatVgjXm1TWy5jItooC416YQ= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x53b50e3020a01e1fd6acf832a871feee240183f0 | 1 | st6KVE+nTPsQgtEtxSbgJZCzSSuSB2ZsJAMbXFNLw/k= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x5c846224b8704683a1c576aec7c8d9c3413d87c1 | 0 | KO0Fr9uCPnT3KxOEishyzas33le4J9fAGg7iEOOzo7A= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x6fe4cf8d2c21f23f2aacf60f30c98ff9e2c78226 | 0 | p2evKbTirwEoF1PxGIu5USAsSdkxzh1sUD/OxBfpdNE= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xa28dd252ab5b984a8c1da699bbe10e7f09947a12 | 0 | 6VT+8479aijA8tYmab7YatVgjXm1TWy5jItooC416YQ= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> Showing 4 results. ``` diff --git a/crates/sui-framework/sources/object_basics.move b/sui_programmability/examples/basics/sources/object_basics.move similarity index 98% rename from crates/sui-framework/sources/object_basics.move rename to sui_programmability/examples/basics/sources/object_basics.move index f1c054881d42b..289dd404b6cf2 100644 --- a/crates/sui-framework/sources/object_basics.move +++ b/sui_programmability/examples/basics/sources/object_basics.move @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 /// Test CTURD object basics (create, transfer, update, read, delete) -module sui::object_basics { +module basics::object_basics { use sui::event; use sui::object::{Self, UID}; use sui::tx_context::{Self, TxContext}; diff --git a/sui_programmability/examples/fungible_tokens/sources/managed.move b/sui_programmability/examples/fungible_tokens/sources/managed.move index fd99db185d348..e8fdedabf3677 100644 --- a/sui_programmability/examples/fungible_tokens/sources/managed.move +++ b/sui_programmability/examples/fungible_tokens/sources/managed.move @@ -32,11 +32,6 @@ module fungible_tokens::managed { coin::burn(treasury_cap, coin); } - /// Manager can transfer the treasury capability to a new manager - public entry fun transfer_cap(treasury_cap: TreasuryCap, recipient: address) { - coin::transfer_cap(treasury_cap, recipient); - } - #[test_only] /// Wrapper of module initializer for testing public fun test_init(ctx: &mut TxContext) { diff --git a/sui_programmability/examples/games/sources/sea_hero.move b/sui_programmability/examples/games/sources/sea_hero.move index d9a753841be08..da2e0c3745781 100644 --- a/sui_programmability/examples/games/sources/sea_hero.move +++ b/sui_programmability/examples/games/sources/sea_hero.move @@ -115,13 +115,6 @@ module games::sea_hero { transfer::transfer(monster, recipient) } - /// Send `monster` to `recipient` - public fun transfer_monster( - monster: SeaMonster, recipient: address - ) { - transfer::transfer(monster, recipient) - } - /// Reward a hero will reap from slaying this monster public fun monster_reward(monster: &SeaMonster): u64 { balance::value(&monster.reward) diff --git a/sui_programmability/examples/games/sources/sea_hero_helper.move b/sui_programmability/examples/games/sources/sea_hero_helper.move index 0d6bd174a251f..179ccc4d00964 100644 --- a/sui_programmability/examples/games/sources/sea_hero_helper.move +++ b/sui_programmability/examples/games/sources/sea_hero_helper.move @@ -87,7 +87,7 @@ module games::sea_hero_helper { helper_reward: _ } = wrapper; object::delete(id); - sea_hero::transfer_monster(monster, monster_owner) + transfer::transfer(monster, monster_owner) } /// Return the number of coins that `wrapper.owner` will earn if the diff --git a/crates/sui-framework/sources/bag.move b/sui_programmability/examples/nfts/sources/bag.move similarity index 99% rename from crates/sui-framework/sources/bag.move rename to sui_programmability/examples/nfts/sources/bag.move index 041d106117ea6..56740c96882fa 100644 --- a/crates/sui-framework/sources/bag.move +++ b/sui_programmability/examples/nfts/sources/bag.move @@ -9,7 +9,7 @@ /// could mutate the objects in the Bag. /// Bag is different from the Collection type in that Collection /// only supports owning objects of the same type. -module sui::bag { +module nfts::bag { use sui::object::{Self, ID, UID}; use sui::transfer; use sui::typed_id::{Self, TypedID}; diff --git a/crates/sui-framework/sources/collection.move b/sui_programmability/examples/nfts/sources/collection.move similarity index 95% rename from crates/sui-framework/sources/collection.move rename to sui_programmability/examples/nfts/sources/collection.move index 4e414e2b2badb..d6079611b2346 100644 --- a/crates/sui-framework/sources/collection.move +++ b/sui_programmability/examples/nfts/sources/collection.move @@ -11,7 +11,7 @@ /// Collection allows us to own a list of same-typed objects, but still able to /// access and operate on each individual object. /// In contrast to `Bag`, `Collection` requires all objects have the same type. -module sui::collection { +module nfts::collection { use sui::object::{Self, ID, UID}; use sui::transfer; use sui::typed_id::{Self, TypedID}; @@ -113,11 +113,6 @@ module sui::collection { transfer::transfer(object, tx_context::sender(ctx)); } - /// Transfer the entire collection to `recipient`. - public entry fun transfer(c: Collection, recipient: address) { - transfer::transfer(c, recipient) - } - public fun transfer_to_object_id( obj: Collection, owner_id: &mut UID, diff --git a/sui_programmability/examples/nfts/sources/discount_coupon.move b/sui_programmability/examples/nfts/sources/discount_coupon.move index ef90e9347d5af..41978e426c9c7 100644 --- a/sui_programmability/examples/nfts/sources/discount_coupon.move +++ b/sui_programmability/examples/nfts/sources/discount_coupon.move @@ -4,7 +4,7 @@ module nfts::discount_coupon { use sui::coin; use sui::object::{Self, UID}; - use sui::sui::{Self, SUI}; + use sui::sui::SUI; use sui::transfer; use sui::tx_context::{Self, TxContext}; @@ -15,7 +15,7 @@ module nfts::discount_coupon { const EOutOfRangeDiscount: u64 = 1; /// Discount coupon NFT. - struct DiscountCoupon has key, store { + struct DiscountCoupon has key { id: UID, // coupon issuer issuer: address, @@ -46,7 +46,7 @@ module nfts::discount_coupon { expiration, }; transfer::transfer(coupon, recipient); - sui::transfer(coin, recipient); + transfer::transfer(coin, recipient); } /// Burn DiscountCoupon. diff --git a/sui_programmability/examples/nfts/sources/geniteam.move b/sui_programmability/examples/nfts/sources/geniteam.move index b2f260459c401..582d181567c45 100644 --- a/sui_programmability/examples/nfts/sources/geniteam.move +++ b/sui_programmability/examples/nfts/sources/geniteam.move @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 module nfts::geniteam { - use sui::bag::{Self, Bag}; - use sui::collection::{Self, Collection}; + use nfts::bag::{Self, Bag}; + use nfts::collection::{Self, Collection}; use sui::object::{Self, UID}; use sui::typed_id::{Self, TypedID}; use sui::tx_context::{Self, TxContext}; diff --git a/sui_programmability/examples/nfts/sources/marketplace.move b/sui_programmability/examples/nfts/sources/marketplace.move index 353eae2f7840e..2dd375a30a501 100644 --- a/sui_programmability/examples/nfts/sources/marketplace.move +++ b/sui_programmability/examples/nfts/sources/marketplace.move @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 module nfts::marketplace { - use sui::bag::{Self, Bag}; + use nfts::bag::{Self, Bag}; use sui::tx_context::{Self, TxContext}; use sui::object::{Self, ID, UID}; use sui::typed_id::{Self, TypedID}; @@ -124,11 +124,11 @@ module nfts::marketplace { #[test_only] module nfts::marketplaceTests { use sui::object::{Self, UID}; - use sui::bag::{Self, Bag}; use sui::transfer; use sui::coin::{Self, Coin}; use sui::sui::SUI; use sui::test_scenario::{Self, Scenario}; + use nfts::bag::{Self, Bag}; use nfts::marketplace::{Self, Marketplace, Listing}; // Simple Kitty-NFT data structure. diff --git a/sui_programmability/examples/nfts/tests/auction_tests.move b/sui_programmability/examples/nfts/tests/auction_tests.move index 52ab264e099fc..9e3a14ef9b448 100644 --- a/sui_programmability/examples/nfts/tests/auction_tests.move +++ b/sui_programmability/examples/nfts/tests/auction_tests.move @@ -9,6 +9,7 @@ module nfts::auction_tests { use sui::sui::SUI; use sui::object::{Self, UID}; use sui::test_scenario::Self; + use sui::transfer; use sui::tx_context::TxContext; use nfts::auction::{Self, Bid}; @@ -29,8 +30,8 @@ module nfts::auction_tests { fun init(ctx: &mut TxContext, bidders: vector
) { while (!vector::is_empty(&bidders)) { let bidder = vector::pop_back(&mut bidders); - let coin = coin::mint_for_testing(100, ctx); - coin::transfer(coin, bidder); + let coin = coin::mint_for_testing(100, ctx); + transfer::transfer(coin, bidder); }; } diff --git a/crates/sui-framework/tests/bag_tests.move b/sui_programmability/examples/nfts/tests/bag_tests.move similarity index 97% rename from crates/sui-framework/tests/bag_tests.move rename to sui_programmability/examples/nfts/tests/bag_tests.move index 1e427e75e0d3b..86d986e6cf353 100644 --- a/crates/sui-framework/tests/bag_tests.move +++ b/sui_programmability/examples/nfts/tests/bag_tests.move @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 #[test_only] -module sui::bag_tests { - use sui::bag::{Self, Bag}; +module nfts::bag_tests { + use nfts::bag::{Self, Bag}; use sui::object::{Self, UID}; use sui::test_scenario; use sui::typed_id; diff --git a/crates/sui-framework/tests/collection_tests.move b/sui_programmability/examples/nfts/tests/collection_tests.move similarity index 93% rename from crates/sui-framework/tests/collection_tests.move rename to sui_programmability/examples/nfts/tests/collection_tests.move index fcabaa2f93dea..9b81b57d4a66e 100644 --- a/crates/sui-framework/tests/collection_tests.move +++ b/sui_programmability/examples/nfts/tests/collection_tests.move @@ -2,11 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 #[test_only] -module sui::collection_tests { - use sui::bag::{Self, Bag}; - use sui::collection::{Self, Collection}; +module nfts::collection_tests { + use nfts::bag::{Self, Bag}; + use nfts::collection::{Self, Collection}; use sui::object::{Self, UID}; use sui::test_scenario; + use sui::transfer; use sui::typed_id; use sui::tx_context; @@ -111,7 +112,7 @@ module sui::collection_tests { // Sui::collection::DEFAULT_MAX_CAPACITY is not readable outside the module let max_capacity = 65536; let collection = collection::new_with_max_capacity(&mut ctx, max_capacity + 1); - collection::transfer(collection, tx_context::sender(&ctx)); + transfer::transfer(collection, tx_context::sender(&ctx)); } #[test] @@ -119,7 +120,7 @@ module sui::collection_tests { fun test_init_with_zero() { let ctx = tx_context::dummy(); let collection = collection::new_with_max_capacity(&mut ctx, 0); - collection::transfer(collection, tx_context::sender(&ctx)); + transfer::transfer(collection, tx_context::sender(&ctx)); } #[test] @@ -132,6 +133,6 @@ module sui::collection_tests { collection::add(&mut collection, obj1, &mut ctx); let obj2 = Object { id: object::new(&mut ctx) }; collection::add(&mut collection, obj2, &mut ctx); - collection::transfer(collection, tx_context::sender(&ctx)); + transfer::transfer(collection, tx_context::sender(&ctx)); } } diff --git a/sui_programmability/examples/nfts/tests/discount_coupon_tests.move b/sui_programmability/examples/nfts/tests/discount_coupon_tests.move index 4e3fb07248fae..e8726b3109962 100644 --- a/sui_programmability/examples/nfts/tests/discount_coupon_tests.move +++ b/sui_programmability/examples/nfts/tests/discount_coupon_tests.move @@ -7,6 +7,7 @@ module nfts::discount_coupon_tests { use sui::coin::{Self, Coin}; use sui::sui::SUI; use sui::test_scenario::Self; + use sui::transfer; use sui::tx_context::TxContext; const ISSUER_ADDRESS: address = @0xA001; @@ -20,8 +21,8 @@ module nfts::discount_coupon_tests { // be available in Sui genesis state (e.g., mints and distributes // coins to users). fun init(ctx: &mut TxContext) { - let coin = coin::mint_for_testing(100, ctx); - coin::transfer(coin, ISSUER_ADDRESS); + let coin = coin::mint_for_testing(100, ctx); + transfer::transfer(coin, ISSUER_ADDRESS); } #[test] diff --git a/sui_programmability/examples/nfts/tests/shared_auction_tests.move b/sui_programmability/examples/nfts/tests/shared_auction_tests.move index e5e21972573e0..f1024d705ddf2 100644 --- a/sui_programmability/examples/nfts/tests/shared_auction_tests.move +++ b/sui_programmability/examples/nfts/tests/shared_auction_tests.move @@ -9,6 +9,7 @@ module nfts::shared_auction_tests { use sui::sui::SUI; use sui::object::{Self, UID}; use sui::test_scenario::Self; + use sui::transfer; use sui::tx_context::TxContext; use nfts::shared_auction; @@ -33,8 +34,8 @@ module nfts::shared_auction_tests { fun init(ctx: &mut TxContext, bidders: vector
) { while (!vector::is_empty(&bidders)) { let bidder = vector::pop_back(&mut bidders); - let coin = coin::mint_for_testing(COIN_VALUE, ctx); - coin::transfer(coin, bidder); + let coin = coin::mint_for_testing(COIN_VALUE, ctx); + transfer::transfer(coin, bidder); }; } diff --git a/sui_programmability/examples/objects_tutorial/sources/color_object.move b/sui_programmability/examples/objects_tutorial/sources/color_object.move index 812fd39252629..c3bdb0b5453b8 100644 --- a/sui_programmability/examples/objects_tutorial/sources/color_object.move +++ b/sui_programmability/examples/objects_tutorial/sources/color_object.move @@ -47,10 +47,6 @@ module tutorial::color_object { object::delete(id); } - public entry fun transfer(object: ColorObject, recipient: address) { - transfer::transfer(object, recipient) - } - // == Functions covered in Chapter 3 == public entry fun freeze_object(object: ColorObject) { @@ -77,6 +73,7 @@ module tutorial::color_objectTests { use sui::test_scenario; use tutorial::color_object::{Self, ColorObject}; use sui::object; + use sui::transfer; use sui::tx_context; // == Tests covered in Chapter 1 == @@ -180,7 +177,7 @@ module tutorial::color_objectTests { test_scenario::next_tx(scenario, &owner); { let object = test_scenario::take_owned(scenario); - color_object::transfer(object, recipient); + transfer::transfer(object, recipient); }; // Check that owner no longer owns the object. test_scenario::next_tx(scenario, &owner); diff --git a/sui_programmability/examples/objects_tutorial/sources/trusted_swap.move b/sui_programmability/examples/objects_tutorial/sources/trusted_swap.move index 5fa9b3fcb8249..499689093d0f2 100644 --- a/sui_programmability/examples/objects_tutorial/sources/trusted_swap.move +++ b/sui_programmability/examples/objects_tutorial/sources/trusted_swap.move @@ -33,10 +33,6 @@ module tutorial::trusted_swap { transfer::transfer(object, tx_context::sender(ctx)) } - public entry fun transfer_object(object: Object, recipient: address) { - transfer::transfer(object, recipient) - } - /// Anyone owns an `Object` can request swapping their object. This object /// will be wrapped into `ObjectWrapper` and sent to `service_address`. public entry fun request_swap(object: Object, fee: Coin, service_address: address, ctx: &mut TxContext) {