# Feature constraints

Source: https://docs.settlemint.com/docs/architects/components/token-features/feature-constraints
Understand DALP token feature dependencies, mutually exclusive pairs, feature-closure expansion, validated configuration ranges, and the split between UI, API, and smart-contract enforcement.



Token feature constraints keep an instrument deployable before an asset reaches issuance. DALP validates the selected set: dependencies must be present, mutually exclusive pairs cannot coexist, and closure can add directly implied items when a selected entry requires its counterpart.

Use this reference when you design an [instrument template](/docs/operators/asset-creation/instrument-templates), review a selection in the Asset Designer, or build an API integration that submits configuration backed by a published template.

## Scope and validation surfaces [#scope-and-validation-surfaces]

The current DALPAsset feature registry drives validation across the Asset Designer, template publishing, the API preflight check, the deployment workflow, and SMART Protocol attachment on EVM networks. Future availability is outside this reference.

The UI, API, and workflow all read the same feature IDs and constraint rules. Smart contracts receive the final ordered configuration during deployment. They attach features atomically and then execute the hooks each module exposes. No separate on-chain registry rechecks Asset Designer dependencies after deployment starts.

## Current feature set [#current-feature-set]

DALP recognizes these token feature IDs for DALPAsset templates:

| Feature ID                   | What it represents                                                       | Detail                                                                                              |
| ---------------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- |
| `historical-balances`        | Balance and supply checkpoints for reporting, voting, and yield support. | [Historical Balances](/docs/architects/components/token-features/historical-balances)               |
| `maturity-redemption`        | Maturity date handling and redemption behavior.                          | [Maturity Redemption](/docs/architects/components/token-features/maturity-redemption)               |
| `fixed-treasury-yield`       | Fixed-rate treasury-funded yield.                                        | [Fixed Treasury Yield](/docs/architects/components/token-features/fixed-treasury-yield)             |
| `voting-power`               | Delegated voting power and governance snapshots.                         | [Voting Power](/docs/architects/components/token-features/voting-power)                             |
| `aum-fee`                    | Time-based management fee collection.                                    | [AUM Fee](/docs/architects/components/token-features/aum-fee)                                       |
| `transaction-fee`            | Per-transfer fee deducted from the token amount.                         | [Transaction Fee](/docs/architects/components/token-features/transaction-fee)                       |
| `transaction-fee-accounting` | Fee accounting without on-chain fee collection.                          | [Transaction Fee Accounting](/docs/architects/components/token-features/transaction-fee-accounting) |
| `external-transaction-fee`   | Fixed fee charged in a separate ERC-20 asset.                            | [External Transaction Fee](/docs/architects/components/token-features/external-transaction-fee)     |
| `conversion`                 | Conversion behavior for a source instrument token.                       | [Conversion](/docs/architects/components/token-features/conversion)                                 |
| `conversion-minter`          | Companion minting behavior for a target conversion token.                | [Conversion](/docs/architects/components/token-features/conversion)                                 |
| `permit`                     | EIP-2612 permit approvals.                                               | [Permit](/docs/architects/components/token-features/permit)                                         |

The list is the supported token-feature vocabulary for selection and validation. Availability still depends on the target environment. Confirm the required asset type and feature factories before you use any of these in production.

## Configurable value ranges [#configurable-value-ranges]

Token configuration combines feature selection with numeric and pricing fields from the instrument template you choose. Keep these ranges consistent across the Asset Designer, your API payloads, and contract-facing values:

| Configuration field     | Accepted value                                                                  | Where it applies                                                                                                                                                                   |
| ----------------------- | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Base price              | Decimal money string with a `priceCurrency`, for example `"10.00"` and `"USD"`. | Asset basics and pricing metadata. DALP records the base-price claim for the token; price-feed and valuation features can use that metadata as the token's starting price context. |
| Metadata `bps`          | Integer from `0` to `10_000`, where `10_000` means 100%.                        | Template metadata fields such as coupon, dividend, or strike-rate inputs that should not exceed 100%.                                                                              |
| Metadata percentage     | Number from `0` to `100` with at most one decimal place.                        | Display-style percentage fields on templates.                                                                                                                                      |
| Fee-rate bps            | Integer from `0` to `10_000`, where `10_000` means 100%.                        | Transaction-fee, AUM-fee, and other fee-feature configuration that maps to fee contracts.                                                                                          |
| Collateral or yield bps | Integer from `0` to `20_000`, where `20_000` means 200%.                        | Ratios that can legitimately exceed 100%, such as collateral ratios and yield rates.                                                                                               |

The API rejects values outside their configured field type. The Asset Designer should prevent the same invalid values before submission.

Smart-contract validation is narrower and later in the flow. Deployment receives the feature set only after the API has accepted dependencies and mutually exclusive pairs. Contract modules then validate the parameters they own: fee, collateral, yield, and lifecycle-hook inputs. Treat UI checks as operator guidance, API checks as the template gate, and contract execution as the final module-level guard when your payload reaches the chain.

## Dependency rules [#dependency-rules]

Feature dependencies state that one option only makes sense when another is also included.

| Selected feature    | Required companion | Why it is required                                                                                                        |
| ------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| `conversion-minter` | `conversion`       | The minter serves the conversion flow. Select it only as part of conversion behavior, not as a standalone token behavior. |

When a template or request lists `conversion-minter` without `conversion`, DALP treats the combination as invalid. Update the template's required entries before you publish or create assets.

## Mutually exclusive rules [#mutually-exclusive-rules]

Mutually exclusive pairs prevent two options from owning the same economic behavior in different ways.

| Feature           | Cannot be combined with      | Why                                                                                                                                                                                        |
| ----------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `transaction-fee` | `transaction-fee-accounting` | `transaction-fee` collects a fee from the transferred amount. `transaction-fee-accounting` tracks fee information without collecting the on-chain fee. Choose one fee model for the token. |

The rule is symmetric. Selecting either option makes the other unavailable for the same template-backed asset.

## Feature-closure expansion [#feature-closure-expansion]

DALP uses feature-closure expansion when it needs the complete set implied by a template selection. The closure keeps the configured sequence, removes duplicates, and appends directly implied dependents at the end.

In the current registry, selecting `conversion` implies `conversion-minter` because the conversion flow needs both sides of the pair.

| Input feature selection           | Expanded feature set                                                               |
| --------------------------------- | ---------------------------------------------------------------------------------- |
| `conversion`                      | `conversion`, `conversion-minter`                                                  |
| `aum-fee`, `conversion`           | `aum-fee`, `conversion`, `conversion-minter`                                       |
| `conversion`, `conversion-minter` | `conversion`, `conversion-minter`                                                  |
| `conversion-minter`               | `conversion-minter` and a dependency violation until `conversion` is also selected |

Expansion does not pull missing prerequisites into an invalid dependent-only selection. When a selected entry has an unmet dependency, DALP reports the problem instead of guessing the operator's intent.

Expansion is intentionally direct. It adds dependents whose own dependencies the selected set already satisfies. It does not chase newly added entries through a transitive chain. The current registry has no transitive dependency chains.

## Composition graph [#composition-graph]

The dependency and incompatibility rules combine into a single composition graph. Use it to size your template scope before you publish.

<Mermaid
  chart="flowchart LR
  HB[historical-balances]
  VP[voting-power]
  AUM[aum-fee]
  TF[transaction-fee]
  TFA[transaction-fee-accounting]
  ETF[external-transaction-fee]
  FTY[fixed-treasury-yield]
  MR[maturity-redemption]
  C[conversion]
  CM[conversion-minter]
  P[permit]

  CM -->|requires| C
  TF -.->|incompatible| TFA
  TFA -.->|incompatible| TF

  classDef independent fill:#e3f2fd,stroke:#1976d2
  classDef linked fill:#fff3e0,stroke:#f57c00
  class HB,VP,AUM,ETF,FTY,MR,P independent
  class C,CM,TF,TFA linked"
/>

Solid arrows mark required-companion dependencies (`conversion-minter` requires `conversion`). Dotted arrows mark mutually exclusive pairs (`transaction-fee` and `transaction-fee-accounting` cannot coexist on the same asset). Features without arrows compose freely with any other feature.

## Order of application [#order-of-application]

Feature sequence is intentional. The configured list is the execution sequence on chain: `DALPAssetFactoryImplementation._addFeaturesToAsset` attaches modules in list order, and SMART Protocol hooks execute in that same sequence during token operations.

For most combinations, the position does not change the observed result, because each feature owns a distinct hook surface. Position matters when two features can both observe or mutate the same operation. For example: a transfer where one feature deducts a fee from the transferred amount and another records a holder-balance checkpoint. Pick an arrangement that matches your intent, and treat the input list as the contract for that choice.

DALP feature-closure expansion preserves the input list verbatim. Directly implied dependents are appended at the end. Reordering it changes the deployed attachment sequence. Re-publish the instrument template with the intended positions rather than relying on chain-side reordering.

Each actor sets its positions at a different point. The table below shows where each takes effect.

| Concern         | Where the order is set                       | Where the order takes effect                                             |
| --------------- | -------------------------------------------- | ------------------------------------------------------------------------ |
| Template author | `requiredFeatures` array in the template     | Deploy payload order, then SMART Protocol attachment order               |
| Asset Designer  | UI-driven `requiredFeatures` selection order | Same as above                                                            |
| API caller      | `featureConfigs` order on a deploy request   | Wins over template default only when both are present and the caller has |
|                 |                                              | authority to override; otherwise the published template's order applies. |

When your template needs a precise attachment sequence to satisfy a fee or rewrite invariant, document the rationale in the template description so future editors do not silently change it.

## Asset Designer constraint display [#asset-designer-constraint-display]

The Asset Designer and template-management screens use the same constraint rules as the API. The UI enforces these rules when an operator edits required features.

* Incompatible options are disabled when their pair is already present.
* Dependent-only choices show the missing required companion.
* The expanded set is stable when the input has not changed.
* Descriptions stay attached to the same feature IDs used by API requests.

This prevents the UI from offering a combination that the publish or creation path would later reject.

## UI, API, and smart-contract validation [#ui-api-and-smart-contract-validation]

The same feature registry drives the Asset Designer and the API, but each surface has a different job. The table below summarizes what each validates and what to expect when it finds a problem.

| Layer                   | What it validates                                                                                                                                                                          | What to expect                                                                                                                                                                     |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Asset Designer          | Required fields, editable template fields, missing feature dependencies, incompatible feature pairs, and feature-closure expansion for deploy payloads.                                    | Operators get early feedback and disabled choices before they publish a template or submit an asset.                                                                               |
| API and template routes | Published-template selection, required-feature dependencies, mutually exclusive pairs, field-type ranges, and feature configuration supplied for template-enabled features.                | Invalid requests fail before deployment. Treat these failures as template or request errors, not as chain-state errors.                                                            |
| Smart contracts         | Constructor and initializer parameters, feature factory availability, access control, lifecycle-hook execution order, fee caps, collateral or yield ratios, and per-feature runtime rules. | Contracts are the final enforcement point. They do not replace template validation; they protect deployment and token operations if an invalid or stale payload reaches the chain. |

For DALPAsset creation, `templateId` is required. DALP reads the selected instrument template, combines its required features with submitted `featureConfigs`, validates dependency and incompatibility rules, and then passes the valid set into deployment.

Use these rules when you build API requests:

1. Select a published instrument template that already includes the token behaviors required for the asset.
2. Submit `featureConfigs` only for template-enabled features that need operator-provided settings.
3. Do not submit settings that imply a mutually exclusive pair on the same asset.
4. Treat unmet dependencies as template configuration errors, not as runtime deployment errors.

## Production checklist [#production-checklist]

Before you publish a template or issue an asset, verify the feature configuration.

* The required feature IDs match the intended asset behavior.
* `conversion-minter` is paired with `conversion` when conversion behavior is needed.
* `transaction-fee` and `transaction-fee-accounting` are not enabled together.
* Base-price, fee-rate, metadata, collateral, and yield values use the accepted ranges for their field types.
* Feature order is intentional because lifecycle hooks execute in the configured order.

Also verify the deployment environment.

* Required feature factories are enabled in the target environment.
* Any configurable settings that operators may edit during asset creation are explicitly marked editable on the template.
* The deployment target has the contracts and roles required to enforce the selected feature set.

For the operator workflow, see [Instrument templates](/docs/operators/asset-creation/instrument-templates). For how features run during token operations, see [Token Features](/docs/architects/components/token-features).
