- Config, docs, scripts, and backup manifests - Submodule refs unchanged (m = modified content in submodules) Made-with: Cursor
16 KiB
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 and dbis_core ISO 20022 integration).
- 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.
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 token’s 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:
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
- Ingest: Receive MX (XML) or Fin (MT) message at an off-chain service (e.g. dbis_core Iso20022Service, Iso20022Adapter, or a dedicated gateway).
- Parse and validate: Check schema, mandatory elements, and business rules (amounts, currency, identifiers). Reject invalid messages before any on-chain step.
- 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).
- Submit to contract: Call the contract’s accept entry point (e.g.
submitInbound/submitOutboundor equivalent) with the canonical payload. The contract must verify sender (relayer/guardian), idempotency (e.g. byinstructionIdormsgId), and policy (ComplianceGuard, PolicyManager, allowlists). - 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 optionallymsgIdoruetr) 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 and dbis_core iso20022-mapping, 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 payload’s
payloadHashmatches 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,uetrwhere 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. The canonical struct supplies
debtorId,creditorId, andpurposefor 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/msgIdin the system. - Payload hash: Compute
payloadHashover 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
tokenis a known, allowed token (e.g. via TokenRegistry or allowlist). - Amount: Ensure
amountis within bounds and, for mints, consistent with reserve/attestation logic.
7.3 Audit and Non-Repudiation
- Store or log
payloadHashandinstructionIdon-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 and 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.
9. Related Documents
| Document | Description |
|---|---|
| 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 | ISO-20022 canonical message and E-Money requirements for GRU multi-chain |
| Mapping_Table.md | ISO 20022 (pain.001, pacs.008, etc.) field-level mapping and validation |
| iso20022-mapping.md | ISO 20022 to DBIS API mapping and Iso20022Adapter usage |
| iso20022-message-flow.md | ISO 20022 message processing flow |
| 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