The Sui blockchain is redefining how developers interact with smart contracts and digital assets. At the heart of this innovation lies the Move programming language—a secure, resource-oriented language designed to prevent common vulnerabilities in smart contract logic. The Let’s Move initiative capitalizes on this momentum by offering a hands-on learning path where participants gain real-world experience building on Sui while earning rewards.
This guide walks you through Task 3 of the Let’s Move program: deploying an NFT smart contract to the Sui mainnet, minting your first NFT, and transferring it to a designated address. Whether you're new to Move or refining your skills, this step-by-step walkthrough ensures you meet all requirements efficiently and securely.
Understanding the Task Requirements
Before diving into code, let’s clarify what Task 3 entails:
- Learn NFT fundamentals: Understand how non-fungible tokens work in the Sui ecosystem.
- Deploy an NFT contract: Publish a Move module that enables NFT creation.
- Mint an NFT: Use your deployed contract to create a unique digital asset.
- Transfer the NFT: Send one NFT to the following address:
0x7b8e0864967427679b4e129f79dc332a885c6087ec9e187b53451a9006ee15f2
These steps mirror real-world blockchain development workflows, making them invaluable for aspiring Web3 engineers.
👉 Discover how to accelerate your Move learning journey with powerful tools
Building the NFT Smart Contract in Move
The foundation of any NFT project is its smart contract. Below is a fully functional Move module named simple_nft, which defines the structure, behavior, and event emissions for your NFTs.
module new_nft::simple_nft {
use sui::url::{Url, Self};
use std::string;
use sui::object::{Self, ID, UID};
use sui::event;
use sui::transfer;
use sui::tx_context::{TxContext, Self};
struct SimpleNFT has key, store {
id: UID,
name: string::String,
description: string::String,
url: Url,
}
struct SimpleNftMintEvent has copy, drop {
object_id: ID,
creator: address,
name: string::String,
}
struct SimpleNftTransferEvent has copy, drop {
object_id: ID,
from: address,
to: address,
}
struct SimpleNftBurnEvent has copy, drop {
object_id: ID,
}
// Public view functions
public fun name(nft: &SimpleNFT): string::String {
nft.name
}
public fun description(nft: &SimpleNFT): string::String {
nft.description
}
public fun url(nft: &SimpleNFT): Url {
nft.url
}
// Entry functions
public entry fun mint_nft(
name: vector<u8>,
description: vector<u8>,
url: vector<u8>,
ctx: &mut TxContext
) {
let sender = tx_context::sender(ctx);
let nft = SimpleNFT {
id: object::new(ctx),
name: string::utf8(name),
description: string::utf8(description),
url: url::new_unsafe_from_bytes(url),
};
event::emit(SimpleNftMintEvent {
object_id: object::id(&nft),
creator: sender,
name: nft.name,
});
transfer::public_transfer(nft, sender);
}
public entry fun transfer_nft(
nft: SimpleNFT,
recipient: address,
_: &mut TxContext
) {
event::emit(SimpleNftTransferEvent {
object_id: object::id(&nft),
from: tx_context::sender(_),
to: recipient,
});
transfer::public_transfer(nft, recipient);
}
public entry fun update_description(
nft: &mut SimpleNFT,
description: vector<u8>,
_: &mut TxContext
) {
nft.description = string::utf8(description);
}
public entry fun burn(
nft: SimpleNFT,
_: &mut TxContext
) {
let SimpleNFT { id, name: _, description: _, url: _ } = nft;
event::emit(SimpleNftBurnEvent {
object_id: object::uid_to_inner(&id),
});
object::delete(id);
}
}Key Features of This Contract
- Resource Safety: The
has key, storeensures the NFT can be stored and looked up. - Event Logging: Minting, transferring, and burning emit events—critical for off-chain indexing.
- Extensibility: Includes optional functionality like updating descriptions and burning tokens.
Deploying to Sui Mainnet
Once your code is ready, it's time to publish it on the Sui mainnet.
Step 1: Switch to Mainnet Environment
Ensure your Sui client is configured for production:
sui client switch --env mainnetYou should see:
Active environment switched to [mainnet]Step 2: Publish the Package
Run the publish command with sufficient gas:
sui client publish --gas-budget 200000000 --skip-dependency-verificationUpon successful deployment, you’ll receive a Package ID—save this permanently.
👉 Access advanced blockchain development resources to streamline your deployments
Step 3: Set Environment Variables
Replace placeholders with actual values:
export PACKAGE_ID=0xf78fb118efd9a86d8e2c54ac18766a1313bd8b0df80c85f859f83d01a5f78981
export NFT_NAME="\"joker\""
export DESCRIPTION="\"simple nft, power by alva-lin\""
export URL="<YOUR_NFT_IMAGE_URL>"Make sure your image URL is publicly accessible (e.g., hosted on IPFS or a CDN).
Step 4: Mint Your NFT
Call the mint_nft function:
sui client call \
--gas-budget 7500000 \
--package $PACKAGE_ID \
--module simple_nft \
--function mint_nft \
--args $NFT_NAME $DESCRIPTION $URLAfter confirmation, you’ll own a unique NFT. Note its Object ID from the response.
Step 5: Transfer NFT to Required Address
Now send it to the designated recipient:
export NFT_ID=0xc1d108cdeef7666aa3f414bb3ead5faa7cd351e4dc75d0307e2888b640232787
export ADDRESS=0x7b8e0864967427679b4e129f79dc332a885c6087ec9e187b53451a9006ee15f2
sui client call \
--gas-budget 7500000 \
--package $PACKAGE_ID \
--module simple_nft \
--function transfer_nft \
--args $NFT_ID $ADDRESSOnce executed, the task is complete.
Core Keywords for SEO and Visibility
To align with search intent and improve discoverability, here are the core keywords naturally integrated throughout this guide:
- Sui Move language
- NFT deployment on Sui
- Move smart contract
- Sui mainnet tutorial
- How to mint NFT on Sui
- Sui blockchain development
- Learn Move programming
- Deploy NFT contract
These terms reflect common queries from developers entering the Sui ecosystem and ensure long-term relevance.
Frequently Asked Questions (FAQ)
What is the purpose of the Let’s Move program?
Let’s Move is an educational initiative that teaches developers how to write secure smart contracts using the Move language on the Sui blockchain. By completing practical tasks like NFT deployment, participants deepen their understanding while contributing to the network's growth.
Why use --skip-dependency-verification when publishing?
This flag allows deployment even if dependencies aren't fully resolved locally. It's useful during development but should be used cautiously in production. On Sui mainnet, the system validates compatibility automatically.
Can I reuse the same contract for multiple NFTs?
Yes. The mint_nft function can be called repeatedly to create different NFTs under the same collection framework. Each will have a unique Object ID and ownership record.
How do I verify my NFT was transferred successfully?
Use the Sui Explorer (suiexplorer.io) and search for the recipient address or the NFT’s Object ID. You’ll see transaction history and current ownership status.
Is it safe to use url::new_unsafe_from_bytes?
While marked "unsafe," it's acceptable when you control input sources. For production systems handling untrusted data, consider additional validation layers.
What happens when an NFT is burned?
Burning permanently destroys the token via object::delete(id). Once deleted, the data cannot be recovered—this enforces scarcity and authenticity.
👉 Get started with Sui development using industry-leading tools and insights
Final Thoughts
Completing Task 3 of Let’s Move isn’t just about fulfilling requirements—it's about mastering foundational skills in Move-based development. From writing type-safe contracts to deploying and interacting with them on mainnet, each step builds confidence and competence.
As Sui continues to grow, expertise in Move becomes increasingly valuable. Whether you're aiming to build decentralized applications, launch digital collectibles, or contribute to open-source projects, this experience lays a solid technical foundation.
Keep building, keep learning, and stay engaged with the evolving world of Web3.