> ## Documentation Index
> Fetch the complete documentation index at: https://docs.story.foundation/llms.txt
> Use this file to discover all available pages before exploring further.

# Access Controller

> Manages all permission-related states and permission checks on Story.

<CardGroup cols={1}>
  <Card title="AccessController.sol" href="https://github.com/storyprotocol/protocol-core-v1/blob/main/contracts/access/AccessController.sol" icon="scroll" color="#ccb092">
    View the smart contract for the Access Controller.
  </Card>
</CardGroup>

Access Controller manages all permission-related states and permission checks on Story. In particular, it maintains the *Permission Table* and *Permission Engine* to process and store permissions. IPAccount permissions are set by the IPAccount owner.

<Frame>
  <img src="https://mintcdn.com/story/Ci-RgMKFKns3XzFq/images/concepts/ac-overview.png?fit=max&auto=format&n=Ci-RgMKFKns3XzFq&q=85&s=93016a879afd62333ac430e4401affa0" alt="Access Controller Diagram" width="3594" height="1748" data-path="images/concepts/ac-overview.png" />
</Frame>

## Permission Table

### Permission Record

| IPAccount  | Signer (caller) | To (only module) | Function Sig | Permission |
| ---------- | --------------- | ---------------- | ------------ | ---------- |
| 0x123..111 | 0x789..222      | 0x790..333       | 0xAaAaAaAa   | Allow      |
| 0x123..111 | 0x789..222      | 0x790..333       | 0xBBBBBBBB   | Deny       |
| 0x123..111 | 0x789..222      | 0x790..333       | 0xCCCCCC     | Abstain    |

Each record defines a permission in the form of the **Signer** (caller) calling the **Func** of the **To** (module) on behalf of the **IPAccount**.

The permission field can be set as "Allow," "Deny," or "Abstain." Abstain indicates that the permission decision is determined by the upper-level permission.

### Wildcard

Wildcard is also supported when defining permissions; it defines a permission that applies to multiple modules and/or functions.

With wildcards, users can easily define a whitelist or blacklist of permissions.

| IPAccount  | Signer (caller) | To (module) | Func | Permission |
| :--------- | :-------------- | :---------- | :--- | :--------- |
| 0x123..111 | 0x789..222      | \*          | \*   | Allow      |
| 0x123..111 | 0x789..222      | 0x790..333  | \*   | Deny       |

The above example shows that the signer (0x789...) is unable to invoke any functions of the module (0x790...) on behalf of the IPAccount (0x123...).

In other words, the IPAccount has blacklisted the signer from calling any functions on the module 0x790...333

* Supported wildcards:

| Parameter                  | Wildcard   |
| -------------------------- | ---------- |
| Func                       | bytes4(0)  |
| Addresses (IPAccount / To) | address(0) |

### Permission Prioritization

Specific permissions override general permissions.

| IPAccount  | Signer (caller) | To (module) | Func       | Permission |
| :--------- | :-------------- | :---------- | :--------- | :--------- |
| 0x123..111 | 0x789..222      | \*          | \*         | Allow      |
| 0x123..111 | 0x789..222      | 0x790..333  | \*         | Deny       |
| 0x123..111 | 0x789..222      | 0x790..333  | 0xCCCCDDDD | Allow      |

The above shows that the signer (0x789...) is not allowed to call any functions of the module (0x790...) on behalf of IPAccount (0x123...), except for the function 0xCCCCDDDD

Furthermore, the signer (0x789...) is permitted to call all other modules on behalf of IPAccount (0x123...).

## Call Flows with Access Control

There exist three types of call flows expected by the Access Controller.

1. An IPAccount calls a module directly.
2. A module calls another module directly.
3. A module calls a registry directly.

### IPAccount calling a Module directly

* IPAccount performs a permission check with the Access Controller.
* The module only needs to check if the `msg.sender` is a valid IPAccount.

When calling a module from an IPAccount, the IPAccount performs an access control check with AccessController to determine if the current caller has permission to make the call. In the module, it only needs to check whether the transaction `msg.sender` is a valid IPAccount.

`AccessControlled` provide a modifier `onlyIpAccount()` helps to perform the access control check.

```solidity Solidity theme={null}
contract MockModule is IModule, AccessControlled {
    function action(string memory param) external view onlyIpAccount() returns (string memory) {
            // do something
    }
}
```

<Frame>
  <img src="https://mintcdn.com/story/Ci-RgMKFKns3XzFq/images/concepts/ac-diagram.png?fit=max&auto=format&n=Ci-RgMKFKns3XzFq&q=85&s=43e686d831d935c7baffa036c2d40e7f" alt="IPAccount calling Module" width="1848" height="1122" data-path="images/concepts/ac-diagram.png" />
</Frame>

## Module calling another Module

* The callee module needs to perform the authorization check itself.

When a module is called directly from another module, it is responsible for performing the access control check using AccessController. This check determines whether the current caller has permission to make the call to the module.

`AccessControlled` provide a modifier `verifyPermission(address ipAccount)` helps to perform the access control check.

```solidity Solidity theme={null}
contract MockModule is IModule, AccessControlled {
    function callFromAnotherModule(address ipAccount) external verifyPermission(ipAccount) returns (string memory) {
        if (!IAccessController(accessController).checkPermission(ipAccount, msg.sender, address(this), this.callFromAnotherModule.selector)) {
		        revert Unauthorized();
        }
			  // do something
    }
}
```

<Frame>
  <img src="https://mintcdn.com/story/Ci-RgMKFKns3XzFq/images/concepts/ac-diagram-2.png?fit=max&auto=format&n=Ci-RgMKFKns3XzFq&q=85&s=33f6a322345e685093dba347eb87f0ed" alt="Module calling Module" width="1782" height="966" data-path="images/concepts/ac-diagram-2.png" />
</Frame>

## Module calling Registry

* The registry performs the authorization check by calling AccessController.
* The registry authorizes modules through set global permission

When a registry is called by a module, it can perform the access control check using AccessController. This check determines whether the callee module has permission to call the registry.

```solidity Solidity theme={null}
// called by StoryProtocl Admin
IAccessController(accessController).setGlobalPermission(address(0), address(module), address(registry), bytes4(0))) {

```

```solidity Solidity theme={null}
contract MockRegistry {
    function registerAction() external returns (string memory) {
        if (!IAccessController(accessController).checkPermission(address(0), msg.sender, address(this), this.registerAction.selector)) {
		        revert Unauthorized();
        }
			  // do something
    }
}
```

<Frame>
  <img src="https://mintcdn.com/story/Ci-RgMKFKns3XzFq/images/concepts/ac-diagram-3.png?fit=max&auto=format&n=Ci-RgMKFKns3XzFq&q=85&s=99d22cec31c03de8a9225867867747e7" alt="Module calling Registry" width="1776" height="964" data-path="images/concepts/ac-diagram-3.png" />
</Frame>

<Note>
  The IPAccount's permissions will be revoked upon transfer of ownership.

  The permissions associated with the IPAccount are exclusively linked to its current owner. When the ownership of the IPAccount is transferred to a new individual, the existing permissions granted to the previous owner are automatically revoked. This ensures that only the current, legitimate owner has access to these permissions. If, in the future, the IPAccount ownership is transferred back to the original owner, the permissions that were initially revoked will be reinstated, restoring the original owner's access and control.
</Note>
