The Sui blockchain is redefining how developers interact with decentralized systems, and at the heart of this evolution is Move, a secure, flexible programming language designed for digital assets. The Let's Move initiative encourages developers to dive into Move by completing practical tasks—like creating and deploying NFTs—and earning rewards in SUI. This guide walks you through Task 3: deploying an NFT smart contract on the Sui mainnet, minting your first NFT, and transferring it to a designated address.
Whether you're new to Move or expanding your blockchain development skills, this step-by-step walkthrough ensures clarity, correctness, and real-world applicability.
Understanding the Task Requirements
Before writing any code, let’s break down what Task 3 entails:
- Learn core concepts of NFTs on Sui
- Deploy a working NFT smart contract to the mainnet
- Mint an NFT to your own wallet address
- Transfer another NFT to the specified recipient address:
0x7b8e0864967427679b4e129f79dc332a885c6087ec9e187b53451a9006ee15f2
This process tests both your understanding of Move syntax and your ability to interact with the Sui network using the command-line interface (CLI). Success means not only writing functional code but also executing it securely on a live blockchain.
👉 Discover how to start building on Sui with powerful tools and resources
Core Components of a Move-Based NFT Contract
The foundation of any NFT project on Sui lies in its Move module. Below is a clean, well-structured version of the simple_nft module that satisfies all task requirements.
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 point to mint an NFT
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);
}
// Transfer ownership of an NFT
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);
}
// Update NFT metadata (description only)
public entry fun update_description(
nft: &mut SimpleNFT,
description: vector<u8>,
_: &mut TxContext
) {
nft.description = string::utf8(description);
}
// Burn (destroy) an NFT
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 Explained
SimpleNFTstruct: Defines the NFT with essential metadata—name, description, and URL.- Event emission: Logs minting, transfers, and burns for transparency and off-chain tracking.
- Entry functions: Securely exposed methods callable via transactions.
- Transfer control: Uses
public_transferfrom Sui framework to ensure safe ownership changes.
These components align perfectly with Sui’s object-centric model and security-first design principles.
Deploying the Contract to Sui Mainnet
Once your code is ready, it’s time to deploy it live.
Step 1: Switch to Mainnet Environment
Ensure your Sui client targets the mainnet:
sui client switch --env mainnetYou’ll see confirmation:
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-verification💡 Tip: The --skip-dependency-verification flag speeds up publishing when dependencies are known and trusted.After successful deployment, note the Package ID—you’ll need it for all subsequent interactions.
👉 Access advanced blockchain development tools to streamline deployment
Minting and Transferring Your First NFT
Now that the contract is live, you can mint and send NFTs.
Step 1: Set Environment Variables
Replace placeholders with actual values:
export PACKAGE_ID=0xf78fb118efd9a86d8e2c54ac18766a1313bd8b0df80c85f859f83d01a5f78981
export NFT_NAME="\"joker\""
export DESCRIPTION="\"simple nft, powered by alva-lin\""
export URL='"https://example.com/nft-image.png"'Step 2: Mint the 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 $URLUpon success, the CLI returns the newly created NFT Object ID.
Step 3: Transfer NFT to Designated Address
Use the returned Object ID and execute the transfer:
export NFT_ID=0xc1d108cdeef7666aa3f414bb3ead5faa7cd351e4dc75d0307e2888b640232787
export RECIPIENT=0x7b8e0864967427679b4e129f79dc332a885c6087ec9e187b53451a9006ee15f2
sui client call \
--gas-budget 7500000 \
--package $PACKAGE_ID \
--module simple_nft \
--function transfer_nft \
--args $NFT_ID $RECIPIENTYour transaction will be processed, and the NFT ownership officially transferred.
Frequently Asked Questions (FAQ)
Q1: What is the purpose of the Let's Move program?
A: Let's Move is an educational initiative that incentivizes developers to learn Move by completing hands-on tasks on the Sui blockchain. Participants gain practical experience while earning SUI rewards.
Q2: Why use vector<u8> instead of string in entry functions?
A: Move does not support direct string arguments in entry functions. Instead, UTF-8 encoded byte vectors (vector<u8>) are used and converted internally using string::utf8().
Q3: Can I update other fields besides description?
A: In this implementation, only description can be updated. Adding name or URL updates requires additional entry functions and careful access control.
Q4: How do I verify my NFT was minted successfully?
A: Use the Sui Explorer (e.g., Sui Vision) and search for your Object ID. You should see the NFT with correct metadata.
Q5: Is burning reversible?
A: No. Once an NFT is burned using object::delete, it is permanently removed from the ledger.
Q6: What happens if I lose my Object ID?
A: Without the Object ID, you cannot reference or transfer the NFT. Always store IDs securely after minting.
Final Thoughts
Completing Task 3 of Let's Move isn't just about fulfilling requirements—it's about mastering fundamental skills in Move programming, smart contract deployment, and on-chain interaction. By building, publishing, and managing NFTs on Sui mainnet, you’re gaining experience directly applicable to real-world Web3 development.
As Sui continues to grow, proficiency in Move becomes increasingly valuable. Whether you're aiming to build scalable dApps or innovate in digital ownership, this foundation sets you on the right path.
👉 Accelerate your journey in Web3 with cutting-edge infrastructure and support