跳转到内容

overloadable_fungible_asset - [mainnet]

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

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,
);