Learn Resources
The 'resource' is the main feature of the Move VM. It's possible to define and create new resources in the code, allowing you to manage digital assets in the same manner as your would use any other data. Resource has strict rules of usage - therefore it was created for safety and to work with digital assets. It was originally implemented as its own type but lated replaced with two abilities: 'store' and 'key'.
the resource type can only be defined and managed in a single module. It's a structure containing a list of abilities. The module sets rules for accessing, destroying, transferring and checking the existence of resources defined in it. A resource can never be duplicated, reused or discarded. It can only be created or destroyed by the module that defines it.
Move resembles object oriented programming so you can think of a resource as an object and a module as a class.

Develop a resource

✈️ See our instructions on how to send a transaction (execute/publish) using the Polkadot JS UI or CLI.
Let's create a swap module that will allow us to swap coins between users.
We will make it easy since it will only support one swap per coin pair. This means you can't create multiple swaps using the same pair in the same account. This module will have just two functions - publishing your offer and allowing other users to swap it for a specified price.
1
address {{sender}} {
2
module Swap {
3
use 0x1::Diem::{Self, Diem};
4
use 0x1::DiemAccount;
5
use 0x1::Signer;
6
7
// The resource of the module which contains swap parameters.
8
struct Swap<Offered: store + key, Expected: store + key> has key, store {
9
offered: Diem<Offered>,
10
price: u64,
11
}
12
13
// Create a swap deal with two coin pairs: Offered and Expected.
14
public fun create<Offered: store + key, Expected: store + key>(sender: &signer, offered: Diem<Offered>, price: u64) {
15
let sender_addr = Signer::address_of(sender);
16
17
assert(!exists_at<Offered, Expected>(sender_addr), 101);
18
19
move_to<Swap<Offered, Expected>>(
20
sender,
21
Swap<Offered, Expected> {
22
offered: offered,
23
price
24
}
25
);
26
}
27
28
// Get the price of the swap deal.
29
public fun get_price<Offered: store + key, Expected: store + key>(seller: address): u64 acquires Swap {
30
let offer = borrow_global<Swap<Offered, Expected>>(seller);
31
offer.price
32
}
33
34
// Change price before swap happens.
35
public fun change_price<Offered: store + key, Expected: store + key>(sender: &signer, new_price: u64) acquires Swap {
36
let offer = borrow_global_mut<Swap<Offered, Expected>>(Signer::address_of(sender));
37
offer.price = new_price;
38
}
39
40
// Swap coins and deposit them to accounts: both creator and buyer.
41
public fun swap<Offered: store + key, Expected: store + key>(sender: &signer, seller: address, exp: Diem<Expected>) acquires Swap {
42
let Swap<Offered, Expected> { offered, price } = move_from<Swap<Offered, Expected>>(seller);
43
let exp_value = Diem::value<Expected>(&exp);
44
45
assert(exp_value == price, 102);
46
DiemAccount::pnt_deposit(seller, exp);
47
DiemAccount::pnt_deposit(Signer::address_of(sender), offered);
48
}
49
50
// Check if the swap pair already exists for the account.
51
public fun exists_at<Offered: store + key, Expected: store + key>(addr: address): bool {
52
exists<Swap<Offered, Expected>>(addr)
53
}
54
}
55
}
Copied!
The provided code creates a new module "Swap" and a resource named "Swap" (default name for default resource in modules), which holds information about the deal.
To create a swap use the "create" function. To make an exchange use the "swap" function. Other methods in this module provide the ability to get/set price and check if the swap option already exists at a specific address. All methods in this example uses generic Offered and Expected, which allows you to make unique resources for each swap.
The resource Diem::Diem represents the account balance of Offered type.
1
// The resource of module which contains swap parameters.
2
struct Swap<Offered: store + key, Expected: store + key> has key, store {
3
offered: Diem<Offered>,
4
price: u64,
5
}
Copied!
Even though there's a lot of code inside, we'll focus on 4 main methods: borrow_global_mut, move_to_sender, move_from, exists and on the acquires keyword.

move_to<T>(&signer, T)

When a resource is created, it needs to be moved to an address (otherwise it will never be actually created - there's no 'contract storage' - only accounts). It is important to note that a newly created resource can be moved only to the sender of a transaction - this makes the initialization of a resource impossible at someone else's address.
To move a resource to a sender, the move_to<T>(&signer, T) method is used where T is a generic type and instance of this type. Below is the resource for reference:
1
// Create a swap deal with two coin pairs: Offered and Expected.
2
public fun create<Offered: store + key, Expected: store + key>(sender: &signer, offered: Diem<Offered>, price: u64) {
3
let sender_addr = Signer::address_of(sender);
4
5
assert(!exists_at<Offered, Expected>(sender_addr), 101);
6
7
move_to<Swap<Offered, Expected>>(
8
sender,
9
Swap<Offered, Expected> {
10
offered: offered,
11
price
12
}
13
);
14
}
Copied!
In the create function we created new resources which contain information about the swap, and moved it to sender. After this, we can start working with our resources.

exists<T>(address)

Allow us to check if the resource already exists on the specific address or not:
1
// Check if swap pair already exists for account.
2
public fun exists_at<Offered: store + key, Expected: store + key>(addr: address): bool {
3
exists<Swap<Offered, Expected>>(addr)
4
}
Copied!

borrow_global_mut<T>(address)

1
// Change price before swap happens.
2
public fun change_price<Offered: store + key, Expected: store + key>(sender: &signer, new_price: u64) acquires Swap {
3
let offer = borrow_global_mut<Swap<Offered, Expected>>(Signer::address_of(sender));
4
offer.price = new_price;
5
}
Copied!
Allows us to get a mutable reference to a resource that can be changed. There is also borrow_global to get an immutable reference:
1
// Get the price of the swap deal.
2
public fun get_price<Offered: store + key, Expected: store + key>(seller: address): u64 acquires Swap {
3
let offer = borrow_global<Swap<Offered, Expected>>(seller);
4
offer.price
5
}
Copied!
borrow_global gives immutable reference to a resource stored under address. You can use this reference to read resource. However, you can't change the resource.

acquires

Every function which accesses an already created resource must have the acquires keyword in its signature after which acquired resources are listed. Look at the usage of borrow_global and borrow_global_mut again. Resource Swap is acquired by both the methods get_price and change_price.

move_from<T>(address)

1
// Swap coins and deposit them to accounts: both creator and buyer.
2
public fun swap<Offered: store + key, Expected: store + key>(sender: &signer, seller: address, exp: Diem<Expected>) acquires Swap {
3
let Swap<Offered, Expected> { offered, price } = move_from<Swap<Offered, Expected>>(seller);
4
let exp_value = Diem::value<Expected>(&exp);
5
6
assert(exp_value == price, 102);
7
DiemAccount::pnt_deposit(seller, exp);
8
DiemAccount::pnt_deposit(Signer::address_of(sender), offered);
9
}
Copied!
The move_from<T>(address) function moves the resource from an address. After taking the resource from the account, it must be used - either destroyed (like in the example below) or passed to another function. Resources are not automatically destroyed like regular variables and their lifetime must be specified.

Summary

The create function creates a new resource, swap function allows you to swap (deposit coins to both accounts and destroy resource T); we've also added methods to get the price of the deal and to change it.

More about resources

Resources are the most interesting and the most complex topic in Move language. But once you've gotten the idea, the rest is easy.
To get to know Move better and to learn about resources specifically, please reference the Move Book:
  • [Programmable Resources](https://move-book.com/resources/index.html
  • [Advanced topics - Structures] (https://move-book.com/advanced-topics/struct.html)
Last modified 2mo ago