Artinals Protocol
  • Introduction
    • What is Artinals?
    • Overview of the Modules
    • Key Concepts and Terminology
  • Getting Started
    • Prerequisites
    • Cloning the Repository
    • Building and Testing the Modules
  • ART20
    • Overview and Capabilities
    • Data Structures
      • NFT
      • CollectionCap
      • UserBalance
      • TokenIdCounter
      • Dual IDs
    • Events
      • NFTMintedEvent
      • CollectionCreatedEvent
      • MetadataUpdateEvent
      • BurnEvent
      • TransferEvent
      • Additional Events
    • Functions and Entry Points
      • Initializing the Module
      • Creating Collections
      • Minting ART20 NFTs
      • Updating Metadata
      • Transfer and Burn Operations
      • Batch Operations
      • Deny List Mechanics and Authority
      • Custom Transfers
    • Value Sources (API, Oracle)
    • Best Practices & Examples
  • SALE Module
    • Purpose and Functionality
    • Interdependence
    • Price Index Module
    • Liquidity Module
    • Data Structures
      • NFTSale
      • NFTListing
  • Events
    • SaleCreated
    • NFTPurchased
    • PriceUpdateEvent
    • CurrencyWithdrawn
    • DenyList & Related Events
    • PoolCreatedEvent
    • OrderCanceled
    • OrderExecuted
  • Functions and Entry Points
    • Creating a Sale
    • Adding NFTs to a Sale
    • Purchasing NFTs from a Sale
    • Withdrawing Proceeds
    • Managing Sale State
    • Core Trading Functionality
  • Integrating with ART20
  • Examples & Best Practices
  • MARKET Module
    • Introduction
    • Testnet (Beta)
    • Smart Contract Overview
    • Data Structures
      • Trade Ledger (TradeLedger)
      • Trade Offer (TradeOffer)
      • Buy Offer (BuyOffer)
      • Ledger Registry (LedgerRegistry)
    • Event Structures
      • Offer Created (OfferCreated)
      • Offer Accepted (OfferAccepted)
      • Buy Offer Created (BuyOfferCreated)
      • Buy Offer Accepted (BuyOfferAccepted)
      • Batch Transactions
    • Event Emissions
    • Functions and Entry Points
      • Trade Ledger Management
      • Register Ledger
      • Get Trade Ledger
      • Create Sell Offer
      • Accept Sell Offer
      • Cancel Sell Offer
      • Create Buy Offer
      • Accept Buy Offer
      • Cancel Buy Offer
      • Batch Accept Sell Offers
      • Batch Accept Buy Offers
  • Security Mechanisms
  • TRADE Module
    • Introduction
    • Purpose and Ecosystem Role
    • Data Structures
      • TradingPool
      • LiquidityPosition
      • PriceOracle
      • CollectionPool
    • Events
      • PoolCreated
      • LiquidityAdded
      • LiquidityRemoved
      • TradeExecuted
      • PoolStatusChanged
      • PoolFeesUpdated
    • Functions and Entry Points
      • Creating and Managing Liquidity Pools
      • Adding/Removing Liquidity
      • Swapping NFTs and Tokens
      • Fee Mechanics and Distribution
      • Emergency Operations and Recovery
  • Working with Price Oracles
  • Metrics and Statistics (24h Volumes, TWAP, Price Impact)
  • Integration with SALE and ART20
  • Integration and Workflows
    • Typical User Journeys
      • Creating a Collection and Minting Tokens (ART20)
      • Listing and Selling NFTs (SALE)
      • Providing Liquidity and Trading NFTs (TRADE)
    • Example Scripts and Transactions
    • Interactions Between Modules
  • Security, Permissions, and Deny Lists
    • Introduction
    • Role of Deny List in ART20
    • Creator vs. Owner Permissions
    • Fee Distribution and Authority
    • Best Practices for Secure Deployment
  • Testing and Troubleshooting
    • Running Unit Tests
    • Common Issues and Solutions
    • Debugging and Emitting Debug Events
  • Advanced Topics
    • Value Sources (API Endpoints and Oracle Addresses)
    • Batch Update Operations
    • Customizing Parameters (Fees, Supply, Price Ranges)
    • Extensibility and Future Integrations
  • Appendices
    • Move Language and Sui Concepts
    • Glossary of Terms
    • Code Style and Conventions
  • Building on Top of the Artinals Contract
    • Overview
    • Package ID
    • Import Modules
    • Commom Integration Patterns
    • Best Practices
    • Common Errors and Solutions
Powered by GitBook
On this page
  • Overview
  • Transfer Functions
  • Purpose
  • Parameters
  • Process Flow
  • Special Features
  • Integration Guide
  • Error Handling
  • Events
  • Best Practices
  • Common Integration Patterns
  1. ART20
  2. Functions and Entry Points

Custom Transfers

Overview

The ART20 module implements a sophisticated transfer mechanism that goes beyond simple ownership changes. It manages user balances, collection integrity, deny lists, and batch operations while ensuring proper state updates across the protocol.

Transfer Functions

1. Standard Transfer

public entry fun transfer_art20(
    tokens: vector<NFT>,
    recipients: vector<address>,
    collection_cap: &CollectionCap,
    mut sender_balances: vector<UserBalance>,
    ctx: &mut TxContext
)

Purpose

Enables secure transfer of NFTs while maintaining protocol state, balances, and collection integrity.

Parameters

  • tokens: Vector of NFTs to transfer

  • recipients: Vector of recipient addresses

  • collection_cap: Collection capability for validation

  • sender_balances: Vector of sender's balance objects

  • ctx: Transaction context

Process Flow

  1. Initial Validation

    let sender = tx_context::sender(ctx);
    let token_count = vector::length(&tokens);
    let recipient_count = vector::length(&recipients);
    assert!(token_count == recipient_count, E_INVALID_LENGTH);
  2. Balance Verification

    let mut total_available = 0u64;
    let mut i = 0;
    while (i < vector::length(&sender_balances)) {
        let balance = vector::borrow(&sender_balances, i);
        total_available = safe_add(total_available, balance.balance);
        i = i + 1;
    };
    assert!(total_available >= token_count, E_INSUFFICIENT_BALANCE);
  3. Deny List Check

    check_deny_list_restrictions(collection_cap, sender);
    for (recipient in recipients) {
        check_deny_list_restrictions(collection_cap, recipient);
    }
  4. Transfer Execution

    let mut i = 0;
    while (i < token_count) {
        let recipient = *vector::borrow(&recipients, i);
        let token = vector::pop_back(&mut tokens);
        
        // Update balances
        update_balances(&mut sender_balances, token_count);
        
        // Create recipient balance if needed
        let recipient_balance = create_user_balance(
            collection_id,
            1,
            ctx
        );
        
        // Transfer token and balance
        transfer::public_transfer(token, recipient);
        transfer::transfer(recipient_balance, recipient);
        
        i = i + 1;
    };
  5. Event Emission

    event::emit(BatchTransferEvent {
        from: sender,
        recipients,
        token_ids,
        amounts,
        collection_id,
        timestamp: tx_context::epoch(ctx)
    });

2. Batch Transfer

public entry fun batch_transfer_art20(
    tokens: vector<NFT>,
    recipient: address,
    quantity: u64,
    collection_cap: &CollectionCap,
    sender_balances: vector<UserBalance>,
    ctx: &mut TxContext
)

Special Features

  1. Balance Management

    • Tracks user token balances

    • Automatically creates recipient balances

    • Handles balance updates atomically

  2. Security Checks

    // Collection verification
    assert!(token.collection_id == collection_cap_id, E_COLLECTION_MISMATCH);
    
    // Balance verification
    assert!(current_balance >= quantity, E_INSUFFICIENT_BALANCE);
    
    // Deny list check
    assert!(!is_denied(collection_cap, recipient), E_ADDRESS_DENIED);
  3. Batch Processing

    • Efficient handling of multiple transfers

    • Atomic updates across all operations

    • Event emission for batch transfers

Integration Guide

1. Basic Transfer

// Transfer single NFT
public fun transfer_single(
    nft: NFT,
    recipient: address,
    collection_cap: &CollectionCap,
    user_balance: &mut UserBalance,
    ctx: &mut TxContext
) {
    let tokens = vector::singleton(nft);
    let recipients = vector::singleton(recipient);
    let balances = vector::singleton(user_balance);
    
    transfer_art20(tokens, recipients, collection_cap, balances, ctx);
}

2. Batch Transfer Example

// Transfer multiple NFTs to single recipient
public fun transfer_batch(
    nfts: vector<NFT>,
    recipient: address,
    quantity: u64,
    collection_cap: &CollectionCap,
    user_balance: &mut UserBalance,
    ctx: &mut TxContext
) {
    let balances = vector::singleton(user_balance);
    
    batch_transfer_art20(nfts, recipient, quantity, collection_cap, balances, ctx);
}

Error Handling

Common errors and their meanings:

Error Code
Description
Solution

E_INSUFFICIENT_BALANCE

Sender lacks required balance

Verify balance before transfer

E_COLLECTION_MISMATCH

NFT doesn't belong to collection

Check collection ID

E_ADDRESS_DENIED

Address in deny list

Verify recipient status

E_INVALID_LENGTH

Mismatched vectors

Ensure equal tokens and recipients

Events

  1. TransferEvent

    • Emitted for individual transfers

    • Tracks from/to addresses, token ID, amount

  2. BatchTransferEvent

    • Emitted for batch transfers

    • Includes all recipients and token IDs

    • Records timestamp and collection ID

Best Practices

  1. Balance Management

    • Always verify balances before transfer

    • Handle balance updates atomically

    • Clean up empty balances

  2. Security

    • Implement deny list checks

    • Verify collection capability

    • Validate all addresses

  3. Gas Optimization

    • Use batch transfers when possible

    • Clean up unused resources

    • Minimize storage operations

Common Integration Patterns

  1. Marketplace Integration

public fun list_for_sale(
    nft: NFT,
    price: u64,
    collection_cap: &CollectionCap,
    user_balance: &mut UserBalance,
    ctx: &mut TxContext
) {
    // Verify ownership and balance
    // Transfer to marketplace contract
    transfer_art20(
        vector::singleton(nft),
        vector::singleton(get_marketplace_address()),
        collection_cap,
        vector::singleton(user_balance),
        ctx
    );
}
  1. Game Integration

public fun transfer_to_game(
    game_nfts: vector<NFT>,
    player: address,
    collection_cap: &CollectionCap,
    user_balance: &mut UserBalance,
    ctx: &mut TxContext
) {
    // Update game state
    // Transfer NFTs to player
    batch_transfer_art20(
        game_nfts,
        player,
        vector::length(&game_nfts),
        collection_cap,
        vector::singleton(user_balance),
        ctx
    );
}
PreviousDeny List Mechanics and AuthorityNextValue Sources (API, Oracle)

Last updated 6 months ago