Skip to content

aptos_coin - [mainnet]

This module defines a minimal and generic Coin and Balance. modified from https://github.com/move-language/move/tree/main/language/documentation/tutorial

use 0x1::coin;
use 0x1::error;
use 0x1::option;
use 0x1::signer;
use 0x1::string;
use 0x1::system_addresses;
use 0x1::vector;

Constants

Mint capability has already been delegated to this specified address

const EALREADY_DELEGATED: u64 = 2;

Cannot find delegation of mint capability to this account

const EDELEGATION_NOT_FOUND: u64 = 3;

Account does not have mint capability

const ENO_CAPABILITIES: u64 = 1;

Structs

DelegatedMintCapability

Delegation token created by delegator and can be claimed by the delegatee as MintCapability.

struct DelegatedMintCapability has store
Fields
to: address

Resources

AptosCoin

struct AptosCoin has key
Fields
dummy_field: bool

MintCapStore

struct MintCapStore has key
Fields
mint_cap: coin::MintCapability<aptos_coin::AptosCoin>

Delegations

The container stores the current pending delegations.

struct Delegations has key
Fields
inner: vector<aptos_coin::DelegatedMintCapability>

Functions

initialize

Can only called during genesis to initialize the Aptos coin.

public(friend) fun initialize(aptos_framework: &signer): (coin::BurnCapability<aptos_coin::AptosCoin>, coin::MintCapability<aptos_coin::AptosCoin>)
Implementation
public(friend) fun initialize(aptos_framework: &signer): (BurnCapability<AptosCoin>, MintCapability<AptosCoin>) {
system_addresses::assert_aptos_framework(aptos_framework);
let (burn_cap, freeze_cap, mint_cap) = coin::initialize_with_parallelizable_supply<AptosCoin>(
aptos_framework,
string::utf8(b"Aptos Coin"),
string::utf8(b"APT"),
8, // decimals
true, // monitor_supply
);
// Aptos framework needs mint cap to mint coins to initial validators. This will be revoked once the validators
// have been initialized.
move_to(aptos_framework, MintCapStore { mint_cap });
coin::destroy_freeze_cap(freeze_cap);
(burn_cap, mint_cap)
}

has_mint_capability

public fun has_mint_capability(account: &signer): bool
Implementation
public fun has_mint_capability(account: &signer): bool {
exists<MintCapStore>(signer::address_of(account))
}

destroy_mint_cap

Only called during genesis to destroy the aptos framework account’s mint capability once all initial validators and accounts have been initialized during genesis.

public(friend) fun destroy_mint_cap(aptos_framework: &signer)
Implementation
public(friend) fun destroy_mint_cap(aptos_framework: &signer) acquires MintCapStore {
system_addresses::assert_aptos_framework(aptos_framework);
let MintCapStore { mint_cap } = move_from<MintCapStore>(@aptos_framework);
coin::destroy_mint_cap(mint_cap);
}

configure_accounts_for_test

Can only be called during genesis for tests to grant mint capability to aptos framework and core resources accounts. Expects account and APT store to be registered before calling.

public(friend) fun configure_accounts_for_test(aptos_framework: &signer, core_resources: &signer, mint_cap: coin::MintCapability<aptos_coin::AptosCoin>)
Implementation
public(friend) fun configure_accounts_for_test(
aptos_framework: &signer,
core_resources: &signer,
mint_cap: MintCapability<AptosCoin>,
) {
system_addresses::assert_aptos_framework(aptos_framework);
// Mint the core resource account AptosCoin for gas so it can execute system transactions.
let coins = coin::mint<AptosCoin>(
18446744073709551615,
&mint_cap,
);
coin::deposit<AptosCoin>(signer::address_of(core_resources), coins);
move_to(core_resources, MintCapStore { mint_cap });
move_to(core_resources, Delegations { inner: vector::empty() });
}

mint

Only callable in tests and testnets where the core resources account exists. Create new coins and deposit them into dst_addr’s account.

public entry fun mint(account: &signer, dst_addr: address, amount: u64)
Implementation
public entry fun mint(
account: &signer,
dst_addr: address,
amount: u64,
) acquires MintCapStore {
let account_addr = signer::address_of(account);
assert!(
exists<MintCapStore>(account_addr),
error::not_found(ENO_CAPABILITIES),
);
let mint_cap = &borrow_global<MintCapStore>(account_addr).mint_cap;
let coins_minted = coin::mint<AptosCoin>(amount, mint_cap);
coin::deposit<AptosCoin>(dst_addr, coins_minted);
}

delegate_mint_capability

Only callable in tests and testnets where the core resources account exists. Create delegated token for the address so the account could claim MintCapability later.

public entry fun delegate_mint_capability(account: signer, to: address)
Implementation
public entry fun delegate_mint_capability(account: signer, to: address) acquires Delegations {
system_addresses::assert_core_resource(&account);
let delegations = &mut borrow_global_mut<Delegations>(@core_resources).inner;
vector::for_each_ref(delegations, |element| {
let element: &DelegatedMintCapability = element;
assert!(element.to != to, error::invalid_argument(EALREADY_DELEGATED));
});
vector::push_back(delegations, DelegatedMintCapability { to });
}

claim_mint_capability

Only callable in tests and testnets where the core resources account exists. Claim the delegated mint capability and destroy the delegated token.

public entry fun claim_mint_capability(account: &signer)
Implementation
public entry fun claim_mint_capability(account: &signer) acquires Delegations, MintCapStore {
let maybe_index = find_delegation(signer::address_of(account));
assert!(option::is_some(&maybe_index), EDELEGATION_NOT_FOUND);
let idx = *option::borrow(&maybe_index);
let delegations = &mut borrow_global_mut<Delegations>(@core_resources).inner;
let DelegatedMintCapability { to: _ } = vector::swap_remove(delegations, idx);
// Make a copy of mint cap and give it to the specified account.
let mint_cap = borrow_global<MintCapStore>(@core_resources).mint_cap;
move_to(account, MintCapStore { mint_cap });
}

find_delegation

fun find_delegation(addr: address): option::Option<u64>
Implementation
fun find_delegation(addr: address): Option<u64> acquires Delegations {
let delegations = &borrow_global<Delegations>(@core_resources).inner;
let i = 0;
let len = vector::length(delegations);
let index = option::none();
while (i < len) {
let element = vector::borrow(delegations, i);
if (element.to == addr) {
index = option::some(i);
break
};
i = i + 1;
};
index
}

Specification

High-level Requirements

No.RequirementCriticalityImplementationEnforcement
1 The native token, APT, must be initialized during genesis. Medium The initialize function is only called once, during genesis. Formally verified via initialize.
2 The APT coin may only be created exactly once. Medium The initialization function may only be called once. Enforced through the coin module, which has been audited.
4 Any type of operation on the APT coin should fail if the user has not registered for the coin. Medium Coin operations may succeed only on valid user coin registration. Enforced through the coin module, which has been audited.

Module-level Specification

pragma verify = true;
pragma aborts_if_is_partial;

initialize

public(friend) fun initialize(aptos_framework: &signer): (coin::BurnCapability<aptos_coin::AptosCoin>, coin::MintCapability<aptos_coin::AptosCoin>)
pragma verify = false;
aborts_if permissioned_signer::spec_is_permissioned_signer(aptos_framework);
let addr = signer::address_of(aptos_framework);
aborts_if addr != @aptos_framework;
aborts_if !string::spec_internal_check_utf8(b"Aptos Coin");
aborts_if !string::spec_internal_check_utf8(b"APT");
aborts_if exists<MintCapStore>(addr);
aborts_if exists<coin::CoinInfo<AptosCoin>>(addr);
aborts_if !exists<aggregator_factory::AggregatorFactory>(addr);
// This enforces high-level requirement 1:
ensures exists<MintCapStore>(addr);
// This enforces high-level requirement 3:
ensures global<MintCapStore>(addr).mint_cap == MintCapability<AptosCoin> {};
ensures exists<coin::CoinInfo<AptosCoin>>(addr);
ensures result_1 == BurnCapability<AptosCoin> {};
ensures result_2 == MintCapability<AptosCoin> {};

destroy_mint_cap

public(friend) fun destroy_mint_cap(aptos_framework: &signer)
let addr = signer::address_of(aptos_framework);
aborts_if addr != @aptos_framework;
aborts_if !exists<MintCapStore>(@aptos_framework);

configure_accounts_for_test

public(friend) fun configure_accounts_for_test(aptos_framework: &signer, core_resources: &signer, mint_cap: coin::MintCapability<aptos_coin::AptosCoin>)
pragma verify = false;

mint

public entry fun mint(account: &signer, dst_addr: address, amount: u64)
pragma verify = false;

delegate_mint_capability

public entry fun delegate_mint_capability(account: signer, to: address)
pragma verify = false;

claim_mint_capability

public entry fun claim_mint_capability(account: &signer)
pragma verify = false;

find_delegation

fun find_delegation(addr: address): option::Option<u64>
aborts_if !exists<Delegations>(@core_resources);
schema ExistsAptosCoin {
requires exists<coin::CoinInfo<AptosCoin>>(@aptos_framework);
}