Creating Managed Access

This example demonstrates the use of the FlatAdmin blueprint to manage access in another blueprint.

You can find the code for the FlatAdmin blueprint here and the code for the ManagedAccess blueprint here.

Note that in order for this example to function, you will have to publish the package containing the FlatAdmin blueprint to your simulator to a specific address (or change the address imported near the top of in this package).

If you wish to publish FlatAdmin to the appropriate address, switch to that directory and run:

resim publish . --address 01ca59a8d6ea4f7efa1765cef702d14e47570c079aedd44992dd09

Importing & Calling a Blueprint

Currently, importing another blueprint requires a few manual steps. We expect to simplify this process in the future, but for now here are the steps:

  1. Publish the package containing the blueprint you wish to import.

  2. Export the ABI for that blueprint using the command resim export-abi <package_address> <blueprint_name>

  3. Copy the output of that command, and paste it into the source file you wish to consume it from. Enclose the content within an opening import! { r#" and enclosing "#} block. Example:

use scrypto::prelude::*;

import! {

Now you’ll be able to call functions on that blueprint like so: FlatAdmin::some_function(<args>)

Resources and Data

struct ManagedAccess {
  admin_badge: ResourceDef,
  flat_admin_controller: Address,
  protected_vault: Vault

Our instantiated component will maintain a single vault which stores XRD. Anyone may deposit to the vault, but only a caller in possession of an admin badge may withdraw from it.

The only state we need to maintain is the aforementioned vault, and the ResourceDef of the badge used for authorization. As a convenience for the user, we will also store the address of the FlatAdmin component which manages the supply of those badges.

Getting Ready for Instantiation

In order to instantiate the ManagedAccess component, we’ll require no parameters and return to the caller a tuple containing the newly instantiated component, and a bucket containing the first admin badge created by our FlatAdmin badge manager:

pub fn new() -> (Component, Bucket) {

Our first step will be to instantiate a FlatAdmin component, and store the results of that instantiation.

let (flat_admin_component, admin_badge) =
  FlatAdmin::new("My Managed Access Badge".into());

That gives us everything we need to populate our component state, instantiate it, and return the results to our caller:

let component = Self {
  admin_badge: admin_badge.resource_def(),
  flat_admin_controller: flat_admin_component.address(),
  protected_vault: Vault::new(RADIX_TOKEN),

// Return the instantiated component and admin badge to the caller
(component, admin_badge)

Adding Methods

First, we’ll create a protected method to allow withdrawal. Only callers who present an admin badge will be able to use it:

pub fn withdraw_all(&mut self) -> Bucket {

The rest of the methods are straightforward. We’ll add a method to permit anyone to deposit XRD, and then some read-only methods to return data about our admin badge and the FlatAdmin controller which manages the supply of badges.

pub fn deposit(&mut self, to_deposit: Bucket) {

pub fn get_admin_badge_address(&self) -> Address {

pub fn get_flat_admin_controller_address(&self) -> Address {

That’s it. Access control components like FlatAdmin are expected to be very commonly consumed by other blueprints, as they provide consistent, re-usable mechanisms to manage privileges.

Trying this example with resim

Let’s deploy, instantiate, and call methods on our component

  1. Create a new account, and save the account address:

    resim new-account
  2. Publish the FlatAdmin and ManagedAccess packages:

    cd examples/core/flat-admin/
    resim publish . --address 01ca59a8d6ea4f7efa1765cef702d14e47570c079aedd44992dd09
    cd ../managed-access/
    resim publish .
  3. Call the new function to instantiate a ManagedAccess component, and save the component address:

    resim call-function <MANAGED_ACCESS_PACKAGE_ADDRESS> ManagedAccess new
  4. Call the deposit method of the component we just instantiated:

    resim call-method <COMPONENT_ADDRESS> deposit 1000,030000000000000000000000000000000000000000000000000004
  5. Look at the resources in your account to get the address of the admin badge:

    resim show <ACCOUNT_ADDRESS>
  6. Call the withdraw_all method by specifying the admin badge:

    resim call-method <COMPONENT_ADDRESS> withdraw_all 1,<ADMIN_BADGE_ADDRESS>