Hello Move | Move dApp Quick Learning 0x01

Authors: Leeduckgo, Ningbo Wang, Junfeng Chen @ NonceGeekDAO

Translator: msfew

We've been evolving from binary to assembly to various high-level languages. Smart contracts, too, have taken a big step forward from Bitcoin's Script to Ethereum's Solidity, but can Solidity take over the world? In fact, the endless security issues that have been plaguing us have largely limited the development of the industry as a whole. "Security" is more important than ever in the financial scenario, especially in the DeFi era, and we cannot turn a blind eye to these issues. If the blockchain industry continues to evolve, there will inevitably be better smart contract languages coming out.

With these premises in mind, a new smart contract language, Move, was designed for "resource" oriented programming. I personally think that "resource-oriented programming" is a change in the smart contract language, and frankly, it is a big step forward.

——jolestar

——https://starcoin.org/zh/developer/blog/starcoin_move_resource

——https://mirror.xyz/jolestar.eth/sQ0nMCO3eNig6gCzqQO7xew1mn8oUi1-rKtfZKmGlNI

This series will explain the Move language and the development of the Move dApp, and the computer principles behind it, using Starcoin as an example.

For a full update of this series, see:

https://github.com/WeLightProject/Web3-dApp-Camp/tree/main/move-dapp

Assignments:

https://github.com/WeLightProject/Web3-dApp-Camp/discussions/categories/projects-others

1 Node Start-up

Download the latest distribution of the Starcoin node program (for MacOS just copy it to the /usr/local/bin directory):

https://github.com/starcoinorg/starcoin/releases

Here is a demonstration of how to start a node based on the Starcoin network:

https://starcoinorg.github.io/starcoin-cookbook/docs/getting-started/setup/

TLDR version - key commands:

# Start a local dev node
$ starcoin -n dev
# Start a local dev node and open the console at the same time. The -d parameter ensures that historical data is kept each time the console is opened instead of reopened
$ mkdir [folder_name]
$ cd [folder_name]
$ pwd
$ starcoin -d [path_to_your_data_folder] -n dev console

starcoin Console commands.

# Designated accounts receive test tokens
starcoin% dev get-coin 0xb7c46353c6c0e3a2559d5b12cad981e4 -v 100STC
# Account list
starcoin% account list
# Single account status view
starcoin% account show 0xb7c46353c6c0e3a2559d5b12cad981e4
# Create new account
starcoin% account create -p [pwd]

2 The first Move contract -- MyCounter

Minimum practicable example:

https://github.com/starcoinorg/starcoin-cookbook/blob/main/examples/my-counter

module MyCounterAddr::MyCounter {
     use StarcoinFramework::Signer;

     struct Counter has key, store {
        value:u64,
     }
     public fun init(account: &signer){
        move_to(account, Counter{value:0});
     }
     public fun incr(account: &signer) acquires Counter {
        let counter = borrow_global_mut<Counter>(Signer::address_of(account));
        counter.value = counter.value + 1;
     }

     public(script) fun init_counter(account: signer){
        Self::init(&account)
     }

     public(script) fun incr_counter(account: signer)  acquires Counter {
        Self::incr(&account)
     }
}

MyCounter source code analysis

A module is a set of functions and structures packaged together at a specific address. To use script, you need to run it with a published module or standard library, which is itself a set of modules published at address 0x1.

module MyCounterAddr::MyCounter{ } then a module is created under this MyCounterAddr address (corresponding to MyCounterAddr = "0xb7c46353c6c0e3a2559d5b12cad981e4" under Move.toml).

use StarcoinFramework::Signer, is using the Signer module under the standard library. Signer is a native Resource-like non-reproducible type that contains the address of the sender of the transaction. One of the reasons for introducing the signer type was to explicitly show which functions require sender privileges and which do not. Thus, functions cannot trick users into unauthorized access to their Resource. See source code for details.

struct Counter has key, store {
        value:u64,
     }

A structure called Counter is defined using struct, modified by both key,store constraints, and Move has a flexible type system where each type can be modified by four constraints. These four constraints, which we call abilities, define whether the type's values can be copied, dropped, and stored.
The four abilities constraints are: Copy, Drop, Store and Key.

Their functions are.

  • Copy - The modified value can be copied.
  • Drop - The modified value can be dropped at the end of the scope.
  • Key - the modified value can be accessed as a key to the global state.
  • Store - The modified value can be stored to the global state.

The key,store modifier here means that it cannot be copied, discarded or reused, but it can be safely stored and transferred.

The following is the definition:

public fun init(account: &signer){
    move_to(account, Counter{value:0});
}
public fun incr(account: &signer) acquires Counter {
    let counter = borrow_global_mut<Counter>(Signer::address_of(account));
    counter.value = counter.value + 1;
}

The definition format is:

public fun functionName(parameter: parameter type){ }

The move functions are private by default and can only be accessed in the module where they are defined. The keyword public will change the default visibility of the function and make it public, i.e. accessible from outside.

The init method argument is a &signer, meaning that the method must be legally signed by an account before it can be called, and move_to is an original language for move, which serves to publish and add Counter resources to the signer's address. move's account model, code and data are stored under an account address.

The following is a list of common original phrases

  • move_to< T >(&signer, T): Publish, add a resource of type T to the address of signer.
  • move_from< T >(addr: address): T - removes a resource of type T from under the address and returns this resource.
  • borrow_global< T >(addr: address): &T - Returns an immutable reference to a resource of type T at the address.
  • borrow_global_mut< T >(addr: address): &mut T - Returns a mutable reference to a resource of type T at address.
  • exists< T >(address): bool: Determines if there is a resource of type T under address.

The incr method argument is also a &signer, meaning that the method must be legally signed by an account before it can be called,

The keyword acquires, placed after the function return value, is used to explicitly define all the Resources acquired by this function.

Signer::address_of(account) gets the address from the signer

borrow_global_mut is described above, variable borrow to address under the resource Counter, and then the value under the Counter structure for +1 operation.

The following two methods are script methods, what is the difference between it and the above two functions?

  • public fun: method can be called from any module.
  • public(script) fun: script function is the entry method in the module, indicating that the method can be called by initiating a transaction from the console, just like a locally executed script

The next version of Move will replace public(script) fun with public entry fun

Self represents its own module.

  public(script) fun init_counter(account: signer){
        Self::init(&account)
     }

     public(script) fun incr_counter(account: signer)  acquires Counter {
        Self::incr(&account)
     }

2.1 Compilation

Download the source code for the first example at:

$ git clone git@github.com:WeLightProject/Web3-dApp-Camp.git
$ cd Web3-dApp-Camp/move-dapp/my-counter

The package management tool for Move is the Move Package Manager (mpm), which is similar to Rust's Cargo or Node's NPM.
You can create a new project with mpm package new my-counter, the typical directory structure is:

my-counter
├── Move.toml
└── sources
    └── MyCounter.move
  • sources is used to archive Move's modules, which are similar to class files in Java.
  • Move.toml - used to store configuration files: including the original package data, dependencies and named addresses.
  • The above files constitute a Move Package.
    For more details on Move Package management refer to the documentation

Change the address in move.toml to the one you use for deployment.

image-20220727123922351
image-20220727123922351

Compiled with:

$ mpm release

Next you will see your compiled binaries in the release folder.

image-20220727124134402
image-20220727124134402

2.2 Console Deployment

Deployment is done by executing the following command in the Starcoin Console:

starcoin% dev deploy [path to blob] -s [addr] -b

-s means --sender,-b means --blocking, which means blocking and waiting for command execution to finish

If the account is locked, use the unlock command to unlock it.

account unlock [addr] -p [pwd]

where pwd is the password created in 1.2.

After successful deployment you can see:

image-20220727124625807
image-20220727124625807

💡 It is important to note that in Move the code is stored on a personal address, not a public address like in Ethereum. So no new address is created after the contract is deployed, when we want to call the contract we need to use the address of the person who deployed the contract + the contract name to call the contract.

2.3 Console calls

https://starcoinorg.github.io/starcoin-cookbook/docs/move/interacting-with-the-contract

  1. Call the init_counter script function to initialize the resource.
starcoin% account execute-function --function {MyCounterAddr-in-Move.toml}::MyCounter::init_counter -s 0x23dc2c167fcd16e28917765848e189ce -b

Among them:

  • {MyCounterAddr-in-Move.toml}::MyCounter::init_counteris the complete address on the function onchain, including the address where the contract is located + package name + function name.
  • -s means --sender,-b means --blocking, which means blocking and waiting for command execution to finish
  1. View Counter resources
starcoin% state get resource 0x23dc2c167fcd16e28917765848e189ce 0x23dc2c167fcd16e28917765848e189ce::MyCounter::Counter

The data of the contract in Move is called Resource(resource), and since reading data does not change the state on the chain, no -s -b is needed, no transactions are executed, and no state is consumed.

Interested students can try to call incr_counter and check again if Counter is +1.

Subscribe to Web3dAppDevCamp
Receive the latest updates directly to your inbox.
Verification
This entry has been permanently stored onchain and signed by its creator.