DApp Admin

When a DApp is first deployed (genesis::run), the account that executed the transaction becomes the DApp admin. The admin can update metadata, transfer ownership, pause the DApp, and top up storage credits.

Admin functions all operate on DappStorage — the per-DApp shared object created during deployment. Access it via the object ID stored in .history/sui_<network>/latest.json after dubhe publish.


What the admin can do

ActionFunction
Update name, description, website, coverset_metadata<DappKey>
Transfer admin rolepropose_ownership<DappKey> + accept_ownership<DappKey>
Emergency pause / resumeset_paused<DappKey>
Top up storage creditsrecharge_credit<DappKey>
Register a new upgradeupgrade_dapp<DappKey>

Updating metadata

use dubhe::dapp_system;
use dubhe::dapp_service::DappStorage;
use mygame::dapp_key::DappKey;
use std::ascii::string;
 
public entry fun update_metadata(dapp_storage: &mut DappStorage, ctx: &mut TxContext) {
    dapp_system::set_metadata<DappKey>(
        dapp_storage,
        string(b"My Game v2"),
        string(b"An on-chain strategy game"),
        string(b"https://mygame.xyz"),
        vector[string(b"https://mygame.xyz/cover.png")],  // cover_url (list)
        vector[string(b"PartnerProtocol")],                // partners (list)
        ctx
    );
}

Only the current admin can call set_metadata. Attempting to call it from any other account aborts with NO_PERMISSION.


Two-step ownership transfer

Dubhe uses the Ownable2Step pattern to prevent accidental loss of admin control. A single typo in the target address cannot permanently lock you out — the nominee must actively accept the role.

Step 1 — Propose

The current admin nominates a new owner:

// Called by the current admin
dapp_system::propose_ownership<DappKey>(
    &mut dapp_storage,
    @0xNEW_ADMIN,
    ctx
);

At this point the existing admin retains full control. The pending_admin field in DappStorage is set to @0xNEW_ADMIN.

To cancel a pending transfer, call propose_ownership again with @0x0:

// Cancel — clears the pending nominee
dapp_system::propose_ownership<DappKey>(&mut dapp_storage, @0x0, ctx);

Step 2 — Accept

The nominated account must confirm by calling accept_ownership from their own wallet:

// Called by the NEW admin (@0xNEW_ADMIN)
dapp_system::accept_ownership<DappKey>(
    &mut dapp_storage,
    ctx
);

On success:

  • The admin field in DappStorage is set to the caller
  • The pending_admin field is cleared to @0x0

If there is no pending transfer (or the caller is not the nominee), the transaction aborts.


Emergency pause

Pause the DApp to halt all writes during an incident:

// Admin pauses — all entry functions guarded by ensure_not_paused will abort
dapp_system::set_paused<DappKey>(
    &mut dapp_storage,
    true,
    ctx
);
 
// Resume when ready
dapp_system::set_paused<DappKey>(
    &mut dapp_storage,
    false,
    ctx
);

For the pause flag to take effect, your entry functions must include the guard:

dapp_system::ensure_not_paused<DappKey>(&dapp_storage);

See Access Control for the recommended guard order.


Topping up storage credits

Anyone can top up a DApp’s storage credits — the admin, a sponsor, or a community member:

use sui::coin;
use dubhe::dapp_service::{DappHub, DappStorage};
use dubhe::dapp_system;
 
// Recharge with 0.1 SUI (100_000_000 MIST)
let payment = coin::split(&mut my_sui_coin, 100_000_000, ctx);
dapp_system::recharge_credit<DappKey>(&dapp_hub, &mut dapp_storage, payment, ctx);
  • Payment is forwarded to the Dubhe framework treasury
  • Credits are added to the DApp’s credit_pool at a 1:1 rate (1 MIST = 1 credit unit)
  • No admin restriction — any account can top up any DApp

See Storage Fees for how credits are consumed and how to estimate how much SUI your DApp needs.


Registering an upgrade

After publishing a new package version, the admin must register it:

dapp_system::upgrade_dapp<DappKey>(
    &mut dapp_storage,
    new_package_id,               // address of the newly published package
    migrate::on_chain_version(),  // must be > current on-chain version
    ctx
);

See Contract Upgrading for the full upgrade workflow.