Facebook has officially announced its new cryptocurrency ‘Libra’ which they plan to launch in the early part of 2020.
This announcement took the cryptocurrency and blockchain industry by storm.
In Libra, the most attractive thing is the new programming language ‘Move’.
According to the Libra official documentation, Move language is a new programming language for implementing custom transaction logic and “smart contracts” on the Libra Blockchain. Because of Libra’s goal to serve billions of people one day, Move language is designed with safety and security as the highest priorities.
Move is written in Rust language.
Move’s primary tasks include:
- Issuing cryptocurrencies, tokens, and digital assets
- Facilitating smooth and secure blockchain transactions
- Secure management of validators
Move, when fully developed, will enable developers to write smart contracts on the Libra blockchain. Until then, developers will have to manage with Move IR to create modules and transaction scripts.
Move IR: The Move IR compiler compiles the Move IR down to its bytecode representation.
Implementation
The features we will implement in our token contract are listed below:
- Check token balance
- Withdraw tokens
- Deposit tokens
- Minting
Token contract:
We start by declaring the module and token resource, which holds the number of tokens.
module DToken {
// A resource representing the DToken
resource T {
// The value of the coin. May be zero
value: u64,
}
}
Move Language has First Class Resources
The key feature of Move language is the ability to define custom resource types.
Move resources can never be duplicated, reused, or discarded. A resource type can only be created or destroyed by the module that defines the type.
- T is a struct type with a single field value of a 64-bit unsigned integer.
- Only the procedures of the DToken module can create or destroy values of type T.
- Other modules and transaction scripts can only write or reference the value field via the public procedures of module
Publishes an initial zero token to the sender:
This function should be called once before using this module. This function publishes initial zero dToken to the sender.
public publish() {
move_to_sender<T>(T{ value: 0 });
return;
}
Mint new token:
Mint a new DToken.T worth value
.
public mint(value: u64): R#Self.T {
return T{value: move(value)};
}
Check token Balance:
The current balance of the Dtoken in the sender’s address. The request will be revert if an initial token hasn’t been published.
public balance(): u64 {
let sender: address;
let token_ref: &mut R#Self.T;
let token_value: u64;
sender = get_txn_sender();
token_ref = borrow_global<T>(move(sender));
token_value = *(&move(token_ref).value);
return move(token_value);
}
BorrowGlobal
a built-in procedure which takes an address as input and returns a reference to the unique instance of T published under that addressget_txn_sender()
is the address currently interacting with the module.get_txn_sender()
is similar to Solidity’smsg.sender
.
Deposit tokens:
By utilizing this type-safe property we can define the function for depositing the `to_deposit` coin into the `payee`’s account
public deposit(payee: address, to_deposit: R#Self.T) {
let payee_token_ref: &mut R#Self.T;
let payee_token_value: u64;
let to_deposit_value: u64;
payee_token_ref = borrow_global<T>(move(payee));
payee_token_value = *(©(payee_token_ref).value);
T{ value: to_deposit_value } = move(to_deposit);
*(&mut move(payee_token_ref).value) = move(payee_token_value) +
move(to_deposit_value);
return;
}
Withdraw the tokens:
Withdraw `amount` DToken.T from the transaction sender’s account
public withdraw(amount: u64): R#Self.T {
let sender: address;
let sender_token_ref: &mut R#Self.T;
let value: u64;
// Load the sender
sender = get_txn_sender();
sender_token_ref = borrow_global<T>(move(sender));
value = *(©(sender_token_ref).value);
// Make sure that sender has enough tokens
assert(copy(value) >= copy(amount), 1);
*(&mut move(sender_token_ref).value) = move(value) - copy(amount);
return T{ value: move(amount) };
}
Testing to verify the published module
import Transaction.DToken;
main() {
let sender: address;
let minted_tokens: R#DToken.T;
let balance: u64;
sender = get_txn_sender();
// Publish an dToken account
DToken.publish();
// Mint 100 dTokens
minted_tokens = DToken.mint(100);
// Deposit the freshly minted tokens
DToken.deposit(move(sender), move(minted_tokens));
// Test that the balance
balance = DToken.balance();
assert(move(balance) == 100, 3);
return;
}
Run the test:
To run the token implementation test, you should perform the following steps:
Clone the Libra Core Repository:
git clone https://github.com/libra/libra.git
Change to the libra directory:
cd libra
Setup Libra Core:
To setup Libra Core, run the setup script to install the dependencies
./scripts/dev_setup.sh
The setup script performs these actions:
- Installs rustup — rustup is an installer for the Rust programming language, which Libra Core is implemented in.
- It Installs the required versions of the rust-toolchain.
- Installs CMake — to manage the build process.
- Installs protoc — a compiler for protocol buffers.
- Also, installs Go — for building protocol buffers.
Copy the dToken Move IR source code to the test folder in the Libra repository located at language/functional_tests/tests/testsuite/module/
dToken Move IR source code:
modules:
module DToken {
// A resource representing the DToken
resource T {
value: u64,
}
// Publishes an initial zero dToken to the sender.
public publish() {
move_to_sender<T>(T{ value: 0 });
return;
}
// Mint new dTokens.
public mint(value: u64): R#Self.T {
return T{value: move(value)};
}
// Returns an account's dToken balance.
public balance(): u64 {
let sender: address;
let token_ref: &mut R#Self.T;
let token_value: u64;
sender = get_txn_sender();
token_ref = borrow_global<T>(move(sender));
token_value = *(&move(token_ref).value);
return move(token_value);
}
// Deposit owned tokens to a payee's address
public deposit(payee: address, to_deposit: R#Self.T) {
let payee_token_ref: &mut R#Self.T;
let payee_token_value: u64;
let to_deposit_value: u64;
payee_token_ref = borrow_global<T>(move(payee));
payee_token_value = *(©(payee_token_ref).value);
// Unpack and destroy to_deposit tokens
T{ value: to_deposit_value } = move(to_deposit);
// Increase the payees balance with the destroyed token amount
*(&mut move(payee_token_ref).value) = move(payee_token_value) + move(to_deposit_value);
return;
}
// Withdraw an amount of tokens of the sender and return it.
public withdraw(amount: u64): R#Self.T {
let sender: address;
let sender_token_ref: &mut R#Self.T;
let value: u64;
sender = get_txn_sender();
sender_token_ref = borrow_global<T>(move(sender));
value = *(©(sender_token_ref).value);
// Make sure that sender has enough tokens
assert(copy(value) >= copy(amount), 1);
// Split the senders token and return the amount specified
*(&mut move(sender_token_ref).value) = move(value) - copy(amount);
return T{ value: move(amount) };
}
}
script:
// Performs simple testing to verify the published modules above.
import Transaction.DToken;
main() {
let sender: address;
let minted_tokens: R#DToken.T;
let balance: u64;
sender = get_txn_sender();
// Publish an dToken account
DToken.publish();
// Mint 100 dTokens
minted_tokens = DToken.mint(100);
// Deposit the freshly minted tokens
DToken.deposit(move(sender), move(minted_tokens));
balance = DToken.balance();
assert(move(balance) == 100, 3);
return;
}
Execute the following command in the Libra repository:
cargo test -p functional_tests dToken
Note: If your tests failed, edit the `dToken.mvir` file and run the following command to rerun the tests:
cargo test -p functional_tests --test testsuite
Wrap up
Now you have an overview of the main characteristics of Move language. Thanks and cheers from the Deqode team.
Must Read: Stablecoins: The End of Volatility in Cryptocurrency
2 Comments
Thank you for this great piece of content. Best Regards
Hey There. I found your blog using msn. This is a really well written article. I will be sure to bookmark it and return to read more of your useful information. Thanks for the post. I will certainly comeback.