---
title: "2. Resources, Vaults, and NFTs"
path: "/developers/scrypto/02-resources-and-nfts"
version: "1.2.0"
author: "Hydrate"
createdAt: "2026-02-22T17:46:02.523Z"
updatedAt: "2026-03-16T18:26:09.976Z"
---

# 2. Resources, Vaults, and NFTs

<Infobox>
| **Resources, [Vaults](https://docs.radixdlt.com/docs/resources-and-data), and [NFTs](https://en.wikipedia.org/wiki/Non-fungible_token)** |
| Difficulty | Intermediate |
| Est. Time | 25 minutes |
| Prerequisites | [Scrypto Fundamentals](/developers/scrypto/01-fundamentals) |
| Language | [Scrypto](/developers/legacy-docs/updates/roadmap/scrypto/scrypto) (Rust) |
| Official Docs | [Resources](/developers/legacy-docs/build/scrypto-1/resources/resources) |
</Infobox>

## Resources

A [resource](https://docs.radixdlt.com/docs/resources) is any digital asset on Radix — tokens, [NFTs](https://en.wikipedia.org/wiki/Non-fungible_token), [badges](https://docs.radixdlt.com/docs/authorization), LP tokens, etc. Unlike [Solidity](https://soliditylang.org) where tokens are contract state, Radix resources are native engine primitives with built-in rules for minting, burning, transferring, and access control.

There are two kinds:

- **Fungible** — identical, interchangeable units (e.g., XRD, stablecoins)
- **Non-fungible** — unique items with individual data (e.g., NFTs, access [badges](https://docs.radixdlt.com/docs/user-badge-pattern))

### Creating Fungible Resources

```rust
let my_token = [ResourceBuilder](https://docs.radixdlt.com/docs/resources-and-data)::new_fungible(OwnerRole::None)
    .metadata(metadata!(
        init {
            "name" => "My Token", locked;
            "symbol" => "MYT", locked;
        }
    ))
    .mint_initial_supply(1_000_000)
    .into();
```
This creates 1 million tokens with locked name and symbol. The `OwnerRole::None` means no one can change the resource's configuration after creation.

### Creating Non-Fungible Resources ([NFTs](https://en.wikipedia.org/wiki/Non-fungible_token))

```rust
#[derive(ScryptoSbor, NonFungibleData)]
pub struct Ticket {
    pub event_name: String,
    pub seat: u32,
    #[mutable]
    pub used: bool,
}

let tickets = [ResourceBuilder](https://docs.radixdlt.com/docs/resources)::new_integer_non_fungible::(OwnerRole::None)
    .metadata(metadata!(
        init {
            "name" => "Event Ticket", locked;
        }
    ))
    .mint_initial_supply([
        (IntegerNonFungibleLocalId::new(1), Ticket {
            event_name: "RadFest".into(),
            seat: 42,
            used: false,
        }),
    ])
    .into();
```
Fields marked `#[mutable]` can be updated later via the `[ResourceManager](https://docs.radixdlt.com/docs/resources-and-data)`. Immutable fields are fixed at mint time.

## Vaults and [Buckets](https://docs.radixdlt.com/docs/resources-and-data)

Resources must always be inside a **container**:

| Container | Lifetime | Purpose |
| --- | --- | --- |
| **Vault** | Permanent (on-ledger state) | Store resources between transactions |
| **Bucket** | Transient (single transaction) | Move resources during a transaction |

The [Radix Engine](/developers/legacy-docs/reference/radix-engine/radix-engine) enforces that **all [buckets](https://docs.radixdlt.com/docs/buckets-and-vaults) must be empty by the end of every transaction**. This guarantees no resources are accidentally lost or left in limbo.

```rust
// Take 10 tokens from a vault into a bucket
let bucket: Bucket = self.my_vault.take(10);

// Put them into another vault
self.other_vault.put(bucket);
```
Typed variants (`FungibleVault`, `NonFungibleVault`, `FungibleBucket`, `NonFungibleBucket`) provide type-safe operations when you know the resource type at compile time.

## Proofs

[Proofs](https://docs.radixdlt.com/docs/auth) let you demonstrate ownership of a resource without transferring it — like showing an ID badge without handing it over.

```rust
// Create a proof from a vault
let proof = self.admin_badge.create_proof_of_all();

// The proof is automatically placed in the Auth Zone
// where the [Radix Engine](/developers/legacy-docs/reference/radix-engine/radix-engine) checks it against [access rules](https://docs.radixdlt.com/docs/authorization)
```
Proofs are central to Radix's [authorization model](/developers/scrypto/03-authorization-and-badges). Protected methods check for proofs in the caller's Auth Zone rather than checking `msg.sender`.

## [ResourceManager](https://docs.radixdlt.com/docs/resources-and-data)

Every resource has a `[ResourceManager](https://docs.radixdlt.com/docs/resources)` — the on-ledger controller for that resource type. Use it to mint, burn, query supply, and update NFT data:

```rust
// Mint more tokens (if resource was created with mint role)
let new_tokens: Bucket = self.resource_manager.mint(500);

// Get total supply
let supply: Decimal = self.resource_manager.total_supply().unwrap();

// Update mutable NFT data
self.resource_manager.update_non_fungible_data(
    &nft_id,
    "used",
    true,
);
```

## External Links

- [Resources documentation](https://docs.radixdlt.com/docs/resources)
- [Non-Fungible Tokens](https://docs.radixdlt.com/docs/non-fungible-tokens)
- [Proofs and Authorization](https://docs.radixdlt.com/docs/auth)
- [What are Vaults and Buckets?](https://learn.radixdlt.com/article/what-are-vaults-and-buckets)