Scrypto documentation has moved!

All Scrypto documentation has moved to the Babylon documentation site.

This page has been preserved so as not to break existing links out in the world, but its content is no longer being updated.

Please switch to the Babylon-specific site.

Access Control - Resources

Resources can have access permissions individually set on various actions, and by setting or adjusting those permissions a developer can change their behavior. A "fixed supply" resource is merely a resource in which the permissions to mint and burn have been permanently disabled. A "freezable" resource is one in which some authority has the ability to change the permissions on withdrawal and deposit.

Here are all the resource actions which can have permissions set:

Rule Description Default


Who may mint additional supply



Who may destroy some quantity



Who may take the resource from a vault



Who may put the resource in a vault



Who may update the resource’s metadata


(Not yet implemented) recallable

Who may remotely seize the resource from any vault



(Non-fungible) Who may update individual metadata


Each of these actions can have an arbitrary set of access rules defined, and the system exposes those rules in a manner that off-ledger products, such as wallets, can understand. That is, if a particular token can have more supply minted, but never burned, that’s something that a user can instantly see right within their wallet, without needing to go read Scrypto code. If a token is currently freely transferrable, but an authority exists which could change it to a frozen state, that’s also directly visible to the user.


Resource rules are best explained by examples, so let’s see a few.

We’ll start with a mutable supply token in which a single authority has the ability to mint new tokens, or burn held tokens:

  .metadata("name", "Mutable supply, single mint/burn authority")
  .mintable(rule!(require(badge_address)), AccessRule::DenyAll)
  .burnable(rule!(require(badge_address)), AccessRule::DenyAll)

The first parameter you provide to the access methods (.mintable(), .burnable(), etc..) is the rule for applying the action and the second is the rule that is checked for updating the previous rule. The rule! macro is where we specify the logic which much evaluate to "true" in order to perform the action. We can arbitrarily combine different conditions, like so:

  .mintable(rule!(require_n_of(2, "list_of_admins") || require(super_admin)), AccessRule::DenyAll)

In the above example, in order to mint you either need any 2 of the badges in the specified Vec variable, or the super admin badge.

Let’s check out a token in which minting is a privileged action, but any holder can freely burn it:

  .metadata("name", "Mutable supply, single mint authority, burnable by any holder")
  .mintable(rule!(require(admin)), AccessRule::DenyAll)
  .burnable(rule!(allow_all), AccessRule::DenyAll)

Or, say you want to hand out a token that the user can safely tuck away, but will not be able to transfer it after they have done so:

  .metadata("name", "Token which can not be withdrawn from a vault once stored")
  .restrict_withdraw(rule!(deny_all), AccessRule::DenyAll)

Updating the rules after creating resources

Up till now, we have specified all rules with a second parameter of AccessRule::DenyAll, which is also the default state for any unspecified rule. AccessRule::DenyAll means that it can never be changed, ever. Instead of AccessRule::DenyAll you could provide a custom rule with the usual rule!() macro. The authority you provide here has the ability to update the rule in the future. They can change the rule at will, and at any point they also have the right to change the rule to a AccessRule::DenyAll state, so that it may never again be changed. Locking is a one-way process…​there’s no going back to a mutable rule once it has been locked.

Here’s an example of playing with some rules around freezing a token:

// Initial creation, rule_admin is some badge address we have previously defined
let resource_address = ResourceBuilder::new_fungible()
  .metadata("name", "Freezable token")
  .restrict_deposit(AccessRule::AllowAll, rule!(require(rule_admin)))
  .restrict_withdraw(AccessRule::AllowAll), rule!(require(rule_admin)))

... // Later in the code

// `rule_admin_vault` is a vault that contains the badge allowed to make the following changes.
self.rule_admin_vault.authorize(|| {
  // Freeze the token, so no one may withdraw or deposit it
  let resource_manager: &ResourceManager = borrow_resource_manager!(resource_address);

  // ...or, make it so only a person presenting the proper badge can withdraw or deposit

  // Unfreeze the token!

  // Lock the token in the unfrozen state, so it may never again be changed

The authorize() method

In the previous example, you saw the use of the authorize method on the rule_admin_vault. This method is available on both Vaults and Buckets and is used to temporarily put a proof of the underlying resources on the auth zone for authorization.

The method takes as parameter a closure with no argument and runs it after putting the proofs on the auth zone. After running the closure, the proofs are removed from the auth zone.

Transient tokens

Let’s do something crazy, and make a non-fungible token which can never be deposited:

  .metadata("name","Undepositable token")
  .mintable(rule!(require(admin)), AccessRule::DenyAll)
  .burnable(rule!(require(admin)), AccessRule::DenyAll)
  .restrict_deposit(AccessRule::DenyAll, AccessRule::DenyAll)

We call this a "transient" token. At this point you may be wondering what possible use such a thing can have. Well, remember that the Radix Engine guarantees that a token can never be "dangling" at the end of a transaction. Any resource floating around outside of a vault at conclusion of operations will cause the transaction to abort. By handing your caller a token which can never be deposited, but which you control the burn authority for, you can compel them to eventually call a method which can burn the token, else the transaction will fail.

This allows for really cool stuff like programming a flash loan in an asset-oriented way, and we have an example of that linked at the bottom of this page.

A flash loan is an obvious example of the utility of transient resources (loan the money, let the caller do whatever they like, but they must pay you back plus a fee before the transaction is done), but this pattern is also useful for operations where you have an ecosystem of components, and you wish to incentivize using them together.

For example, you might have an oracle which receives regular off-ledger price feeds and costs money to keep updated, and costs consumers a fee to fetch price information from. You also control some kind of token selling component. You might set up a specialized entry point on your oracle which will return a price for free, but also give out a transient token. The only way to burn the transient token is to then pass it to your token selling component, which will burn it as long as a purchase of high enough value is performed. In other words, you can make your oracle free to use for people who use that price information to then make a trade on your other component.

Github Examples

Resources are used in one way or another in every Scrypto example, but here are a few highlights which involve using rules to do interesting things: