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.

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.