dispatchable_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 dispatchable_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
The api listed here intended to be an in-place replacement for defi applications that uses fungible_asset api directly and is safe for non-dispatchable (aka vanilla) fungible assets as well.
See AIP-73 for further discussion
use 0x1::error;use 0x1::features;use 0x1::function_info;use 0x1::fungible_asset;use 0x1::object;use 0x1::option;
Constants
Feature is not activated yet on the network.
const ENOT_ACTIVATED: u64 = 3;
Recipient is not getting the guaranteed value;
const EAMOUNT_MISMATCH: u64 = 2;
Dispatch target is not loaded.
const ENOT_LOADED: u64 = 4;
TransferRefStore doesn’t exist on the fungible asset type.
const ESTORE_NOT_FOUND: u64 = 1;
Resources
TransferRefStore
#[resource_group_member(#[group = 0x1::object::ObjectGroup])]struct TransferRefStore has key
Fields
-
transfer_ref: fungible_asset::TransferRef
Functions
register_dispatch_functions
public fun register_dispatch_functions(constructor_ref: &object::ConstructorRef, withdraw_function: option::Option<function_info::FunctionInfo>, deposit_function: option::Option<function_info::FunctionInfo>, derived_balance_function: option::Option<function_info::FunctionInfo>)
Implementation
public fun register_dispatch_functions( constructor_ref: &ConstructorRef, withdraw_function: Option<FunctionInfo>, deposit_function: Option<FunctionInfo>, derived_balance_function: Option<FunctionInfo>,) { fungible_asset::register_dispatch_functions( constructor_ref, withdraw_function, deposit_function, derived_balance_function, ); let store_obj = &object::generate_signer(constructor_ref); move_to<TransferRefStore>( store_obj, TransferRefStore { transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref), } );}
register_derive_supply_dispatch_function
public fun register_derive_supply_dispatch_function(constructor_ref: &object::ConstructorRef, dispatch_function: option::Option<function_info::FunctionInfo>)
Implementation
public fun register_derive_supply_dispatch_function( constructor_ref: &ConstructorRef, dispatch_function: Option<FunctionInfo>) { fungible_asset::register_derive_supply_dispatch_function( constructor_ref, dispatch_function );}
withdraw
Withdraw amount
of the fungible asset from store
by the owner.
The semantics of deposit will be governed by the function specified in DispatchFunctionStore.
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 TransferRefStore { fungible_asset::withdraw_sanity_check(owner, store, false); fungible_asset::withdraw_permission_check(owner, store, amount); let func_opt = fungible_asset::withdraw_dispatch_function(store); if (option::is_some(&func_opt)) { assert!( features::dispatchable_fungible_asset_enabled(), error::aborted(ENOT_ACTIVATED) ); let func = option::borrow(&func_opt); function_info::load_module_from_function(func); let fa = dispatchable_withdraw( store, amount, borrow_transfer_ref(store), func, ); fa } else { fungible_asset::unchecked_withdraw(object::object_address(&store), amount) }}
deposit
Deposit amount
of the fungible asset to store
.
The semantics of deposit will be governed by the function specified in DispatchFunctionStore.
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 TransferRefStore { fungible_asset::deposit_sanity_check(store, false); let func_opt = fungible_asset::deposit_dispatch_function(store); if (option::is_some(&func_opt)) { assert!( features::dispatchable_fungible_asset_enabled(), error::aborted(ENOT_ACTIVATED) ); let func = option::borrow(&func_opt); function_info::load_module_from_function(func); dispatchable_deposit( store, fa, borrow_transfer_ref(store), func ) } else { fungible_asset::unchecked_deposit(object::object_address(&store), fa) }}
transfer
Transfer an amount
of fungible asset from from_store
, which should be owned by sender
, to receiver
.
Note: it does not move the underlying object.
public entry fun transfer<T: key>(sender: &signer, from: object::Object<T>, to: object::Object<T>, amount: u64)
Implementation
public entry fun transfer<T: key>( sender: &signer, from: Object<T>, to: Object<T>, amount: u64,) acquires TransferRefStore { let fa = withdraw(sender, from, amount); deposit(to, fa);}
transfer_assert_minimum_deposit
Transfer an amount
of fungible asset from from_store
, which should be owned by sender
, to receiver
.
The recipient is guranteed to receive asset greater than the expected amount.
Note: it does not move the underlying object.
public entry fun transfer_assert_minimum_deposit<T: key>(sender: &signer, from: object::Object<T>, to: object::Object<T>, amount: u64, expected: u64)
Implementation
public entry fun transfer_assert_minimum_deposit<T: key>( sender: &signer, from: Object<T>, to: Object<T>, amount: u64, expected: u64) acquires TransferRefStore { let start = fungible_asset::balance(to); let fa = withdraw(sender, from, amount); deposit(to, fa); let end = fungible_asset::balance(to); assert!(end - start >= expected, error::aborted(EAMOUNT_MISMATCH));}
derived_balance
Get the derived value of store using the overloaded hook.
The semantics of value will be governed by the function specified in DispatchFunctionStore.
#[view]public fun derived_balance<T: key>(store: object::Object<T>): u64
Implementation
public fun derived_balance<T: key>(store: Object<T>): u64 { let func_opt = fungible_asset::derived_balance_dispatch_function(store); if (option::is_some(&func_opt)) { assert!( features::dispatchable_fungible_asset_enabled(), error::aborted(ENOT_ACTIVATED) ); let func = option::borrow(&func_opt); function_info::load_module_from_function(func); dispatchable_derived_balance(store, func) } else { fungible_asset::balance(store) }}
is_derived_balance_at_least
Whether the derived value of store using the overloaded hook is at least amount
The semantics of value will be governed by the function specified in DispatchFunctionStore.
#[view]public fun is_derived_balance_at_least<T: key>(store: object::Object<T>, amount: u64): bool
Implementation
public fun is_derived_balance_at_least<T: key>(store: Object<T>, amount: u64): bool { let func_opt = fungible_asset::derived_balance_dispatch_function(store); if (option::is_some(&func_opt)) { assert!( features::dispatchable_fungible_asset_enabled(), error::aborted(ENOT_ACTIVATED) ); let func = option::borrow(&func_opt); function_info::load_module_from_function(func); dispatchable_derived_balance(store, func) >= amount } else { fungible_asset::is_balance_at_least(store, amount) }}
derived_supply
Get the derived supply of the fungible asset using the overloaded hook.
The semantics of supply will be governed by the function specified in DeriveSupplyDispatch.
#[view]public fun derived_supply<T: key>(metadata: object::Object<T>): option::Option<u128>
Implementation
public fun derived_supply<T: key>(metadata: Object<T>): Option<u128> { let func_opt = fungible_asset::derived_supply_dispatch_function(metadata); if (option::is_some(&func_opt)) { assert!( features::dispatchable_fungible_asset_enabled(), error::aborted(ENOT_ACTIVATED) ); let func = option::borrow(&func_opt); function_info::load_module_from_function(func); dispatchable_derived_supply(metadata, func) } else { fungible_asset::supply(metadata) }}
borrow_transfer_ref
fun borrow_transfer_ref<T: key>(metadata: object::Object<T>): &fungible_asset::TransferRef
Implementation
inline fun borrow_transfer_ref<T: key>(metadata: Object<T>): &TransferRef acquires TransferRefStore { let metadata_addr = object::object_address( &fungible_asset::store_metadata(metadata) ); assert!( exists<TransferRefStore>(metadata_addr), error::not_found(ESTORE_NOT_FOUND) ); &borrow_global<TransferRefStore>(metadata_addr).transfer_ref}
dispatchable_withdraw
fun dispatchable_withdraw<T: key>(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>( 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,);
dispatchable_derived_balance
fun dispatchable_derived_balance<T: key>(store: object::Object<T>, function: &function_info::FunctionInfo): u64
Implementation
native fun dispatchable_derived_balance<T: key>( store: Object<T>, function: &FunctionInfo,): u64;
dispatchable_derived_supply
fun dispatchable_derived_supply<T: key>(metadata: object::Object<T>, function: &function_info::FunctionInfo): option::Option<u128>
Implementation
native fun dispatchable_derived_supply<T: key>( metadata: Object<T>, function: &FunctionInfo,): Option<u128>;
Specification
pragma verify = false;
dispatchable_withdraw
fun dispatchable_withdraw<T: key>(store: object::Object<T>, amount: u64, transfer_ref: &fungible_asset::TransferRef, function: &function_info::FunctionInfo): fungible_asset::FungibleAsset
pragma opaque;
dispatchable_deposit
fun dispatchable_deposit<T: key>(store: object::Object<T>, fa: fungible_asset::FungibleAsset, transfer_ref: &fungible_asset::TransferRef, function: &function_info::FunctionInfo)
pragma opaque;
dispatchable_derived_balance
fun dispatchable_derived_balance<T: key>(store: object::Object<T>, function: &function_info::FunctionInfo): u64
pragma opaque;
dispatchable_derived_supply
fun dispatchable_derived_supply<T: key>(metadata: object::Object<T>, function: &function_info::FunctionInfo): option::Option<u128>
pragma opaque;