Sui.

Post

Share your knowledge.

290697tz.
Jul 21, 2025
Expert Q&A

How do I verify the authenticity of a deployed package on Sui?

I'm trying to understand this aspect of the Sui Network because I'm either building, debugging, or deploying something that touches this area. I want a detailed explanation of how this mechanism or feature works, along with relevant CLI usage, Move code structure, or architectural concepts. My goal is to gain enough clarity to apply this knowledge in a real project—whether that's a custom smart contract, an NFT system, a wallet integration, or a DeFi tool. The Sui Network has unique features compared to EVM chains, so I'm particularly interested in what sets it apart and how that affects development best practices. It would help to have sample code, command line examples, or typical errors to watch for, especially when using the Sui CLI, SDK, or deploying on localnet/testnet. Ultimately, I want to avoid common mistakes, follow the best security principles, and ensure that the functionality I’m working on behaves as expected under realistic conditions.


  • Sui
  • Architecture
  • SDKs and Developer Tools
5
3
Share
Comments
.

Answers

3
shamueely.
Jul 21 2025, 21:33

To securely use flash loans on Sui with Move, you need to make sure that everything—from taking the loan to paying it back with the fee—happens in one single transaction. You can do this by writing a borrow function that gives out the loan temporarily and hands control to a callback function that handles the logic using the loaned assets. Thanks to Sui’s object-based system, you can track ownership easily and make sure the borrower returns both the original amount and the fee before the transaction finishes. This prevents people from skipping repayment or avoiding fees.

To handle fees safely, you should calculate the fee amount right when the loan is given and store it inside the transaction (like in a temporary struct). Then, once the loan is returned, your contract must check if both the borrowed amount and the fee are fully paid. If not, the transaction is canceled, and nothing goes through.

Sui has some useful tools to help you here. It runs transactions in a predictable way and tracks ownership of objects instead of account balances, which saves gas and avoids mistakes. To make your flash loan contract work with many types of tokens, you can use Move’s generic modules and phantom types, which keep things safe by enforcing strict type rules and making sure each asset is treated properly.

You can learn more about how to build secure flash loans and smart contracts on Sui by visiting the Sui Developer Docs – Move Smart Contracts

Transaction Block (sample structure):

transaction {
    let (loan_obj, callback_cap) = flash_loan::borrow(asset_id, amount, borrower_addr);
    borrower_contract::execute_loan_logic(loan_obj, callback_cap);
    flash_loan::repay_with_fee(asset_id, amount, borrower_addr);
}

This structure guarantees that the entire process—borrowing, using, and repaying—is completed in one atomic transaction, which means it either fully succeeds or fully fails, with no partial execution.

2
Best Answer
Comments
.
Momemtum.
Sep 7 2025, 22:25

Alright, let's talk about Sui's Object Model, because this is really what sets it apart from EVM chains and shapes how you build on it. Instead of an account's internal storage, everything on Sui is an 'object.' Each object has a unique ID, a version, and an explicit owner. Think of it as an object graph rather than a simple key-value store. This design is foundational to Sui's parallel execution capabilities.

There are a few key ownership types:

  1. Owned by an address: This is the most common. Only the object's owner can use or modify it. Crucially, if two transactions operate on different, exclusively owned objects, they can execute in parallel without contention, which boosts performance. Your SUI tokens or an NFT you mint are typical examples.
  2. Shared: These objects can be read and modified by anyone, usually managed by a smart contract. Transactions involving shared objects do require a global consensus order, so they don't benefit from parallelization as much as owned objects, but they're essential for things like DeFi liquidity pools or global registries.
  3. Immutable: Created once, never changed. These are read-only and can be used by anyone, always processed in parallel. Published Move packages or configuration settings often fall into this category. You can make an owned object immutable by 'freezing' it using sui::transfer::freeze_object.
  4. Wrapped/Child Objects: Objects can contain other objects. For instance, a game character object might wrap several inventory item objects. The parent object's ownership determines the children's access.

Sui vs. EVM: In EVM, a contract address holds all its state in a single, mutable storage area, creating a global lock whenever a contract is interacted with. Sui's explicit object ownership eliminates this global lock. Transactions can proceed independently if they access distinct, owned objects, allowing for much higher throughput and eliminating common EVM issues like reentrancy on state writes.

Move Code Structure: You define objects in Move using struct with the has key ability. The sui::object::UID type is mandatory for uniquely identifying your object on-chain. Functions modify objects by taking mutable references (&mut MyObject) or consuming and returning them by value (MyObject).

module example::my_nft {
    use sui::object::{Self, UID};
    use sui::transfer;
    use sui::tx_context::{Self, TxContext};

    struct MyNFT has key, store {
        id: UID,
        name: vector<u8>,
        description: vector<u8>,
    }

    public entry fun mint_nft(
        name: vector<u8>,
        description: vector<u8>,
        ctx: &mut TxContext
    ) {
        let sender = tx_context::sender(ctx);
        let nft = MyNFT {
            id: object::new(ctx),
            name,
            description,
        };
        transfer::public_transfer(nft, sender);
    }

    public entry fun update_nft_description(
        nft: &mut MyNFT,
        new_description: vector<u8>,
        _ctx: &mut TxContext
    ) {
        // Sui's ownership system ensures only the owner can call this
        nft.description = new_description;
    }
}

CLI/SDK Usage: To see objects owned by an address: sui client objects <YOUR_ADDRESS>. To inspect a specific object: sui client object <OBJECT_ID>. When constructing Programmable Transaction Blocks (PTBs), you'll specify input objects by their IDs. Sui's RPC automatically infers if an object needs to be mutable, immutable, or shared based on your Move call.

Best Practices & Pitfalls:

  • Object Versioning: An object's ObjectID is stable, but its version increments every time it's modified. If your application caches object data, be aware that the state for a given ObjectID can change. Always re-fetch if you need the latest state, or ensure your sui client or SDK calls are getting the latest version.
  • Shared Object Contention: While necessary, frequently updating shared objects can become a bottleneck. Design your system to use owned objects as much as possible for parallelization, resorting to shared objects only for truly global, concurrent resources.
  • No Global Mutable State: Unlike EVM, there's no way to have a single, globally mutable variable directly accessible by all contracts. All state mutations must happen on specific objects you pass in, which enforces a clearer, more modular state management pattern.
  • Security: Be deliberate with transfer::public_transfer and transfer::public_share_object. Accidentally sharing a sensitive, mutable object is a major security risk. Always think about who should own and modify each piece of data.
8
Comments
.

Do you know the answer?

Please log in and share it.