RADIX WikiRADIX Wiki

Overview

Radix's asset-oriented programming model uses three core container types:

Vaults

Permanent storage for resources. Every account, component, and dApp stores its assets in vaults. Vaults enforce the conservation law – tokens can only be moved, never duplicated or destroyed (unless explicitly burned).

Buckets

Temporary containers for moving resources between method calls within a transaction manifest. Buckets must be emptied by the end of a transaction – they cannot be stored, preventing tokens from being "stuck" in contract state.

Proofs

Non-transferable evidence of resource ownership. Proofs are placed in auth zones to satisfy access rules without moving the underlying asset. This enables badge-gated access patterns.

A vault answers to the resource, not to its holder

The three containers are usually taught as storage classes, which understates what a vault is. A vault is a node in the engine's own state tree, created and owned by a component, holding exactly one resource type. Its methods are not free functions on the owning component. They are blueprint methods, and each one is gated by a role that is defined on the resource. In the fungible vault blueprint the map is explicit: take, take_advanced and lock_fee require the withdrawer role, put the depositor role, recall the recaller role, burn the burner role, and freeze and unfreeze the freezer role.

On a freely transferable token most of those roles are set open at creation, because a token nobody may withdraw is not a token. What protects a user's balance is therefore not the vault. It is the account component that holds the vault, whose own access rules put the owner badge in front of withdraw. A manifest reaches the vault by going through the account, and the account is where the check lives. The vault is the container; the component around it is the lock. Distinguishing the two matters for anyone writing a blueprint that stores other people's assets, because a vault handed out or reachable by another route carries no protection of its own.

Buckets are the other half of the same design. A bucket exists only for the length of a transaction, cannot be written into component state, and must be empty or returned to a vault before the transaction finalizes. That single rule is what makes the conservation guarantee checkable by the engine instead of by an auditor: a transaction that would lose, duplicate or strand a token fails at commit rather than succeeding quietly, and there is no path by which tokens become permanently stuck in a contract that forgot to implement a withdrawal. Proofs sit outside this flow entirely. A proof is evidence that some quantity of a resource is held, placed in an auth zone for the duration of a call and then dropped. It moves nothing, so presenting a badge to a method that demands one costs neither the badge nor a transfer.

When the boundary failed (August 2026)

The distinction above stopped being academic on 31 August 2026. In the Hyperlane asset drain and network halt, transactions took resources out of vaults belonging to other people without ever going through the accounts that held them. The engine's reference check accepted a vault named directly in a manifest as a valid direct-access reference on the strength of its blueprint alone, and once the caller held that reference, take was gated only by the resource's withdrawer role, which on a freely transferable token is open. The account's access rules were never consulted because the account was never called. The full account of the defect, with the source references, is on the Radix Engine page.

Nothing in the container model itself was broken by this. Conservation held, buckets still balanced, and no token was duplicated or destroyed. What failed was the assumption that a vault is only ever reachable through the component that owns it, which is the assumption everything above rests on.

HydrateLast updated 5d agov1.4.18 revisionsVerified Sep 2, 2026