Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TOK] Add helpers to token #4516

Merged
merged 2 commits into from
Sep 25, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 51 additions & 45 deletions aptos-move/framework/aptos-token/sources/token.move
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ module aptos_token::token {
name,
);
// only creator of the tokendata can mint more tokens for now
assert!(token_data_id.creator == signer::address_of(account), error::permission_denied(ENO_MINT_CAPABILITY));
assert!(token_data_id.creator == signer::address_of(account), error::permission_denied(ENO_MINT_CAPABILITY));
mint_token(
account,
token_data_id,
Expand Down Expand Up @@ -417,7 +417,7 @@ module aptos_token::token {
property_map::update_property_map(&mut token_data.default_properties, keys, values, types);
}

public fun mutate_one_token(
public fun mutate_one_token(
account: &signer,
token_owner: address,
token_id: TokenId,
Expand Down Expand Up @@ -474,7 +474,7 @@ module aptos_token::token {

token_data.largest_property_version = cur_property_version;
// burn the orignial property_version 0 token after mutation
let Token {id: _, amount: _, token_properties: _} = token;
let Token { id: _, amount: _, token_properties: _ } = token;
new_token_id
} else {
// only 1 copy for the token with property verion bigger than 0
Expand Down Expand Up @@ -635,7 +635,7 @@ module aptos_token::token {

public fun split(dst_token: &mut Token, amount: u64): Token {
assert!(dst_token.id.property_version == 0, error::invalid_state(ENFT_NOT_SPLITABLE));
assert!(dst_token.amount > amount, error::invalid_argument(ETOKEN_SPLIT_AMOUNT_LARGER_THAN_TOKEN_AMOUNT));
assert!(dst_token.amount > amount, error::invalid_argument(ETOKEN_SPLIT_AMOUNT_LARGER_THAN_TOKEN_AMOUNT));
dst_token.amount = dst_token.amount - amount;
Token {
id: dst_token.id,
Expand Down Expand Up @@ -718,7 +718,7 @@ module aptos_token::token {
let token_store = borrow_global_mut<TokenStore>(account_addr);
event::emit_event<WithdrawEvent>(
&mut token_store.withdraw_events,
WithdrawEvent{ id, amount },
WithdrawEvent { id, amount },
);
let tokens = &mut borrow_global_mut<TokenStore>(account_addr).tokens;
assert!(
Expand All @@ -729,7 +729,7 @@ module aptos_token::token {
let balance = &mut table::borrow_mut(tokens, id).amount;
if (*balance > amount) {
*balance = *balance - amount;
Token{ id, amount, token_properties: property_map::empty() }
Token { id, amount, token_properties: property_map::empty() }
} else {
table::remove(tokens, id)
}
Expand All @@ -754,7 +754,7 @@ module aptos_token::token {
if (!exists<Collections>(account_addr)) {
move_to(
creator,
Collections{
Collections {
collection_data: table::new(),
token_data: table::new(),
create_collection_events: account::new_event_handle<CreateCollectionEvent>(creator),
Expand All @@ -772,7 +772,7 @@ module aptos_token::token {
);

let mutability_config = create_collection_mutability_config(&mutate_setting);
let collection = CollectionData{
let collection = CollectionData {
description,
name: *&name,
uri,
Expand Down Expand Up @@ -869,7 +869,7 @@ module aptos_token::token {
largest_property_version: 0,
supply: 0,
uri,
royalty: Royalty{
royalty: Royalty {
royalty_points_denominator,
royalty_points_numerator,
payee_address: royalty_payee_address,
Expand Down Expand Up @@ -923,7 +923,7 @@ module aptos_token::token {
assert!(table::contains(all_token_data, token_data_id), error::not_found(ETOKEN_DATA_NOT_PUBLISHED));
let token_data = table::borrow(all_token_data, token_data_id);

if (token_data.maximum > 0 ) {
if (token_data.maximum > 0) {
option::some(token_data.supply)
} else {
option::none<u64>()
Expand All @@ -944,7 +944,7 @@ module aptos_token::token {
}

public fun create_token_mutability_config(mutate_setting: &vector<bool>): TokenMutabilityConfig {
TokenMutabilityConfig{
TokenMutabilityConfig {
maximum: *vector::borrow(mutate_setting, TOKEN_MAX_MUTABLE_IND),
uri: *vector::borrow(mutate_setting, TOKEN_URI_MUTABLE_IND),
royalty: *vector::borrow(mutate_setting, TOKEN_ROYALTY_MUTABLE_IND),
Expand All @@ -954,7 +954,7 @@ module aptos_token::token {
}

public fun create_collection_mutability_config(mutate_setting: &vector<bool>): CollectionMutabilityConfig {
CollectionMutabilityConfig{
CollectionMutabilityConfig {
description: *vector::borrow(mutate_setting, COLLECTION_DESCRIPTION_MUTABLE_IND),
uri: *vector::borrow(mutate_setting, COLLECTION_URI_MUTABLE_IND),
maximum: *vector::borrow(mutate_setting, COLLECTION_MAX_MUTABLE_IND),
Expand Down Expand Up @@ -1014,15 +1014,15 @@ module aptos_token::token {
assert!(table::contains(all_token_data, token_data_id), error::not_found(ETOKEN_DATA_NOT_PUBLISHED));
let token_data = table::borrow_mut(all_token_data, token_data_id);

if (token_data.maximum > 0 ) {
if (token_data.maximum > 0) {
assert!(token_data.supply + amount <= token_data.maximum, error::invalid_argument(EMINT_WOULD_EXCEED_TOKEN_MAXIMUM));
token_data.supply = token_data.supply + amount;
};

// we add more tokens with property_version 0
let token_id = create_token_id(token_data_id, 0);
deposit_token(account,
Token{
Token {
id: token_id,
amount,
token_properties: property_map::empty(), // same as default properties no need to store
Expand Down Expand Up @@ -1057,15 +1057,15 @@ module aptos_token::token {
assert!(table::contains(all_token_data, token_data_id), error::not_found(ETOKEN_DATA_NOT_PUBLISHED));
let token_data = table::borrow_mut(all_token_data, token_data_id);

if (token_data.maximum > 0 ) {
if (token_data.maximum > 0) {
assert!(token_data.supply + amount <= token_data.maximum, error::invalid_argument(EMINT_WOULD_EXCEED_TOKEN_MAXIMUM));
token_data.supply = token_data.supply + amount;
};

// we add more tokens with property_version 0
let token_id = create_token_id(token_data_id, 0);
direct_deposit(receiver,
Token{
Token {
id: token_id,
amount,
token_properties: property_map::empty(), // same as default properties no need to store
Expand Down Expand Up @@ -1126,15 +1126,15 @@ module aptos_token::token {
let token_store = borrow_global_mut<TokenStore>(owner);
event::emit_event<BurnTokenEvent>(
&mut token_store.burn_events,
BurnTokenEvent { id: token_id, amount: burned_amount},
BurnTokenEvent { id: token_id, amount: burned_amount },
);

if (token_data.maximum > 0) {
token_data.supply = token_data.supply - burned_amount;

// Delete the token_data if supply drops to 0.
if (token_data.supply == 0) {
let TokenData{
let TokenData {
maximum: _,
largest_property_version: _,
supply: _,
Expand Down Expand Up @@ -1179,7 +1179,7 @@ module aptos_token::token {
);

assert!(
property_map::contains_key(&token_data.default_properties, &string::utf8(BURNABLE_BY_OWNER)),
property_map::contains_key(&token_data.default_properties, &string::utf8(BURNABLE_BY_OWNER)),
error::permission_denied(EOWNER_CANNOT_BURN_TOKEN)
);
let burn_by_owner_flag = property_map::read_bool(&token_data.default_properties, &string::utf8(BURNABLE_BY_OWNER));
Expand All @@ -1190,7 +1190,7 @@ module aptos_token::token {
let token_store = borrow_global_mut<TokenStore>(signer::address_of(owner));
event::emit_event<BurnTokenEvent>(
&mut token_store.burn_events,
BurnTokenEvent { id: token_id, amount: burned_amount},
BurnTokenEvent { id: token_id, amount: burned_amount },
);

// Decrease the supply correspondingly by the amount of tokens burned.
Expand All @@ -1206,7 +1206,7 @@ module aptos_token::token {

// Delete the token_data if supply drops to 0.
if (token_data.supply == 0) {
let TokenData{
let TokenData {
maximum: _,
largest_property_version: _,
supply: _,
Expand All @@ -1222,7 +1222,7 @@ module aptos_token::token {
}

public fun create_token_id(token_data_id: TokenDataId, property_version: u64): TokenId {
TokenId{
TokenId {
token_data_id,
property_version,
}
Expand All @@ -1244,13 +1244,16 @@ module aptos_token::token {
name: String,
property_version: u64,
): TokenId {
TokenId{
TokenId {
token_data_id: create_token_data_id(creator, collection, name),
property_version,
}
}

public fun balance_of(owner: address, id: TokenId): u64 acquires TokenStore {
if (!exists<TokenStore>(owner)) {
return 0
};
let token_store = borrow_global<TokenStore>(owner);
if (table::contains(&token_store.tokens, id)) {
table::borrow(&token_store.tokens, id).amount
Expand All @@ -1259,6 +1262,10 @@ module aptos_token::token {
}
}

public fun has_token_store(owner: address): bool {
exists<TokenStore>(owner)
}

public fun get_royalty(token_id: TokenId): Royalty acquires Collections {
let token_data_id = token_id.token_data_id;
let creator_addr = token_data_id.creator;
Expand Down Expand Up @@ -1440,6 +1447,8 @@ module aptos_token::token {
vector<bool>[false, false, false],
vector<bool>[false, false, false, false, false],
);
assert!(balance_of(signer::address_of(&owner), token_id) == 0, 1);

direct_transfer(&creator, &owner, token_id, 1);
let token = withdraw_token(&owner, token_id, 1);
deposit_token(&creator, token);
Expand Down Expand Up @@ -1482,9 +1491,9 @@ module aptos_token::token {
mutate_setting
);

let default_keys = if(vector::length<String>(&property_keys) == 0) {vector<String>[string::utf8(b"attack"), string::utf8(b"num_of_use")]} else {property_keys};
let default_vals = if (vector::length<vector<u8>>(&property_values) == 0) {vector<vector<u8>>[bcs::to_bytes<u64>(&10), bcs::to_bytes<u64>(&5)] } else {property_values};
let default_types = if (vector::length<String>(&property_types) == 0) {vector<String>[string::utf8(b"u64"), string::utf8(b"u64")] } else {property_types};
let default_keys = if (vector::length<String>(&property_keys) == 0) { vector<String>[string::utf8(b"attack"), string::utf8(b"num_of_use")] } else { property_keys };
let default_vals = if (vector::length<vector<u8>>(&property_values) == 0) { vector<vector<u8>>[bcs::to_bytes<u64>(&10), bcs::to_bytes<u64>(&5)] } else { property_values };
let default_types = if (vector::length<String>(&property_types) == 0) { vector<String>[string::utf8(b"u64"), string::utf8(b"u64")] } else { property_types };
let mutate_setting = token_mutate_setting;
create_token_script(
creator,
Expand Down Expand Up @@ -1727,7 +1736,7 @@ module aptos_token::token {
assert!(property_map::read_u64(&og_pm, &string::utf8(b"attack")) == 1, 1);
}

#[test(framework = @0x1, creator=@0xcafe)]
#[test(framework = @0x1, creator = @0xcafe)]
fun test_withdraw_with_proof(creator: &signer, framework: &signer): Token acquires TokenStore, Collections {
timestamp::set_time_has_started_for_testing(framework);
account::create_account_for_test(signer::address_of(creator));
Expand All @@ -1746,7 +1755,7 @@ module aptos_token::token {
timestamp::update_global_time_for_test(1000000);

// provide the proof to the account
let cap = create_withdraw_capability(
let cap = create_withdraw_capability(
creator, // ask user to provide address to avoid ambiguity from rotated keys
token_id,
1,
Expand All @@ -1756,7 +1765,7 @@ module aptos_token::token {
withdraw_with_capability(cap)
}

#[test(creator=@0xcafe, another_creator=@0xde)]
#[test(creator = @0xcafe, another_creator = @0xde)]
fun test_burn_token_from_both_limited_and_unlimited(
creator: &signer,
another_creator: &signer,
Expand Down Expand Up @@ -1805,7 +1814,7 @@ module aptos_token::token {
assert!(pre - aft == 1, 1);
}

#[test(creator=@0xcafe, owner=@0xafe)]
#[test(creator = @0xcafe, owner = @0xafe)]
fun test_mint_token_to_different_address(
creator: &signer,
owner: &signer,
Expand All @@ -1823,15 +1832,14 @@ module aptos_token::token {
vector<String>[],
vector<bool>[false, false, false],
vector<bool>[false, false, false, false, false],

);
let owner_addr = signer::address_of(owner);
opt_in_direct_transfer(owner, true);
mint_token_to(creator, owner_addr, token_id.token_data_id, 1);
assert!(balance_of(owner_addr, token_id) == 1, 1);
}

#[test(creator=@0xcafe, owner=@0xafe)]
#[test(creator = @0xcafe, owner = @0xafe)]
#[expected_failure(abort_code = 327696)]
fun test_opt_in_direct_transfer_fail(
creator: &signer,
Expand All @@ -1856,7 +1864,7 @@ module aptos_token::token {
transfer(creator, token_id, owner_addr, 1);
}

#[test(creator=@0xcafe, owner=@0xafe)]
#[test(creator = @0xcafe, owner = @0xafe)]
#[expected_failure(abort_code = 327696)]
fun test_opt_in_direct_deposit_fail(
creator: &signer,
Expand Down Expand Up @@ -1895,11 +1903,10 @@ module aptos_token::token {
opt_in_direct_transfer(owner, true);
initialize_token_store(owner);
transfer(creator, token_id, signer::address_of(owner), 2);
burn_by_creator(creator, signer::address_of(owner), get_collection_name(), get_token_name(), 0,1);

burn_by_creator(creator, signer::address_of(owner), get_collection_name(), get_token_name(), 0, 1);
}

#[test(creator=@0xcafe, owner=@0x456)]
#[test(creator = @0xcafe, owner = @0x456)]
#[expected_failure(abort_code = 327710)]
fun test_burn_token_by_owner_without_burnable_config(
creator: &signer,
Expand All @@ -1923,10 +1930,10 @@ module aptos_token::token {
initialize_token_store(owner);
transfer(creator, token_id, signer::address_of(owner), 2);

burn(owner, signer::address_of(creator), get_collection_name(), get_token_name(), 0,1);
burn(owner, signer::address_of(creator), get_collection_name(), get_token_name(), 0, 1);
}

#[test(creator=@0xcafe, owner=@0x456)]
#[test(creator = @0xcafe, owner = @0x456)]
fun test_burn_token_by_owner_and_creator(
creator: &signer,
owner: &signer,
Expand All @@ -1940,7 +1947,7 @@ module aptos_token::token {
4,
4,
vector<String>[string::utf8(BURNABLE_BY_CREATOR), string::utf8(BURNABLE_BY_OWNER)],
vector<vector<u8>>[bcs::to_bytes<bool>(&true), bcs::to_bytes<bool>(&true)],
vector<vector<u8>>[bcs::to_bytes<bool>(&true), bcs::to_bytes<bool>(&true)],
vector<String>[string::utf8(b"bool"), string::utf8(b"bool")],
vector<bool>[false, false, false],
vector<bool>[false, false, false, false, false],
Expand All @@ -1949,11 +1956,11 @@ module aptos_token::token {
initialize_token_store(owner);
transfer(creator, token_id, signer::address_of(owner), 2);
burn_by_creator(creator, signer::address_of(owner), get_collection_name(), get_token_name(), 0, 1);
burn(owner, signer::address_of(creator), get_collection_name(), get_token_name(), 0,1);
burn(owner, signer::address_of(creator), get_collection_name(), get_token_name(), 0, 1);
assert!(balance_of(signer::address_of(owner), token_id) == 0, 1);
}

#[test(creator=@0xcafe, owner=@0x456)]
#[test(creator = @0xcafe, owner = @0x456)]
fun test_mutate_default_token_properties(
creator: &signer,
) acquires Collections, TokenStore {
Expand Down Expand Up @@ -1992,12 +1999,12 @@ module aptos_token::token {
);

let all_token_data = &borrow_global<Collections>(signer::address_of(creator)).token_data;
assert!(table::contains(all_token_data, token_id.token_data_id), 1);
assert!(table::contains(all_token_data, token_id.token_data_id), 1);
let props = &table::borrow(all_token_data, token_id.token_data_id).default_properties;
assert!(property_map::read_u64(props, &string::utf8(b"attack")) == 1, 1);
}

#[test(creator=@0xcafe)]
#[test(creator = @0xcafe)]
fun test_mutate_token_uri(
creator: &signer,
) acquires Collections, TokenStore {
Expand All @@ -2015,7 +2022,6 @@ module aptos_token::token {
vector<bool>[false, true, false, false, false],
);
mutate_tokendata_uri(creator, token_id.token_data_id, string::utf8(b"new_url"));
assert!(get_tokendata_uri(signer::address_of(creator), token_id.token_data_id) == string::utf8(b"new_url"), 1);
assert!(get_tokendata_uri(signer::address_of(creator), token_id.token_data_id) == string::utf8(b"new_url"), 1);
}

}