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
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. | Requirement | Criticality | Implementation | Enforcement |
---|---|---|---|---|
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);}