Resources

There are two kinds of state that a component can contain: data and resources.

Data is what you are already familiar with when dealing with typical programming concepts like variables and values. Data can freely be created, destroyed, copied, and passed around – just like normal.

Resources are special, and are a crucial part of how Scrypto makes financial applications and transactions more safe and predictable. Unlike data, once resources are created they can only be moved from owner to owner, never copied or unintentionally destroyed or lost.

Resources must always be stored in special containers – either a Vault or a Bucket – and Radix Engine enforces that no resource can ever be lost. In short, Radix Engine ensures that resources behave like "physical things" which is why they are used on Radix for all types of assets, like tokens or NFTs. Even the utility token of the Radix network, XRD, is a resource.

resource overview

Fungible and Non-Fungible Resources

All resources are created from a resource definition that defines how all of the individual resources of that type behave. For example, a set of tokens with their own name, symbol, and supply would be defined in a resource definition, with the individual token resources of that resource definition then being stored in Vaults or Buckets. Each resource definition has its own unique ID.

The most important decision to make in the resource definition is if that type of resource will be fungible or non-fungible.

A quantity of fungible resources can be freely split into smaller quantities (up to a defined limit of divisibility), and smaller quantities can be recombined. Typical tokens (including the XRD token), where no two tokens have an individual identity, are created as fungible resources. Example uses of fungible resources include:

  • Utility or governance tokens

  • Stablecoins

  • Fractionalizable shares

  • Liquidity provider tokens

  • Tokenized representations of commodities

  • Authorization roles

With non-fungible resources, each individual resource unit is uniquely addressable and not divisible. You can think of a non-fungible resource definition as a grouped set of individual objects that have the same behavior, but where each unit is a standalone object with its own identity (and potentially its own unique associated data). Non-fungible resources are used (perhaps obviously) for NFTs.

Even though non-fungible resources can be addressed individually, Scrypto also allows them to be addressed in a fungible way in situations where you don’t care about the individual identities of the resources.

Example uses of non-fungible resources include:

  • Ownership of unique digital art pieces

  • A set of generated avatars

  • Tickets to an event with seat numbers

  • Representations of unique numbered documents or products

  • Deeds of ownership of property or other real assets

  • Transactable unique debt positions or derivatives

In Scrypto documentation, you will often see reference to badge resources. Badges are not their own low-level type of resource, but are a usage pattern where a resource is used to confer authorization to an account or other component to do something. Badges may be modeled as either fungible or non-fungible resources, depending on the intended use.

Resource Definition Parameters

In addition to setting a resource definition as either fungible or non-fungible, there are many parameters that allow you to customize and define the behavior of a set of resources depending on their purpose. The table below summarizes all the currently available parameters associated with each resource definition.

Name Description

resource_type

The type of resource, either fungible or non-fungible. Fungible resources are associated with the divisibility property.

metadata

Shared key-value metadata for the resource definition. Both keys and values are strings.

current_flags

The set of flags currently enabled for this resource. More flags may be turned on if mutable.

mutable_flags

The set of flags that may be adjusted by the right badge owners.

authorities

Definition of the the set of badges with authorization to perform various actions.

Resource Flags

These may be set on a resource definition when certain properties are desired.

Name Description Notes

MINTABLE

More of the resource may be minted

BURNABLE

Resources may be burned

FREELY_BURNABLE

May be burned without any authority. If you are holding it, you can burn it

It is not necessary to set BURNABLE if FREELY_BURNABLE is set

SHARED_METADATA_MUTABLE

Shared resource definition metadata may be changed

INDIVIDUAL_METADATA_MUTABLE

The mutable data of an individual unit may be modified

Applies to non-fungible resources only. This property applies to the entire class of that resource, not an individual unit

RESTRICTED_TRANSFER

May only be withdrawn from a vault if the proper authority is presented

RECALLABLE

May be seized from any vault if the proper authority is presented

Not yet implemented!

For all of these flags, the proper authority can toggle any flag. The authority may also permanently lock each flag, such that its state can never be toggled again.

Resource Permissions

Name Description

MAY_MINT

May create new resources

MAY_BURN

May destroy resources

MAY_MANAGE_RESOURCE_FLAGS

May toggle flags or lock them

MAY_CHANGE_SHARED_METADATA

Top-level shared metadata may be changed

MAY_CHANGE_INDIVIDUAL_METADATA

May alter the contents of the mutable part of an individual NFT’s data

MAY_TRANSFER

May take the resource from a vault (only has meaning when RESTRICTED_TRANSFER is enabled)

MAY_RECALL

May seize from any vault (only has meaning when RECALLABLE is enabled)

To Create a Resource

The creation of a resource can be achieved using ResourceBuilder by specifying the resource parameters specified above and the initial supply of the resource to be created and returned.

 let my_bucket: Bucket = ResourceBuilder::new_fungible(DIVISIBILITY_MAXIMUM)
    .metadata("name", "TestToken")
    .metadata("symbol", "TT")
    .metadata("description", "This is a test token")
    .flags(SHARED_METADATA_MUTABLE)
    .mutable_flags(MINTABLE | SHARED_METADATA_MUTABLE)
    .badge(some_resource_address, ALL_PERMISSIONS)
    .badge(another_resource_address, MAY_MINT | MAY_TRANSFER)
    .initial_supply_fungible(100);

If the resource is mintable but no initial supply is desired when creating the resource definition, .no_initial_supply() should be used as the last statement. In this case, the resource definition will be returned instead of a bucket of resource.

If the resource being created is non-fungible, each individual resource unit may have its own set of data associated with it. All data for all resources of a given non-fungible resource definition must however follow the same scheme.

You will need to define the schema of the data first, for example:

#[derive(NftData)]
pub struct NbaPlayer {
    name: String,
    #[scrypto(mutable)]
    score: u8
}

And then provide the initial supply:

.initial_supply_non_fungible([
    (
        1, // The ID of the first NFT
        NbaPlayer {
            name: "Test 1",
            score: 111,
        }
    ),
    (
        2, // The ID of the second NFT
        NbaPlayer {
            name: "Test 2",
            score: 222,
        }
    )
]);

Minting Resources

Resource minting is done through the resource definition, with proper badge authorization.

For example, assuming the badge (with permission of MAY_MINT) is held in a vault mint_badge owned by a component, we use the following code to mint fungible resources:

let tokens: Bucket = self.mint_badge.authorize(|auth| {
    ResourceDef::from(resource_address).mint(100, auth)
});

And non-fungible resource:

let nfts: Bucket = self.mint_badge.authorize(|auth| {
    ResourceDef::from(resource_address).mint_nft(
        // The NFT id
        1234,
        // The NFT data
        NbaPlayer {
            name: "Test 3",
            score: 333,
        },
        // authorization to mint
        auth
    )
});

Burning Resources

Resources can be burned if its definition has either the BURNABLE or FREELY_BURNABLE flag set

To burn a freely burnable resource, we need to pass a bucket to the resource definition.

For example, if FREELY_BURNABLE:

ResourceDef::from(resource_address).burn(some_bucket);
// OR
// some_bucket.burn();

Or if BURNABLE:

self.burn_badge.authorize(|auth| {
    ResourceDef::from(resource_address).burn_with_auth(some_bucket, auth);
    // OR
    // some_bucket.burn_with_auth(auth);
});

Combining, Splitting, and Transferring Resources

Resources are temporarily stored in a Bucket and eventually stored in a Vault by the end of execution. Each Bucket and Vault only holds resources of the same type (ie. the same resource definition).

You can split or combine quantities of resources, respectively, using the take() and put() methods on the resource container.

You may also query the quantity of resources within a bucket, by calling the amount() method.

It is important to note that buckets do not define a "send" method. If you want to send a token to a component, that component needs to define a method which accepts a Bucket as input. The standard account component provides such a method for common usage.

Here is another example of a method that accepts a Bucket as input:

fn some_method(&mut self, bucket1: Bucket) {
    // Take 5 from `some_vault`
    let bucket2 = self.some_vault.take(5);
    // Put `bucket2` into `bucket1` (`bucket2` is destroyed afterwards)
    bucket1.put(bucket2);
    // Put `bucket1` into `another_vault` (`bucket1` is destroyed afterwards)
    self.another_vault.put(bucket1);
}