# Issuance Volume Limit

Source: https://docs.settlemint.com/docs/architecture/security/compliance/issuance-volume-limit
How to configure DALP issuance-volume-limit controls for periodic token-unit minting quotas, fixed or rolling windows, and burn capacity release.



Issuance Volume Limit caps how many raw token units may be minted during a configured window. Use it when an asset programme needs a periodic issuance quota, tranche release limit, vesting throttle, or operational minting cap. The control applies to minting only. Transfers and forced transfers do not consume quota, and burns release capacity according to the configured accounting mode.

Related compliance references:

* [Compliance overview](/docs/architecture/security/compliance)
* [Capital Raise Limit](/docs/architecture/security/compliance/capital-raise-limit)
* [Supply and investor limits](/docs/architecture/security/compliance/supply-investor-limits)
* [Mint assets in the console](/docs/user-guides/asset-servicing/mint-assets)

## Choose this control when the cap is in token units [#choose-this-control-when-the-cap-is-in-token-units]

Use `issuance-volume-limit` when the question is: how many token units may this asset mint in the current window?

| Requirement                                             | Use this control? | Better fit when it is not this control                                                    |
| ------------------------------------------------------- | ----------------- | ----------------------------------------------------------------------------------------- |
| Limit a mint programme to 100,000 token units per month | Yes               | None                                                                                      |
| Release a fixed tranche amount each quarter             | Yes               | None                                                                                      |
| Slow vesting or distribution by token amount            | Yes               | None                                                                                      |
| Cap gross fiat proceeds from issuance                   | No                | [Capital Raise Limit](/docs/architecture/security/compliance/capital-raise-limit)         |
| Cap total outstanding supply for the token              | No                | [Supply cap and collateral](/docs/architecture/security/compliance/supply-cap-collateral) |
| Prove off-chain collateral or reserves                  | No                | Reserve and backing evidence stays outside this token-unit quota                          |

## Before you enable it [#before-you-enable-it]

Confirm these prerequisites before adding the control to a token or template:

1. The module is available in the deployment and appears in the compliance controls list as **Issuance Volume Limit**.
2. The asset has a mint operator with the Supply Management permission.
3. The planned mint recipient can pass the token's holder eligibility policy. A treasury, issuer, fund, vessel, or SPC wallet still needs the required OnchainID and claims when it receives minted units.
4. The quota is expressed in raw token units, including the token decimals. A quota of 1,000 units on an 18-decimal token is configured as `1000000000000000000000`.
5. The accounting window is known before installation. The period length and window mode are locked after the module is enabled.

## Configure the control [#configure-the-control]

1. Open the token or template compliance controls.
2. Select **Issuance Volume Limit**.
3. Set **Maximum supply** to the maximum raw token units that may be minted in the window. The value must be greater than `0`.
4. Set **Period length** in days. The value must be at least `1`.
5. Choose **Rolling window** when capacity should slide day by day. Leave it off when capacity should reset at fixed period boundaries.
6. Save and enable the control, then run a small mint to a compliant recipient before operating the full issuance programme.

The dapp validates the same core constraints as the contract. Rolling windows accept periods up to `730` days. Fixed windows accept periods up to `36500` days. After the module is enabled, the dapp disables **Period length** and **Rolling window** because the contract rejects changes to those fields.

## Configuration fields [#configuration-fields]

```solidity
struct IssuanceVolumeLimitConfig {
    uint256 maxSupply;    // Per-window cap in raw token units. Must be greater than 0.
    uint256 periodLength; // Window length in days. Must be greater than 0.
    bool    rolling;      // true = rolling window, false = fixed window.
}
```

| Field          | Can change after enabling? | Rule                                                                                                                            |
| -------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `maxSupply`    | Yes                        | Operators can raise or tighten the per-window quota in place. Tightening affects future mint checks only.                       |
| `periodLength` | No                         | Changing the window length via `updateConfig` reverts. Deploy a new module instance to use a different period.                  |
| `rolling`      | No                         | Changing between rolling and fixed mode via `updateConfig` reverts. Deploy a new module instance to change the accounting mode. |

## How minting is counted [#how-minting-is-counted]

The module checks only mint operations, where the sender is the zero address. A mint fails when the current in-window minted amount plus the requested amount would exceed `maxSupply`.

| Mode           | Tracker                                                                 | What happens as time moves                                                                                       |
| -------------- | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| Rolling window | A 730-slot daily circular buffer stores minted amounts by day.          | Daily slots age out of the read window. The module sums the last `periodLength` days before each mint check.     |
| Fixed window   | A single `periodStart` and `totalSupply` pair stores the active period. | At `periodStart + periodLength * 1 days`, the old period is no longer active. The next mint starts a new period. |

Transfers and forced transfers do not change the tracker. They remain governed by other installed compliance controls, but they do not consume or release issuance quota.

## How burns release capacity [#how-burns-release-capacity]

Burns do not fail just because the issuance tracker cannot attribute the full burned amount. The token-layer burn succeeds, and the quota tracker releases only the capacity it can match to in-window mints.

| Mode           | Burn handling                                                                                    | Operational meaning                                                                       |
| -------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- |
| Rolling window | Burns walk backward from the current day and consume the newest non-empty daily slots first.     | Recent mints release capacity before older slots that are closer to ageing out naturally. |
| Fixed window   | Burns subtract from the active period total only while the current fixed period is still active. | A burn after the fixed period has expired does not reopen quota in the old period.        |

When a burn amount is larger than the in-window tracked supply, the unattributed remainder increments `absorbedBurnExcess()` and emits `BurnExceededWindow(attempted, absorbed, windowSpan)`. Treat this as an operations signal that the burn included supply the current window did not track, such as older supply or pre-window minted tokens.

## Update an installed control [#update-an-installed-control]

Only update **Maximum supply** in place. If the new quota is lower than the amount already minted in the current window, the module does not undo past mints. It blocks future mints until the window advances or burns release enough tracked capacity.

To change the period length or switch between rolling and fixed accounting:

1. Plan the replacement window and quota.
2. Remove the installed issuance volume limit from the token or template policy.
3. Add a new Issuance Volume Limit control with the new period length or window mode.
4. Re-test minting with a small amount before returning to the normal issuance workflow.

## Failure behavior [#failure-behavior]

| Failure                                                                                        | What it means                                               | What to check                                                                                                        |
| ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `InvalidConfig("Maximum supply must be greater than zero")`                                    | The quota is `0`.                                           | Set **Maximum supply** to a positive raw token-unit amount.                                                          |
| `InvalidConfig("Period length must be greater than zero")`                                     | The window length is `0`.                                   | Set **Period length** to at least `1` day.                                                                           |
| `InvalidConfig("Rolling window cannot exceed 730 days (2 years) to prevent gas limit issues")` | Rolling mode is enabled with a window above `730` days.     | Use `730` days or less, or choose fixed mode when the programme needs a longer period.                               |
| `InvalidConfig("Fixed window cannot exceed 36500 days (~100 years) to prevent overflow")`      | Fixed mode is configured with an impractical period length. | Use a shorter fixed period.                                                                                          |
| `ComplianceCheckFailed` with `COMPLIANCE_CHECK_REASON_EXCEEDS_QUOTA`                           | The mint would exceed the active issuance quota.            | Mint a smaller amount, wait for the window to advance, or burn tracked in-window supply if the programme permits it. |
| `InvalidConfig("periodLength cannot be changed; redeploy module")`                             | An update tried to change the locked period length.         | Remove and add a new module instance with the new period.                                                            |
| `InvalidConfig("rolling cannot be changed; redeploy module")`                                  | An update tried to switch the locked accounting mode.       | Remove and add a new module instance with the desired mode.                                                          |

A recipient eligibility error is separate from the issuance quota. If a mint fails because the recipient cannot receive the asset, check holder registration, OnchainID, trusted issuers, and required claims before changing the quota.

## What this control does not prove [#what-this-control-does-not-prove]

Issuance Volume Limit is a token-unit minting quota. It does not prove that reserves exist, that an off-chain treasury is reconciled, or that a legal fundraising cap has been satisfied. Pair it with the right operating evidence, reserve reconciliation, holder eligibility controls, and issuer approvals when the asset programme requires those controls.
