RADIX WikiRADIX Wiki

Introduction

Scrypto separates the concept of "smart contract" into two distinct things: blueprints (reusable templates) and components (live instances on the ledger). This separation enables a modular architecture where small, well-tested blueprints are composed into larger systems – much like how object-oriented programming uses classes and composition. The official Scrypto Design Patterns documentation recommends this approach as the default for non-trivial dApps.

Separation of Concerns

Instead of building a monolithic blueprint, decompose your dApp into small blueprints with a single responsibility:

  • TokenSale – handles pricing and token distribution
  • Treasury – manages collected funds, fee withdrawal
  • AccessControl – issues and manages badges
  • PriceFeed – wraps an oracle and exposes prices to other components

Each blueprint is easier to test in isolation, reason about for security, and audit independently. Smaller blueprints are also more reusable – a Treasury blueprint can serve a DEX, a lending protocol, or a DAO with no changes.

Inter-Component Calls

Components call each other's methods using their on-ledger address. A component can store another component's address in its state and invoke methods on it:

#[blueprint]
mod my_dapp {
    // Treasury and PriceFeed are blueprints in the same package.
    use super::price_feed::PriceFeed;
    use super::treasury::Treasury;
 
    struct MyDapp {
        treasury: Global<Treasury>,
        price_feed: Global<PriceFeed>,
        tokens: FungibleVault,
    }
 
    impl MyDapp {
        pub fn buy(&mut self, payment: Bucket) -> Bucket {
            let price = self.price_feed.get_price("XRD/USD".to_string());
            let owed = payment.amount() * price;
            self.treasury.deposit(payment);
            self.tokens.take(owed).into()
        }
    }
}

Compiled and run under Scrypto 1.4.0 on 6 October 2026, with a Treasury holding an XRD vault and a PriceFeed returning 2: a call to buy with 10 XRD left 10 XRD in the treasury and 20 tokens in the caller's account. Two details the compiler enforces. get_price takes a String, so a bare "XRD/USD" is a type error (E0308) and needs .to_string(). And the use lines are required: cargo flags them as unused imports, but without them Global<Treasury> does not resolve (E0412).

Blueprint Reuse & the Catalog

Radix encourages sharing blueprints as published packages that anyone can instantiate. The Blueprint Catalog concept allows developers to find, audit, and reuse existing blueprints rather than reimplementing common patterns.

Importing External Blueprints

To use a blueprint from another package, import it by its package address and instantiate or call it. The Scrypto extern_blueprint! macro generates type-safe bindings. It goes inside the #[blueprint] module, because the attribute macro is what finds and expands it (source); written at the crate root, it fails with cannot find macro:

#[blueprint]
mod pricing_user {
    extern_blueprint! {
        "package_rdx1...",   // the package's address on the network you deploy to
        PriceFeed {
            fn instantiate() -> Global<PriceFeed>;
            fn get_price(&self, pair: String) -> Decimal;
        }
    }
 
    struct PricingUser {
        price_feed: Global<PriceFeed>,
    }
 
    impl PricingUser {
        pub fn instantiate() -> Global<PricingUser> {
            let price_feed = Blueprint::<PriceFeed>::instantiate();
            Self { price_feed }.instantiate().prepare_to_globalize(OwnerRole::None).globalize()
        }
 
        pub fn quote(&self) -> Decimal {
            self.price_feed.get_price("XRD/USD".to_string())
        }
    }
}

This generates a type you can use in your component's state and method signatures, with full compile-time type checking. Functions listed in the block are called through Blueprint::<PriceFeed>, methods on a Global<PriceFeed>. Tested on 6 October 2026 by publishing the PriceFeed package to resim and importing it from a second package by that address: quote returned 2.

Factory Pattern

A common pattern for dApps that create multiple similar components (e.g. a DEX creating liquidity pools): write a factory blueprint whose instantiation function creates and configures child components, returning their addresses and any admin badges.

Next Steps

HydrateLast updated Oct 6, 2026v1.4.011 revisionsVerified Oct 6, 2026
CiteRADIX Wiki. "7. Multi-Component Architecture." October 6, 2026. https://radix.wiki/developers/scrypto/07-multi-component-architecture