Modules
Learn about Move modules, which are the fundamental building blocks of on-chain logic and data storage.
Modules
Modules are the fundamental building blocks of on-chain logic. They act as libraries that define structs (data types) and functions (behaviors) that operate on those structs. Structs describe the schema of Move’s global storage, determining how data is organized and stored on-chain, while module functions define the rules and permissions for creating, reading, and updating that data.
Key Characteristics of Modules:
- Encapsulation: Modules group related structs and functions together
- Reusability: Modules can be imported and used by other modules
- Security: Modules enforce access control and data privacy
- Global Storage: Modules define how data is stored on the blockchain
Syntax of Modules
Modules are defined using the module keyword, followed by the address and identifier of the module. Modules can be declared using named addresses. Named addresses are declared at the source language level in Move syntax and replaced at the bytecode level with the actual address.
module <address>::<identifier> {
(<use> | <friend> | <type> | <function> | <constant>)*
}Module members include:
- use: Import declarations (
use <address>::<identifier>) - friend: Friend module declarations (
friend <address>::<identifier>) - struct: Type definitions (
struct <name> { ... }) - function: Function definitions (
fun <name>(<parameters>) -> <return_type> { ... }) - const: Constant declarations (
const <name>: <type> = <value>)
The module members can be defined at the source code level in this way:
module test::MyModule {
// import
use std::debug::print;
// friend
friend 0x1::otherModule;
// a struct
struct Struct {}
// function
fun function(_: &Struct) { /* function body */ }
// a constant
const CONST: u8 = 0;
}Example of Modules
Let's create a simple module that defines a struct and a function to create an instance of that struct.
module test::MyModule {
use std::debug::print;
struct MyStruct {
field: u64
}
fun create_my_struct(field: u64): MyStruct {
let my_struct = MyStruct { field }
print(&my_struct);
my_struct
}
}In this example, we define a module named MyModule using the named address test. The module contains:
- A struct named
MyStructwith a single field of typeu64 - A function named
create_my_structthat takes au64parameter and returns an instance ofMyStruct
Note: During compilation, the named address
testis replaced with a real address (like0x1in the example below).
module 0x1::MyModule {
use std::debug::print;
struct MyStruct {
field: u64
}
fun create_my_struct(field: u64): MyStruct {
let my_struct = MyStruct { field }
print(&my_struct);
my_struct
}
}Module Naming Conventions
Module names must adhere to the following rules:
- Must start with a letter (
a-zorA-Z) - After the first character, can contain underscores (
_), letters (a-z,A-Z), or digits (0-9) - Cannot be Move keywords (e.g.,
move,public,fun, etc.)
Module Addresses
Modules are published at specific addresses on the blockchain. There are two ways to specify addresses:
Named Addresses
Used during development for readability:
module my_project::token {
// module content
}Literal Addresses
The actual hexadecimal addresses used on-chain:
module 0x1::token {
// module content
}Named addresses must be configured in your Move.toml file to map to actual addresses during compilation.
Module Publication
Once a module is published to an address:
- All its public functions and structs become available to other modules
- The module's bytecode is stored permanently on the blockchain
- Gas fees are required for publication