---
title: "Access Rules & Auth Zones"
url: "https://radix-wiki.miow.me/contents/tech/core-concepts/access-rules-and-auth-zones"
updated: 2026-10-03
description: "An access rule is the unit of authorization on Radix. It is data attached to an object by the Role Assignment module, not code inside a component, and it is…"
---

# Access Rules & Auth Zones

| Layer | [Radix Engine](/contents/tech/core-protocols/radix-engine) (system module) |
| --- | --- |
| Pattern | Declarative role-based access control |
| Rule variants | `AllowAll`, `DenyAll`, `Protected(..)` |
| Checked | Before the method body runs, once per call frame |
| Max rule depth | 8 nested requirement nodes |
| Max rule nodes | 64 composite requirements |
| Defined in | [`proof_rule.rs`](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine-interface/src/blueprints/resource/proof_rule.rs), [`auth_module.rs`](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine/src/system/system_modules/auth/auth_module.rs) |

## Overview

An **access rule** is the unit of authorization on Radix. It is data attached to an object by the [Role Assignment module](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine-interface/src/blueprints/resource/role_assignment.rs), not code inside a [component](/contents/tech/core-concepts/components), and it is evaluated by the [Radix Engine auth module](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine/src/system/system_modules/auth/auth_module.rs) before the called method body begins executing. The evidence a rule is tested against lives in the **auth zone**, a per-call-frame collection of [proofs](https://docs.radixdlt.com/docs/auth) that the engine creates on entry and tears down on exit.

The separation matters because it changes what a reader of a [blueprint](/contents/tech/core-concepts/blueprints-and-packages) can know. A rule set is stored state, so anyone can read the current permissions of a deployed component out of the ledger without reading its code, and the engine will refuse an unauthorized call whether or not the blueprint author remembered to check. What it does not do is choose the rule for you: the engine enforces the rule that was declared, so a rule declared too loosely is enforced too loosely (see _What the model does not do_, below).

## The rule grammar

[`AccessRule`](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine-interface/src/blueprints/resource/proof_rule.rs) has exactly three variants: `AllowAll`, `DenyAll`, and `Protected(CompositeRequirement)`. `AllowAll` authorizes unconditionally, `DenyAll` fails unconditionally, and everything else is a requirement tree.

A `CompositeRequirement` is either a single `BasicRequirement` or an `AnyOf` / `AllOf` list of further composite requirements, so rules nest. The five basic requirements are:

- `Require(resource or non-fungible)` – a proof of that [resource](/contents/tech/core-concepts/resources), or of that specific non-fungible, must be present
- `AmountOf(amount, resource)` – a proof of at least the given amount
- `CountOf(n, list)` – proofs of at least _n_ distinct entries from the list, which is how N-of-M multi-signature is expressed
- `AllOf(list)` – proofs of every entry
- `AnyOf(list)` – a proof of any one entry

The tree is bounded. [The execution constants](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-common/src/constants/transaction_execution.rs) cap it at `MAX_ACCESS_RULE_DEPTH` of 8 and `MAX_COMPOSITE_REQUIREMENTS` of 64 nodes, and [the Role Assignment package](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine/src/object_modules/role_assignment/package.rs) rejects any rule that exceeds either at the point it is set rather than at the point it is checked.

Because the requirements name resources, an authorization token on Radix is an ordinary resource used as a credential rather than a special type. That convention is what the wiki calls a [badge](/contents/tech/core-concepts/badges).

## The auth zone

[The auth zone substate](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine/src/blueprints/resource/auth_zone/auth_zone_substates.rs) holds three separate kinds of evidence, and only the first is what most descriptions mean by "the proofs":

- `proofs` – real [proof](https://docs.radixdlt.com/docs/auth) objects pushed into the zone from a [bucket or vault](/contents/tech/core-concepts/buckets-proofs-and-vaults)
- `simulate_all_proofs_under_resources` – resources under which every possible proof is treated as present
- `implicit_non_fungible_proofs` – virtual badges the engine supplies without anyone creating them

The implicit set is the part with no equivalent elsewhere. A transaction signature places a virtual non-fungible badge under the Ed25519 or secp256k1 signature resource, which is how a rule can require "signed by this key" without any token existing. On top of that the engine derives two caller badges for each frame: `package_of_direct_caller`, naming the package that made the call, and `global_caller`, naming the global component or the blueprint function it originated from. A component can therefore gate a method on being called by a particular package or by a particular sibling component, with no shared secret and nothing to pass in.

The zone is per call frame, not per transaction. [The auth module](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine/src/system/system_modules/auth/auth_module.rs) creates a fresh auth zone on every `CALL_FUNCTION` and `CALL_METHOD` and destroys it when the frame finishes. It links the new zone to its parent only when the call stays inside the same global context; when the call crosses into a different global component the parent is set to `None`, so proofs do not leak across the boundary. Calling a component does not hand it your badges.

The zone is also addressable directly. [Its blueprint interface](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine-interface/src/blueprints/resource/auth_zone.rs) exposes `push`, `pop`, `drain`, `create_proof_of_amount`, `create_proof_of_non_fungibles`, `create_proof_of_all`, `assert_access_rule`, and three separate drops: `drop_proofs`, `drop_regular_proofs`, and `drop_signature_proofs`. The last is the one that matters for [manifest](/contents/tech/core-concepts/blind-signing-and-transaction-manifests) hygiene, because it removes the signature-derived virtual badges while leaving explicitly created proofs in place.

## How a check is resolved

[On a method call](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine/src/system/system_modules/auth/auth_module.rs) the engine resolves the method to a permission and then tests it, in that order, before the body runs. The permission comes from the blueprint's own declaration and is one of four kinds: `Public`, `OuterObjectOnly` (used by the Validator blueprint to restrict certain methods to the [Consensus Manager](/contents/tech/core-concepts/consensus-manager)), `OwnPackageOnly`, or `RoleProtected` with a list of role names.

A role name is then resolved to a rule against the object's own role assignment, and [the resolution has two special cases worth knowing](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine/src/system/system_modules/auth/authorization.rs):

- `_self_` is not stored. It resolves to `require(global_caller())`, meaning the object calling itself.
- **An undefined role does not deny.** If the role has no entry in the role-assignment key-value store, the engine reads the object's **owner role** and tests that rule instead. A role a blueprint declares but never assigns is owner-gated, not locked.

The rule is then evaluated against the auth zone of the calling frame, walking up the parent chain where one exists. `AllowAll` passes, `DenyAll` fails and returns the rule itself in the failure, and a protected rule is checked node by node against the three kinds of evidence above.

## What the model does not do

System-level enforcement removes one class of defect: a method cannot execute with its guard forgotten, because the guard is not in the method. It does not remove authorization bugs as a category, and three limits are worth stating plainly.

- **The rule is a design decision.** `AllowAll` on a mint role is enforced exactly as faithfully as a badge requirement. The engine has no opinion about which was intended.
- **Undefined roles inherit the owner rule** rather than failing closed, per [the resolution path above](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine/src/system/system_modules/auth/authorization.rs). An incomplete role assignment is a permissive outcome, not a restrictive one.
- **Ownership can be mutable or fixed, and the difference is set once.** [The owner role](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine-interface/src/blueprints/resource/role_assignment.rs) is declared as `None`, `Fixed`, or `Updatable` at instantiation; see the [Role Assignment module](/contents/tech/core-concepts/role-assignment-module) for what each implies.

What the model does change is auditability. Because the rules are stored state rather than control flow, the permissions of a live component can be read off the ledger and compared against what its documentation claims, without trusting either the source code or the deployer.

## External Links

- [Radix Docs: Authorization & Access Rules](https://docs.radixdlt.com/docs/auth)
- [Radix Docs: Access Rules & Roles](https://docs.radixdlt.com/docs/advanced-accessrules)
- [radixdlt-scrypto: `proof_rule.rs` (AccessRule and the requirement grammar)](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine-interface/src/blueprints/resource/proof_rule.rs)
- [radixdlt-scrypto: `auth_zone_substates.rs` (what the auth zone holds)](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine/src/blueprints/resource/auth_zone/auth_zone_substates.rs)
- [radixdlt-scrypto: `auth_module.rs` (call-frame auth zones and the global-context barrier)](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine/src/system/system_modules/auth/auth_module.rs)
- [radixdlt-scrypto: execution constants (rule depth and node caps)](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-common/src/constants/transaction_execution.rs)
