Skip to content

Commit

Permalink
Use init_module in managed_fungible_asset
Browse files Browse the repository at this point in the history
  • Loading branch information
movekevin committed Mar 28, 2023
1 parent 1d06360 commit fea8099
Showing 1 changed file with 41 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
/// This module provides an addtional ready-to-use solution on top of `FungibleAssetMetadata` that manages the refs of
/// mint, burn and transfer for the creator in a straightforward scheme. It offers creators to destory any refs in an
/// on-demand manner too.
/// By deploying this module, the deployer will be creating a new managed fungible asset with the hardcoded
/// maximum supply, name, symbol, and decimals. The address of the asset can be obtained via get_asset().
/// The deployer will also become the initial admin and can mint/burn/freeze/unfreeze accounts.
/// The admin can transfer the asset via object::transfer() at any point to set a new admin.
module fungible_asset::managed_fungible_asset {
use aptos_framework::fungible_asset::{Self, MintRef, TransferRef, BurnRef, FungibleAsset};
use aptos_framework::object::{Self, Object, ConstructorRef};
use aptos_framework::object::{Self, Object};
use aptos_framework::primary_wallet;
use std::error;
use std::signer;
use std::string::String;
use std::string::utf8;

/// Only fungible asset metadata owner can make changes.
const ENOT_OWNER: u64 = 1;

const ASSET_SYMBOL: vector<u8> = b"APT";

#[resource_group_member(group = aptos_framework::object::ObjectGroup)]
/// Hold refs to control the minting, transfer and burning of fungible assets.
struct ManagedFungibleAsset has key {
Expand All @@ -21,19 +24,14 @@ module fungible_asset::managed_fungible_asset {
}

/// Initialize metadata object and store the refs.
public fun init_managed_fungible_asset(
constructor_ref: &ConstructorRef,
maximum_supply: u64,
name: String,
symbol: String,
decimals: u8
) {
fun init_module(admin: &signer) {
let constructor_ref = &object::create_named_object(admin, ASSET_SYMBOL);
let (mint_ref, transfer_ref, burn_ref) = fungible_asset::make_object_fungible(
constructor_ref,
maximum_supply,
name,
symbol,
decimals
0, /* maximum_supply. 0 means no maximum */
utf8(b"Aptos Token"), /* name */
utf8(ASSET_SYMBOL), /* symbol */
8, /* decimals */
);
let metadata_object_signer = object::generate_signer(constructor_ref);
move_to(
Expand All @@ -42,86 +40,92 @@ module fungible_asset::managed_fungible_asset {
)
}

#[view]
/// Return the address of the managed fungible asset that's created when this module is deployed.
public fun get_asset(): address {
object::create_object_address(&@fungible_asset, ASSET_SYMBOL)
}

/// Mint as the owner of metadata object.
public entry fun mint<T: key>(
metadata_owner: &signer,
admin: &signer,
metadata: Object<T>,
amount: u64,
to: address
) acquires ManagedFungibleAsset {
let mint_ref = &authorized_borrow_refs<T>(metadata_owner, metadata).mint_ref;
let mint_ref = &authorized_borrow_refs<T>(admin, metadata).mint_ref;
let to_wallet = primary_wallet::ensure_primary_wallet_exists(to, metadata);
fungible_asset::deposit(to_wallet, fungible_asset::mint(mint_ref, amount));
}

/// Transfer as the owner of metadata object ignoring `allow_ungated_transfer` field.
public entry fun transfer<T: key>(
metadata_owner: &signer,
admin: &signer,
metadata: Object<T>,
from: address,
to: address,
amount: u64,
) acquires ManagedFungibleAsset {
let transfer_ref = &authorized_borrow_refs<T>(metadata_owner, metadata).transfer_ref;
let transfer_ref = &authorized_borrow_refs<T>(admin, metadata).transfer_ref;
let from_wallet = primary_wallet::ensure_primary_wallet_exists(from, metadata);
let to_wallet = primary_wallet::ensure_primary_wallet_exists(to, metadata);
fungible_asset::transfer_with_ref(transfer_ref, from_wallet, amount, to_wallet);
}

/// Burn fungible assets as the owner of metadata object.
public entry fun burn<T: key>(
metadata_owner: &signer,
admin: &signer,
metadata: Object<T>,
from: address,
amount: u64
) acquires ManagedFungibleAsset {
let burn_ref = &authorized_borrow_refs<T>(metadata_owner, metadata).burn_ref;
let burn_ref = &authorized_borrow_refs<T>(admin, metadata).burn_ref;
let from_wallet = primary_wallet::ensure_primary_wallet_exists(from, metadata);
fungible_asset::burn(burn_ref, from_wallet, amount);
}

/// Freeze an account so it cannot transfer or receive fungible assets.
public entry fun freeze_account<T: key>(
metadata_owner: &signer,
admin: &signer,
metadata: Object<T>,
account: address,
) acquires ManagedFungibleAsset {
let transfer_ref = &authorized_borrow_refs<T>(metadata_owner, metadata).transfer_ref;
let transfer_ref = &authorized_borrow_refs<T>(admin, metadata).transfer_ref;
let wallet = primary_wallet::ensure_primary_wallet_exists(account, metadata);
fungible_asset::set_ungated_transfer(transfer_ref, wallet, false);
}

/// Unfreeze an account so it can transfer or receive fungible assets.
public entry fun unfreeze_account<T: key>(
metadata_owner: &signer,
admin: &signer,
metadata: Object<T>,
account: address,
) acquires ManagedFungibleAsset {
let transfer_ref = &authorized_borrow_refs<T>(metadata_owner, metadata).transfer_ref;
let transfer_ref = &authorized_borrow_refs<T>(admin, metadata).transfer_ref;
let wallet = primary_wallet::ensure_primary_wallet_exists(account, metadata);
fungible_asset::set_ungated_transfer(transfer_ref, wallet, true);
}

/// Withdraw as the owner of metadata object ignoring `allow_ungated_transfer` field.
public fun withdraw<T: key>(
metadata_owner: &signer,
admin: &signer,
metadata: Object<T>,
amount: u64,
from: address,
): FungibleAsset acquires ManagedFungibleAsset {
let transfer_ref = &authorized_borrow_refs<T>(metadata_owner, metadata).transfer_ref;
let transfer_ref = &authorized_borrow_refs<T>(admin, metadata).transfer_ref;
let from_wallet = primary_wallet::ensure_primary_wallet_exists(from, metadata);
fungible_asset::withdraw_with_ref(transfer_ref, from_wallet, amount)
}

/// Deposit as the owner of metadata object ignoring `allow_ungated_transfer` field.
public fun deposit<T: key>(
metadata_owner: &signer,
admin: &signer,
metadata: Object<T>,
to: address,
fa: FungibleAsset
) acquires ManagedFungibleAsset {
let transfer_ref = &authorized_borrow_refs<T>(metadata_owner, metadata).transfer_ref;
let transfer_ref = &authorized_borrow_refs<T>(admin, metadata).transfer_ref;
let to_wallet = primary_wallet::ensure_primary_wallet_exists(to, metadata);
fungible_asset::deposit_with_ref(transfer_ref, to_wallet, fa);
}
Expand All @@ -138,27 +142,19 @@ module fungible_asset::managed_fungible_asset {

#[test_only]
use aptos_framework::fungible_asset::{FungibleAssetMetadata};
#[test_only]
use std::string;

#[test_only]
public fun init_test_managing_refs(creator: &signer): Object<FungibleAssetMetadata> {
let (constructor_ref, _) = fungible_asset::create_test_token(creator);
init_managed_fungible_asset(
&constructor_ref,
100 /* max supply */,
string::utf8(b"USDA"),
string::utf8(b"$$$"),
0
);
object::object_from_constructor_ref<FungibleAssetMetadata>(&constructor_ref)
fun get_metadata(creator: &signer): Object<FungibleAssetMetadata> {
let addr = object::create_object_address(&signer::address_of(creator), ASSET_SYMBOL);
object::address_to_object<FungibleAssetMetadata>(addr)
}

#[test(creator = @0xcafe)]
fun test_basic_flow(
creator: &signer,
) acquires ManagedFungibleAsset {
let metadata = init_test_managing_refs(creator);
init_module(creator);
let metadata = get_metadata(creator);
let creator_address = signer::address_of(creator);
let aaron_address = @0xface;

Expand All @@ -180,7 +176,8 @@ module fungible_asset::managed_fungible_asset {
creator: &signer,
aaron: &signer
) acquires ManagedFungibleAsset {
let metadata = init_test_managing_refs(creator);
init_module(creator);
let metadata = get_metadata(creator);
let creator_address = signer::address_of(creator);
mint(aaron, metadata, 100, creator_address);
}
Expand Down

0 comments on commit fea8099

Please sign in to comment.