Functions, view Functions & Visibility
Function
Overview
Function syntax in Move is shared between module functions and script functions. Functions inside of modules are reusable, whereas script functions are only used once to invoke a transaction.
Declaring Address Variables
fun name(params: type): return_type {
todo!()
}
// example
fun plus(what_plus: u64): u64 {
let result = 0 + what_plus;
return result;
}
View Function
Definition
A view function is a function that retrieves data from the blockchain without making any changes. It is used to read and display data stored on the blockchain.
Importance
View functions are important in the Movement blockchain because:
- They allow external applications to access and display data on the blockchain without direct access to the blockchain.
- They improve the efficiency and security of the blockchain network.
Benefits
- Create a GET API structure to display complex states of smart contracts.
- Simplify the process of retrieving complex data, saving time and resources.
- Significantly improve the usability of the Aptos blockchain.
- Make the blockchain more accessible to developers.
How to Use
Use the #[view]
decorator to define a view function:
#[view]
public fun get_todos(todo_address: address): vector<String> acquires TodoStore {
borrow_global<TodoStore>(todo_address).todos
}
Advantages
- Retrieve complex states from smart contracts more efficiently.
- Define functions that return specific data from smart contracts.
- Provide a simple API for external invokers to retrieve data from the blockchain.
- Receive specific required data instead of the entire database with each query.
Conclusion
Significantly improving its usability and accessibility. They help developers create more efficient applications by simplifying the process of retrieving data from the blockchain.
Function Visibilities
Private
- The functions can only be used within the module where they are defined.
- Think of them as "module-only" functions. No other module or script can access them.
module movement::PrivModule {
fun pri_func(): u8 {
return 0;
}
}
module movement::PublModule {
fun other_func(): u8 {
// This will error
let result: u8 = movement::PrivModule::pri_func(); // Error
return result;
}
}
Public
- The functions can be used by any other module or script.
- They are like "open to everyone" functions.
module movement::PrivModule {
use std::debug::print;
fun pri_func(): u8 {
return 0
}
fun call_public_func() {
let result = movement::PublModule::public_func();
print(&result);
}
#[test]
fun test_call_public_func() {
call_public_func();
}
}
module movement::PublModule {
public fun public_func(): u8 {
return 0
}
}
Public(friend)
- The functions can be used by the module where they are defined and by specific modules listed as "friends." - It’s like having "VIP access" that only selected friends can use these functions.
module movement::PrivModule {
use std::debug::print;
fun call_public_func() {
// This will error
let result = movement::PublModule::public_func(); // Error
// This will error
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid call to
// This will error
'(movement=0xDB8A45E0E06D2BD305CDB824FDA101CEC6A24721CB03188C5543A5E5A8C3F3B0)::PublModule::public_func'
print(&result);
}
}
module movement::PublModule {
public(friend) fun public_func(): u8 {
return 0
}
}
To allow PrivModule
to call public(friend)
from within PublModule
, we need to add PrivModule
to the friend list of PublModule
by doing the following:
module movement::PrivModule {
use std::debug::print;
fun call_public_func() {
let result = movement::PublModule::public_func();
print(&result);
}
#[test]
fun test_call_public_func() {
call_public_func();
}
}
module movement::PublModule {
friend movement::PrivModule;
public(friend) fun public_func(): u8 {
return 0
}
}
Entry
- These are special functions where the Move program starts running or where the user can call into the contract.
- You can combine "entry" with "public" or "public(friend)" to specify who can initiate execution.
Example:
module movement::FunctionVisibilities {
use std::string::utf8;
use std::debug::print;
public(friend) entry fun internal_transfer() { // public friend entry
print(&utf8(b"internal transfer"));
}
public entry fun pub_transfer() { // public entry
print(&utf8(b"public transfer"));
}
entry fun transfer(){ // private entry
print(&utf8(b"transfer"));
}
}
- Movement CLI
movement move publish --named-addresses movement=default
- Result
{
"Result": {
"transaction_hash": "0x995bff9d25cbb2863b1171d097e3af93c2c1867b0325ceeb1bd3ec44c841270a",
"gas_used": 1280,
"gas_unit_price": 100,
"sender": "bcbcad47635cf19f831e82a0abd0775b4892cb79bb8600592a99e73c727f717c",
"sequence_number": 0,
"success": true,
"timestamp_us": 1726818525771069,
"version": 17512651,
"vm_status": "Executed successfully"
}
}
Call Entry Function
movement move run --function-id 'default::FunctionVisibilities::internal_transfer'
movement move run --function-id 'default::FunctionVisibilities::pub_transfer'
movement move run --function-id 'default::FunctionVisibilities::transfer'
{
"Result": {
"transaction_hash": "0xdf1e9661d7408034273fa49a8cecb4ca7acc2656705b348e0aee76a2a4799ce7",
"gas_used": 3,
"gas_unit_price": 100,
"sender": "e084b2010bb36fb4802d2c8bad7c66ade3728b202a30e330e58cd1904d65a043",
"sequence_number": 2,
"success": true,
"timestamp_us": 1726819967229264,
"version": 2034,
"vm_status": "Executed successfully"
}
}