Saltearse al contenido

overloadable_fungible_asset - [testnet]

Esta página aún no está disponible en tu idioma.

This defines the fungible asset module that can issue fungible asset of any Metadata object. The metadata object can be any object that equipped with Metadata resource.

The overloadable_fungible_asset wraps the existing fungible_asset module and adds the ability for token issuer to customize the logic for withdraw and deposit operations. For example:

  • Deflation token: a fixed percentage of token will be destructed upon transfer.
  • Transfer allowlist: token can only be transfered to addresses in the allow list.
  • Predicated transfer: transfer can only happen when some certain predicate has been met.
  • Loyalty token: a fixed loyalty will be paid to a designated address when a fungible asset transfer happens

See AIP-73 for further discussion

use 0x1::error;
use 0x1::function_info;
use 0x1::fungible_asset;
use 0x1::object;
use 0x1::signer;
use 0x1::string;

Constants

Trying to register overload functions to fungible asset that has already been initialized with custom transfer function.

const EALREADY_REGISTERED: u64 = 5;

Fungibility is only available for non-deletable objects.

const EOBJECT_IS_DELETABLE: u64 = 18;

Recipient is not getting the guaranteed value;

const EAMOUNT_MISMATCH: u64 = 4;

Provided deposit function type doesn’t meet the signature requirement.

const EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH: u64 = 2;

Calling overloadable api on non-overloadable fungible asset store.

const EFUNCTION_STORE_NOT_FOUND: u64 = 3;

Provided withdraw function type doesn’t meet the signature requirement.

const EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH: u64 = 1;

Resources

OverloadFunctionStore

#[resource_group_member(#[group = 0x1::object::ObjectGroup])]
struct OverloadFunctionStore has key
Fields
withdraw_function: function_info::FunctionInfo
deposit_function: function_info::FunctionInfo
transfer_ref: fungible_asset::TransferRef

Functions

register_overload_functions

Create a fungible asset store whose transfer rule would be overloaded by the provided function.

public fun register_overload_functions(constructor_ref: &object::ConstructorRef, withdraw_function: function_info::FunctionInfo, deposit_function: function_info::FunctionInfo)
Implementation
public fun register_overload_functions(
constructor_ref: &ConstructorRef,
withdraw_function: FunctionInfo,
deposit_function: FunctionInfo,
) {
let dispatcher_withdraw_function_info = function_info::new_function_info(
@aptos_framework,
string::utf8(b"overloadable_fungible_asset"),
string::utf8(b"dispatchable_withdraw"),
);
// Verify that caller type matches callee type so wrongly typed function cannot be registered.
assert!(function_info::check_dispatch_type_compatibility(
&dispatcher_withdraw_function_info,
&withdraw_function
), error::invalid_argument(EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH));
let dispatcher_deposit_function_info = function_info::new_function_info(
@aptos_framework,
string::utf8(b"overloadable_fungible_asset"),
string::utf8(b"dispatchable_deposit"),
);
// Verify that caller type matches callee type so wrongly typed function cannot be registered.
assert!(function_info::check_dispatch_type_compatibility(
&dispatcher_deposit_function_info,
&deposit_function
), error::invalid_argument(EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH));
assert!(!object::can_generate_delete_ref(constructor_ref), error::invalid_argument(EOBJECT_IS_DELETABLE));
assert!(!exists<OverloadFunctionStore>(object::address_from_constructor_ref(constructor_ref)), error::already_exists(EALREADY_REGISTERED));
// Freeze the FungibleStore to force usign the new overloaded api.
let extend_ref = object::generate_extend_ref(constructor_ref);
fungible_asset::set_global_frozen_flag(&extend_ref, true);
let store_obj = &object::generate_signer(constructor_ref);
// Store the overload function hook.
move_to<OverloadFunctionStore>(store_obj, OverloadFunctionStore {
withdraw_function,
deposit_function,
transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref),
});
}

withdraw

Withdraw amount of the fungible asset from store by the owner.

The semantics of deposit will be governed by the function specified in OverloadFunctionStore.

public fun withdraw<T: key>(owner: &signer, store: object::Object<T>, amount: u64): fungible_asset::FungibleAsset
Implementation
public fun withdraw<T: key>(
owner: &signer,
store: Object<T>,
amount: u64,
): FungibleAsset acquires OverloadFunctionStore {
let metadata_addr = object::object_address(&fungible_asset::store_metadata(store));
let owner_address = signer::address_of(owner);
assert!(exists<OverloadFunctionStore>(metadata_addr), error::not_found(EFUNCTION_STORE_NOT_FOUND));
let overloadable_store = borrow_global<OverloadFunctionStore>(metadata_addr);
dispatchable_withdraw(
owner_address,
store,
amount,
&overloadable_store.transfer_ref,
&overloadable_store.withdraw_function,
)
}

deposit

Deposit amount of the fungible asset to store.

The semantics of deposit will be governed by the function specified in OverloadFunctionStore.

public fun deposit<T: key>(store: object::Object<T>, fa: fungible_asset::FungibleAsset)
Implementation
public fun deposit<T: key>(
store: Object<T>,
fa: FungibleAsset
) acquires OverloadFunctionStore {
let metadata_addr = object::object_address(&fungible_asset::store_metadata(store));
assert!(exists<OverloadFunctionStore>(metadata_addr), error::not_found(EFUNCTION_STORE_NOT_FOUND));
let overloadable_store = borrow_global<OverloadFunctionStore>(metadata_addr);
dispatchable_deposit(
store,
fa,
&overloadable_store.transfer_ref,
&overloadable_store.deposit_function,
);
}

transfer_fixed_send

A transfer with a fixed amount debited from the sender

public fun transfer_fixed_send<T: key>(_sender: &signer, from: object::Object<T>, to: object::Object<T>, send_amount: u64)
Implementation
public fun transfer_fixed_send<T: key>(
_sender: &signer,
from: Object<T>,
to: Object<T>,
send_amount: u64,
) acquires OverloadFunctionStore {
let metadata_addr = object::object_address(&fungible_asset::store_metadata(from));
assert!(exists<OverloadFunctionStore>(metadata_addr), error::not_found(EFUNCTION_STORE_NOT_FOUND));
let overloadable_store = borrow_global<OverloadFunctionStore>(metadata_addr);
let fa = fungible_asset::withdraw_with_ref(&overloadable_store.transfer_ref, from, send_amount);
deposit(to, fa);
}

transfer_fixed_receive

A transfer with a fixed amount credited to the recipient

public fun transfer_fixed_receive<T: key>(sender: &signer, from: object::Object<T>, to: object::Object<T>, receive_amount: u64)
Implementation
public fun transfer_fixed_receive<T: key>(
sender: &signer,
from: Object<T>,
to: Object<T>,
receive_amount: u64,
) acquires OverloadFunctionStore {
let fa = withdraw(sender, from, receive_amount);
let metadata_addr = object::object_address(&fungible_asset::store_metadata(from));
let overloadable_store = borrow_global<OverloadFunctionStore>(metadata_addr);
assert!(fungible_asset::amount(&fa) == receive_amount, error::aborted(EAMOUNT_MISMATCH));
fungible_asset::deposit_with_ref(&overloadable_store.transfer_ref, to, fa);
}

dispatchable_withdraw

fun dispatchable_withdraw<T: key>(owner: address, store: object::Object<T>, amount: u64, transfer_ref: &fungible_asset::TransferRef, function: &function_info::FunctionInfo): fungible_asset::FungibleAsset
Implementation
native fun dispatchable_withdraw<T: key>(
owner: address,
store: Object<T>,
amount: u64,
transfer_ref: &TransferRef,
function: &FunctionInfo,
): FungibleAsset;

dispatchable_deposit

fun dispatchable_deposit<T: key>(store: object::Object<T>, fa: fungible_asset::FungibleAsset, transfer_ref: &fungible_asset::TransferRef, function: &function_info::FunctionInfo)
Implementation
native fun dispatchable_deposit<T: key>(
store: Object<T>,
fa: FungibleAsset,
transfer_ref: &TransferRef,
function: &FunctionInfo,
);