# Issuer-signed scalar feed

Source: https://docs.settlemint.com/docs/architecture/components/capabilities/issuer-signed-scalar-feed
Issuer-signed scalar feeds let trusted issuers publish signed integer values
for a subject and topic, then expose the latest value through a
Chainlink-compatible read interface.




An issuer-signed scalar feed is DALP's primitive for publishing a signed number on-chain.
Use it when an asset, identity, or global feed subject needs a topic value attested by a trusted issuer.

The feed answers three questions for downstream systems:

1. Which subject and topic does this value belong to?
2. Which trusted issuer signed the update?
3. What current scalar value should consumers read through the feed interface?

For the procedural API flow, see [Create feeds](/docs/developer-guides/feeds/create-feeds).
For the wider registry and adapter model, see [Feeds system](/docs/architecture/components/infrastructure/feeds-system).

## Where it fits [#where-it-fits]

Issuer-signed scalar feeds are deployed by the `IssuerSignedScalarFeedFactory`.
Each feed instance is pinned at creation time to a subject, a numeric topic ID, and the scalar schema hash for that topic.
Issuer-signed scalar feeds require the topic scheme to match the scalar `(int256 value)` schema.
The factory derives the schema hash from the topic scheme registry, deploys the feed, then registers it in the FeedsDirectory as a scalar feed.

Consumers do not need to know who deployed the feed.
Consumers resolve the `(subject, topic)` pair through the FeedsDirectory, then read the current value from the returned feed or from an adapter.

## Deployment configuration [#deployment-configuration]

The create API and factory set the same feed invariants, but they do not accept exactly the same input shape.
The API accepts either `topicName` or `topicId` and checks that both refer to the same registered topic when both are supplied.
Direct factory calls use the numeric `topicId` only.
These values are immutable for the feed instance.

| Setting                  | Type                                | What it controls                                                                       |
| ------------------------ | ----------------------------------- | -------------------------------------------------------------------------------------- |
| `subject`                | EVM address                         | The asset, identity, or global zero address the feed is about.                         |
| `topicName` or `topicId` | string                              | API input for the registered topic. Direct factory calls use the numeric `topicId`.    |
| `decimals`               | integer, 0 to 18                    | How to interpret fixed-point integer answers.                                          |
| `description`            | string                              | Human-readable feed description returned by the aggregator interface.                  |
| `historyMode`            | `LATEST_ONLY`, `BOUNDED`, or `FULL` | How much historical round data the feed keeps on-chain.                                |
| `historySize`            | non-negative integer                | Ring-buffer size for `BOUNDED` history. Must be greater than zero for bounded history. |
| `requirePositive`        | boolean                             | Whether the feed rejects zero and negative values.                                     |
| `driftAllowance`         | integer seconds                     | How far `observedAt` may be in the future relative to the current block timestamp.     |

`driftAllowance` is a timestamp tolerance, not a percentage price-change guard.
A value of `0` means the submitted `observedAt` cannot be later than the current block timestamp.

## Update verification [#update-verification]

Every update is an EIP-712 signed `FeedUpdate` with these fields:

| Field        | Meaning                                                                         |
| ------------ | ------------------------------------------------------------------------------- |
| `topicId`    | Must match the feed's pinned topic.                                             |
| `schemaHash` | Must match the feed's pinned schema hash.                                       |
| `value`      | The signed scalar integer.                                                      |
| `observedAt` | The timestamp used as the feed round's `startedAt` and `updatedAt`.             |
| `nonce`      | The issuer's next sequential nonce for this feed. The first valid nonce is `1`. |
| `deadline`   | Signature expiry timestamp. `0` means no deadline.                              |

When `submit` is called, the feed verifies the update before it changes state:

1. The topic and schema hash match the feed instance.
2. The issuer is authorized for the feed's topic and subject in the trusted issuers registry.
3. The EIP-712 signature recovers to an EOA signer.
4. The signer has CLAIM purpose on the issuer identity.
5. The issuer nonce is exactly one greater than the previous nonce.
6. The deadline has not expired, unless the deadline is `0`.
7. If `requirePositive` is true, the value is greater than zero.
8. `observedAt` is not zero.
9. `observedAt` does not move backwards compared with the latest accepted update.
10. `observedAt` is not farther in the future than `driftAllowance` permits.

Only after these checks pass does the feed increment the round, store the latest answer, update the issuer nonce, and emit `FeedUpdated`.

## History modes [#history-modes]

History mode controls what `getRoundData` can return.

| Mode          | Behavior                                                                                                               | Use when                                                                                                       |
| ------------- | ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `LATEST_ONLY` | Stores the latest answer only. `getRoundData` reverts because historical rounds are not retained.                      | Consumers only need the current value.                                                                         |
| `BOUNDED`     | Stores recent rounds in a ring buffer of `historySize`. Older slots are overwritten and evicted rounds cannot be read. | Consumers need recent verification history without unbounded storage.                                          |
| `FULL`        | Stores every accepted round by round ID.                                                                               | Consumers require full on-chain round history and the update frequency is low enough for that storage profile. |

`latestRoundData` works in every mode and returns the current round ID, answer, timestamp, and answered-in-round value using the Chainlink-style aggregator shape.

## Value format [#value-format]

Feed answers are signed integers. The feed's `decimals` value defines how consumers convert that integer to a human-readable number.

```text
human-readable value = answer / 10^decimals
```

For example, an answer of `15000` with `decimals = 2` represents `150.00`. The feed stores and returns the integer value. Consumers are responsible for applying the decimal scale consistently.

When `requirePositive` is enabled, the feed rejects `0` and negative answers.
A feed that represents negative values, such as a spread or rate delta, needs `requirePositive` disabled.

## Discovery path [#discovery-path]

The FeedsDirectory is the discovery layer for issuer-signed scalar feeds.

1. The factory deploys the feed with the configured subject, topic, schema, decimals, history mode, positivity rule, and timestamp tolerance.
2. The factory registers the feed in the FeedsDirectory as a scalar feed for the same subject and topic.
3. Consumers resolve the `(subject, topic)` pair to find the feed address.
4. Consumers read the latest value from the feed, or use an aggregator adapter if they need a stable address that can follow future directory changes.

The feed instance itself is not upgradeable. If consumers need a stable integration point across feed replacement, use the adapter and directory path rather than hard-coding the feed address.

## Rejection conditions [#rejection-conditions]

Common rejects are deliberate safety checks, not partial writes. A rejected update leaves the feed's latest answer, round counter, and issuer nonce unchanged.

| Rejection                                                              | Trigger                                                                                                  | Typical fix                                                                              |
| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `TopicMismatch` or `SchemaHashMismatch`                                | The signed update does not match the feed's pinned topic or schema.                                      | Sign an update for the same topic and schema as the feed.                                |
| `IssuerNotAuthorized`                                                  | The trusted issuers registry has no matching entry for the issuer, topic, and subject.                   | Configure the issuer in the registry before submitting.                                  |
| `InvalidSigner` or `InvalidSignature`                                  | The signature cannot be recovered or the signer is not a CLAIM-purpose key on the issuer identity.       | Sign with an authorized issuer key and use a standard 65-byte ECDSA signature.           |
| `InvalidNonce`                                                         | The nonce is not the issuer's next sequential nonce.                                                     | Read the issuer nonce and resubmit with `nonce + 1`.                                     |
| `DeadlineExpired`                                                      | The update has a non-zero deadline in the past.                                                          | Create a fresh signed update.                                                            |
| `ValueNotPositive`                                                     | `requirePositive` is enabled and the value is zero or negative.                                          | Submit a positive value, or create a different feed for values that may be non-positive. |
| `InvalidObservedAt`, `StaleObservation`, or `ObservedAtTooFarInFuture` | The observation timestamp is zero, older than the latest accepted observation, or too far in the future. | Use a real observation timestamp that is monotonic and within the feed's tolerance.      |
| `HistoryNotSupported` or `RoundNotFound`                               | A consumer asks for history outside the feed's retained rounds.                                          | Use `latestRoundData`, choose a history-retaining mode, or request a retained round.     |

## See also [#see-also]

* [Create feeds](/docs/developer-guides/feeds/create-feeds)
* [Read feed data](/docs/developer-guides/feeds/read-data)
* [Feeds system](/docs/architecture/components/infrastructure/feeds-system)
* [Feeds update flow](/docs/architecture/flows/feeds-update-flow)
* [Claims and identity model](/docs/architecture/concepts/claims-and-identity)
