Explore
Connect with communities and discover new ideas.
Communities
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Top postsTop members- 396
- 360
- 345
Move is an executable bytecode language used to implement custom transactions and smart contracts.
Top postsTop members- 271
- 260
- 251
The InterPlanetary File System (IPFS) is a protocol, hypermedia and file sharing peer-to-peer network for storing and sharing data in a distributed file system.
Top postsTop members- 25
- 20
- 20
Walrus is a decentralized storage and data availability protocol designed specifically for large binary files, or "blobs"
Top postsTop members- 25
- 21
- 20
Peera is a decentralized questions and answers protocol for Web3 where users can organize and store their interests and skills, creating a common community platform
Top members- 328
- 286
- 225
Bounty
- +10ForMoveMar 11, 2025
Sui Move vs Aptos Move - What is the difference?
Sui Move and Aptos Move - two prominent implementations of the Move programming language. While both are rooted in the same foundational principles, they have diverged significantly in design, execution, and ecosystem development. To better understand their differences, we need to uncover some of their key aspects: How do their runtimes differ? Both Sui and Aptos implement their own custom Move virtual machines (VMs). How does this impact performance, scalability, and developer experience? For instance: Does Sui's runtime optimize for parallel execution differently than Aptos'? Are there notable differences in transaction lifecycle management or gas models? What are the differences between their standard libraries? The Move standard library is a critical component for building smart contracts. However, Sui and Aptos have forked their implementations, leading to divergence: Are there modules or functions unique to one implementation but absent in the other? How do these differences affect common use cases like token creation, NFTs, or decentralized finance (DeFi)? How does data storage differ between them? One of the most significant distinctions lies in how Sui and Aptos handle data storage: Sui uses an object-centric model, where each object has its own ownership and permissions. Aptos, on the other hand, retains a more traditional account-based model similar to Ethereum. How does this impact state management, composability, and gas efficiency? Is it fair to say that Aptos is closer to EVM while Sui is closer to SVM? Some developers argue that Aptos' account-based architecture resembles Ethereum's EVM, while Sui's object-centric approach aligns more closely with Solana's SVM. Do you agree with this analogy? Why or why not? How does this architectural choice influence developer ergonomics and application design? Are there universal packages working for both Sui Move and Aptos Move? Given their shared origins, it would be ideal if some libraries or tools were interoperable across both ecosystems. Are there any existing universal packages or frameworks that work seamlessly on both platforms? If not, what are the main barriers to achieving compatibility? Can one of them be transpiled into another? If a project is built on Sui Move, could it theoretically be transpiled to run on Aptos Move, or vice versa? What are the technical challenges involved in such a process? Are there tools or compilers currently available to facilitate this kind of migration?
21 - +10ForSuiMar 05, 2025
Multiple Source Verification Errors" in Sui Move Module Publications - Automated Error Resolution
Developers working with Sui Move frequently encounter issues related to "Multiple source verification errors found" when attempting to publish or upgrade modules. These errors occur due to mismatches between local dependencies and their on-chain counterparts, leading to failed publications and deployment challenges. Below is a consolidated example of the errors developers face: Failed to publish the Move module(s), reason: [warning] Multiple source verification errors found: Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::vec_set Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::vec_map Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000001::MoveStdlib::bit_vector Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000001::MoveStdlib::ascii Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::hex Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::zklogin_verified_id Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::prover Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::coin Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::dynamic_field Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::transfer On-chain version of dependency Sui::zklogin_verified_id was not found. On-chain version of dependency Sui::zklogin_verified_issuer was not found. Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::tx_context Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::transfer_policy Local dependency did not match its on-chain version at 0000000000000000000000000000000000000000000000000000000000000002::Sui::kiosk This issue often arises due to: Mismatched versions between the local development environment (e.g., Sui CLI) and the on-chain state. Differences in package configurations across networks (e.g., Mainnet vs. Testnet). Missing or outdated dependencies in the on-chain environment. Key Questions How can we automate the detection and resolution of these dependency mismatches during the publication process? What tools or scripts can be developed to ensure that local dependencies always align with their on-chain counterparts? Is there a way to streamline this process by integrating dependency checks into existing CI/CD pipelines or enhancing the Sui SDK? Your task is to propose a solution that addresses these challenges, ensuring smoother and more reliable deployments for Sui Move developers. Make sure to post your solution below.
41
Newest
- ForWalrusMay 01, 2025
Where else can I get SUI from a faucet?
I've been using a SUI faucet for some transactions, but I'm looking for alternative options to receive SUI tokens. Are there other faucets or methods I can try?
01 How to fix Sui wallet and Ledger connection issues?
I'm having trouble with my Sui wallet on Brave browser, protected by my Ledger device. When I try to send funds to an exchange, it prompts me to connect the Ledger, but it claims it's disconnected. How can I resolve this issue? And do I need the seed recovery phrase to reconnect my Ledger?
00Is my file private when uploaded to Walrus?
I'm thinking of using Walrus for storing some files. My main concern is whether my files are private by default when I upload them. I don't really want my personal or sensitive data out in the open for everyone to see. Can someone let me know if there's a way to keep my files private, or should I be looking into alternatives?
01
Unanswered
How to fix Sui wallet and Ledger connection issues?
I'm having trouble with my Sui wallet on Brave browser, protected by my Ledger device. When I try to send funds to an exchange, it prompts me to connect the Ledger, but it claims it's disconnected. How can I resolve this issue? And do I need the seed recovery phrase to reconnect my Ledger?
00Walrus Protocol - The hidden gem on SUI
The term "Walrus" in the context of the documents you provided refers to a decentralized storage platform developed by Mysten Labs, which is a part of the Sui ecosystem. Walrus is designed to handle large-scale data storage needs that traditional blockchains cannot manage efficiently. It offers a cost-effective, scalable, and programmable storage solution, reinforcing Sui's position as a global coordination layer. The Walrus platform is also associated with the WAL token, which plays a crucial role in powering the network through delegated proof-of-stake and ensuring reliable data storage via novel attestation challenges. Additionally, Walrus is used for storing media content, as demonstrated by Decrypt, a leading Web3 media outlet, which is posting its entire content library to Walrus. For more detailed information, you can refer to the Walrus Whitepaper.
10
Trending
- 0xduckmove220ForSuiApr 08, 2025
👀 SEAL- I Think Web3 Data Privacy Is About to Change
👀SEAL is Live on Sui Testnet – I Think Web3 Data Privacy Is About to Change In the Web3, it’s common to hear phrases like “users own their data” or “decentralized by design”. But when you look closely, many applications still rely on centralized infrastructures to handle sensitive data — using services like AWS or Google Cloud for key management. This introduces a contradiction: decentralization on the surface, centralization underneath. But what if there was a way to manage secrets securely, without giving up decentralization?Introducing SEAL – Decentralized Secrets Management (DSM), now live on the Sui Testnet. SEAL aims to fix one of Web3’s biggest hypocrisies: shouting decentralization while secretly using AWS You maybe ask me: What is SEAL? SEAL is a protocol that lets you manage sensitive data securely and decentrally – built specifically for the Web3 world. Think of it as a privacy-first access control layer that plugs into your dApp. You can think of SEAL as a kind of programmable lock for your data. You don’t just lock and unlock things manually — you write policies directly into your smart contracts, using Move on Sui. Let’s say you’re building a dApp where: Only NFT holders can unlock a premium tutorial Or maybe a DAO has to vote before sensitive files are revealed Or you want metadata to be time-locked and only accessible after a specific date SEAL makes all of that possible. The access control lives onchain, fully automated, no need for an admin to manage it. Just logic, baked right into the blockchain. SEAL makes all of that possible. The access control lives onchain, fully automated, no need for an admin to manage it. Just logic, baked right into the blockchain. Another interesting piece is how SEAL handles encryption. It uses something called threshold encryption, which means: no single node can decrypt the data. It takes a group of servers to work together — kinda like multi-sig, but for unlocking secrets. This distributes trust and avoids the usual single-point-of-failure problem. And to keep things truly private, SEAL encrypts and decrypts everything on the client side. Your data is never visible to any backend. It stays in your hands — literally — on your device. and SEAL doesn’t care where you store your data. Whether it’s IPFS, Arweave, Walrus, or some other platform, SEAL doesn’t try to control that part. It just focuses on who’s allowed to see what, not where things are stored. So yeah, it’s not just a library or API — it’s an onchain-first, access-controlled, privacy-by-default layer for your dApp. SEAL fills a pretty critical gap. Let’s break that down a bit more. If you’re building a dApp that deals with any form of sensitive data — gated content, user documents, encrypted messages, even time-locked NFT metadata — you’ll run into the same problem: ➡️ How do you manage access securely, without relying on a centralized service? Without something like SEAL, most teams either: Use centralized tools like AWS KMS or Firebase, which clearly goes against decentralization Or try to patch together half-baked encryption logic themselves, which usually ends up brittle and hard to audit https://x.com/EmanAbio/status/1908240279720841425?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1908240279720841425%7Ctwgr%5E697f93dc65359d0c8c7d64ddede66c0c4adeadf1%7Ctwcon%5Es1_&ref_url=https%3A%2F%2Fwww.notion.so%2Fharryph%2FSEAL-Launches-on-Sui-Testnet-1cc4f8e09bb380969c0dcc627b96cc22 Neither of those scales well. Especially not when you’re trying to build trustless apps across multiple chains or communities. SEAL makes that entire process modular and programmable. You define your access rules in Move smart contracts, and SEAL handles the rest — key generation, decryption approvals, and access enforcement — all without anyone manually issuing keys or running backend checks. Even better, those rules are auditable and immutable — once they’re onchain, they follow the contract, not a human admin. So instead of asking “who should manage access to this data?” you just ask: “What logic should define access?” …and let the chain handle it. Clean and scalable. That’s what makes SEAL relevant for more than just “security tools” — it’s a base layer for any dApp that cares about privacy, compliance, or dynamic access logic. It’s a small shift — but it changes a lot about how we think of data in Web3. Instead of encrypting after deployment, or relying on external services, you start with privacy built-in — and access handled entirely by smart contract logic. And that’s exactly what Web3 needs right now. How Does SEAL Actually Work? We’ve covered what SEAL is and why Web3 needs it, let’s take a look at how it’s actually built under the hood. This part is where things get more technical — but in a good way. The architecture is elegant once you see how all the pieces fit together. At a high level, SEAL works by combining onchain access logic with offchain key management, using a technique called Identity-Based Encryption (IBE). This allows devs to encrypt data to an identity, and then rely on smart contracts to define who is allowed to decrypt it. Step 1: Access Rules in Smart Contracts (on Sui) Everything starts with the smart contract. When you’re using SEAL, you define a function called seal_approve in your Move contract — this is where you write your conditions for decryption. For example, here’s a simple time-lock rule written in Move: entry fun seal_approve(id: vector, c: &clock::Clock) { let mut prepared: BCS = bcs::new(id); let t = prepared.peel_u64(); let leftovers = prepared.into_remainder_bytes(); assert!((leftovers.length() == 0) && (c.timestamp_ms() >= t), ENoAccess); } Once deployed, this contract acts as the gatekeeper. Whenever someone wants to decrypt data, their request will get checked against this logic. If it passes, the key gets released. If not, they’re blocked. No one has to intervene. Step 2: Identity-Based Encryption (IBE) Here’s where the magic happens. Instead of encrypting data for a specific wallet address (like with PGP or RSA), SEAL uses identity strings — meaning you encrypt to something like: 0xwalletaddress dao_voted:proposal_xyz PkgId_2025_05_01 (a timestamp-based rule) or even game_user_nft_holder When the data is encrypted, it looks like this: Encrypt(mpk, identity, message) mpk = master public key (known to everyone) identity = the logic-defined recipient message = the actual data Later, if someone wants to decrypt, the key server checks if they match the policy (via the seal_approve call onchain). If it’s approved, it returns a derived private key for that identity. Derive(msk, identity) → sk Decrypt(sk, encrypted_data) The user can then decrypt the content locally. So encryption is done without needing to know who will decrypt ahead of time. You just define the conditions, and SEAL figures out the rest later. It’s dynamic. Step 3: The Key Server – Offchain, But Not Centralized You might wonder: who’s holding these master keys? This is where SEAL’s Key Server comes in. Think of it as a backend that: Holds the master secret key (msk) Watches onchain contracts (like your seal_approve logic) Only issues derived keys if the conditions are satisfied But — and this is key — SEAL doesn’t rely on just one key server. You can run it in threshold mode, where multiple independent servers need to agree before a decryption key is issued. For example: 3-of-5 key servers must approve the request. This avoids central points of failure and allows decentralization at the key management layer too. Even better, in the future SEAL will support MPC (multi-party computation) and enclave-based setups (like TEE) — so you can get even stronger guarantees without compromising usability. Step 4: Client-Side Decryption Once the key is returned to the user, the actual decryption happens on their device. This means: The server never sees your data The backend never stores decrypted content Only the user can access the final message It’s a solid privacy model. Even if someone compromises the storage layer (IPFS, Arweave, etc.), they still can’t read the data without passing the access logic. Here’s the quick mental model: This structure makes it easy to build dApps where access rules aren’t hardcoded — they’re dynamic, auditable, and fully integrated into your chain logic. The Team Behind SEAL SEAL is led by Samczsun, a well-known figure in the blockchain security community. Formerly a Research Partner at Paradigm, he has audited and saved multiple ecosystems from major exploits. Now, he’s focused full-time on building SEAL into a core piece of Web3’s privacy infrastructure. With his background and credibility, SEAL is not just another experimental tool — it’s a serious attempt at making decentralized data privacy both practical and scalable. As SEAL goes live on the Sui Testnet, it brings a new standard for how Web3 applications can manage secrets. By combining onchain access control, threshold encryption, and client-side privacy, SEAL offers a more trustworthy foundation for decentralized data handling. Whether you’re building dApps, DAOs, or decentralized games — SEAL provides a powerful toolkit to enforce access control and protect user data without compromising on decentralization. If Web3 is going to move forward, secure infrastructure like SEAL is not optional — it’s essential
8 - harry phan360ForSuiApr 24, 2025
Cross-Module Child Management with public_receive
This is the part 3 of "Parent-Child Objects in Sui Move" series. Sometimes your parent and child types are defined in different modules or even different packages. For example, you might have a generic Warehouse object that can store any kind of Parcel objects. The Warehouse module wants to pull out a Parcel child, but the Parcel type is defined elsewhere. In such cases, we use transfer::public_receive, which is the cross-module cousin of receive. receive vs public_receive As we saw, transfer::receive can only be called in the module that defines T (or a friend) because it doesn’t require T: store . The Move bytecode verifier actually ensures that in any call to receive, the type T is from the current module . This is a safety restriction for key-only objects. transfer::public_receive is a variant that requires T: key + store but allows receiving outside T’s module . In other words, if the object type has the store ability (meaning it’s allowed to exist in global storage freely), then any module (given a &mut UID of the parent) can receive it using public_receive . This is perfect for cases where the parent’s module is different from the child’s module. Why require store? Because store marks that the object can be safely persisted and passed around outside of its defining module. Key-only objects might have custom invariants that the original module wants to enforce on transfer/receive; by excluding those from public_receive, Sui forces developers to handle them in-module (as we’ll see with soul-bound objects). If an object has store, it’s more permissive, and Sui allows generic transfer/receive logic to manage it externally . Example: Separate Parent and Child Modules Let’s illustrate with a simple scenario: a Warehouse that stores Parcel objects. The Parcel type is defined in its own module, and the Warehouse in another. We’ll show how Warehouse can receive a Parcel child using public_receive. module demo::parcel { // Child module use sui::object::{Self, UID}; use sui::tx_context::{Self, TxContext}; /// A parcel object that can be stored in a Warehouse. /// It has both key and store, so it can be transferred across modules. struct Parcel has key, store { id: UID, contents: vector } public entry fun create_parcel(contents: vector, ctx: &mut TxContext): Parcel { Parcel { id: object::new(ctx), contents } } } module demo::warehouse { // Parent module use sui::transfer::{Self, Receiving, public_receive}; use demo::parcel::{Self, Parcel}; use sui::object::{UID}; use sui::tx_context::{Self, TxContext}; struct Warehouse has key { id: UID, location: address } public entry fun create_warehouse(location: address, ctx: &mut TxContext): Warehouse { Warehouse { id: object::new(ctx), location } } /// Receive a Parcel that was sent to this Warehouse. /// Returns the Parcel to the caller (transferred to caller's address). public entry fun withdraw_parcel( warehouse: &mut Warehouse, parcel_ticket: Receiving, ctx: &mut TxContext ): Parcel { // Using public_receive because Parcel is defined in another module and has store let parcel = public_receive(&mut warehouse.id, parcel_ticket) oai_citation_attribution:27‡docs.sui.io oai_citation_attribution:28‡github.com; // Transfer the parcel to the transaction sender (so the caller gets ownership) transfer::transfer(parcel, tx_context::sender(ctx)); // We return nothing because we've transferred the Parcel out to the caller. } } Let’s break down what’s happening in withdraw_parcel: We call public_receive(&mut warehouse.id, parcel_ticket). Because Parcel has the store ability, this call is allowed even though we’re not in the parcel module . Under the hood, this does the same check and extraction as receive, but it’s permitted cross-module since store indicates it’s safe to do so. https://github.com/MystenLabs/sui/blob/main/crates/sui-framework/packages/sui-framework/sources/transfer.move#:~:text=public%20fun%20public_receive,T%3E%29%3A%20T We then immediately transfer the received Parcel to the caller’s address (tx_context::sender(ctx)). This step ensures the parcel leaves the warehouse and goes to the user who initiated the withdrawal. We could also have just returned Parcel from the function, and Sui would treat it as an output to be owned by the caller’s address (since it’s an entry function output). Doing an explicit transfer is more verbose, but makes it clear what’s happening (and allows us to do any checks before releasing the object). Why include store in Parcel? If Parcel lacked the store ability (i.e. was only has key), the public_receive call in demo::warehouse would not compile – Sui enforces that T has store for public_receive . In that case, we’d be forced to retrieve the parcel using receive within the parcel module itself (or use some friend relationship), which complicates cross-module design. By adding store to Parcel, we effectively say “this object can be freely moved and received by external modules,” which is what we want for a generic container pattern. Function call pattern: To use these in a transaction, the flow would be: Deposit (transfer to object): Call transfer::public_transfer(parcel_obj, @warehouse_id) to send a Parcel into a Warehouse. This marks the parcel’s owner as the warehouse. (We use public_transfer here because it’s outside the Parcel module and Parcel has store . Inside the parcel’s module, a plain transfer would work too.) Withdraw (receive back): Later, call withdraw_parcel(warehouse_obj, Receiving(parcel_id, ...)). The Receiving can be obtained by the SDK by referencing the parcel’s ID and latest version. The function will call public_receive and then transfer the parcel to you. After the withdraw_parcel call, the parcel’s owner is back to an address (yours), so it’s a normal address-owned object again. The warehouse no longer owns it. Cross-module considerations: Notice that the Warehouse module needed to know about the Parcel type (we use demo::parcel::Parcel). This is because we explicitly type the Receiving as Receiving. If you wanted a truly generic container that could receive any type of object, you’d have to use generics or a different approach (possibly dynamic fields with type erasure). But for most use-cases, you’ll know what types of children you expect. Why public_receive instead of just calling receive? If we tried transfer::receive(&mut warehouse.id, parcel_ticket) in the warehouse module, the Move verifier would reject it because Parcel is not defined in demo::warehouse. Sui provides the public_receive as the blessed way to do this with an extra ability check (requiring store). Similarly, Sui has transfer vs public_transfer, freeze_object vs public_freeze_object, etc., following the same pattern: the public_ versions are for use outside the defining module and require store . Don’t forget the parent’s permission: Even with public_receive, you still need that &mut warehouse.id. We got it because withdraw_parcel is in Warehouse’s module and accepts &mut Warehouse. Thus, only someone who could call that (the warehouse’s owner) can withdraw the parcel. If the warehouse module didn’t provide such a function publicly, no one could externally call public_receive on its children either. So cross-module doesn’t bypass the parent’s control; it just allows the parent’s code to work with children of types it didn’t define. A note on store ability: Giving an object store makes it more flexible but slightly less restricted – any module with the parent reference can pull it out using public_receive. If you want to restrict how an object is retrieved (for example, enforce custom logic or prevent easy extraction), you might deliberately make it key-only. We’ll see an example of that with soul-bound objects. In those cases, you might implement a custom receive function instead of relying on public_receive. To sum up this part: public_receive is your friend for managing child objects defined in other modules, as long as those objects have the store ability. It allows you to build cross-module systems (like our Warehouse/Parcel) while still respecting ownership and access control. Just remember to include store on child types and use public_transfer when sending them to a parent from outside their module .
5 - 0xduckmove220ForSuiApr 25, 2025
Recap the video can supercharge your Sui Dev Journey
Let’s be real if you’ve ever built on Sui, you’ve probably hit some walls. From cryptic object IDs to juggling CLIs and spinning up localnets, it’s like prepping for a boss fight before you even write your first line of business logic. During a recent workshop as part of the Road to Overflow series, Moven from Dubhe Foundation broke down how Dubhe Engine works, what problems it solves, and how it’s more than just a tool — it’s a growing movement. Video link: https://www.youtube.com/watch?v=CHkOS-TYehM The Problem: Fragmented Tooling, Heavy Setup Moven kicked things off with some real talk about the current Sui dev landscape: Newcomers face a steep learning curve: setting up wallets, claiming test tokens, scaffolding packages, learning Move syntax, spinning up local testnets, configuring SDKs, and more. Even experienced developers find themselves wasting time on repetitive setup tasks rather than focusing on actual DApp logic. Codebases become monolithic fast — large, messy .move files with data structs, constructors, helpers, and entry functions all crammed together. In short: the ecosystem is growing fast, but the tools haven’t kept up until now. The Solution: Schema-Based Code Generation At the heart of Dubhe Engine is one key idea: schema-first development. With just one configuration file (d.config.ts), devs can define: Their onchain data structures Events Errors Custom types (even 2D vectors of self-defined structs!) From there, one command (pnpm dub schema:gen) auto-generates a fully structured Move package and frontend integration, complete with: Modularized file structure Onchain composability (via imports from Sui’s published packages) Localnet setup, build, deploy, and frontend support (Next.js ready) You write the logic. Dubhe handles the boilerplate. ⏱️ Real Impact: 80% Less Repetitive Code In internal experiments, Dubb-generated projects showed that only 20% of the code had to be written manually — the rest was scaffolding auto-generated via schemas. This means faster prototyping, fewer bugs, and more time to focus on what actually matters: your app’s core value. A Dev Ecosystem Engine Dubb isn’t stopping at scaffolding. Movin made it clear: this is infrastructure for a new developer economy. Here’s how the Dubb Engine community is evolving: Gas Subsidies:** For new builders experimenting with Dubb Task Bounties:** Like GitHub’s “good first issues,” but with rewards Governance Layer (D-OS):** Onchain voting for project prioritization Launchpad Support:** Helping mature projects secure funding DApp Staking:** Users can stake D-tokens to support their favorite DApps and vote on roadmap decisions This feedback loop fuels the whole Sui ecosystem: more devs → more apps → more users → more devs.
5