Movement Packages

This section examines the Move standard library and Aptos framework. These are the most common starting points in M1 development.

Disclaimer: there are many more useful modules in the standard library and framework. We will discuss some of them in this course and encourage you to explore them as you go.


aptos_std::debug::print serializes and prints a Move value to the console using a VM native func. The associated [debug] outputs are easiest to view when unit testing.

aptos_std::debug::print_stack_trace prints the current stack.

The below is an example demonstrating print string nuances in 💻 hello_world.

fn main() {
module hello_world::hello_world {

    use std::string;
    use std::signer;
    use aptos_std::debug;

    #[test(account = @0x1)]
    public entry fun sender_can_set_message(account: signer) {
        let addr = signer::address_of(&account);
        let message = b"Hello, world!";
        let str_message = string::utf8(message);

std::vector and aptos_std::big_vector

A useful dynamically size collection with an aptos_std:: counterpart optimized for a large number of elements.

The below is an example of searching through std::vector in open addressing hash map implementation from 💻 data_structures.

fn main() {
public fun find<K, V>(map: &OaHashMap<K, V>, key: &K) : &Option<Entry<K, V>> {
    let index = compute_hash_index(key, map.size);
    let count = 0;
    loop {
        let option_value = vector::borrow(&map.entries, index % map.size);
        if (option::is_none(option_value)) {
            return option_value
        } else {
            let entry = option::borrow(option_value);
            if (key_equals(&entry.key, key)) {
                return option_value
        index = index + 1;
        count = count + 1;
        if (count > map.size) {
            abort ENO_BUFFER_EXHAUSTED



An associative array.

fn main() {
fun run_table(account: signer) {
    let t = table::new<u64, u8>();
    let key: u64 = 100;
    let error_code: u64 = 1;
    assert!(!table::contains(&t, key), error_code);
    assert!(*table::borrow_with_default(&t, key, &12) == 12, error_code);
    add(&mut t, key, 1);
    assert!(*table::borrow_with_default(&t, key, &12) == 1, error_code);
    move_to(&account, TableHolder{ t });


This module defines the Option type and its methods to represent and handle an optional value. The implementation is based on a vector.

fn main() {
fun option_contains() {
    let none = option::none<u64>();
    let some = option::some(5);
    let some_other = option::some(6);
    assert!(option::contains(&some, &5), 0);
    assert!(option::contains(&some_other, &6), 1);
    assert!(!option::contains(&none, &5), 2);
    assert!(!option::contains(&some_other, &5), 3);


One of the most notable features of the aptos_framework is its resource accounts. Per Aptos, "a resource account is a developer feature used to manage resources independent of an account managed by a user, specifically publishing modules and automatically signing for transactions." In some ways, you can think of a resource account as an administrator or service account. In most large projects, you will want to use resource accounts to--in the least--manage deployments.

Using resource accounts takes some practice. We encourage you to closely consider the code in 💻 mini_dex to get a better sense of how to use resource accounts.

fn main() {
public entry fun initialize_lp_account(
    minidx_admin: &signer,
    lp_coin_metadata_serialized: vector<u8>,
    lp_coin_code: vector<u8>
) {
    assert!(signer::address_of(minidx_admin) == @mini_dex, EInvalidAccount);

    let (lp_acc, signer_cap) =
        account::create_resource_account(minidx_admin, b"LP_CREATOR_SEED");
    move_to(minidx_admin, CapabilityStorage { signer_cap });

For many common coin and NFT operations, the Aptos framework provides a set of methods that will manage capabilities. For example, the below is a snippet from an aptos-core example demonstrating how to initialize a coin:

fn main() {
/// initialize the module and store the signer cap, mint cap and burn cap within 
fun init_module(account: &signer) {
    // store the capabilities within `ModuleData`
    let resource_signer_cap = resource_account::retrieve_resource_account_cap(account, @source_addr);
    let (burn_cap, freeze_cap, mint_cap) = coin::initialize<ChloesCoin>(
        string::utf8(b"Chloe's Coin"),
    move_to(account, ModuleData {

    // destroy freeze cap because we aren't using it

    // regsiter the resource account with both coins so it has a CoinStore to store those coins

However, you will also often have to define your own capabilities. In the Aptos Framework, you will usually find it most idiomatic and convenient to use use aptos_framework::account::SignerCapability for this.

Review 💻 mini_dex for an example of how to use SignerCapability to manage unique capabilities. As a challenge, design your own simple module including resource account logic and a SignerCapability.