RADIX WikiRADIX Wiki

Introduction

Radix enforces a strict invariant: every resource must exist inside a container at all times. There are two container types: Vaults (permanent, on-ledger storage) and Buckets (temporary, transaction-scoped carriers). The Radix Engine guarantees that resources cannot be duplicated, accidentally destroyed, or left in limbo — if your transaction ends with an undeposited bucket, it fails. This "physical resource" model eliminates entire categories of bugs common in other smart contract platforms.

Vault Patterns

Single-Vault Component

The simplest pattern: a component holds one vault to store a single resource type. A token sale component, for example, stores tokens in a vault and returns XRD payment to the buyer's account.

struct TokenSale {
    token_vault: Vault,    // holds tokens for sale
    xrd_vault: Vault,      // collects XRD payments
    price: Decimal,
}

Multi-Vault Component (HashMap)

When a component needs to manage arbitrary resource types (e.g. a DEX liquidity pool or a wallet-like component), use a HashMap<ResourceAddress, Vault>. When a new resource type is deposited, create a new vault; when an existing type arrives, deposit into the matching vault.

struct MultiVault {
    

Vault Take & Put

Withdraw resources from a vault with .take(amount) (returns a Bucket) or .take_all(). Deposit with .put(bucket). For non-fungibles, use .take_non_fungible(&id) or .take_non_fungibles(&ids) to withdraw specific items.

Bucket Patterns

Bucket Passing (Move Semantics)

Buckets use Rust's ownership model — passing a bucket to a function moves it. The caller no longer has access. This prevents double-spending at the language level:

// Caller creates a bucket, passes it to the component
let payment: Bucket = account.withdraw(xrd_address, dec!("100"));
let tokens: Bucket = sale_component.buy(payment);
// 'payment' is now consumed — cannot be used again
account.deposit(tokens);

Bucket Splitting

Use .take(amount) on a bucket to split it into two buckets — the original retains the remainder. This is how you implement partial fills, fee extraction, or distributing resources across multiple destinations within a single transaction.

The Worktop

In transaction manifests, returned resources land on the worktop — a temporary staging area. Use TAKE_FROM_WORKTOP to create named buckets from worktop resources, then pass them to subsequent method calls. The transaction fails if any resources remain on the worktop at the end.