# Transferability & Update Rules

> Lock collection permissions to make properties permanently immutable or permanently permitted

**Category:** Advanced

## Summary

Controls whether collection properties can be changed after creation.

* Two states: FROZEN (permanentlyForbiddenTimes: FOREVER) or NEUTRAL (empty \[])
* NEUTRAL \[] = manager can update now AND can freeze it later. Use this for editable fields.
* FROZEN = permanent and irreversible. Use for fields that should never change.
* AVOID permanentlyPermittedTimes — it permanently prevents locking. Almost never needed.
* canUpdateCollectionApprovals: controls transfer rule mutability
  * SECURITY: If manager can update Mint approvals, they can mint unlimited tokens
  * Default to frozen unless user requests updatable
* List IDs in permissions: ONLY use reserved IDs ("All", "Mint", "!Mint", direct "bb1..." addresses)
* permanentlyForbiddenTimes: \[{ "start": "1", "end": "18446744073709551615" }] = frozen forever

## Instructions

## Transferability & Update Rules Configuration

When configuring collection permissions for transferability and update rules, you MUST follow these critical requirements:

### Critical Permission Rules

**canUpdateCollectionApprovals**:

* **CRITICAL**: Controls whether transfer rules (approvals) can be changed after creation
* **SECURITY RISK**: If the manager can update approvals from the "Mint" address, they can mint any amount
* **DEFAULT**: Should be **forbidden (frozen)** for collections where transfer rules should be locked
* **Format**: Uses CollectionApprovalPermission format (see below)

### CollectionApprovalPermission Format

```json
{
  "fromListId": "All",
  "toListId": "All",
  "initiatedByListId": "All",
  "transferTimes": [{ "start": "1", "end": "18446744073709551615" }],
  "tokenIds": [{ "start": "1", "end": "18446744073709551615" }],
  "ownershipTimes": [{ "start": "1", "end": "18446744073709551615" }],
  "approvalId": "All",
  "permanentlyPermittedTimes": [],
  "permanentlyForbiddenTimes": [{ "start": "1", "end": "18446744073709551615" }]
}
```

**Key Fields:**

* **List IDs** (fromListId, toListId, initiatedByListId): Use ONLY reserved list IDs:
  * "All" — Any address
  * "Mint" — Mint address
  * "!Mint" — Everything except Mint
  * "bb1..." — Direct address
  * "!bb1..." — Everything except the specific address
  * "bb1abc:bb1xyz" — Colon-separated addresses
  * **DO NOT USE**: Custom list IDs — only reserved IDs or direct addresses
* **approvalId**: "All" to restrict all approvals, or a specific approvalId string

### Example: Immutable Transfer Rules (All Frozen)

```json
{
  "collectionPermissions": {
    "canUpdateCollectionApprovals": [{
      "fromListId": "All",
      "toListId": "All",
      "initiatedByListId": "All",
      "transferTimes": [{ "start": "1", "end": "18446744073709551615" }],
      "tokenIds": [{ "start": "1", "end": "18446744073709551615" }],
      "ownershipTimes": [{ "start": "1", "end": "18446744073709551615" }],
      "approvalId": "All",
      "permanentlyForbiddenTimes": [{ "start": "1", "end": "18446744073709551615" }],
      "permanentlyPermittedTimes": []
    }]
  }
}
```

### Example: Restricting Only Mint Approvals

```json
{
  "canUpdateCollectionApprovals": [{
    "fromListId": "Mint",
    "toListId": "All",
    "initiatedByListId": "All",
    "transferTimes": [{ "start": "1", "end": "18446744073709551615" }],
    "tokenIds": [{ "start": "1", "end": "18446744073709551615" }],
    "ownershipTimes": [{ "start": "1", "end": "18446744073709551615" }],
    "approvalId": "All",
    "permanentlyForbiddenTimes": [{ "start": "1", "end": "18446744073709551615" }],
    "permanentlyPermittedTimes": []
  }]
}
```

### Example: Restricting Specific Approval ID

```json
{
  "canUpdateCollectionApprovals": [{
    "fromListId": "All",
    "toListId": "All",
    "initiatedByListId": "All",
    "transferTimes": [{ "start": "1", "end": "18446744073709551615" }],
    "tokenIds": [{ "start": "1", "end": "18446744073709551615" }],
    "ownershipTimes": [{ "start": "1", "end": "18446744073709551615" }],
    "approvalId": "mint-approval",
    "permanentlyForbiddenTimes": [{ "start": "1", "end": "18446744073709551615" }],
    "permanentlyPermittedTimes": []
  }]
}
```

### Empty Permission Arrays — CRITICAL

**IMPORTANT**: If a permission entry has both `permanentlyPermittedTimes` and `permanentlyForbiddenTimes` as empty arrays, the entire permission entry is redundant and should be replaced with an empty array.

**For ActionPermission** (canDeleteCollection, canArchiveCollection, etc.):

* Wrong: `"canArchiveCollection": [{ "permanentlyPermittedTimes": [], "permanentlyForbiddenTimes": [] }]`
* Correct: `"canArchiveCollection": []`

**For TokenIdsActionPermission** (canUpdateTokenMetadata, canUpdateValidTokenIds):

* Wrong: `"canUpdateTokenMetadata": [{ "tokenIds": [...], "permanentlyPermittedTimes": [], "permanentlyForbiddenTimes": [] }]`
* Correct: `"canUpdateTokenMetadata": []`

**For CollectionApprovalPermission** (canUpdateCollectionApprovals):

* If both time arrays are empty, use empty array: `"canUpdateCollectionApprovals": []`

### Permission Presets

Three common permission configurations:

**1. Fully Immutable** — Everything frozen. Nothing can change after creation.

* ALL permissions set to permanentlyForbiddenTimes: FOREVER
* Use when: the collection should never change

**2. Manager Controlled** — Manager can change everything except delete.

* canDeleteCollection: frozen
* Everything else: NEUTRAL \[] (editable now, can be frozen later)
* Use when: the manager needs full control (issuer-controlled tokens, evolving collections)

**3. Locked Approvals (recommended default)** — Approvals and supply frozen, metadata editable.

* canDeleteCollection: frozen
* canUpdateStandards: frozen
* canUpdateManager: frozen
* canUpdateValidTokenIds: frozen
* canUpdateCollectionApprovals: frozen
* canUpdateCollectionMetadata: NEUTRAL \[]
* canUpdateTokenMetadata: NEUTRAL \[]
* canArchiveCollection: NEUTRAL \[]
* canUpdateCustomData: NEUTRAL \[]
* Use when: supply and rules should be immutable but metadata needs updates

**Understanding permission states:**

* Empty array \[] = NEUTRAL (manager can update now AND can lock it later — preserves maximum flexibility)
* permanentlyForbiddenTimes: FOREVER = FROZEN (can never be changed — permanent and irreversible)
* permanentlyPermittedTimes: FOREVER = PERMANENTLY ALLOWED (can never be frozen — almost never needed)

**IMPORTANT**: For editable fields, ALWAYS use NEUTRAL (empty \[]) instead of permanentlyPermittedTimes. Neutral gives the same current behavior (manager can update) but preserves the option to freeze it later. Only use permanentlyPermittedTimes if the user explicitly requests a guarantee that a field can never be locked.

### Security Considerations

* **Mint Transfer Rules**: If canUpdateCollectionApprovals is allowed for Mint, the manager could mint unlimited tokens
* **Post-Mint Transfer Rules**: If post-mint transfer rules can be updated, the manager could change transferability
* **Best Practice**: Default to locked (frozen) transfer rules unless user explicitly requests updatable rules
* Only allow updates for dynamic collections where the user explicitly requests flexibility

## Common Mistakes

* DON'T use custom list IDs in permissions — only reserved IDs: "All", "Mint", "!Mint", or direct bb1... addresses.
* DON'T leave both permanentlyPermittedTimes and permanentlyForbiddenTimes as empty arrays in a permission entry — this is redundant. Replace the entire entry with an empty array \[].
* DON'T forget that unfrozen Mint approval permissions means the manager can mint unlimited tokens — freeze canUpdateCollectionApprovals for Mint if supply should be fixed.
* DON'T confuse empty permission array \[] (neutral/unset) with a frozen permission — empty means the field is still updatable.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bitbadges.io/token-standard/skills/immutability.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
