Files
proxmox/docs/04-configuration/SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md

263 lines
16 KiB
Markdown
Raw Permalink Normal View History

# Methodology: Smart Contracts Accepting ISO-20022 and Fin Messages
**Version:** 1.0
**Last Updated:** 2026-02-23
**Status:** Active
**Scope:** Chain 138 (and multi-chain) e-money and bridge contracts
---
## 1. Purpose and Scope
This document defines the **methodology** for designing and operating smart contracts that **accept** ISO-20022 financial messages (MX/XML) and, where applicable, **SWIFT Fin** (MT) messages, by normalising them to a single **canonical on-chain representation** and processing them through a well-defined contract interface.
### 1.1 Objectives
- **Interoperability:** Enable value transfers and settlement flows that originate from or are traceable to ISO-20022 (and Fin) messaging.
- **Auditability:** Ensure every on-chain transfer, mint, burn, or cross-chain action can be correlated with a standardised message identifier and metadata (e.g. MsgId, UETR, debtor/creditor, purpose).
- **Compliance:** Support regulatory and E-Money requirements (par redeemability, safeguarded reserves, transaction monitoring) while preserving ISO-20022 semantics at the boundary.
### 1.2 Out of Scope
- Off-chain generation or routing of ISO-20022/Fin messages (covered by [ISO 20022 Mapping Table](../../gru-docs/docs/integration/iso20022/Mapping_Table.md) and [dbis_core ISO 20022 integration](../../dbis_core/docs/nostro-vostro/iso20022-mapping.md)).
- Contract deployment or network topology (see deployment runbooks).
---
## 2. Message Sources: ISO-20022 and Fin
### 2.1 ISO-20022 (MX) Messages
| Message Type | Purpose | Typical Use in Smart Contract Context |
|-------------------|----------------------------------|----------------------------------------|
| **pain.001** | Customer credit transfer initiation | Initiation of a payment that may settle on-chain |
| **pacs.008** | FI-to-FI customer credit transfer | Settlement instruction; primary input for on-chain credit |
| **pacs.009** | FI-to-FI direct debit | Debit-side settlement |
| **pacs.002** | Payment status report | Status/correlation off-chain or in events |
| **camt.053** | Bank statement | Off-chain reconciliation |
| **camt.054** | Debit/credit notification | Notifications; optional event mapping |
Messages are **XML** with namespaces per ISO 20022 XSDs (e.g. `urn:iso:std:iso:20022:tech:xsd:pacs.008.001.10`). Parsing and validation are done **off-chain**; only a **canonical payload** is passed to the contract.
### 2.2 SWIFT Fin (MT) Messages
Where legacy flows use **SWIFT Fin** (e.g. MT103, MT202), the methodology treats them as **additional input formats** that must be **mapped into the same canonical structure** as ISO-20022 before being passed to smart contracts.
| MT Type | Purpose | Mapping Notes |
|-----------|----------------------|----------------------------------------------------|
| **MT103** | Single customer transfer | Field 20 → instructionId; 32A → amount/currency; 50/59 → debtor/creditor |
| **MT202** | Bank transfer | Map to pacs.008-like canonical fields |
Fin messages are **normalised to the canonical format** (Section 3) so that contracts do not need separate MT vs MX logic.
---
## 3. Canonical Message Format (On-Chain Contract View)
All accepted messages (ISO-20022 MX or SWIFT Fin) are reduced to a **single canonical struct** used in contract interfaces and events. This aligns with the extended CanonicalMessage described in [MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md).
### 3.1 Canonical Struct (Semantic Definition)
| Field | Type | Purpose |
|--------------------|---------|--------|
| `msgType` | string | Message type: `pacs.008`, `pain.001`, `camt.054`, or normalized equivalent (e.g. `MT103`) |
| `instructionId` | bytes32 | InstrId unique instruction reference (hashed if longer than 32 bytes) |
| `endToEndId` | string | EndToEndId (optional) |
| `msgId` | string | MsgId (optional) |
| `uetr` | string | UETR (optional) |
| `accountRefId` | string | Account reference (debtor account or equivalent) |
| `counterpartyRefId`| string | Counterparty account reference (creditor or equivalent) |
| `debtorId` | string | Debtor identifier (optional) |
| `creditorId` | string | Creditor identifier (optional) |
| `purpose` | string | Purpose / remittance info (optional) |
| `settlementMethod` | string | Settlement method (optional) |
| `categoryPurpose` | string | Category purpose (optional) |
| `token` | address | Token contract address |
| `amount` | uint256 | Amount (in tokens smallest unit) |
| `currencyCode` | string | Currency code (ISO 4217) |
| `payloadHash` | bytes32 | Hash of off-chain payload (full MX/MT or selected elements) for audit |
Strings that exceed on-chain limits (e.g. 32 bytes for a single storage slot) should be **hashed** for storage and the full value emitted in events or stored in an off-chain index keyed by `instructionId` or `msgId`.
### 3.2 Solidity-Oriented Representation
Contracts may use a struct such as:
```solidity
struct CanonicalMessage {
string msgType;
bytes32 instructionId;
string endToEndId;
string msgId;
string uetr;
string accountRefId;
string counterpartyRefId;
string debtorId;
string creditorId;
string purpose;
string settlementMethod;
string categoryPurpose;
address token;
uint256 amount;
string currencyCode;
bytes32 payloadHash;
}
```
Optional fields can be empty strings or zero values where not applicable. Events should expose at least `instructionId`, `msgId` (if present), `token`, `amount`, `debtorId`, `creditorId`, and `payloadHash` so that off-chain systems can map back to ISO-20022.
---
## 4. End-to-End Flow: From Fin/ISO-20022 to Smart Contract
### 4.1 High-Level Pipeline
```
[ISO-20022 MX / SWIFT Fin] → Parse & Validate (off-chain) → Map to Canonical → Submit to Contract → Contract applies policy & executes
```
1. **Ingest:** Receive MX (XML) or Fin (MT) message at an off-chain service (e.g. [dbis_core Iso20022Service](../../dbis_core/src/integration/iso20022/iso20022.service.ts), [Iso20022Adapter](../../dbis_core/src/integration/plugins/iso20022-adapter.ts), or a dedicated gateway).
2. **Parse and validate:** Check schema, mandatory elements, and business rules (amounts, currency, identifiers). Reject invalid messages before any on-chain step.
3. **Map to canonical:** Fill the canonical struct from the message (see Section 5). For MT, use a dedicated MT→canonical mapping (e.g. MT103 field 20 → instructionId, 32A → amount/currencyCode, 50/59 → debtorId/creditorId).
4. **Submit to contract:** Call the contracts **accept** entry point (e.g. `submitInbound` / `submitOutbound` or equivalent) with the canonical payload. The contract must verify sender (relayer/guardian), idempotency (e.g. by `instructionId` or `msgId`), and policy (ComplianceGuard, PolicyManager, allowlists).
5. **Execute and emit:** Contract performs transfer/mint/burn/cross-chain and emits events that include canonical metadata so that off-chain systems can map to ISO-20022 reports (pacs.002, camt.054, etc.).
### 4.2 Idempotency and Replay Protection
- **Unique key:** Use `instructionId` (and optionally `msgId` or `uetr`) as the idempotency key. Contracts must maintain a mapping (e.g. `processedInstructions[instructionId]`) and **revert or no-op** if the same key is submitted again.
- **Replay:** Ensure the same MX/Fin message cannot be replayed on another chain or at another time by binding the canonical payload to chain and, if needed, to a nonce or timestamp validated off-chain or on-chain.
---
## 5. Mapping Rules: ISO-20022 and Fin → Canonical
### 5.1 ISO-20022 MX → Canonical
Use the same semantic mapping as in the [ISO 20022 Mapping Table](../../gru-docs/docs/integration/iso20022/Mapping_Table.md) and [dbis_core iso20022-mapping](../../dbis_core/docs/nostro-vostro/iso20022-mapping.md), then project onto the canonical struct:
| Canonical Field | ISO-20022 Source (e.g. pacs.008) |
|----------------------|-----------------------------------|
| msgType | Message type (e.g. `pacs.008`) |
| instructionId | `PmtId/InstrId` (hash if needed) |
| endToEndId | `PmtId/EndToEndId` |
| msgId | `GrpHdr/MsgId` |
| uetr | UETR element if present |
| accountRefId | `DbtrAcct/Id` (IBAN or Othr/Id) |
| counterpartyRefId | `CdtrAcct/Id` (IBAN or Othr/Id) |
| debtorId | `Dbtr/Nm` or `Dbtr/Id` |
| creditorId | `Cdtr/Nm` or `Cdtr/Id` |
| purpose | `RmtInf/Ustrd` or `Purp` |
| settlementMethod | Settlement method element |
| categoryPurpose | `CategoryPurp` |
| token | Resolved from currency/account (off-chain config) |
| amount | `IntrBkSttlmAmt` (scaled to token decimals) |
| currencyCode | `IntrBkSttlmAmt/@Ccy` |
| payloadHash | `keccak256(rawMessage)` or hash of selected elements |
### 5.2 SWIFT Fin (MT) → Canonical
Example for **MT103**:
| Canonical Field | MT103 Field | Notes |
|----------------------|-------------|--------|
| msgType | — | Set to `MT103` |
| instructionId | 20 | Hash if > 32 bytes |
| endToEndId | 121 (UETR) or 20 | If present |
| msgId | — | From header or generate |
| uetr | 121 | If present |
| accountRefId | 50a / 52a | Sender account |
| counterpartyRefId | 59a | Beneficiary account |
| debtorId | 50K / 50a | Ordering customer |
| creditorId | 59 / 59a | Beneficiary |
| purpose | 72 | Sender to receiver info |
| token | — | From currency in 32A + config |
| amount | 32A | Parse amount; scale to token decimals |
| currencyCode | 32A | Currency from 32A |
| payloadHash | — | Hash of MT text block or full message |
Contracts only ever see the **canonical** struct; they do not need to know whether the source was MX or MT.
---
## 6. Contract Interface Requirements
### 6.1 Entry Points for “Accepting” Messages
Smart contracts that **accept** ISO-20022/Fin semantics should expose at least one of the following (or equivalent):
- **Inbound (e.g. submitInbound):** For instructions that result in **credit** to the chain (e.g. mint, or release from bridge). Caller must be an authorised relayer/guardian; payload is the canonical struct.
- **Outbound (e.g. submitOutbound):** For instructions that result in **debit** from the chain (e.g. burn, or lock for bridge). Same authorisation and canonical payload.
Naming may vary (e.g. `processInboundMessage`, `acceptCreditTransfer`); the important part is that the **payload is the canonical struct** and that **idempotency** and **policy checks** are enforced.
### 6.2 Authorisation
- Only designated roles (e.g. `ROUTER_ROLE`, `RELAYER_ROLE`, or a guard contract) may call the submit functions. Use AccessControl or equivalent.
- Optionally, require that the **sender** of the transaction is a known **guardian** or **relayer** address list, and that the canonical payloads `payloadHash` matches an off-chain attested hash.
### 6.3 Events
Emit events that carry enough canonical metadata for off-chain systems to map to ISO-20022 status and reporting (e.g. pacs.002, camt.054):
- At least: `instructionId`, `msgId` (if any), `token`, `amount`, `debtorId`, `creditorId`, `payloadHash`, success/failure.
- Prefer including `msgType`, `endToEndId`, `uetr` where available so that reconciliation and compliance reporting are straightforward.
### 6.4 Integration with E-Money and Compliance
- **ComplianceGuard / PolicyManager / ComplianceRegistry:** Before executing the transfer/mint/burn, contracts should enforce allowlists, KYT, and circuit breakers as described in [MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md). The canonical struct supplies `debtorId`, `creditorId`, and `purpose` for policy checks.
- **Reserve and par redeemability:** For base-money mints, ensure reserve attestation and par redeemability rules are applied as in the same runbook; the canonical message does not replace those checks.
---
## 7. Validation and Security
### 7.1 Off-Chain Validation (Before Submit)
- **Schema:** Validate MX against the appropriate ISO 20022 XSD; validate MT format per SWIFT rules.
- **Business rules:** Amount > 0, currency matches token, mandatory identifiers present, no duplicate `instructionId`/`msgId` in the system.
- **Payload hash:** Compute `payloadHash` over the raw or normalized message and attach to the canonical struct so the contract (or a verifier) can optionally check it.
### 7.2 On-Chain Checks
- **Idempotency:** Revert or skip if `instructionId` (or chosen key) already processed.
- **Role:** Only authorised roles can call submit.
- **Token:** Ensure `token` is a known, allowed token (e.g. via TokenRegistry or allowlist).
- **Amount:** Ensure `amount` is within bounds and, for mints, consistent with reserve/attestation logic.
### 7.3 Audit and Non-Repudiation
- Store or log `payloadHash` and `instructionId` on-chain so that auditors can match on-chain execution to off-chain MX/Fin messages.
- Prefer emitting full canonical metadata in events and indexing them off-chain for compliance and reconciliation.
---
## 8. Implementation Checklist
- [ ] **Off-chain:** Parser for ISO-20022 MX (and optionally SWIFT Fin MT) producing the canonical struct.
- [ ] **Off-chain:** Mapping tables and validation rules (amounts, currency, identifiers) aligned with [Mapping_Table.md](../../gru-docs/docs/integration/iso20022/Mapping_Table.md) and [iso20022-mapping.md](../../dbis_core/docs/nostro-vostro/iso20022-mapping.md).
- [ ] **Contract:** Canonical struct and submit interface (e.g. `submitInbound`/`submitOutbound`) with role-based access.
- [ ] **Contract:** Idempotency (e.g. `processedInstructions[instructionId]`) and policy hooks (ComplianceGuard, PolicyManager, ComplianceRegistry).
- [ ] **Contract:** Events that expose canonical metadata for ISO-20022 mapping and reporting.
- [ ] **Integration:** Bridge and e-money entry points (BridgeVault, UniversalCCIPBridge, etc.) carry or reference canonical metadata in events as per [MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md).
---
## 9. Related Documents
| Document | Description |
|----------|-------------|
| [ISO20022_INTAKE_GATEWAY_CONTRACT_MULTI_NETWORK.md](ISO20022_INTAKE_GATEWAY_CONTRACT_MULTI_NETWORK.md) | How the intake/gateway contract receives ISO messages on different blockchain networks (relayer vs cross-chain, same address, per-chain config) |
| [MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md) | ISO-20022 canonical message and E-Money requirements for GRU multi-chain |
| [Mapping_Table.md](../../gru-docs/docs/integration/iso20022/Mapping_Table.md) | ISO 20022 (pain.001, pacs.008, etc.) field-level mapping and validation |
| [iso20022-mapping.md](../../dbis_core/docs/nostro-vostro/iso20022-mapping.md) | ISO 20022 to DBIS API mapping and Iso20022Adapter usage |
| [iso20022-message-flow.md](../../dbis_core/docs/flows/iso20022-message-flow.md) | ISO 20022 message processing flow |
| [LEGAL_COMPLIANCE_REQUIREMENTS.md](../../explorer-monorepo/docs/LEGAL_COMPLIANCE_REQUIREMENTS.md) | Legal and ISO 20022 compliance for smart contracts |
---
**Document Control**
- **Owner:** Configuration / Integration
- **Review:** Align with runbook and mapping table changes
- **Next review:** When contract interfaces or ISO-20022 message set change