Movement Labs LogoMovement Docs
Move Book

Friends

Learn about the friend system in Move for controlled access between modules.

Friends

The friend system allows modules to grant trusted access to specific other modules. Friend modules can call functions with public(friend) visibility, creating controlled inter-module relationships without exposing functionality publicly.

This system enables building modular architectures where related modules can collaborate while maintaining encapsulation from external access.

Friend Declaration

Modules declare friends using friend statements to grant access to public(friend) functions. Friend declarations can reference modules by their full name or through aliases.

Syntax:

friend <module_address>::<module_name>;
friend <module_alias>;

Full Module Name Declaration

Use the complete module path including address when declaring friends:

module 0x42::core {
    friend 0x42::utils;      // Grant friend access to utils module
    friend 0x42::helpers;    // Grant friend access to helpers module
    
    public(friend) fun internal_operation(): u64 {
        42
    }
}

Module Alias Declaration

Import modules with use statements, then reference them by alias in friend declarations:

module 0x42::core {
    use 0x42::utils;         // Import utils module
    use 0x42::helpers as h;  // Import helpers with alias 'h'
    
    friend utils;            // Declare friend using module name
    friend h;                // Declare friend using alias
    
    public(friend) fun internal_operation(): u64 {
        42
    }
}

Declaration rules:

  • Friend declarations must be at module scope (not within functions)
  • Multiple friends can be declared to form a friend list
  • Recommended to place friend declarations near the top for readability

Usage Example

Here's how friend modules interact:

module 0x42::vault {
    friend 0x42::admin;
    
    struct Vault has key, drop {
        balance: u64
    }
    
    // Only admin module can call this
    public(friend) fun emergency_withdraw(vault: &mut Vault): u64 {
        let amount = vault.balance;
        vault.balance = 0;
        amount
    }
    
    // Public function - anyone can call
    public fun get_balance(vault: &Vault): u64 {
        vault.balance
    }

    public fun deposit(vault: &mut Vault, amount: u64) {
        vault.balance += amount;
    }

    public(friend) fun create_vault(initial_amount: u64): Vault {
        Vault { balance: initial_amount }
    }
}

module 0x42::admin {
    use 0x42::vault::{Self};
    
    public fun perform_emergency_withdrawal(): u64 {
        let vault = vault::create_vault(20);
        vault::emergency_withdraw(&mut vault)
    }
}

Declaration Rules

The friend system enforces several important constraints:

No Self-Declaration

Modules cannot declare themselves as friends:

module 0x42::example {
    friend Self;  // ERROR: Cannot declare self as friend
    friend 0x42::example;  // ERROR: Cannot declare self as friend
}

Same Address Requirement

Friend modules must be within the same account address:

module 0x42::core {
    friend 0x43::external;  // ERROR: Different address
}

No Circular Dependencies

Friend relationships cannot create dependency cycles:

module 0x42::a {
    use 0x42::c;
    friend 0x42::b;  // a uses c, friends b
}

module 0x42::b {
    friend 0x42::c;  // ERROR: Creates cycle (a->c, a friends b, b friends c)
}

No Duplicates

Each module can only be declared as a friend once:

module 0x42::core {
    use 0x42::utils as u;
    
    friend 0x42::utils;
    friend u;  // ERROR: Duplicate friend declaration
}

Summary

The friend system provides controlled access between modules:

  • Purpose: Allows modules to grant selective access to public(friend) functions
  • Access control: Enables fine-grained control over which modules can call specific functions
  • Declaration rules: Must prevent self-declaration, circular dependencies, and duplicate declarations
  • Same address requirement: Friend modules must be within the same account address
  • Use cases: Ideal for creating trusted relationships between related modules in a package