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

# Token Standard V1 / V2 cross-version compatibility

Support for the Token Standard V2 interfaces ([CIP-112](https://github.com/canton-foundation/cips/blob/main/cip-0112/cip-0112.md))
was added in version **0.14** of the Registry App Daml models. Starting with this version, the Registry App provides
cross-version compatibility between the V1 ([CIP-56](https://github.com/canton-foundation/cips/blob/main/cip-0056/cip-0056.md))
and V2 interfaces.

This page only clarifies the Registry App specific aspects of cross-version compatibility, in particular for DvP
settlements. For the token standard V2 itself, refer to the CIP-112 specification:

* [Functional extensions](https://github.com/canton-foundation/cips/blob/main/cip-0112/cip-0112.md#4-functional-extensions)
  such as accounts, batch settlement via the `SettlementFactory`, and committed allocations and iterated settlement.
* [Backwards compatibility](https://github.com/canton-foundation/cips/blob/main/cip-0112/cip-0112.md#5-backwards-compatibility),
  including the compatibility rules for apps, assets and wallets, and the allocation compatibility matrix.

## How V1 and V2 relate in the Registry App

### Holdings

There is a one-to-one correspondence between the Holding V1 and Holding V2 views, achieved by encoding the V2 data
(such as account information) into the metadata of the V1 view. Every Registry holding can be read through either
interface.

### Transfers

The Token Standard V2 transfer implementation is built on top of the Token Standard V1 transfer
implementation.

### Allocations

In line with the CIP-112 [compatibility rules](https://github.com/canton-foundation/cips/blob/main/cip-0112/cip-0112.md#51-compatibility-rules),
the Registry App maintains two allocation templates:

* The `DvpLegAllocation` template implements both the V1 and the V2 allocation interfaces. It can therefore
  be executed as part of a V2 settlement batch, using only the executors' authority. Multiple executors and
  accounts are supported by encoding them in the V1 metadata.
* The `AllocationV2` template **only** implements the V2 allocation interface. It was added because a V1 allocation
  can in general be upcast to a V2 allocation, but not the other way around: a V2 allocation cannot in general be
  represented as a V1 allocation.

| Template | Allocation V1 interface | Allocation V2 interface | Multiple executors | Committed settlement | Iterated settlement |
| :- | :-: | :-: | :-: | :-: | :-: |
| `DvpLegAllocation` | Yes | Yes | Yes (via V1 metadata) | No | No |
| `AllocationV2` | No | Yes | Yes | Yes | Yes |

Committed allocations and iterated settlement are described in
[CIP-112, 4.1.6](https://github.com/canton-foundation/cips/blob/main/cip-0112/cip-0112.md#416-committed-allocations-for-prefunded-trading-and-iterated-settlement)
and [4.3.6](https://github.com/canton-foundation/cips/blob/main/cip-0112/cip-0112.md#436-committed-allocations-and-iterated-settlement).

As a result, from version 0.14 onwards, an allocation request from a trading venue that implements both the V1 and
V2 `AllocationRequest` interfaces can be fulfilled using either a V1 or a V2 wallet. Since a `DvpLegAllocation` is
also a V2 allocation, allocations created by V1 wallets can be executed as part of a V2 settlement.

> [!WARNING]
>
> Cross-version compatibility is **one-directional**. The `AllocationV2` template is intended for V2 allocations
> only: it is more generic and supports multiple transfer legs, whereas a V1 allocation only addresses a single
> transfer leg. A V2 wallet calling the V2 allocation factory creates `AllocationV2` contracts, which **only**
> implement CIP-112 and are therefore not compatible with CIP-56.
>
> * A `DvpLegAllocation` created through a V1 wallet **can** be executed as part of a V2 settlement flow.
> * An `AllocationV2` instance **cannot** be settled as part of a V1 settlement flow.
>
> Trading venues that send out V2 `AllocationRequest`s are therefore expected to settle **exclusively through V2**.

## Registry App version requirements

Besides the Token Standard version, the **Registry App DAR version** vetted by each participant matters. Each minor
release is a [smart contract upgrade](https://docs.canton.network/appdev/deep-dives/smart-contract-upgrade) (SCU) of
the previous one, and we support the [two minor versions](https://docs.digitalasset.com/registry/releases/versioning.md) before the current release.
With 0.14, participants may therefore still legitimately run 0.12 or 0.13, which contain **no V2 functionality**:
there, `DvpLegAllocation` does not implement the V2 allocation interface.

V1 / V2 cross-version settlement therefore requires **all participants involved in the settlement transaction to
have vetted 0.14 or later**. A V1 allocation of an admin that has only vetted 0.12 or 0.13 cannot be exercised as a
V2 allocation.

| Registry version vetted | V1 settlement | V2 settlement (cross-version) |
| :- | :-: | :-: |
| 0.12 / 0.13 by any involved participant | Supported | Not supported |
| 0.14 or later by all involved participants | Supported | Supported |

> [!NOTE]
>
> This is a transitional limitation: once support for 0.12 and 0.13 has been dropped and these versions have been
> unvetted, V1 / V2 cross-version settlement can be orchestrated for all participants.

### Single package version per transaction

Canton's [package selection algorithm](https://docs.canton.network/appdev/deep-dives/smart-contract-upgrade#package-selection-in-the-ledger-api)
(topology-aware package selection, TAPS) resolves **a single version per package name for the entire transaction**:
the highest version vetted by all participants involved. It does not select different versions for different
subtransactions, even where this would be possible in principle. This is a current implementation of
Canton.

This matters in particular for DvPs where **both** assets are issued on the Registry App, e.g. an instrument of
issuer A traded against an instrument of issuer B. Although the two legs are settled by different instrument admins
on different participants, both are implemented by the **same** Registry App packages (same package names). TAPS
therefore has to pick a single Registry App version for both legs, which must be vetted by the participants of both
issuers and all traders. A DvP against an asset implemented by a different package (e.g. Canton Coin) is not
affected in the same way, as different package names are resolved independently.

> [!WARNING]
>
> **Any** involved participant (instrument admin, trader, venue, or any other informee) that has only vetted an older
> Registry App version forces the **whole** settlement transaction onto that version. For example, if issuer A has
> only vetted 0.13 and issuer B has vetted 0.13 and 0.14, a trade involving both settles all legs on 0.13, so a V1 / V2
> cross-version settlement is not possible, also not for issuer B's instruments. If no common version exists, the
> submission fails.

## Recommended approach for trading venues

Until all participants have vetted 0.14 or later, a trading venue should determine per settlement whether a V2 flow
can be used. **If any involved participant is on an older Registry App version, orchestrate a V1 settlement for all
Registry App instruments**, as TAPS selects that older version for the whole settlement transaction. Batches settled
in separate transactions are resolved independently by TAPS, at the cost of atomicity across batches.

Always settle through the token standard interfaces (`SettlementFactory`, `Allocation`, ...) rather than referencing
Registry App templates directly, so that the Registry App version is resolved at submission time through TAPS.

**1. Check V2 support of the instrument admins**

For every instrument involved in the settlement, call the token metadata endpoint of the Registry App:

```
GET /registry/metadata/v1/instruments/{instrumentId}
```

Inspect the `supportedApis` field of the response. If any instrument admin does not signal support for
`splice-api-token-allocation-v2` (the entry is missing or set to `0`), send out **V1 `AllocationRequest`s only**
and orchestrate the legacy V1 settlement flow.

**2. Check the Registry DAR version of all settlement participants**

If all instrument admins signal V2 support, additionally verify that **every** participant taking part in the
settlement (instrument admins, traders, the venue itself, and any other informee) has vetted the Registry App
DARs at version **0.14 or later**. If not, orchestrate a V1 settlement for all Registry App instruments.

**3. Orchestrate a V2 settlement**

Only when both conditions above are met should the venue orchestrate a V2 settlement. In this case, send out an
allocation request that has **both V1 and V2 implementations**, so that users can respond with either a V1 or a
V2 wallet.

Note that once support for versions before 0.14 has been dropped, both conditions are trivially met, and a V2
settlement can always be orchestrated.

```mermaid theme={null}
flowchart TD
    A[New settlement] --> B{All instrument admins signal<br/>splice-api-token-allocation-v2?}
    B -- No --> V1[Send V1 AllocationRequests<br/>Run V1 settlement flow]
    B -- Yes --> C{All participants vetted<br/>Registry DARs >= 0.14?}
    C -- No --> V1
    C -- Yes --> V2[Send AllocationRequest with V1 and V2 implementations<br/>Run V2 settlement flow]
```

## V2 settlement with V1 and V2 wallets

In a V2 settlement, the trading app creates one allocation request per trader that implements **both** the V1 and
the V2 `AllocationRequest` interfaces, and settles through the Registry App's V2 settlement factory. How each trader's
wallet responds depends on its token standard version and on its role in the trade:

| Wallet | Response to the allocation request |
| :- | :- |
| V2 wallet | Accepts the request through the V2 interface and, in the same transaction, creates an `AllocationV2` for its side(s) via the V2 allocation factory. |
| V1 wallet as **sender** | Reads the request through the V1 interface and creates a `DvpLegAllocation` via the V1 allocation factory. It cannot accept the request, as V1 has no accept choice, so the request stays open. The `DvpLegAllocation` also implements the V2 allocation interface and can be settled through V2. |
| V1 wallet as **receiver** | Creates nothing, as in V1 only senders create allocations. |

All four sender / receiver combinations of V1 and V2 wallets can be settled through V2:

| Sender wallet | Receiver wallet | Sender allocation | Receiver allocation |
| :- | :- | :- | :- |
| V2 | V2 | V2 allocation, created by the sender's wallet | V2 allocation, created by the receiver's wallet |
| V1 | V2 | `DvpLegAllocation`, created by the sender's wallet | V2 allocation, created by the receiver's wallet |
| V2 | V1 | V2 allocation, created by the sender's wallet | V2 receipt allocation, **created by the trading app** |
| V1 | V1 | `DvpLegAllocation`, created by the sender's wallet | V2 receipt allocation, **created by the trading app** |

### Receipt allocations for V1 wallet users

Trading apps are expected to create the V2 receipt allocation on behalf of receivers using a V1 wallet, based on an
agreement in which the receiver delegates this right to the trading app. For example, the Splice V2 reference trading
app uses a `TradeSettlementAgreement` for this purpose. The trading app is also responsible for archiving allocation
requests that remain open, for example those of V1 wallet senders, as part of settlement.

> [!WARNING]
>
> Creating and settling receipt allocations **atomically** (in the same transaction) is **not supported** by the
> Registry App. It needs to be done in two steps:
>
> 1. Create the receipt allocation.
> 2. Settle the batch using `SettlementFactory_SettleBatch`.
>
> The Registry App off-ledger endpoint for `SettlementFactory_SettleBatch` only provides the choice context and
> disclosures for allocations that already exist on-ledger.
>
> Do not manually compose choice contexts obtained from different endpoints. Their internal structure may change
> without notice.

To reduce the need for trading apps to manage V2 receipt allocations, trading parties are strongly recommended to
migrate to V2 wallets as early as possible.

## See also

* [Token Standard APIs (CIP 56 / CIP 112)](https://docs.digitalasset.com/registry/apis/token-standard)
* [Account compatibility](https://docs.digitalasset.com/registry/apis/token-standard/compatibility-v1-wallets.md)
* [Off-ledger API](https://docs.digitalasset.com/registry/apis/token-standard/off-ledger-api)
* [Smart Contract Upgrades overview](https://docs.canton.network/appdev/modules/m6-overview)
