> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://docs.prividium.com/api/mcp` to find what you need.
>
> **Have feedback?** Use `submit_feedback` on the same MCP server.

Contract permissions are the fine-grained **resource authorization** layer in Prividium™. For each role, they control
two things, both enforced through the **Prividium™ API**: which contract **functions** the role may call (read or
write), and which contract **events** the role may read. Function rules are role-based (RBAC) and can add attribute
conditions (ABAC) — for example, restricting an argument to the caller's own address. Administrators configure
permissions in the **Admin Dashboard** under **Contract Permissions**.

***

### 1. Open the Permissions page

1. Go to the **Admin Dashboard** at `http://localhost:3000`.
2. Select **Contract Permissions** from the sidebar.
3. You will see a list of all registered contracts and their function-level access rules.

### 2. Register a contract

> **Note:** [System contracts](/configuring/contracts/system-contracts) are registered automatically at startup.
> You cannot create, edit, or delete them. Skip to **step 3** to configure their permissions.

Before you can assign permissions, register the smart contract that needs access control.

1. Click **Add contract** (or **+ Add contract**).
2. Fill in the details:
   * **Contract Name** (Required)
   * **Contract Address** (Required, starts with `0x`)
   * **Description** (Optional)
   * **Template** (Optional): Select a pre-defined template to inherit default permissions.
   * **Contract ABI**: Paste the full JSON ABI of the contract.
3. **Disclosure Settings** (Optional, only shown when [selective disclosure](/configuring/contracts/selective-disclosure)
   is enabled — it is disabled by default):
   * Check **Disclose bytecode** to make the bytecode hash public.
   * Check **Disclose Erc 20 Supply** to expose total supply data (if it's an ERC20 token).
4. Click **Save Changes**.

After you save, the panel opens the new contract's details page on the **Function Permissions** tab. Continue with
**3. Configure function permissions** below.

### Edit a registered contract

To update a registered contract's details, click the contract in the list, then click **Edit**.

You can update any field including the **Contract Address**. Use this when a contract is redeployed to a new address —
all existing function and event permissions transfer automatically to the new address. After saving, the page redirects
to the new address.

> **Note:** You cannot change the address to one that belongs to an existing contract or a system contract.

### 3. Configure function permissions

Permissions are managed directly from the contract details page. There are two types of permissions you can configure:
**Function Permissions** and **Event Permissions**.

To configure functions:

1. Open the contract's details page. After you register a contract, the panel opens it for you. Otherwise, click the
   contract in the **Contracts** list.
2. Ensure the **Function Permissions** tab is selected (default).
3. For each function row:
   * **Permission Level**: Select the desired level from the dropdown:
     * **Forbidden**: No one can call this function (default).
     * **All Users**: Any authenticated user can call it.
     * **Check Role**: Only users with specific roles can call it.
     * **Restrict Argument**: Restricts arguments (e.g., user can only use their own address).
   * **Access Details**:
     * If **Check Role** is selected, choose the authorized role(s).
     * If **Restrict Argument** is selected, choose the argument index to restrict.
4. Changes are saved automatically (or click the checkmark if present).

:::note[EIP-712 signing permissions]
Grant **Read** access to `eip712Domain()` on each application contract that users sign typed data for, directly or
through its template. Choose **All Users** or **Check Role** to allow the intended signing users. SSO also reads the
account's domain; verify that the account's contract or `sso-smart-account` template grants access.

Domain reads require permission even when they include `from`; the former global exemption has been removed.
Exact domain reads without `from` can use these rules, but wallet-dependent **Restrict Argument** checks deny them.
Sequencer policy enforcement also requires an associated `from` address. See the
[RPC rules and limitations](/rpc/rpc-support#base-rpc-methods).
:::

### 4. Function permission rule types

| Rule Type             | Description                                                     | Example Use Case                                                    |
| --------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------- |
| **All Users**         | Allows any authenticated user to call this function             | Read-only views like `getGreeting()`                                |
| **Check Role**        | Requires the caller to hold one of the listed roles             | Only users with `Trader` role can call `transfer()`                 |
| **Restrict Argument** | Ensures a function argument matches the caller's wallet address | User can only `updateGreeting(address)` if the address is their own |
| **Forbidden**         | Blocks all access to the function                               | Internal or deprecated functions                                    |

#### Argument decoding limits

Argument checks decode the function's complete calldata, including unrestricted arguments. Each evaluation enforces
these limits before decoding:

| Resource                                             | Limit   |
| ---------------------------------------------------- | ------- |
| Calldata, including the function selector            | 1 MiB   |
| Decoded bytes                                        | 256 KiB |
| Decoded values, including array and tuple containers | 4096    |
| ABI schema nodes                                     | 4096    |
| Nested type levels                                   | 32      |

Each scalar consumes 32 decoded bytes. Dynamic `bytes` and `string` values consume their byte length. Shared tails
count once per reference, including nested references. A sole `address[4095]` argument fits the value limit;
`address[4096]` exceeds it because its container also counts.

Dynamic offsets must be word-aligned and point beyond their enclosing head. Shared or overlapping tails can pass
within the limits, subject to the ABI decoder's own checks. Type strings cannot exceed 256 characters, and each fixed
array dimension cannot exceed 4096 elements.

Malformed or over-budget calldata fails the argument check. These limits also apply to combined role/argument rules
and batched authorization. An OR rule can still grant access through its role condition. **All Users** and
**Check Role** rules do not decode arguments. These limits apply per evaluation, not cumulatively across a request.

[Policy](/configuring/chain/policy#operation-type-is-derived-never-declared) applies the same limits when decoding a
governed contract call, including calls granted by **All Users** or **Check Role** permissions.

### 5. Configure event permissions

Admins can also control which roles are allowed to read specific smart contract events (e.g., via `eth_getLogs`).
Similar to functions, events are restricted by default.

1. In the **Contracts** list, click on the contract you want to manage.
2. Select the **Event Permissions** tab.
3. Click **+ Add Permission**.
4. In the **Add Event Permission** modal:
   * **Event**: Select the specific event you want to allow (e.g., `GreetingUpdated`) or choose **All Events** to apply
     the rule to all events in the contract.
   * **Roles**: Select the role(s) that should have access to these events.
5. Click **Create**.

The new permission rule will appear in the Event Permissions table. Users with the assigned roles can now query logs for
these events.

By design, Prividium™ uses a **deny-by-default** model: if a function is set to **Forbidden** (the default state for
new contracts), the Prividium™ rpc blocks all access to it.

### 6. Edit or remove a permission rule

* **For Functions:**
  * **To update:** Change the **Permission Level** or **Access Details** dropdowns in the Function Permissions table.
  * **To reset:** Set the Permission Level back to **Forbidden**.

* **For Events:**
  * **To delete:** Click the trash icon next to the event permission rule in the Event Permissions table.

> Tip: If a function or event is not listed, check that your ABI is correct and up to date.

### 7. Default access policy

By design, Prividium™ uses a **deny-by-default** model: if a function or event is not explicitly permitted, the Proxy
blocks access to it.

This ensures that only explicitly authorized functions can be called and events queried, reducing risk of accidental
exposure.

### 8. Enforcement across internal calls

The checks above apply to the top-level call of each request. When the Prividium™ API runs the **policy listener**
(`POLICY_PORT` set), the sequencer also submits the internal calls of every transaction and `eth_call` to it. Each
`CALL`, `DELEGATECALL` and `STATICCALL` is checked against the same function permissions, evaluated for the original
signer. The request succeeds only if every contract and method it reaches is permitted. One forbidden internal call
rejects the whole request.

This stops a permitted entry point such as a multicall, router or proxy from reaching a forbidden contract or method
internally. Without the policy listener only the top-level call is checked, which leaves the
[authorization bypasses](/developers/applications/security-limitations) open at the entry point.

How the per-call check resolves a frame:

* A `DELEGATECALL` is checked against the calling contract's rules, so a proxy needs rules on its own address only.
* A constructor has no selector and is not checked itself. The calls it makes are.
* A plain native-token transfer to an externally owned account needs no rule.

**Umbrella.** Some permitted methods make many internal calls by design, such as a withdrawal entry point or a contract
that always calls the same immutable dependencies. Tick **Umbrella** on the method's row in the Function Permissions
table (the column is shown when the policy listener is configured) to cover its whole internal-call subtree in one
permission decision. With organizations disabled, an allowed method skips the function-permission checks on calls beneath
it. With organizations enabled, those calls follow a relaxed permission rule; see
[Umbrella Permissions in Multi-Org Mode](/configuring/chain/bridging#umbrella-permissions-in-multi-org-mode).
[Organization admins](/configuring/chain/organizations) cannot set the flag.

:::warning[Never umbrella user-controlled targets]
Only enable Umbrella on methods whose internal call targets are fixed and trusted: hardcoded addresses or a trusted
on-chain registry. Never enable it on methods that forward to caller-supplied addresses, such as a multicall or a
generic call router. Umbrella can bypass individual function-permission checks. Published policy rules still apply to
the inner calls that policy governs.
:::

### 9. Testing permissions

After updating permissions:

1. Open the **User Dashboard**.
2. Log in as a user with a specific role.
3. Interact with the connected dApp or contract through the Prividium™ RPC.
4. Verify that allowed functions/events succeed and restricted ones fail.

If the Prividium™ RPC returns `403 Forbidden`, the user lacks permission for that function or event.

### 10. Example configuration

| Contract | Function/Event              | Access | Rule Type         | Allowed Roles   |
| -------- | --------------------------- | ------ | ----------------- | --------------- |
| Token    | `transfer(address,uint256)` | Write  | Check Role        | Trader          |
| Token    | `approve(address,uint256)`  | Write  | Restrict Argument | Trader          |
| Token    | `balanceOf(address)`        | Read   | Check Role        | Trader, Auditor |
| Token    | `Transfer` (Event)          | Read   | Check Role        | Auditor         |
| Registry | `register(address,string)`  | Write  | Check Role        | Admin           |

### 11. Best practices

* Keep **All Users** rules to a minimum to ensure authenticated control.
* Use **Restrict Argument** for address-sensitive functions.
* Review permissions regularly, especially after contract upgrades.
* Document your role-to-permission mapping for audits.

***
