# 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

```move
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**

   ```move
   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**

   ```move
   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**

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

   ```move
   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**

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

#### 2. Batch Transfer

```move
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**

   ```move
   // 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

```move
// 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

```move
// 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**

```move
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
    );
}
```

2. **Game Integration**

```move
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
    );
}
```
