# Aptos: 第一个 Move 智能合约

Original: <https://lifelonglearn.ing/into-aptos-and-move>

Author: [奶爸](https://lifelonglearn.ing/users/3b04650c-8231-499b-8ef0-381fc4d7efb0)

Published: 2022-10-21T13:50:25Z

Updated: 2026-09-27T06:57:43Z

Version: 1

昨天刚刚上手 Aptos，部署一个 move 合约测试测试，结果调用合约时总不成功，今天晚上再次测试成功调用，记录一下详细过程。

1. 首先安装 ​**aptos-cli**​，预编译二进制 [下载地址 ✈️](https://lifelonglearn.ing/r/go?url=aHR0cHM6Ly9naXRodWIuY29tL2FwdG9zLWxhYnMvYXB0b3MtY29yZS9yZWxlYXNlcw==)
2. 创建新账号，选择 `devnet`（默认）会自动领取水龙头
   ```shell
   aptos init
   ```
3. 创建项目文件夹
   ```shell
   mkdir -p learn-move/sources && cd learn-move
   ```
4. 在文件夹中创建文件 `Move.toml`，文件内容如下
   ```toml
   [package]
   name = "TestCoin"
   version = "0.0.1"

   [dependencies]
   AptosFramework = { git = "https://github.com/aptos-labs/aptos-core.git", subdir = "aptos-move/framework/aptos-framework/", rev = "devnet" }
   MoveStdlib = { git = "https://github.com/aptos-labs/aptos-core.git", subdir = "aptos-move/framework/move-stdlib", rev = "devnet" }

   [addresses]
   NBCOIN = '_'
   ```
5. 在 `sources` 文件夹中创建智能合约文件 `TestCoin.move`，内容如下
   ```move
   module NBCOIN::TestCoin{
       use std::signer;
       use std::string;

       struct Coin has store {
           value : u128,
       }

       struct CoinStore has key {
           coin : Coin,
       }

       struct CoinInfo has key {
           // name
           name: string::String,
           // symbol
           symbol: string::String,
           // decimals
           decimals: u8,
           // suppley
           supply: u128,
           // capcity
           cap: u128,
       }

       /// Address of the owner of this module
       const MODULE_OWNER: address = @NBCOIN;

       const THE_ACCOUNT_HAS_BEEN_REGISTERED : u64 = 1;

       const INVALID_TOKEN_OWNER : u64 = 2;

       const THE_ACCOUNT_IS_NOT_REGISTERED : u64 = 3;

       const INSUFFICIENT_BALANCE : u64 = 4;

       const ECOIN_INFO_ALREADY_PUBLISHED : u64 = 5;

       const EXCEEDING_THE_TOTAL_SUPPLY : u64 = 6;

       public fun getBalance(owner: address) : u128 acquires CoinStore{

           assert!(is_account_registered(owner), THE_ACCOUNT_IS_NOT_REGISTERED);

           borrow_global<CoinStore>(owner).coin.value
       }


       public fun is_account_registered(account_addr : address) : bool{
           exists<CoinStore>(account_addr)
       }

       fun deposit(account_addr : address, coin : Coin) acquires CoinStore {

           assert!(is_account_registered(account_addr), THE_ACCOUNT_IS_NOT_REGISTERED);

           let balance = getBalance(account_addr);

           let balance_ref = &mut borrow_global_mut<CoinStore>(account_addr).coin.value;

           *balance_ref = balance + coin.value;

           let Coin { value:_ } = coin;
       }

       fun withdraw(account_addr : address, amount : u128) : Coin acquires CoinStore {
           assert!(is_account_registered(account_addr), THE_ACCOUNT_IS_NOT_REGISTERED);
           let balance = getBalance(account_addr);

           assert!(balance >= amount, INSUFFICIENT_BALANCE);

           let balance_ref = &mut borrow_global_mut<CoinStore>(account_addr).coin.value;

           *balance_ref = balance - amount;

           Coin { value: amount }
       }


       public entry fun initialize(address : &signer, name : string::String, symbol : string::String, decimals : u8, supply : u128)  {

           assert!(signer::address_of(address) == MODULE_OWNER, INVALID_TOKEN_OWNER);

           assert!(!exists<CoinInfo>(MODULE_OWNER), ECOIN_INFO_ALREADY_PUBLISHED);

           move_to(address, CoinInfo{name : name, symbol : symbol, decimals, supply, cap : 0});
       }


       public entry fun register(address : &signer) {
           let account = signer::address_of(address);

           assert!(!exists<CoinStore>(account), THE_ACCOUNT_HAS_BEEN_REGISTERED);

           move_to(address, CoinStore{ coin : Coin{ value : 0 } });
       }


       public entry fun mint(owner : &signer,to : address,amount : u128) acquires CoinStore,CoinInfo{

           assert!(signer::address_of(owner) == MODULE_OWNER, INVALID_TOKEN_OWNER);

           assert!(borrow_global<CoinInfo>(MODULE_OWNER).cap + amount <= borrow_global<CoinInfo>(MODULE_OWNER).supply,EXCEEDING_THE_TOTAL_SUPPLY);

           deposit(to, Coin { value : amount });

           let cap = &mut borrow_global_mut<CoinInfo>(MODULE_OWNER).cap;
           *cap = *cap + amount;
       }



       public entry fun transfer(from : &signer, to : address, amount : u128) acquires CoinStore {

           let coin = withdraw(signer::address_of(from), amount);

           deposit(to, coin);
       }


       public entry fun burn(owner : &signer, amount : u128) acquires CoinStore,CoinInfo {

           assert!(signer::address_of(owner) == MODULE_OWNER, INVALID_TOKEN_OWNER);

           let coin = withdraw(signer::address_of(owner), amount);
           let Coin { value: amount } = coin;

           let cap = &mut borrow_global_mut<CoinInfo>(MODULE_OWNER).cap;
           *cap = *cap - amount;

           let supply = &mut borrow_global_mut<CoinInfo>(MODULE_OWNER).supply;
           *supply = *supply - amount;
       }
   }
   ```
6. 编译合约
   ```shell
   aptos move compile --named-addresses NBCOIN=default
   ```
7. 部署合约
   ```shell
   aptos move publish --named-addresses NBCOIN=default
   ```
8. 初始化 TestCoin
   ```shell
   aptos move run \
     --function-id 'default::TestCoin::initialize' \
     --args 'string:NBCOIN' 'string:NBC' u8:8 u128:1000000
   ```
9. 将默认账户注册到 TestCoin
   ```shell
   aptos move run \
     --function-id 'default::TestCoin::register'
   ```
10. 为默认账户 mint 一些代币
    ```shell
    aptos move run \
      --function-id 'default::TestCoin::mint' \
      --args address:default u128:1000000
    ```
11. 创建新账户`a2`（使用 `devnet`，会自动领水龙头）
    ```shell
    aptos init --profile a2
    ```
12. 给 `a2` 账户注册
    ```shell
    aptos move run \
      --profile a2 \
      --function-id 'default::TestCoin::register'
    ```
13. 使用 `default` 账户给 `a2` 转账
    ```shell
    aptos move run \
      --function-id 'default::TestCoin::transfer' \
      --args address:a2 u128:10000
    ```

全流程结束～
