🌱
Dev Compendium
  • Ethereum
    • Solidity
      • EVM
      • Architecture
      • Execution Context
      • Transactions
      • Gas
      • Calldata, Memory & Storage
      • Gas Optimisation
      • Function Declarations
      • receive() & fallback()
      • CALL vs. DELEGATE CALL
    • Yul
      • Introduction
      • Types
      • Basic Operations
      • Storage
      • Memory
        • Arrays
        • Structs
        • Tuples, revert, keccak256
        • Logs and Events
        • Gotchas
        • abi.encode
      • Calldata
        • External Calls
        • Dynamic Length Inputs
        • Transferring Value
        • Receiving Contract Calls
      • Contracts in Yul
      • Other Yul Functions
    • Foundry
    • Security
      • Common Vulnerabilities
      • Best Practices
      • Development Workflow
      • Contract Migration
    • Auditing Tools
      • Slither
      • Mythril
      • Fuzzing
    • Upgradable Contracts
      • Upgrade Patterns
      • ERC-1967 Implementation
      • Deployment
    • MEV
    • Tooling
      • Chainlink
      • IPFS
      • Radicle
    • Frontend
      • Contract Hooks
      • Wallet Connection
        • wagmi.sh
        • Rainbow Kit
      • thirdweb
    • Protocol Research
      • Uniswap v2
      • Uniswap v3
      • Curve
      • GMX
  • Starkware
    • Fundamentals
    • Account Abstraction
    • Universal Deployer
    • Cairo 1.0
    • starknet.js
    • Security Model
  • Zero Knowledge
    • Group Theory
    • ECDSA
  • Rust
    • Basic Operations
    • Set up
    • Primitives
    • Control Flow
    • Mutability & Shadowing
    • Adding Behavior
    • Lifetimes
    • Std Library
  • SUI
    • Architecture
    • Consensus Mechanism
    • Local Node Setup
    • Sui Client CLI
    • Move Contracts
      • Move
      • Move.toml
      • Move.lock
      • Accessing Time in Sui Move
      • Set up Development Framework
      • Debug & Publish
      • Package Upgrades
      • Sui Move Library
      • Difference from Core Move
    • Object Programming
      • Object Basics
      • Using Objects
      • Immutable Objects
      • Object Wrapping
      • Dynamic Fields
      • Collections
      • Unit Testing
      • Deployment with CLI
  • NEAR
    • Architecture
    • Contract Standards
      • Fungible Token (NEP-141)
      • Non-Fungible Token (NEP-171)
      • Storage Management (NEP-145)
      • Events (NEP-297)
      • Meta-Transactions
    • Rust Contracts
      • Development Workflow
      • Smart Contract Layout
      • Storage Management
      • Events & Meta-transactions
      • Method Types
      • Upgrading Contracts
      • Unit Testing
    • NEAR Libraries
    • Environment Variables
    • Serialisation
    • Security Concepts
    • Collections
    • JS SDK
Powered by GitBook
On this page
  1. SUI
  2. Object Programming

Object Basics

PreviousObject ProgrammingNextUsing Objects

Last updated 2 years ago

Define Sui Object

In Sui Move, besides primitive data types, you can define organized data structures using struct. For example:

struct Color {
    red: u8,
    green: u8,
    blue: u8,
}

The struct defines a data structure to represent RGB color. You can use a struct like this to organize data with complicated semantics. However, an instance of a struct, such as Color, is not a Sui object yet. To define a struct that represents a Sui object type, you must add a key capability to the definition. The first field of the struct must be the id of the object with type UID from the - a module from the core .

use sui::object::UID;

struct ColorObject has key {
    id: UID,
    red: u8,
    green: u8,
    blue: u8,
}

The ColorObject represents a Sui object type that you can use to create Sui objects that can eventually be stored on the Sui network.

Important: In both core Move and Sui Move, the denotes a type that can appear as a key in global storage. However, the structure of global storage is a bit different: core Move uses a (type, address)-indexed map, whereas Sui Move uses a map keyed by object IDs.

The UID type is internal to Sui, and you most likely won't need to deal with it directly. For curious readers, it contains the "unique ID" that defines an object on the Sui network. It is unique in the sense that no two values of type UID will ever have the same underlying set of bytes.

Create Sui Object

To define a constructor for ColorObject

// object creates an alias to the object module, which allows you to call
// functions in the module, such as the `new` function, without fully
// qualifying, for example `sui::object::new`.
use sui::object;
// tx_context::TxContext creates an alias to the TxContext struct in the tx_context module.
use sui::tx_context::TxContext;

fun new(red: u8, green: u8, blue: u8, ctx: &mut TxContext): ColorObject {
    ColorObject {
        id: object::new(ctx),
        red,
        green,
        blue,
    }
}

Sui Move supports field punning, which allows you to skip the field values if the field name happens to be the same as the name of the value variable it is bound to. The preceding code example leverages this to write "red," as shorthand for "red: red,".

Store Sui Object

You now have a constructor for the ColorObject. If you call this constructor, it puts the value in a local variable. The local variable can be returned from the current function, passed to other functions, or stored inside another struct. The object can be placed in persistent global storage, be read by anyone, and accessed in subsequent transactions.

public fun transfer<T: key>(obj: T, recipient: address)

A common use of this API is to transfer the object to the sender/signer of the current transaction, such as when you mint an NFT owned by you. The only way to obtain the sender of the current transaction is to rely on the transaction context passed in from an entry function. The last argument to an entry function must be the current transaction context, defined as ctx: &mut TxContext.

To obtain the current signer's address, you can call tx_context::sender(ctx).

The following code sample creates a new ColorObject and sets the owner to the sender of the transaction:

use sui::transfer;

// This is an entry function that you can call directly by a Transaction.
public entry fun create(red: u8, green: u8, blue: u8, ctx: &mut TxContext) {
    let color_object = new(red, green, blue, ctx);
    transfer::transfer(color_object, tx_context::sender(ctx))
}

You can also add a getter to ColorObject that returns the color values so that modules outside of ColorObject are able to read their values:

Note: Naming convention: Constructors are typically named new, which returns an instance of the struct type. The create function is typically defined as an entry function that constructs the struct and transfers it to the desired owner (most commonly the sender).

You can also add a getter to ColorObject that returns the color values so that modules outside of ColorObject are able to read their values:

public fun get_color(self: &ColorObject): (u8, u8, u8) {
    (self.red, self.green, self.blue)
}

After you define a Sui object type you can create or instantiate a Sui object. To create a new Sui object from its type, you must assign an initial value to each of the fields, including id. The only way to create a new UID for a Sui object is to call object::new. The new function takes the current transaction context as an argument to generate unique IDs. The transaction context is of type &mut TxContext and should be passed down from an . You can call Entry functions directly from a transaction.

All of the APIs for adding objects to persistent storage are defined in the module. One key API is:

This places obj in global storage along with the metadata that records recipient as the owner of the object. In Sui, every object must have an owner. The owner can be either an address, another object, or "shared". See for more details.

Reference:

object module
Sui Framework
key ability
entry function
transfer
Object ownership
https://github.com/MystenLabs/sui/blob/main/sui_programmability/examples/objects_tutorial/sources/color_object.move