Modules on Aptos
Aptos allows for permissionless publishing of modules within a package as well as upgrading those that have appropriate compatibility policy set.
A module contains several structs and functions, much like Rust.
During package publishing time, a few constraints are maintained:
- Both Structs and public function signatures are published as immutable.
Legacy: init_module (deprecated)
Section titled “Legacy: init_module (deprecated)”Historically, module initialization was handled by an init_module function:
- When a module was published for the first time (i.e., the module did not exist on-chain), the VM would search for and execute the
init_module(account: &signer)function. - When upgrading an existing on-chain module,
init_moduleis NOT called. - The signer of the publishing account was passed in. The function had to be private, take at most one
&signerparameter, have no generic parameters, and return no value.
Because this implicit publish-time execution is being removed, new modules should use the explicit pattern below instead.
Recommended: explicit initialize entry function
Section titled “Recommended: explicit initialize entry function”Expose an entry fun initialize that the module publisher calls in a separate transaction after publishing the package. Guard it so it runs only once, and only for the publisher:
module my_addr::my_module { use std::signer; use aptos_framework::error;
/// Caller is not the module publisher. const ENOT_AUTHORIZED: u64 = 1; /// Module is already initialized. const EALREADY_INITIALIZED: u64 = 2;
struct ModuleData has key { /* fields */ }
entry fun initialize(publisher: &signer) { assert!(signer::address_of(publisher) == @my_addr, error::permission_denied(ENOT_AUTHORIZED)); assert!(!exists<ModuleData>(@my_addr), error::already_exists(EALREADY_INITIALIZED)); move_to(publisher, ModuleData { /* ... */ }); }}