Skip to content

Commit

Permalink
[move-examples] pre-minted managed FA
Browse files Browse the repository at this point in the history
  • Loading branch information
lightmark authored and xbtmatt committed Jul 25, 2023
1 parent 04b196d commit 27f5314
Show file tree
Hide file tree
Showing 14 changed files with 229 additions and 216 deletions.
49 changes: 37 additions & 12 deletions aptos-move/e2e-move-tests/src/tests/fungible_asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,57 +23,82 @@ fn test_basic_fungible_token() {
let mut build_options = aptos_framework::BuildOptions::default();
build_options
.named_addresses
.insert("fungible_token".to_string(), *alice.address());
.insert("example_addr".to_string(), *alice.address());

let result = h.publish_package_with_options(
&alice,
&common::test_dir_path("../../../move-examples/fungible_token"),
&common::test_dir_path("../../../move-examples/fungible_asset/managed_fungible_asset"),
build_options.clone(),
);

assert_success!(result);
let result = h.publish_package_with_options(
&alice,
&common::test_dir_path("../../../move-examples/fungible_asset/managed_fungible_token"),
build_options,
);
assert_success!(result);

let metadata = h
.execute_view_function(
str::parse(&format!(
"0x{}::managed_fungible_token::get_metadata",
*alice.address()
))
.unwrap(),
vec![],
vec![],
)
.unwrap()
.pop()
.unwrap();
let metadata = bcs::from_bytes::<AccountAddress>(metadata.as_slice()).unwrap();

let result = h.run_entry_function(
&alice,
str::parse(&format!(
"0x{}::managed_fungible_token::mint",
"0x{}::managed_fungible_asset::mint_to_primary_stores",
*alice.address()
))
.unwrap(),
vec![],
vec![
bcs::to_bytes::<u64>(&100).unwrap(), // amount
bcs::to_bytes(alice.address()).unwrap(),
bcs::to_bytes(&metadata).unwrap(),
bcs::to_bytes(&vec![alice.address()]).unwrap(),
bcs::to_bytes(&vec![100u64]).unwrap(), // amount
],
);
assert_success!(result);

let result = h.run_entry_function(
&alice,
str::parse(&format!(
"0x{}::managed_fungible_token::transfer",
"0x{}::managed_fungible_asset::transfer_between_primary_stores",
*alice.address()
))
.unwrap(),
vec![],
vec![
bcs::to_bytes(alice.address()).unwrap(),
bcs::to_bytes(bob.address()).unwrap(),
bcs::to_bytes::<u64>(&30).unwrap(), // amount
bcs::to_bytes(&metadata).unwrap(),
bcs::to_bytes(&vec![alice.address()]).unwrap(),
bcs::to_bytes(&vec![bob.address()]).unwrap(),
bcs::to_bytes(&vec![30u64]).unwrap(), // amount
],
);

assert_success!(result);
let result = h.run_entry_function(
&alice,
str::parse(&format!(
"0x{}::managed_fungible_token::burn",
"0x{}::managed_fungible_asset::burn_from_primary_stores",
*alice.address()
))
.unwrap(),
vec![],
vec![
bcs::to_bytes(bob.address()).unwrap(),
bcs::to_bytes::<u64>(&20).unwrap(), // amount
bcs::to_bytes(&metadata).unwrap(),
bcs::to_bytes(&vec![bob.address()]).unwrap(),
bcs::to_bytes(&vec![20u64]).unwrap(), // amount
],
);
assert_success!(result);
Expand Down
6 changes: 6 additions & 0 deletions aptos-move/move-examples/fungible_asset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Fungible Asset

* Managed fungible asset: A full-fledged fungible asset with customizable management capabilities and associated functions, based on which a light example is provided to show how to issue coin.
* Managed fungible token: A fungible token example that adds token resource to the metadata object.
* Simple managed coin: an all-in-one module implementing managed coin using fungible asset with limited functionalities (only deal with primary fungible stores).
* Pre-minted managed coin: An example issuing pre-minting coin based on managed fungible asset.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "ManagedFungibleAsset"
version = "0.0.0"

[addresses]
aptos_framework = "0x1"
aptos_token_objects = "0x4"
example_addr = "_"

[dependencies]
AptosFramework = { local = "../../../framework/aptos-framework" }
AptosTokenObjects = { local = "../../../framework/aptos-token-objects" }
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/// A coin example using managed_fungible_asset to create a fungible "coin" and helper functions to only interact with
/// primary fungible stores.
/// primary fungible stores only.
module example_addr::coin_example {
use aptos_framework::object;
use aptos_framework::fungible_asset::{Metadata, FungibleAsset};
use aptos_framework::fungible_asset::{Self, Metadata, FungibleAsset};
use aptos_framework::object::Object;
use example_addr::managed_fungible_asset;
use std::string::utf8;
Expand Down Expand Up @@ -83,9 +83,8 @@ module example_addr::coin_example {
use aptos_framework::primary_fungible_store;
#[test_only]
use std::signer;
use aptos_framework::fungible_asset;

#[test(creator = @0xcafe)]
#[test(creator = @example_addr)]
fun test_basic_flow(creator: &signer) {
init_module(creator);
let creator_address = signer::address_of(creator);
Expand All @@ -104,7 +103,7 @@ module example_addr::coin_example {
burn(creator, creator_address, 90);
}

#[test(creator = @0xcafe, aaron = @0xface)]
#[test(creator = @example_addr, aaron = @0xface)]
#[expected_failure(abort_code = 0x50001, location = example_addr::managed_fungible_asset)]
fun test_permission_denied(creator: &signer, aaron: &signer) {
init_module(creator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ module example_addr::managed_fungible_asset {
object_from_constructor_ref<Metadata>(constructor_ref)
}

#[test(creator = @0xcafe)]
#[test(creator = @example_addr)]
fun test_basic_flow(
creator: &signer,
) acquires ManagingRefs {
Expand Down Expand Up @@ -406,7 +406,7 @@ module example_addr::managed_fungible_asset {
assert!(primary_fungible_store::balance(aaron_address, metadata) == 0, 11);
}

#[test(creator = @0xcafe, aaron = @0xface)]
#[test(creator = @example_addr, aaron = @0xface)]
#[expected_failure(abort_code = 0x50001, location = Self)]
fun test_permission_denied(
creator: &signer,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "ManagedFungibleToken"
version = "0.0.0"

[addresses]
aptos_framework = "0x1"
aptos_token_objects = "0x4"
example_addr = "_"

[dependencies]
AptosFramework = { local = "../../../framework/aptos-framework" }
AptosTokenObjects = { local = "../../../framework/aptos-token-objects" }
ManagedFungibleAsset = { local = "../managed_fungible_asset" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/// An example combining fungible assets with token as fungible token. In this example, a token object is used as
/// metadata to create fungible units, aka, fungible tokens.
module example_addr::managed_fungible_token {
use aptos_framework::fungible_asset::Metadata;
use aptos_framework::object::{Self, Object};
use std::string::{utf8, String};
use std::option;
use aptos_token_objects::token::{create_named_token, create_token_seed};
use aptos_token_objects::collection::create_fixed_collection;
use example_addr::managed_fungible_asset;

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

/// Initialize metadata object and store the refs.
fun init_module(admin: &signer) {
let collection_name: String = utf8(b"test collection name");
let token_name: String = utf8(b"test token name");
create_fixed_collection(
admin,
utf8(b"test collection description"),
1,
collection_name,
option::none(),
utf8(b"http://aptoslabs.com/collection"),
);
let constructor_ref = &create_named_token(admin,
collection_name,
utf8(b"test token description"),
token_name,
option::none(),
utf8(b"http://aptoslabs.com/token"),
);

managed_fungible_asset::initialize(
constructor_ref,
0, /* maximum_supply. 0 means no maximum */
utf8(b"test fungible token"), /* name */
utf8(ASSET_SYMBOL), /* symbol */
0, /* decimals */
utf8(b"http://example.com/favicon.ico"), /* icon */
utf8(b"http://example.com"), /* project */
vector[true, true, true], /* mint_ref, transfer_ref, burn_ref */
);
}

#[view]
/// Return the address of the managed fungible asset that's created when this module is deployed.
/// This function is optional as a helper function for offline applications.
public fun get_metadata(): Object<Metadata> {
let collection_name: String = utf8(b"test collection name");
let token_name: String = utf8(b"test token name");
let asset_address = object::create_object_address(
&@example_addr,
create_token_seed(&collection_name, &token_name)
);
object::address_to_object<Metadata>(asset_address)
}

#[test(creator = @example_addr)]
fun test_init(creator: &signer) {
init_module(creator);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "ManagedFungibleToken"
version = "0.0.0"

[addresses]
aptos_framework = "0x1"
example_addr = "_"

[dependencies]
AptosFramework = { local = "../../../framework/aptos-framework" }
ManagedFungibleAsset = { local = "../managed_fungible_asset" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/// This module shows an example how to issue preminted coin with only `transfer` and `burn` managing capabilities.
/// It leveraged `managed_fungible_asset` module with only `TransferRef` and `BurnRef` stored after pre-minting a
/// pre-defined totally supply to a reserve account. After the initialization, the total supply can increase by no means
/// since `MintRef` of this fungible asset does not exist anymore.
/// The `init_module()` code can be modified to customize the managing refs as needed.
module example_addr::preminted_managed_coin {
use aptos_framework::fungible_asset::{Self, Metadata};
use aptos_framework::object::{Self, Object};
use aptos_framework::primary_fungible_store;
use example_addr::managed_fungible_asset;
use std::signer;
use std::string::utf8;

const ASSET_SYMBOL: vector<u8> = b"MEME";
const PRE_MINTED_TOTAL_SUPPLY: u64 = 10000;

/// Initialize metadata object and store the refs.
fun init_module(admin: &signer) {
let constructor_ref = &object::create_named_object(admin, ASSET_SYMBOL);
managed_fungible_asset::initialize(
constructor_ref,
1000000000, /* maximum_supply */
utf8(b"preminted coin"), /* name */
utf8(ASSET_SYMBOL), /* symbol */
8, /* decimals */
utf8(b"http://example.com/favicon.ico"), /* icon */
utf8(b"http://example.com"), /* project */
vector[false, true, true], /* mint_ref, transfer_ref, burn_ref */
);

// Create mint ref to premint fungible asset with a fixed supply volume into a specific account.
// This account can be any account including normal user account, resource account, multi-sig account, etc.
// We just use the creator account to show the proof of concept.
let mint_ref = fungible_asset::generate_mint_ref(constructor_ref);
let admin_primary_store = primary_fungible_store::ensure_primary_store_exists(
signer::address_of(admin),
get_metadata()
);
fungible_asset::mint_to(&mint_ref, admin_primary_store, PRE_MINTED_TOTAL_SUPPLY);
}

#[view]
/// Return the address of the metadata that's created when this module is deployed.
/// This function is optional as a helper function for offline applications.
public fun get_metadata(): Object<Metadata> {
let metadata_address = object::create_object_address(&@example_addr, ASSET_SYMBOL);
object::address_to_object<Metadata>(metadata_address)
}

#[test_only]
use std::option;

#[test(creator = @example_addr)]
#[expected_failure(abort_code = 0x60004, location = example_addr::managed_fungible_asset)]
fun test_basic_flow(creator: &signer) {
init_module(creator);
let creator_address = signer::address_of(creator);
let metadata = get_metadata();

assert!(option::destroy_some(fungible_asset::supply(metadata)) == (PRE_MINTED_TOTAL_SUPPLY as u128), 1);
managed_fungible_asset::mint_to_primary_stores(creator, metadata, vector[creator_address], vector[100]);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[package]
name = "FungibleAsset"
name = "SimpleManagedCoin"
version = "0.0.0"

[addresses]
aptos_framework = "0x1"
example_addr = "_"

[dependencies]
AptosFramework = { local = "../../framework/aptos-framework" }
AptosFramework = { local = "../../../framework/aptos-framework" }
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ module example_addr::simple_managed_coin {
borrow_global<ManagedFungibleAsset>(object::object_address(&asset))
}

#[test(creator = @0xcafe)]
#[test(creator = @example_addr)]
fun test_basic_flow(
creator: &signer,
) acquires ManagedFungibleAsset {
Expand All @@ -143,7 +143,7 @@ module example_addr::simple_managed_coin {
burn(creator, creator_address, 90);
}

#[test(creator = @0xcafe, aaron = @0xface)]
#[test(creator = @example_addr, aaron = @0xface)]
#[expected_failure(abort_code = 0x50001, location = Self)]
fun test_permission_denied(
creator: &signer,
Expand Down
12 changes: 0 additions & 12 deletions aptos-move/move-examples/fungible_token/Move.toml

This file was deleted.

Loading

0 comments on commit 27f5314

Please sign in to comment.