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

# IPolicyRegistry.createCompositePolicy

> Creates a new composite policy that combines existing simple policies under a UNION or INTERSECT logic gate.

## Signature

```solidity IPolicyRegistry.sol theme={null}
function createCompositePolicy(address admin, PolicyType policyType, uint64[] calldata childPolicyIds) external returns (uint64 newPolicyId);
```

| Field               | Value                                           |
| ------------------- | ----------------------------------------------- |
| Selector            | `0x6fdd1491`                                    |
| Canonical signature | `createCompositePolicy(address,uint8,uint64[])` |

## Description

Creates a composite policy that combines two to four existing simple policies (`ALLOWLIST` or `BLOCKLIST`) under a single logic gate:

| `policyType` | Authorized when                    |
| ------------ | ---------------------------------- |
| `UNION`      | Any child authorizes the account   |
| `INTERSECT`  | Every child authorizes the account |

The registry stores references to the children, not a snapshot of their members. Every call to `isAuthorized` reads each child's current member set, so updates to a child policy are immediately visible through the composite.

Creation is permissionless. The `admin` you supply is the only address that can later call `updateComposite`, `stageUpdateAdmin`, or `renounceAdmin` on this policy.

On success, emits `PolicyCreated(newPolicyId, creator, policyType)`, `PolicyAdminUpdated(newPolicyId, address(0), admin)`, and `CompositePolicyUpdated(newPolicyId, creator, childPolicyIds)`.

## Parameters

| Name             | Type                   | Description                                                                                                                        |
| ---------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `admin`          | `address`              | Initial admin authorized to update child policies and transfer or renounce administration. Cannot be `address(0)`.                 |
| `policyType`     | `PolicyType` (`uint8`) | Must be `UNION` or `INTERSECT`.                                                                                                    |
| `childPolicyIds` | `uint64[]`             | IDs of existing simple policies to combine. Count must be in `[MIN_COMPOSITE_CHILD_POLICIES, MAX_COMPOSITE_CHILD_POLICIES]` (2–4). |

## Returns

| Name          | Type     | Description                             |
| ------------- | -------- | --------------------------------------- |
| `newPolicyId` | `uint64` | The newly assigned composite policy ID. |

## Reverts

| Error                               | Condition                                                                                               |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `ZeroAddress()`                     | `admin` is `address(0)`                                                                                 |
| `IncompatiblePolicyType()`          | `policyType` is not `UNION` or `INTERSECT`                                                              |
| `ChildPoliciesOutsideOfRange()`     | `childPolicyIds.length` is outside `[MIN_COMPOSITE_CHILD_POLICIES, MAX_COMPOSITE_CHILD_POLICIES]` (2–4) |
| `PolicyNotFound()`                  | Any child policy ID does not exist in the registry                                                      |
| `InvalidChildPolicy(childPolicyId)` | Any child is not an existing simple policy (composites and built-in sentinels are not valid children)   |
| Panic `0x11`                        | The policy ID counter has reached its maximum value                                                     |

## Access Control

Permissionless, any caller may create a composite policy.

## Example

```solidity Create a KYC-and-sanctions composite lines wrap expandable highlight={10} theme={null}
// 1. Create a KYC allowlist and a sanctions blocklist first.
uint64 kycId       = registry.createPolicy(admin, PolicyType.ALLOWLIST);
uint64 sanctionsId = registry.createPolicy(admin, PolicyType.BLOCKLIST);

// 2. Combine them: an account must be KYC'd AND not sanctioned.
uint64[] memory children = new uint64[](2);
children[0] = kycId;
children[1] = sanctionsId;

uint64 gateId = registry.createCompositePolicy(admin, PolicyType.INTERSECT, children);

// 3. Bind the composite to the token's transfer and mint scopes.
token.updatePolicy(B20Constants.TRANSFER_SENDER_POLICY, gateId);
token.updatePolicy(B20Constants.TRANSFER_RECEIVER_POLICY, gateId);
token.updatePolicy(B20Constants.MINT_RECEIVER_POLICY, gateId);
```

<Note>
  Updating a child policy's membership (via `updateAllowlist` or `updateBlocklist`) takes effect on the next `isAuthorized` call through any composite that references it. No second `updateComposite` is needed on the token.
</Note>
