跳转到内容

token_transfers - [testnet]

此内容尚不支持你的语言。

This module provides the foundation for transferring of Tokens

use 0x1::account;
use 0x1::error;
use 0x1::event;
use 0x1::features;
use 0x1::signer;
use 0x1::string;
use 0x1::table;
use 0x3::token;

Constants

Token offer doesn’t exist

const ETOKEN_OFFER_NOT_EXIST: u64 = 1;

Structs

TokenOfferId

#[event]
struct TokenOfferId has copy, drop, store
Fields
to_addr: address
token_id: token::TokenId

TokenOffer

#[event]
struct TokenOffer has drop, store
Fields
to_address: address
token_id: token::TokenId
amount: u64

Offer

#[event]
struct Offer has drop, store
Fields
account: address
to_address: address
token_id: token::TokenId
amount: u64

TokenCancelOfferEvent

#[event]
struct TokenCancelOfferEvent has drop, store
Fields
to_address: address
token_id: token::TokenId
amount: u64

CancelOffer

#[event]
struct CancelOffer has drop, store
Fields
account: address
to_address: address
token_id: token::TokenId
amount: u64

TokenClaimEvent

#[event]
struct TokenClaimEvent has drop, store
Fields
to_address: address
token_id: token::TokenId
amount: u64

Claim

#[event]
struct Claim has drop, store
Fields
account: address
to_address: address
token_id: token::TokenId
amount: u64

TokenOfferEvent

#[event]
#[deprecated]
struct TokenOfferEvent has drop, store
Fields
to_address: address
token_id: token::TokenId
amount: u64

TokenCancelOffer

#[event]
#[deprecated]
struct TokenCancelOffer has drop, store
Fields
to_address: address
token_id: token::TokenId
amount: u64

TokenClaim

#[event]
#[deprecated]
struct TokenClaim has drop, store
Fields
to_address: address
token_id: token::TokenId
amount: u64

Resources

PendingClaims

struct PendingClaims has key
Fields
pending_claims: table::Table<token_transfers::TokenOfferId, token::Token>
offer_events: event::EventHandle<token_transfers::TokenOfferEvent>
cancel_offer_events: event::EventHandle<token_transfers::TokenCancelOfferEvent>
claim_events: event::EventHandle<token_transfers::TokenClaimEvent>

Functions

initialize_token_transfers

fun initialize_token_transfers(account: &signer)
Implementation
fun initialize_token_transfers(account: &signer) {
move_to(
account,
PendingClaims {
pending_claims: table::new<TokenOfferId, Token>(),
offer_events: account::new_event_handle<TokenOfferEvent>(account),
cancel_offer_events: account::new_event_handle<TokenCancelOfferEvent>(account),
claim_events: account::new_event_handle<TokenClaimEvent>(account),
}
)
}

create_token_offer_id

fun create_token_offer_id(to_addr: address, token_id: token::TokenId): token_transfers::TokenOfferId
Implementation
fun create_token_offer_id(to_addr: address, token_id: TokenId): TokenOfferId {
TokenOfferId {
to_addr,
token_id
}
}

offer_script

public entry fun offer_script(sender: signer, receiver: address, creator: address, collection: string::String, name: string::String, property_version: u64, amount: u64)
Implementation
public entry fun offer_script(
sender: signer,
receiver: address,
creator: address,
collection: String,
name: String,
property_version: u64,
amount: u64,
) acquires PendingClaims {
let token_id = token::create_token_id_raw(creator, collection, name, property_version);
offer(&sender, receiver, token_id, amount);
}

offer

public fun offer(sender: &signer, receiver: address, token_id: token::TokenId, amount: u64)
Implementation
public fun offer(
sender: &signer,
receiver: address,
token_id: TokenId,
amount: u64,
) acquires PendingClaims {
let sender_addr = signer::address_of(sender);
if (!exists<PendingClaims>(sender_addr)) {
initialize_token_transfers(sender)
};
let pending_claims =
&mut PendingClaims[sender_addr].pending_claims;
let token_offer_id = create_token_offer_id(receiver, token_id);
let token = token::withdraw_token(sender, token_id, amount);
if (!pending_claims.contains(token_offer_id)) {
pending_claims.add(token_offer_id, token);
} else {
let dst_token = pending_claims.borrow_mut(token_offer_id);
token::merge(dst_token, token);
};
if (std::features::module_event_migration_enabled()) {
event::emit(
Offer {
account: sender_addr,
to_address: receiver,
token_id,
amount,
}
)
} else {
event::emit_event<TokenOfferEvent>(
&mut PendingClaims[sender_addr].offer_events,
TokenOfferEvent {
to_address: receiver,
token_id,
amount,
},
);
}
}

claim_script

public entry fun claim_script(receiver: signer, sender: address, creator: address, collection: string::String, name: string::String, property_version: u64)
Implementation
public entry fun claim_script(
receiver: signer,
sender: address,
creator: address,
collection: String,
name: String,
property_version: u64,
) acquires PendingClaims {
let token_id = token::create_token_id_raw(creator, collection, name, property_version);
claim(&receiver, sender, token_id);
}

claim

public fun claim(receiver: &signer, sender: address, token_id: token::TokenId)
Implementation
public fun claim(
receiver: &signer,
sender: address,
token_id: TokenId,
) acquires PendingClaims {
assert!(exists<PendingClaims>(sender), ETOKEN_OFFER_NOT_EXIST);
let pending_claims =
&mut PendingClaims[sender].pending_claims;
let token_offer_id = create_token_offer_id(signer::address_of(receiver), token_id);
assert!(pending_claims.contains(token_offer_id), error::not_found(ETOKEN_OFFER_NOT_EXIST));
let tokens = pending_claims.remove(token_offer_id);
let amount = token::get_token_amount(&tokens);
token::deposit_token(receiver, tokens);
if (std::features::module_event_migration_enabled()) {
event::emit(
Claim {
account: sender,
to_address: signer::address_of(receiver),
token_id,
amount,
}
)
} else {
event::emit_event<TokenClaimEvent>(
&mut PendingClaims[sender].claim_events,
TokenClaimEvent {
to_address: signer::address_of(receiver),
token_id,
amount,
},
);
};
}

cancel_offer_script

public entry fun cancel_offer_script(sender: signer, receiver: address, creator: address, collection: string::String, name: string::String, property_version: u64)
Implementation
public entry fun cancel_offer_script(
sender: signer,
receiver: address,
creator: address,
collection: String,
name: String,
property_version: u64,
) acquires PendingClaims {
let token_id = token::create_token_id_raw(creator, collection, name, property_version);
cancel_offer(&sender, receiver, token_id);
}

cancel_offer

public fun cancel_offer(sender: &signer, receiver: address, token_id: token::TokenId)
Implementation
public fun cancel_offer(
sender: &signer,
receiver: address,
token_id: TokenId,
) acquires PendingClaims {
let sender_addr = signer::address_of(sender);
let token_offer_id = create_token_offer_id(receiver, token_id);
assert!(exists<PendingClaims>(sender_addr), ETOKEN_OFFER_NOT_EXIST);
let pending_claims =
&mut PendingClaims[sender_addr].pending_claims;
let token = pending_claims.remove(token_offer_id);
let amount = token::get_token_amount(&token);
token::deposit_token(sender, token);
if (std::features::module_event_migration_enabled()) {
event::emit(
CancelOffer {
account: sender_addr,
to_address: receiver,
token_id,
amount,
},
)
} else {
event::emit_event<TokenCancelOfferEvent>(
&mut PendingClaims[sender_addr].cancel_offer_events,
TokenCancelOfferEvent {
to_address: receiver,
token_id,
amount,
},
);
}
}

Specification

pragma verify = false;
pragma aborts_if_is_strict;

Get the amount from sender token

fun spce_get(
account_addr: address,
id: TokenId,
amount: u64
): u64 {
use aptos_token::token::{TokenStore};
use aptos_std::table::{Self};
let tokens = global<TokenStore>(account_addr).tokens;
let balance = table::spec_get(tokens, id).amount;
if (balance > amount) {
amount
} else {
table::spec_get(tokens, id).amount
}
}

initialize_token_transfers

fun initialize_token_transfers(account: &signer)
include InitializeTokenTransfersAbortsIf;

Abort according to the code

schema InitializeTokenTransfersAbortsIf {
account: &signer;
let addr = signer::address_of(account);
aborts_if exists<PendingClaims>(addr);
let account = global<Account>(addr);
aborts_if !exists<Account>(addr);
aborts_if account.guid_creation_num + 3 >= account::MAX_GUID_CREATION_NUM;
aborts_if account.guid_creation_num + 3 > MAX_U64;
}

create_token_offer_id

fun create_token_offer_id(to_addr: address, token_id: token::TokenId): token_transfers::TokenOfferId
aborts_if false;

offer_script

public entry fun offer_script(sender: signer, receiver: address, creator: address, collection: string::String, name: string::String, property_version: u64, amount: u64)
pragma verify = false;
let token_id = token::create_token_id_raw(creator, collection, name, property_version);

offer

public fun offer(sender: &signer, receiver: address, token_id: token::TokenId, amount: u64)
pragma verify = false;
let sender_addr = signer::address_of(sender);
include !exists<PendingClaims>(sender_addr) ==> InitializeTokenTransfersAbortsIf{account : sender};
let pending_claims = global<PendingClaims>(sender_addr).pending_claims;
let token_offer_id = create_token_offer_id(receiver, token_id);
let tokens = global<TokenStore>(sender_addr).tokens;
aborts_if amount <= 0;
aborts_if token::spec_balance_of(sender_addr, token_id) < amount;
aborts_if !exists<TokenStore>(sender_addr);
aborts_if !table::spec_contains(tokens, token_id);
aborts_if !table::spec_contains(pending_claims, token_offer_id);
let a = table::spec_contains(pending_claims, token_offer_id);
let dst_token = table::spec_get(pending_claims, token_offer_id);
aborts_if dst_token.amount + spce_get(signer::address_of(sender), token_id, amount) > MAX_U64;

claim_script

public entry fun claim_script(receiver: signer, sender: address, creator: address, collection: string::String, name: string::String, property_version: u64)
pragma aborts_if_is_partial;
let token_id = token::create_token_id_raw(creator, collection, name, property_version);
aborts_if !exists<PendingClaims>(sender);
let pending_claims = global<PendingClaims>(sender).pending_claims;
let token_offer_id = create_token_offer_id(signer::address_of(receiver), token_id);
aborts_if !table::spec_contains(pending_claims, token_offer_id);
let tokens = table::spec_get(pending_claims, token_offer_id);
include token::InitializeTokenStore{account: receiver };
let account_addr = signer::address_of(receiver);
let token = tokens;
let token_store = global<TokenStore>(account_addr);
let recipient_token = table::spec_get(token_store.tokens, token.id);
let b = table::spec_contains(token_store.tokens, token.id);
aborts_if token.amount <= 0;

claim

public fun claim(receiver: &signer, sender: address, token_id: token::TokenId)
pragma aborts_if_is_partial;
aborts_if !exists<PendingClaims>(sender);
let pending_claims = global<PendingClaims>(sender).pending_claims;
let token_offer_id = create_token_offer_id(signer::address_of(receiver), token_id);
aborts_if !table::spec_contains(pending_claims, token_offer_id);
let tokens = table::spec_get(pending_claims, token_offer_id);
include token::InitializeTokenStore{account: receiver };
let account_addr = signer::address_of(receiver);
let token = tokens;
let token_store = global<TokenStore>(account_addr);
let recipient_token = table::spec_get(token_store.tokens, token.id);
let b = table::spec_contains(token_store.tokens, token.id);
aborts_if token.amount <= 0;

cancel_offer_script

public entry fun cancel_offer_script(sender: signer, receiver: address, creator: address, collection: string::String, name: string::String, property_version: u64)
pragma aborts_if_is_partial;
let token_id = token::create_token_id_raw(creator, collection, name, property_version);
let sender_addr = signer::address_of(sender);
aborts_if !exists<PendingClaims>(sender_addr);
let pending_claims = global<PendingClaims>(sender_addr).pending_claims;
let token_offer_id = create_token_offer_id(receiver, token_id);
aborts_if !table::spec_contains(pending_claims, token_offer_id);
include token::InitializeTokenStore{account: sender };
let dst_token = table::spec_get(pending_claims, token_offer_id);
let account_addr = sender_addr;
let token = dst_token;
let token_store = global<TokenStore>(account_addr);
let recipient_token = table::spec_get(token_store.tokens, token.id);
let b = table::spec_contains(token_store.tokens, token.id);
aborts_if token.amount <= 0;

cancel_offer

public fun cancel_offer(sender: &signer, receiver: address, token_id: token::TokenId)
pragma aborts_if_is_partial;
let sender_addr = signer::address_of(sender);
aborts_if !exists<PendingClaims>(sender_addr);
let pending_claims = global<PendingClaims>(sender_addr).pending_claims;
let token_offer_id = create_token_offer_id(receiver, token_id);
aborts_if !table::spec_contains(pending_claims, token_offer_id);
include token::InitializeTokenStore{account: sender };
let dst_token = table::spec_get(pending_claims, token_offer_id);
let account_addr = sender_addr;
let token = dst_token;
let token_store = global<TokenStore>(account_addr);
let recipient_token = table::spec_get(token_store.tokens, token.id);
let b = table::spec_contains(token_store.tokens, token.id);
aborts_if token.amount <= 0;