🌱
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

Object Programming

Objects

In contrast to many other blockchains where storage is centered around accounts and each account contains a key-value store, Sui's basic storage unit is an object. Objects are the building blocks of programming in Sui Move, and they are characterized by having the following two properties:

  • All objects are annotated with the has key keyword following their struct declaration.

  • All objects have id: UID as their first field.

struct Car has key {
	id: UID,
	speed: u8,
	acceleration: u8,
	handling: u8
}

Object ownership can be classified using the following four methods:

Owned by an address: A Move object, upon creation in the Move code, can be transferred to an address. After the transfer, the address owns that object. An object owned by an address can be used (i.e. passed as a Move call parameter) only by transactions signed by that owner address. Owned objects can be passed as a Move call parameter in any of these three forms: read-only reference (&T), mutable reference (&mut T), and by-value (T).

struct ObjectA has key { id: UID }

public entry fun create_object_owned_by_an_address(ctx: &mut TxContext) {
	transfer::transfer({
		ObjectA { id: object::new(ctx) }
	}, tx_context::sender(ctx))
}
struct ObjectB has key, store { id: UID }

public entry fun create_object_owned_by_an_object(parent: &mut ObjectA, ctx: &mut TxContext) {
	let child = ObjectB { id: object::new(ctx) };
	ofield::add(&mut parent.id, b"child", child);
}

Immutable: You can't mutate an immutable object, and an immutable object doesn't have an exclusive owner. Anyone can use an immutable object in a Move call. All Move packages are immutable objects: you can't change a Move package after you publish it. You can convert a Move object into an immutable object using the freeze_object operation. You can only pass an immutable object in Move calls as a read-only reference (&T).

struct ObjectD has key { id: UID }

public entry fun create_immutable_object(ctx: &mut TxContext) {
	transfer::freeze_object(ObjectD { id: object::new(ctx) })
}

Shared: An object can be shared, meaning that anyone can read or write this object. In contrast to mutable owned objects (which are single-writer), shared objects require consensus to sequence reads and writes. In other blockchains, every object is shared. However, Sui programmers often have the choice to implement a particular use-case using shared objects, owned objects, or a combination. This choice can have implications for performance, security, and implementation complexity.

struct ObjectC has key { id: UID }

public entry fun create_shared_object(ctx: &mut TxContext) {
	transfer::share_object(ObjectC { id: object::new(ctx) })
}

Functions

Several visibility modifiers limit or gate access to Sui Move functions. public functions allow other modules to import a particular function. public(friend) functions allow modules given explicit permission to import a particular function. entry functions allow a function to be called directly, such as in a transaction. A special function called init gets executed only once, when its associated module is published. It always has the same signature and only one argument: ctx: &mut TxContext.

Capabilities

A capability is a special pattern in Sui Move that gates access to certain functions. Capabilities can be used in conjunction with the init function to ensure that only one capability will ever exist, and that it will be sent to the module publisher.

struct AdminCapability has key { 
	id: UID 
}

fun init(ctx: &mut TxContext) {
	transfer::transfer(AdminCapability {
		id: object::new(ctx),
	}, tx_context::sender(ctx))
}
PreviousDifference from Core MoveNextObject Basics

Last updated 2 years ago

Owned by another object: When an object is owned by another object, it's not wrapped. The child object still exists independently as a top-level object and can be accessed directly in Sui storage. We will cover this in greater detail in the fourth session as we discuss .

Dynamic Fields