RADIX WikiRADIX Wiki

Introduction

In most smart contract platforms, access control is based on the caller's address — a pattern that leads to fragile permission systems and common exploits like reentrancy. Radix takes a fundamentally different approach: access is gated by badges, which are standard resources (fungible or non-fungible) that serve as unforgeable credentials. A caller is authorised not because of who they are but because of what they hold.

This pattern is central to Scrypto development and appears in virtually every non-trivial dApp on Radix.

How It Works

Access Rules

When a component is instantiated, its methods can be protected with access rules that specify which badge(s) must be present for a call to succeed. The Radix Engine checks these rules automatically before executing any method — there is no manual require(msg.sender == owner) logic.

enable_method_auth! {
    roles {
        admin => updatable_by: [];
        minter => updatable_by: [admin];
    },
    methods {
        mint_tokens => restrict_to: [minter, admin];
        update_price => restrict_to: [admin];
        buy => PUBLIC;
    }
}

Proofs and the Auth Zone

When a method requires a badge, the caller provides a Proof — a cryptographic attestation that a resource exists in the caller's possession without transferring it. Proofs can be placed on the Auth Zone (a transaction-scoped container) so that multiple method calls within the same transaction can share the same authorisation context.

# 

Moving Badge-Gated and Restricted Resources

Because authorisation on Radix depends on presenting a Proof, a resource whose withdrawal is gated by a badge cannot be moved with the Radix Wallet's built-in transfer screen — that flow builds a plain withdraw-and-deposit transaction manifest and never creates the proof the access rule demands. Moving it requires a manifest — typically supplied by a dApp — that creates the required proof first (the CREATE_PROOF_FROM_ACCOUNT_OF_AMOUNT pattern shown above) and then performs the withdrawal within the same transaction.

For dApp builders this means: if your users hold badge-gated assets, give them an in-app action that sends the wallet a correctly-authorised manifest, rather than expecting a manual wallet transfer to succeed. It is also why soulbound badges stay put — their Withdraw action is locked outright, so no proof can unlock it.

Wallet support for this may be coming. Two pull requests opened on 23 July 2026 by community developer genkipool would have the wallet attach the required badge itself: sargon #452 injects badge ResourceSpecifiers into the PerAssetTransfers manifest builder via create_proof_of_amount and create_proof_of_non_fungibles, and babylon-wallet-android #1446 builds the transfer feature on top. Both were still open as of 29 July 2026.

For the full picture of movement rules on a resource — including freeze, recall, and why a deposit rule cannot check what the recipient holds — see Permissioned and Regulated Assets.

Common Badge Patterns

Admin Badge

The most basic pattern: mint a single non-fungible badge at instantiation and return it to the deployer. Methods like withdraw_fees, update_config, or pause are gated behind this badge.

User Badge

The User Badge Pattern issues a non-fungible badge to each user when they register. The badge's non-fungible data stores user-specific state (balances, permissions, membership tier). Methods read the caller's badge data to personalise behaviour without maintaining a separate user registry.

Multi-Signature

Access rules support boolean logic: require_n_of(2, [badge_a, badge_b, badge_c]) creates a 2-of-3 multi-sig gate. This is useful for treasury management, protocol upgrades, or any high-stakes operation.

Soulbound Badges

By creating a non-transferable resource (restrict Deposit and Withdraw actions), a badge becomes soulbound to the original recipient's account. This is ideal for identity credentials, certificates, or membership tokens that should not change hands.

Next Steps