diff --git a/aptos-move/framework/aptos-token-objects/doc/collection.md b/aptos-move/framework/aptos-token-objects/doc/collection.md index 8c992d2badc36..59b704ea47bc0 100644 --- a/aptos-move/framework/aptos-token-objects/doc/collection.md +++ b/aptos-move/framework/aptos-token-objects/doc/collection.md @@ -980,9 +980,6 @@ TODO: Hide this until we bring back meaningful way to enforce burns royalty::init(&constructor_ref, option::extract(&mut royalty)) }; - let transfer_ref = object::generate_transfer_ref(&constructor_ref); - object::disable_ungated_transfer(&transfer_ref); - constructor_ref } diff --git a/aptos-move/framework/aptos-token-objects/doc/token.md b/aptos-move/framework/aptos-token-objects/doc/token.md index b4c53eb85ef63..0068cdeaf002b 100644 --- a/aptos-move/framework/aptos-token-objects/doc/token.md +++ b/aptos-move/framework/aptos-token-objects/doc/token.md @@ -380,6 +380,16 @@ The URI is over the maximum length + + +The calling signer is not the owner + + +
const ENOT_OWNER: u64 = 8;
+
+ + + The description is over the maximum length @@ -542,7 +552,7 @@ The token name is over the maximum length royalty: Option<Royalty>, uri: String, ) { - assert!(collection::creator(collection) == signer::address_of(creator), error::unauthenticated(ENOT_CREATOR)); + assert!(object::owner(collection) == signer::address_of(creator), error::unauthenticated(ENOT_OWNER)); if (option::is_some(&name_with_index_suffix)) { // Be conservative, as we don't know what length the index will be, and assume worst case (20 chars in MAX_U64) diff --git a/aptos-move/framework/aptos-token-objects/sources/collection.move b/aptos-move/framework/aptos-token-objects/sources/collection.move index b3adbf6f3bc6a..af88007f84dfa 100644 --- a/aptos-move/framework/aptos-token-objects/sources/collection.move +++ b/aptos-move/framework/aptos-token-objects/sources/collection.move @@ -296,9 +296,6 @@ module aptos_token_objects::collection { royalty::init(&constructor_ref, option::extract(&mut royalty)) }; - let transfer_ref = object::generate_transfer_ref(&constructor_ref); - object::disable_ungated_transfer(&transfer_ref); - constructor_ref } @@ -750,9 +747,9 @@ module aptos_token_objects::collection { } #[test(creator = @0x123, trader = @0x456)] - #[expected_failure(abort_code = 0x50003, location = aptos_framework::object)] entry fun test_create_and_transfer(creator: &signer, trader: &signer) { let creator_address = signer::address_of(creator); + let trader_address = signer::address_of(trader); let collection_name = string::utf8(b"collection name"); create_collection_helper(creator, collection_name); @@ -760,7 +757,9 @@ module aptos_token_objects::collection { create_collection_address(&creator_address, &collection_name), ); assert!(object::owner(collection) == creator_address, 1); - object::transfer(creator, collection, signer::address_of(trader)); + // Transferring collections is allowed + object::transfer(creator, collection, trader_address); + assert!(object::owner(collection) == trader_address, 1); } #[test(creator = @0x123)] diff --git a/aptos-move/framework/aptos-token-objects/sources/token.move b/aptos-move/framework/aptos-token-objects/sources/token.move index 0d944c99c5cfc..4187f5306393e 100644 --- a/aptos-move/framework/aptos-token-objects/sources/token.move +++ b/aptos-move/framework/aptos-token-objects/sources/token.move @@ -33,6 +33,8 @@ module aptos_token_objects::token { const EDESCRIPTION_TOO_LONG: u64 = 6; /// The seed is over the maximum length const ESEED_TOO_LONG: u64 = 7; + /// The calling signer is not the owner + const ENOT_OWNER: u64 = 8; const MAX_TOKEN_NAME_LENGTH: u64 = 128; const MAX_TOKEN_SEED_LENGTH: u64 = 128; @@ -154,7 +156,7 @@ module aptos_token_objects::token { royalty: Option, uri: String, ) { - assert!(collection::creator(collection) == signer::address_of(creator), error::unauthenticated(ENOT_CREATOR)); + assert!(object::owner(collection) == signer::address_of(creator), error::unauthenticated(ENOT_OWNER)); if (option::is_some(&name_with_index_suffix)) { // Be conservative, as we don't know what length the index will be, and assume worst case (20 chars in MAX_U64) @@ -722,8 +724,8 @@ module aptos_token_objects::token { } #[test(creator = @0x123, trader = @0x456)] - #[expected_failure(abort_code = 0x40002, location = aptos_token_objects::token)] - fun test_create_token_non_creator(creator: &signer, trader: &signer) { + #[expected_failure(abort_code = 0x40008, location = aptos_token_objects::token)] + fun test_create_token_non_collection_owner(creator: &signer, trader: &signer) { let constructor_ref = &create_fixed_collection(creator, string::utf8(b"collection name"), 5); let collection = get_collection_from_ref(&object::generate_extend_ref(constructor_ref)); create_token( @@ -733,16 +735,16 @@ module aptos_token_objects::token { } #[test(creator = @0x123, trader = @0x456)] - #[expected_failure(abort_code = 0x40002, location = aptos_token_objects::token)] - fun test_create_named_token_non_creator(creator: &signer, trader: &signer) { + #[expected_failure(abort_code = 0x40008, location = aptos_token_objects::token)] + fun test_create_named_token_non_collection_owner(creator: &signer, trader: &signer) { let constructor_ref = &create_fixed_collection(creator, string::utf8(b"collection name"), 5); let collection = get_collection_from_ref(&object::generate_extend_ref(constructor_ref)); create_token_with_collection_helper(trader, collection, string::utf8(b"token name")); } #[test(creator = @0x123, trader = @0x456)] - #[expected_failure(abort_code = 0x40002, location = aptos_token_objects::token)] - fun test_create_named_token_object_non_creator(creator: &signer, trader: &signer) { + #[expected_failure(abort_code = 0x40008, location = aptos_token_objects::token)] + fun test_create_named_token_object_non_collection_owner(creator: &signer, trader: &signer) { let constructor_ref = &create_fixed_collection(creator, string::utf8(b"collection name"), 5); let collection = get_collection_from_ref(&object::generate_extend_ref(constructor_ref)); create_named_token_object( @@ -752,8 +754,8 @@ module aptos_token_objects::token { } #[test(creator = @0x123, trader = @0x456)] - #[expected_failure(abort_code = 0x40002, location = aptos_token_objects::token)] - fun test_create_named_token_from_seed_non_creator(creator: &signer, trader: &signer) { + #[expected_failure(abort_code = 0x40008, location = aptos_token_objects::token)] + fun test_create_named_token_from_seed_non_collection_owner(creator: &signer, trader: &signer) { let constructor_ref = &create_fixed_collection(creator, string::utf8(b"collection name"), 5); let collection = get_collection_from_ref(&object::generate_extend_ref(constructor_ref)); create_named_token_object( @@ -784,6 +786,43 @@ module aptos_token_objects::token { assert!(option::some(expected_royalty) == royalty(token), 2); } + #[test(creator = @0x123, trader = @0x456)] + #[expected_failure(abort_code = 0x40008, location = aptos_token_objects::token)] + fun test_create_token_after_transferring_collection(creator: &signer, trader: &signer) { + let constructor_ref = &create_fixed_collection(creator, string::utf8(b"collection name"), 5); + let collection = get_collection_from_ref(&object::generate_extend_ref(constructor_ref)); + create_token( + creator, collection, string::utf8(b"token description"), string::utf8(b"token name"), + option::some(royalty::create(25, 10000, signer::address_of(creator))), string::utf8(b"uri"), + ); + + object::transfer(creator, collection, signer::address_of(trader)); + + // This should fail as the collection is no longer owned by the creator. + create_token( + creator, collection, string::utf8(b"token description"), string::utf8(b"token name"), + option::some(royalty::create(25, 10000, signer::address_of(creator))), string::utf8(b"uri"), + ); + } + + #[test(creator = @0x123, trader = @0x456)] + fun create_token_works_with_new_collection_owner(creator: &signer, trader: &signer) { + let constructor_ref = &create_fixed_collection(creator, string::utf8(b"collection name"), 5); + let collection = get_collection_from_ref(&object::generate_extend_ref(constructor_ref)); + create_token( + creator, collection, string::utf8(b"token description"), string::utf8(b"token name"), + option::some(royalty::create(25, 10000, signer::address_of(creator))), string::utf8(b"uri"), + ); + + object::transfer(creator, collection, signer::address_of(trader)); + + // This should pass as `trader` is the new collection owner + create_token( + trader, collection, string::utf8(b"token description"), string::utf8(b"token name"), + option::some(royalty::create(25, 10000, signer::address_of(creator))), string::utf8(b"uri"), + ); + } + #[test(creator = @0x123)] fun test_collection_royalty(creator: &signer) acquires Token { let collection_name = string::utf8(b"collection name");