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