Module Flows

Module instantiation and execution is a process that is somewhat hidden from the end-user and developer. This section aims to elaborate on the message execution flows for these actions.

Installing and Uninstalling Modules

The following are sequence diagrams of the process of installing and uninstalling a module on an Abstract Account. As you can see, the process happens via the Account, and it can be done by the Account owner through the web-app.

sequenceDiagram
    autonumber
    actor U as Owner
    participant A as Account
    participant MF as Module Factory
    participant REG as Registry
    U ->> A: InstallModule
    A ->> MF: InstallModule
    MF -->>+ REG: Query Module Details
    alt adapter
        REG -->>+ MF: Return address
    else app / standalone
        REG -->>- MF: Return code_id
        MF -> MF: Instantiate module
    end
    MF ->> A: Register module address
    A ->> A: Update module allowlist
Installing a Module

At this point you should be able to understand the message flow depicted above. Just to be sure, we’ll briefly outline the process’s steps.

Installing a module starts by the Owner of the Account requesting the installation of the module. The request contains the module ID(s) and possible instantiate messages for any App/Standalone modules that should be installed (aka instantiated).

The Account contract verifies the request and forwards it to the Module Factory. The Module Factory then queries the Registry (the on-chain module registry) for the module details. These module details contain both the version of the module as well as its type-specific data. This type-specific data is depicted by the two alternatives (alt) of the returned query.

Either the query returns an Adapter’s address (which is already instantiated) or it returns an App/Standalone code-id. This code-id is then used by the Module Factory to instantiate an instance of that module.

After instantiating the modules, the Account registers the modules internally and updates its whitelist. This whitelisting provides the modules with the ability to proxy message execution through the Account.

sequenceDiagram
    autonumber
    actor U as Owner
    participant A as Account
    U ->> A: UninstallModule
    A -> A: Deregister module
    A ->> A: Update Account Whitelist
Uninstalling a Module

Uninstalling a Module follows a similar execution flow as shown above.

Info

In both flows we omitted the dependency-check logic, which will be discussed in more detail later.

Example Execution Flows

The following are sequence diagrams of the process of executing a function on a module of an Abstract Account. We show three examples of executing a module: Owner Execution, Adapter Execution, and Dependency Execution.

Let’s explore each of them.

Owner Execution

To execute a (permissioned) message on a specific module, the Owner can call the module directly. The Module knows who the Owner of the Account is.

sequenceDiagram
    autonumber
    actor U as Owner
    participant Md as Module ("addr123")
    U ->> Md: Execute

Adapter Execution

In the following example, the abstract:dex adapter is installed on an Account, and the Owner requests a swap on a dex. By providing the address of the Account in the call, the adapter can assert that the caller is the Owner of the Account.

sequenceDiagram
    autonumber
    actor U as Owner
    participant D as abstract:dex
    participant REG as Registry
    participant A as ANS
    participant A as Account
    participant T as Dex Pool
    Note right of U: Dex::Swap {account: "juno1xd..."}
    U ->> D: Call module
    D -->+ REG: Load address for Account
    REG -->- D: Address
    D -->>+ A: Resolve asset names
    A -->> D: Asset infos
    D --> A: Resolve dex pool
    A -->>- D: Pool metadata
    D --> D: Build swap msg for target dex
    D ->> A: Forward execution
    Note over REG, A: DexMsg
    A ->> T: Execute
    Note right of A: DexMsg

Dependency Execution

In this example, we use the Equilibrium App’s Rebalance function as an example. Modules with dependencies (equilibrium:balancer is dependent on abstract:etf and abstract:dex) have their addresses dynamically resolved when called.

sequenceDiagram
    autonumber
    actor U as User
    participant B as equilibrium:balancer
    participant A as Account
    participant D as abstract:dex
    participant T as Target Dex
    U ->> B: Rebalance
    B -->>+ A: Query Allocations
    A -->>- B: Allocations
    B --> B: Calculate rebalancing requirements
    B -->>+ A: Query abstract:dex address
    A -->>- B: Address
    B ->> D: Call SwapRouter on dex
    D --> D: Build swap msg for target dex
    D --> D: Load account address
    D ->> A: Forward execution
    Note over A: DexMsg
    A ->> T: Execute
    Note over D, A: DexMsg

s