
Immersion in Move - Facebook's Libra blockchain programming language
- Transfer
Next, we will examine in detail the main characteristics of the Move language and what are its key differences with another, already popular language for smart contracts - Solidity (on the Ethereum platform). The material is based on a study of an available on-line 26-page whitepaper.
Move is an executable bytecode language that is used to execute user transactions and smart contracts. Pay attention to two points:
Translation made by the INDEX Protocol project team. We previously translated a lot of material describing the Libra project , now it is the turn to look at the Move language a little more in depth. The translation was made in conjunction with the coolsiu habrayuzer.
A key feature of Move is the ability to define custom resource types with linear logic semantics: the resource can never be copied or implicitly deleted, only moved. Functionally, this is similar to the capabilities of the Rust language. Values in Rust can only be assigned to one name at a time. Assigning a value to another name makes it inaccessible under the previous name.

For example, the following code fragment will throw an error: Use of moved value 'x'.This is because there is no garbage collection in Rust. When variables go out of scope, the memory to which they refer is also freed. Simply put, there can only be one “owner” of data. In this example, x is the original owner, and then y becomes the new owner. Read more about this behavior here .
There are two properties of physical assets that are difficult to digitally represent:
These two characteristics, which are natural for physical assets, need to be implemented for digital objects, if we want to consider them assets. For example, a rare metal - has a natural deficit, and only you have access to it (holding in your hands, for example) and you can sell or spend it.
To illustrate how we arrived at these two properties, let's start with the following sentences:

The above solution has several serious problems:

Now we are monitoring the situation so that the number of Ka coins is at least n before the transfer transaction. Nevertheless, although this solves the shortage problem, there is no information about who can send Alice's coins (so far everyone can do this, the main thing is not to violate the rule of quantity limits).

We solve this problem with the verify_sig digital signature mechanism before checking the balance, which means that Alice uses her private key to sign the transaction and confirm that she owns her coins.
Existing blockchain languages face the following problems (all of them were solved in Move (note: unfortunately, the author of the article only appeals to Ethereum in his comparisons, so you should take them only in this context. For example, most of the following is also solved in EOS )):
Indirect representation of assets . An asset is encoded using an integer, but an integer value is not the same as an asset. In fact, there is no type or value representing bitcoin / ether / <Any Coin>! This makes writing programs that use assets difficult and error prone. Patterns such as transferring assets to / from procedures or storing assets in structures require special language support.
Deficit is non-expandable. Language represents only one scarce asset. In addition, remedies against deficit are hardwired directly into the semantics of the language itself. A developer, if he wants to create a user asset, must carefully monitor all aspects of the resource himself. These are just the problems of Ethereum smart contracts.
Users issue their assets, ERC-20 standard tokens, using integers to determine both cost and total issue. Whenever new tokens are created, the smart contract code must independently verify compliance with the emission rules. In addition, the indirect representation of assets leads, in some cases, to serious errors - duplication, double spending or even a complete loss of assets.
Lack of flexible access control. The only access control policy currently in use is a signature scheme using asymmetric cryptography. Like deficit protection, access control policies are deeply embedded in the semantics of the language. But how to expand the language to allow programmers to define their own access control policies is often a very non-trivial task.
This is also true for Ethereum, where smart contracts do not have native cryptography support for access control. Developers must manually prescribe access control, for example, using the onlyOwner modifier.
Although I am a big fan of Ethereum, I believe that asset properties should be natively supported by the language for security reasons. In particular, transferring Ether to a smart contract involves dynamic dispatching, which has led to the emergence of a new class of errors known as re-entrancy vulnerabilities. Dynamic dispatching here means that the logic of code execution will be determined at runtime (dynamic), and not at compile time (static).
Thus, in Solidity, when contract A invokes the function of contract B, contract B can run code that was not provided by the developer of contract A, which can lead to re-entry vulnerabilities. (contract A accidentally acts as contract B to withdraw money before the actual deduction of account balances).
Speaking at a higher level, the interaction between modules / resources / procedures in the Move language is very similar to the relations between classes / objects and methods in OOP languages.
Modules in Move are similar to smart contracts in other blockchains. The module declares resource types and procedures that set the rules for creating, destroying, and updating declared resources. But all this is just conventions (“ jargon ”) in Move. A little later we will illustrate this point.
Move adds Libra flexibility through scripting. Each transaction in Libra includes a script, which is actually the main transaction procedure. The script can perform either one specified action, for example, payments according to the specified list of recipients, or reuse other resources - for example, by calling a procedure in which the general logic is specified. This is why Move transaction scripts offer more flexibility. The script can use both one-time and repetitive behaviors, while Ethereum can only execute repetitive scripts (calling a smart contract method by calling one method). The reason it is called “multiple” is because the functions of a smart contract can be executed multiple times. (note:here the moment is very subtle. On the one hand, transaction scripts in the form of pseudo-bytecode are also available in Bitcoin. On the other hand, as I understand it, Move expands this language, in fact, to the level of a full-fledged language of smart contracts ).
The Move executable format is bytecode, which, on the one hand, is a language of a higher level than assembler, but lower level than the source code. The bytecode is checked in on-chain for the availability of resources, types and memory security using the bytecode verifier, and then executed by the interpreter. This approach allows Move to provide security specific to the source code, but without the compilation process and the need to add a compiler to the system. Making Move a bytecode language is a really good solution. There is no need to compile it from the source, as is the case with Solidity, no need to worry about possible crashes or attacks on the compiler infrastructure.
We are aimed at performing as easy checks as possible, since all this goes on-chain (note: on-line, in the process of each transaction, therefore any delay leads to a slowdown of the entire network ), however, the language design is initially ready for use and off-chain means of static verification. Although this is more preferable, so far the development of verification tools (as a separate toolkit) has been postponed for the future, and now only dynamic verification in run-time (on-chain) is supported.
Move modules provide data abstraction and localize critical operations on resources. The encapsulation provided by the module, combined with the protection provided by the Move type system, ensures that the properties set for the module types cannot be violated by code outside the module. This is a well-thought-out design of abstraction, meaning that the data inside the contract can only be changed as part of the execution of the contract, but not from the outside.

An example transaction script demonstrates that malicious or reckless actions of a programmer outside a module cannot violate the security of module resources. Next, we will look at examples of how modules, resources and procedures are used to program the Libra blockchain.

The amount of coins specified in the amount will be transferred from the balance of the sender to the recipient.
There are several new points (highlighted in red):
We parse the code: in the first step, the sender calls a procedure called withdraw_from_sender from the module stored in 0x0.Currency . At the second stage, the sender transfers the funds to the recipient, moving the value of the coin resource into the deposit procedure of module 0x0.Currency .
Here are three examples of errors in the code that will be rejected by the checks:
Duplication of funds by changing the move (coin) call to copy (coin) . Resources can only be moved. Attempting to duplicate the amount of a resource (for example, by calling copy (coin) in the above example) will result in an error while checking the bytecode.
Reuse of funds by specifying move (coin)twice . Adding the line 0x0.Currency.deposit (copy (some_other_payee), move (coin)) to the example above will allow the sender to "spend" coins twice - the first time with the payee, and the second with some_other_payee . This is an undesirable behavior, impossible with a physical asset. Fortunately, Move will reject this program.
Loss of funds due to failure in move (coin) . If you do not move the resource (for example, by deleting the line containing move (coin) ), an error will be generated by checking the bytecode. This protects Move programmers from accidental or malicious loss of funds.

Each account can contain 0 or more modules (depicted as rectangles) and one or more resource values (depicted as cylinders). For example, an account at 0x0 contains a 0x0.Currency module and a resource value of type 0x0.Currency.Coin . The account at 0x1 has two resources and one module; The account at 0x2 has two modules and one resource value.
Some moments:

A module named Currency and a resource type named Coin
Some points:

This procedure takes the Coin resource as input and combines it with the Coin resource stored in the recipient's account:
Some moments:

This procedure:
Some moments:
We examined the main characteristics of the Move language, compared it with Ethereum, and also got acquainted with the basic syntax of scripts. In conclusion, I highly recommend looking through the original white paper . It includes many details regarding the principles of programming language design, as well as many useful links.
Introduction
Move is an executable bytecode language that is used to execute user transactions and smart contracts. Pay attention to two points:
- While Move is a bytecode language that can be directly executed on the Move virtual machine, Solidity (smart contract language in Ethereum) is a higher-level language that is first compiled into bytecode before being executed in EVM (Ethereum Virtual Machine )
- Move can be used not only for the implementation of smart contracts, but also for user transactions (more on this later), while Solidity is a language only for smart contracts.
Translation made by the INDEX Protocol project team. We previously translated a lot of material describing the Libra project , now it is the turn to look at the Move language a little more in depth. The translation was made in conjunction with the coolsiu habrayuzer.
A key feature of Move is the ability to define custom resource types with linear logic semantics: the resource can never be copied or implicitly deleted, only moved. Functionally, this is similar to the capabilities of the Rust language. Values in Rust can only be assigned to one name at a time. Assigning a value to another name makes it inaccessible under the previous name.

For example, the following code fragment will throw an error: Use of moved value 'x'.This is because there is no garbage collection in Rust. When variables go out of scope, the memory to which they refer is also freed. Simply put, there can only be one “owner” of data. In this example, x is the original owner, and then y becomes the new owner. Read more about this behavior here .
Representation of digital assets in open systems
There are two properties of physical assets that are difficult to digitally represent:
- Rarity (Scarcity, in the original - scarcity). The amount of assets (issue) in the system should be controlled. Duplication of existing assets must be prohibited, and the creation of new ones is a privileged operation.
- Access control . The system participant must be able to protect assets with access control policies.
These two characteristics, which are natural for physical assets, need to be implemented for digital objects, if we want to consider them assets. For example, a rare metal - has a natural deficit, and only you have access to it (holding in your hands, for example) and you can sell or spend it.
To illustrate how we arrived at these two properties, let's start with the following sentences:
Proposition 1: The simplest rule without scarcity and access control

- G [K]: = n means updating the number accessible by key K in the global state of the blockchain with the new value n .
- transaction ⟨Alice, 100⟩ means setting the balance of Alice's account to 100.
The above solution has several serious problems:
- Alice can receive an unlimited number of coins simply by sending transaction ⟨Alice, 100⟩.
- The coins Alice sends to Bob are useless, as Bob could send himself an unlimited number of coins using the same technique.
Proposal No. 2: We take into account the deficit

Now we are monitoring the situation so that the number of Ka coins is at least n before the transfer transaction. Nevertheless, although this solves the shortage problem, there is no information about who can send Alice's coins (so far everyone can do this, the main thing is not to violate the rule of quantity limits).
Proposition 3: Combining Deficit and Access Control

We solve this problem with the verify_sig digital signature mechanism before checking the balance, which means that Alice uses her private key to sign the transaction and confirm that she owns her coins.
Blockchain programming languages
Existing blockchain languages face the following problems (all of them were solved in Move (note: unfortunately, the author of the article only appeals to Ethereum in his comparisons, so you should take them only in this context. For example, most of the following is also solved in EOS )):
Indirect representation of assets . An asset is encoded using an integer, but an integer value is not the same as an asset. In fact, there is no type or value representing bitcoin / ether / <Any Coin>! This makes writing programs that use assets difficult and error prone. Patterns such as transferring assets to / from procedures or storing assets in structures require special language support.
Deficit is non-expandable. Language represents only one scarce asset. In addition, remedies against deficit are hardwired directly into the semantics of the language itself. A developer, if he wants to create a user asset, must carefully monitor all aspects of the resource himself. These are just the problems of Ethereum smart contracts.
Users issue their assets, ERC-20 standard tokens, using integers to determine both cost and total issue. Whenever new tokens are created, the smart contract code must independently verify compliance with the emission rules. In addition, the indirect representation of assets leads, in some cases, to serious errors - duplication, double spending or even a complete loss of assets.
Lack of flexible access control. The only access control policy currently in use is a signature scheme using asymmetric cryptography. Like deficit protection, access control policies are deeply embedded in the semantics of the language. But how to expand the language to allow programmers to define their own access control policies is often a very non-trivial task.
This is also true for Ethereum, where smart contracts do not have native cryptography support for access control. Developers must manually prescribe access control, for example, using the onlyOwner modifier.
Although I am a big fan of Ethereum, I believe that asset properties should be natively supported by the language for security reasons. In particular, transferring Ether to a smart contract involves dynamic dispatching, which has led to the emergence of a new class of errors known as re-entrancy vulnerabilities. Dynamic dispatching here means that the logic of code execution will be determined at runtime (dynamic), and not at compile time (static).
Thus, in Solidity, when contract A invokes the function of contract B, contract B can run code that was not provided by the developer of contract A, which can lead to re-entry vulnerabilities. (contract A accidentally acts as contract B to withdraw money before the actual deduction of account balances).
Move language design basics
First order resources
Speaking at a higher level, the interaction between modules / resources / procedures in the Move language is very similar to the relations between classes / objects and methods in OOP languages.
Modules in Move are similar to smart contracts in other blockchains. The module declares resource types and procedures that set the rules for creating, destroying, and updating declared resources. But all this is just conventions (“ jargon ”) in Move. A little later we will illustrate this point.
Flexibility
Move adds Libra flexibility through scripting. Each transaction in Libra includes a script, which is actually the main transaction procedure. The script can perform either one specified action, for example, payments according to the specified list of recipients, or reuse other resources - for example, by calling a procedure in which the general logic is specified. This is why Move transaction scripts offer more flexibility. The script can use both one-time and repetitive behaviors, while Ethereum can only execute repetitive scripts (calling a smart contract method by calling one method). The reason it is called “multiple” is because the functions of a smart contract can be executed multiple times. (note:here the moment is very subtle. On the one hand, transaction scripts in the form of pseudo-bytecode are also available in Bitcoin. On the other hand, as I understand it, Move expands this language, in fact, to the level of a full-fledged language of smart contracts ).
Security
The Move executable format is bytecode, which, on the one hand, is a language of a higher level than assembler, but lower level than the source code. The bytecode is checked in on-chain for the availability of resources, types and memory security using the bytecode verifier, and then executed by the interpreter. This approach allows Move to provide security specific to the source code, but without the compilation process and the need to add a compiler to the system. Making Move a bytecode language is a really good solution. There is no need to compile it from the source, as is the case with Solidity, no need to worry about possible crashes or attacks on the compiler infrastructure.
Verifiability
We are aimed at performing as easy checks as possible, since all this goes on-chain (note: on-line, in the process of each transaction, therefore any delay leads to a slowdown of the entire network ), however, the language design is initially ready for use and off-chain means of static verification. Although this is more preferable, so far the development of verification tools (as a separate toolkit) has been postponed for the future, and now only dynamic verification in run-time (on-chain) is supported.
Modularity
Move modules provide data abstraction and localize critical operations on resources. The encapsulation provided by the module, combined with the protection provided by the Move type system, ensures that the properties set for the module types cannot be violated by code outside the module. This is a well-thought-out design of abstraction, meaning that the data inside the contract can only be changed as part of the execution of the contract, but not from the outside.

Move Review
An example transaction script demonstrates that malicious or reckless actions of a programmer outside a module cannot violate the security of module resources. Next, we will look at examples of how modules, resources and procedures are used to program the Libra blockchain.
Peer-to-Peer Payments

The amount of coins specified in the amount will be transferred from the balance of the sender to the recipient.
There are several new points (highlighted in red):
- 0x0 : address of the account where the module is stored
- Currency : module name
- Coin : resource type
- The coin value returned by the procedure is a resource value whose type is 0x0.Currency.Coin
- move () : value cannot be used again
- copy () : value can be used later
We parse the code: in the first step, the sender calls a procedure called withdraw_from_sender from the module stored in 0x0.Currency . At the second stage, the sender transfers the funds to the recipient, moving the value of the coin resource into the deposit procedure of module 0x0.Currency .
Here are three examples of errors in the code that will be rejected by the checks:
Duplication of funds by changing the move (coin) call to copy (coin) . Resources can only be moved. Attempting to duplicate the amount of a resource (for example, by calling copy (coin) in the above example) will result in an error while checking the bytecode.
Reuse of funds by specifying move (coin)twice . Adding the line 0x0.Currency.deposit (copy (some_other_payee), move (coin)) to the example above will allow the sender to "spend" coins twice - the first time with the payee, and the second with some_other_payee . This is an undesirable behavior, impossible with a physical asset. Fortunately, Move will reject this program.
Loss of funds due to failure in move (coin) . If you do not move the resource (for example, by deleting the line containing move (coin) ), an error will be generated by checking the bytecode. This protects Move programmers from accidental or malicious loss of funds.
Currency module

Each account can contain 0 or more modules (depicted as rectangles) and one or more resource values (depicted as cylinders). For example, an account at 0x0 contains a 0x0.Currency module and a resource value of type 0x0.Currency.Coin . The account at 0x1 has two resources and one module; The account at 0x2 has two modules and one resource value.
Some moments:
- The transaction script is atomic - either completely executed, or not at all.
- A module is a long-lived piece of code globally available.
- The global state is structured as a hash table, where the key will be the account address
- Accounts can contain no more than one resource value of a given type and no more than one module with a given name (an account at 0x0 cannot contain an additional resource 0x0.Currency.Coin or another module named Currency )
- The address of the declared module is part of the type ( 0x0.Currency.Coin and 0x1.Currency.Coin are separate types that cannot be used interchangeably)
- Programmers can store several instances of this type of resource in the account by defining their custom resource - ( resource TwoCoins {c1: 0x0.Currency.Coin, c2: 0x0.Currency.Coin} )
- You can refer to a resource by its name without conflicts, for example, you can refer to two resources using TwoCoins.c1 and TwoCoins.c2 .
Coin Resource Ad

A module named Currency and a resource type named Coin
Some points:
- Coin is a single-field structure of type u64 (64-bit unsigned integer)
- Only Currency module procedures can create or destroy Coin values .
- Other modules and scripts can write or reference the value field only through open procedures provided by the module.
Deposit Implementation

This procedure takes the Coin resource as input and combines it with the Coin resource stored in the recipient's account:
- Destroying the Coin input resource and recording its value.
- Getting a link to a unique Coin resource stored on the recipient’s account.
- Changing the value of the Coin amount by the value passed in the parameter when the procedure is called.
Some moments:
- Unpack, BorrowGlobal - built-in procedures
- Unpack
this is the only way to delete a resource of type T. The procedure takes the resource to the input, destroys it and returns the value associated with the fields of the resource. - Borrowglobal
accepts the address as input and returns a link to a unique instance of T published (owned) by this address - & mut Coin is a link to the Coin resource
Implement withdraw_from_sender

This procedure:
- Gets a link to a unique Coin resource linked to the sender’s account
- Decreases the value of the Coin resource by reference to the specified amount
- Creates and returns a new Coin resource with an updated balance.
Some moments:
- Deposit can be called by anyone, but withdraw_from_sender has access only to the coins of the calling account
- GetTxnSenderAddress is similar to msg.sender in Solidity
- RejectUnless is similar to require in Solidity. If this check fails, the transaction is stopped and all changes are rolled back.
- Pack
it is also a built-in procedure that creates a new resource of type T. - Just like Unpack
, Pack can only be called inside the module where resource T is described
Conclusion
We examined the main characteristics of the Move language, compared it with Ethereum, and also got acquainted with the basic syntax of scripts. In conclusion, I highly recommend looking through the original white paper . It includes many details regarding the principles of programming language design, as well as many useful links.