Tokenize Platform

Enterprise-grade blockchain financial infrastructure. Cross-border payments, tokenized deposits, tokenized money market funds (TMMF), and tokenized mutual funds (TMF) — all on-chain. Running on Sepolia testnet under the EU DLT Pilot Regime (EU 2022/858).

Think of Tokenize as a modern bank: you deposit euros, earn interest, send money internationally, and invest in regulated funds — but with blockchain technology making everything faster and cheaper. Features atomic FX swaps, ZK-privacy, and cross-chain interoperability.

Core Architecture: Two Parallel Channels

Every payment uses two completely separate channels simultaneously. One channel carries the full payment data (SWIFT ISO 20022 XML). The other channel provides on-chain hash verification (blockchain). They share the same txId as the link between them.

Channel 1: SWIFT (Banking)

  • • Carries full ISO 20022 XML (invoice, line items, tax)
  • • Delivered via SWIFT pacs.008 to recipient's bank BIC
  • • Same as traditional correspondent banking

Channel 2: Blockchain (Verification)

  • • Stores keccak256 hash of the ISO 20022 XML
  • • Escrows USDC until hash verification succeeds
  • • 3-of-5 multi-sig releases funds

Why two channels? SWIFT alone is slow (3-5 days). Blockchain alone can't carry rich payment data. Together: SWIFT delivers the data, blockchain provides tamper-proof verification. This is the same pattern used by SWIFT GPI and Ripple — parallel channels, not replacement.

See full architecture diagram →

Supported Standards & Protocols

ERC-20 (Permissioned) ERC-3643 (T-REX) ERC-4626 (Vaults) ERC-7540 (Async) ERC-1643 (Docs) ISO 20022 SEPA Instant MiCA / MiFID II ZK-Privacy Chainlink CCIP FATF Travel Rule

Industry Reference: BlackRock BUIDL (custom ERC-20 + Securitize compliance), UBS uMINT (ERC-20 + Chainlink DTA), BNY/GS Fundshare (private ledger + BNY LiquidityDirect)

Four Core Banking Scenarios

Tokenized Mutual Fund (TMF)

Higher-risk mutual fund (AIFMD/UCITS) with variable NAV. Transition from TMMF or direct purchase. Target yield subject to risk — not guaranteed.

Higher risk • Variable NAV • T+2 redemption

Complete Platform Overview

Cross-Border USDC Payment Rail

In Plain English

Imagine sending money from New York to Berlin. Normally it takes 3-5 days and costs $35. With Tokenize, the on-chain transfer completes in under 10 seconds and costs 2 cents — like sending an email instead of a letter. The full end-to-end flow includes off-chain banking steps (SWIFT messaging, SEPA credit) which add time but still beat traditional correspondent banking. Your money moves on blockchain, but the payment details travel through normal banking channels (SWIFT), so both banks can verify everything matches.

How It Works

Alice in the US sends 1,000 USDC to Bob in the EU. The payment leverages the CBPR (Cross-Border Payment Rail) smart contract on Sepolia testnet, with embedded compliance checks, corridor validation, and real-time settlement.

Demo vs Production: This demo shows direct USDC transfer (simplest flow). In production, the PvP FX swap (described below) converts USDC → EURC atomically, then EURC is redeemed to EUR fiat via SEPA Instant — so Bob receives EUR, not USDC.

UCITS Audit Trail: Under UCITS/AIFMD regulations, the TMMF→TMF transition is treated as two separate transactions: (1) redemption of TMMF shares (redemption event) and (2) subscription to TMF shares (new subscription). The smart contract emits two separate events (TMMFRedeemed and TMFSubscribed) to maintain the required audit trail for fund administrator sign-off and depositary verification.

Enterprise Architecture Context

Business Value: This demo replaces legacy SWIFT MT103 wire transfers (3-5 day settlement, $25-50 fees) with on-chain USDC settlement in under 10 seconds at ~$0.02 cost. Production uses ISO 20022 pacs.008 — under the SWIFT CBPR+ programme, MT messages were retired for cross-border payments in November 2025 (coexistence mode ran alongside during the transition). The CBPR contract acts as a smart escrow — funds are locked when the payment is initiated, validated against corridor rules and compliance status, then released to the recipient upon settlement confirmation.

Integration Architecture: In production, this blockchain layer sits alongside legacy banking systems. The Middleware Service receives payment instructions from SAP/Oracle Financials, validates them against the CorridorRegistry for routing rules, checks the IdentityRegistry for KYC/AML compliance, and then submits the transaction to the CBPR contract. Settlement status flows back to the legacy core via the same middleware.

3-5 days
Legacy SWIFT Settlement
~$35.00
Traditional Wire Fee
<10 sec
Tokenize Settlement

Architecture Flow — Cross-Border Payment

Standards used: ERC-20 (USDC transfers), FATF Travel Rule (KYC/AML), ISO 20022 pacs.008 (payment data), SWIFT (bank routing), hash commitment (data integrity).

1
Payment Initiation
Frontend

Alice enters payment details. Frontend looks up Bob's BIC from IdentityRegistry (ERC-3643 T-REX identity standard for regulated tokens; custom contract on-chain, not ERC-725 which is a key manager standard).

2
Compliance Check
On-Chain

IdentityRegistry.checkCompliance() — FATF Travel Rule: verifies KYC, accreditation level, sanctions screening.

3
Corridor Validation
On-Chain

CorridorRegistry.validateCorridor() — checks active routes, min/max limits, sanctions restrictions.

4
USDC Escrow (ERC-20)
On-Chain Transfer

USDC.transferFrom() — Alice's USDC (ERC-20) transferred to CBPR contract as escrow.

5
Hash Commitment + SWIFT
Two Channels

Channel 1 (Blockchain): keccak256(SWIFT_XML) stored on-chain as tamper-proof receipt.

Channel 2 (SWIFT): ISO 20022 pacs.008 XML sent to Bob's bank BIC — carries full payment data (invoice, line items, tax).

6
Settlement & Verification
Final

Bob's bank: Receives ISO 20022 XML via SWIFT → computes hash → compares to on-chain hash → verifies integrity → credits Bob's account.

Blockchain: 3-of-5 multi-sig releases USDC from escrow to Bob's wallet address (ERC-20 transfer).

Step-by-Step Data Flow & System Integration Demo Flow — Direct USDC Transfer

1
Payment Initiation — Frontend / Mobile App
User Action

Alice opens the Tokenize web application and enters the payment details: recipient address, amount, corridor (US-EU), and purpose of payment (memo). The frontend validates the inputs and displays a summary screen showing all payment details including fees, exchange rates, and estimated settlement time.

// Frontend constructs payment object
{ recipient: "0x9ABC...DEF0", amount: 1000, corridor: "US-EU", memo: "Invoice #INV-2024-001" }
2
Compliance Check — IdentityRegistry Contract
On-Chain Validation

Before any funds move, the CBPR contract calls identityRegistry.checkCompliance(Alice) to verify that Alice has completed KYC and is not on any sanctions list. This is a non-revertible check — if Alice is unverified, the transaction reverts immediately with "UNVERIFIED_SENDER". This ensures regulatory compliance at the smart contract level, not just at the application layer.

// CBPR.sol:83 — Compliance check
require(identityRegistry.checkCompliance(msg.sender), "UNVERIFIED_SENDER");
3
Corridor Validation — CorridorRegistry Contract
On-Chain Validation

The CBPR contract validates the requested corridor (US-EU) against the CorridorRegistry. This checks that: (a) the corridor is active, (b) the payment amount falls within allowed min/max limits for this corridor, and (c) there are no sanctions or restrictions on this route. In production, this would also include AML screening against OFAC, EU, and UN sanctions lists. The Middleware Service pre-validates this data before the on-chain call, but the contract performs the definitive check.

// CBPR.sol:81 — Corridor validation
require(corridorRegistry.validateCorridor(corridorId, amount), "INVALID_CORRIDOR");
4
Fund Escrow — USDC Token Transfer
On-Chain Transfer

Alice's USDC is transferred from her wallet to the CBPR contract using transferFrom(). This requires Alice to have previously approved the CBPR contract to spend her USDC (a one-time ERC-20 allowance). The funds now sit in the CBPR contract as an escrow — they are locked until the settlement is confirmed. This two-phase approach (escrow → release) provides a safety mechanism: if settlement fails, funds can be reversed back to the sender.

// CBPR.sol:84 — Escrow transfer
require(usdcToken.transferFrom(msg.sender, address(this), amount), "USDC_TRANSFER_FAILED");
5
Transaction Recording — Blockchain Ledger
Immutable Record

The CBPR contract generates a unique transaction ID using keccak256(abi.encodePacked(sender, recipient, amount, timestamp, corridorId)). This ID serves as the immutable reference for the entire payment lifecycle. The transaction is recorded on-chain with status PENDING and a PaymentInitiated event is emitted. This event is picked up by the Middleware Service, which updates the legacy core banking system (SAP/Oracle) with the new payment status.

// Event emitted to all listeners
emit PaymentInitiated(txId, sender, recipient, amount, corridorId);
// Middleware Service picks up event → updates SAP/Oracle
6
Settlement Confirmation — Multi-Sig Governance
Multi-Sig Release

Settlement requires 3-of-5 multi-signature approval via Gnosis Safe. The five signers are: (1) Sending Bank Node, (2) Receiving Bank Node, (3) Compliance Officer, (4) Platform Treasury, (5) Independent Validator. This ensures no single party can unilaterally release or freeze funds. The CBPR contract then transfers the USDC from escrow to Bob's address. The transaction status is updated to SETTLED and a SettlementConfirmed event is emitted. The Middleware Service propagates this to the legacy systems, completing the payment lifecycle.

// CBPR.sol:108 — Release escrow to recipient
require(usdcToken.transfer(paymentTx.recipient, paymentTx.amount), "USDC_TRANSFER_FAILED");

Payment Details

Sender

Alice (0x1234...5678)

Recipient

Bob (0x9ABC...DEF0)

Amount

1,000 USDC

Corridor

🇺🇸 US → 🇪🇺 EU

Purpose of Payment

Goods — Invoice #INV-2024-001

Transaction ID

0x... (generated on-chain)

Traditional Cost

$35.00

Tokenize Cost

~$0.02

Cost breakdown: The ~$0.02 figure reflects Sepolia testnet gas costs. In production, the platform would deploy on Base L2 (≈$0.001-0.01 per tx) or a permissioned EVM chain (zero gas). Legacy SWIFT MT103 fees ($25-50) include correspondent bank margins, not just network fees.

Receiver Information (KYC-Verified)

Legal Name

Robert Müller

Country

🇩🇪 Germany

Wallet Address

0x9ABC...DEF0

KYC Status

Verified

Bank (Legacy)

Deutsche Bank AG

IBAN

DE89 3704 0044 0532 0130 00

Legacy System Integration Points

SAP S/4HANA / Oracle Financials

Receives payment status updates via Middleware Service REST API. Ledger entries created for accounting reconciliation.

SWIFT Network (ISO 20022 pacs.008)

Used for rich payment data exchange between banks. The blockchain runs in parallel for USDC escrow and hash verification — it does not replace SWIFT.

KYC Provider (Sumsub / Jumio)

Off-chain identity verification performed before on-chain registration. Results stored as on-chain compliance flags.

Live Contract Interaction

Simulation Mode — All demos work without MetaMask. Click buttons to simulate the full flow.

Banking Production: Customers never pay gas directly. The bank sponsors all transactions via ERC-4337 Account Abstraction paymaster (planned for production) — customers interact with a simple web UI, no wallet setup needed.

Two channels require two identifiers:

Blockchain:
Wallet address (USDC escrow)
SWIFT:
BIC/SWIFT code (routes ISO 20022 XML)

For USDC escrow on-chain

For ISO 20022 XML delivery via SWIFT network

Stored off-chain; referenced by txId on-chain

Tokenized Deposits

In Plain English

You deposit €10,000 in your bank account and get €10,000 in digital tokens. These tokens are exactly like euros — you can use them to buy investment funds instantly, no paperwork, no waiting. When you want your euros back, you burn the tokens and get your euros credited to your bank account. It's like having a bank account that works as fast as sending a text message.

Customers deposit EUR into the platform and receive EUR tokens representing their deposit value. These tokens can be used to purchase both TMMF (Tokenized Money Market Fund) and TMF (Tokenized Mutual Fund) shares — just like how banks let customers move from savings accounts to investment products.

Architecture Flow — Tokenized Deposits

Standards used: ERC-3643/T-REX (EUR tokens — MiCA EMT, permissioned transfers), ERC-4626 (TMMF/TMF vault accounting), ERC-7540 (async redemption requests), ERC-1643 (prospectus/KID document anchoring), SEPA Instant, MiCA Art. 48 EMT, UCITS/AIFMD.

1
EUR Deposit via SEPA
Off-Chain

Customer transfers EUR via SEPA/SEPA Instant to the platform's bank account. Bank confirms receipt.

2
MintEscrow — 2-Stage Minting
On-Chain

Stage 1 (Provisional): SEPA receipt confirmed by bank → provisional EUR tokens minted, marked as uncleared.
Stage 2 (Definitive): SEPA clearing confirmed (D+0) → tokens unlocked and fully transferable. If clearing fails, provisional tokens are burned.

3
EUR Tokens Minted (ERC-20)
ERC-20 Transfer

Customer receives EUR tokens (ERC-3643/T-REX — permissioned, not open ERC-20) in their wallet. Each token = €1.00 backed 1:1 by fiat deposit. Transfers restricted to verified, accredited addresses only per MiCA Art. 48 EMT requirements.

4
Purchase TMMF (ERC-4626 Vault)
ERC-4626

TMMF.purchaseWithEURTokens() — EUR tokens burned, TMMF shares minted based on current NAV. Follows ERC-4626 vault standard.

5
Purchase TMF or Transition from TMMF
ERC-4626

Direct: TMF.purchaseWithEURTokens() — buy TMF shares directly with EUR tokens.

Transition: requestTMFTransition() — convert TMMF shares → TMF shares based on NAV ratio.

1
Customer deposits 10,000 EUR via bank transfer (SEPA)
2
MintEscrow contract receives EUR (2-stage minting)
3
Platform mints EUR tokens (1:1 with deposit) to customer
4
Customer uses EUR tokens to purchase TMMF shares (low-risk, ~4.5% yield)
5
Customer can transition TMMF → TMF or purchase TMF directly (higher-risk, ~6-8% yield)

Deposit Details

Deposit Amount 10,000 EUR
Token Received 10,000 EUR tokens (1:1)
Token Value €1.00 per token
Token Use Purchase TMMF shares
Token Use (TMF) Purchase TMF shares
Withdrawal Burn tokens → receive EUR back
Redemption flow: Customer calls redeem() → tokens burned → Middleware triggers SEPA Credit Transfer to customer's IBAN → EUR arrives in SEPA Instant window (<10 seconds).
Reserve model: EUR tokens are 1:1 backed by segregated client money accounts (per E-Money Directive 2009/110/EC Article 19 and MiCA Article 54 safeguarding rules). The EUR token is classified as an e-money token under MiCA Article 48. Reserve custodian address is registered in the IdentityRegistry. Monthly third-party attestation verifies 1:1 backing (cf. Circle USDC model).
Depositary/Custodian: Under UCITS/AIFMD, an independent depositary is mandatory. The depositary holds the underlying EUR deposits in segregated accounts, verifies 1:1 backing, and has liability for loss of assets. In the architecture, this is represented by the ReserveCustodian contract address, which must sign off on any mint/burn operation.
Atomic Delivery vs Payment (DVP)

Eliminates counterparty risk: EUR tokens are burned and fund shares are minted in a single atomic transaction. Either both happen or neither does — no risk of losing tokens without receiving shares.

Step 1: approve(EUR tokens, TMMF contract)
Step 2: purchaseWithEURTokens(amount)
Inside purchase(): eurToken.burn(msg.sender, amount)mint(msg.sender, shares)
Both operations in single transaction — atomic guarantee
EUR Token → TMMF Shares Flow
Customer deposits EUR via bank transfer to the platform's bank account.
MintEscrow receives EUR and triggers minting of EUR tokens. The platform mints 10,000 EUR tokens (1:1 with deposit).
Customer receives 10,000 EUR tokens in their wallet. These tokens represent their EUR deposit value.
Customer approves EUR tokens for the TMMF contract to spend.
Customer calls TMMF.purchaseWithEURTokens() — EUR tokens are burned and TMMF shares are minted based on the current NAV.
EUR Token → TMF Shares Flow
Customer has EUR tokens from their bank deposit (same as above).
Customer approves EUR tokens for the TMF contract to spend.
Customer calls TMF.purchaseWithEURTokens() — EUR tokens are burned and TMF shares are minted based on the current NAV.
Customer now holds TMF shares (higher risk, variable NAV, ~6-8% target yield)

Deposit & Purchase TMMF

Demo Mode: Works without MetaMask. Click buttons to simulate the full flow — deposit EUR, mint EUR tokens, purchase TMMF shares. All transactions are simulated with realistic hashes and delays.

EUR bank transfer → EUR tokens minted 1:1

Purchase TMMF Shares with EUR Tokens
Purchase TMF Shares with EUR Tokens
Current TMMF Status
NAV €1.0000
Annual Yield ~4.5%
Your TMMF Shares 0

Tokenized Money Market Fund (TMMF)

In Plain English

Think of this like a savings account that earns ~4.5% interest. Your money is very safe — it's invested in short-term, low-risk assets like government bonds. The value stays stable at €1.00 per share, and you earn daily interest payments. You can request a withdrawal at any time — actual fiat settlement follows SEPA processing times (T+0 for SEPA Instant). Note: UCITS redemption gates may suspend redemptions during market stress.

Institutional investors gain access to a fractionalized money market fund with daily NAV updates managed by the asset management team. Built on a layered ERC standard stack: ERC-3643/T-REX (permissioned shell with ONCHAINID), ERC-4626 (vault accounting), ERC-7540 (async redemption requests for T+1 settlement), ERC-1643 (prospectus/KID document anchoring). Regulated as a UCITS-compliant LVNAV money market fund under MMFR (EU) 2017/1131, supervised by FSMA under the Belgian Act of 11 December 2025 transposing MiCA (Wet van 11 december 2025 betreffende de markten voor cryptoactiva).

Industry Reference: How Banks Actually Offer TMMF
BlackRock BUIDL — Uses a customized ERC-20 with built-in whitelist transfer control (NOT ERC-3643). Securitize handles KYC/AML compliance off-chain as the transfer agent. BNY Mellon is custodian and administrator. Multi-chain (Ethereum, Solana, Polygon) via Wormhole. Circle provides instant USDC redemption.
UBS uMINT — Tokenized MMF on Ethereum + Polygon. Uses Chainlink Digital Transfer Agent (DTA) standard for on-chain compliance and transfer management. First in-production tokenized fund using Chainlink DTA.
BNY Mellon + Goldman Sachs — Uses "Fundshare" tokens on Goldman's private blockchain (GS DAP). BNY's LiquidityDirect platform connects for real-time subscription/redemption. Traditional MMF shares mirrored as digital tokens.
JPMorgan Onyx — Handles billions in tokenized short-term investments using blockchain for real-time settlement. Uses permissioned channels for institutional clients.
Key Pattern: Banks use permissioned ERC-20 (whitelist-controlled transfers) with an external compliance layer (Securitize, Chainlink DTA, or proprietary). ERC-3643/T-REX is the emerging open standard for this pattern. ERC-7540 (async redemption) addresses T+1/T+2 settlement windows. ERC-1643 anchors regulatory documents (prospectus, KID) on-chain.

Architecture Flow — TMMF (ERC-4626 Vault)

Standards used: ERC-3643/T-REX (permissioned shell + ONCHAINID), ERC-4626 (vault accounting), ERC-7540 (async redemption), ERC-1643 (prospectus/KID anchoring), FATF Travel Rule (KYC-gated), oracle price feeds (NAV updates).

1
KYC Compliance Check
On-Chain

IdentityRegistry.checkCompliance() — FATF Travel Rule: investor must be verified and accredited to access TMMF vault.

2
NAV Update (Oracle)
Oracle Feed

NAV updated daily via Chainlink-style push oracle: authorized oracle submitter (asset management team) calls updateNAV(newNAV). Circuit breaker: if NAV hasn't been updated in 48 hours, all deposits/redeems freeze automatically. Underlying assets: EU sovereign short-term debt, repo agreements, and investment-grade commercial paper with maturity <397 days, per MMFR Article 10. ERC-4626: getNAV() returns share value.

Oracle Security Note: To prevent NAV manipulation, production uses a multi-source oracle (e.g., Bloomberg + Refinitiv + Chainlink) with time-weighted average price (TWAP) over 5-minute windows. The depositary must sign off on the NAV before it is written on-chain.
3
Yield Distribution
ERC-4626

YieldDistributionEngine accrues yield via ERC-4626 accumulating model. Under MMFR and UCITS, yield distribution requires NAV calculation by a fund administrator and sign-off — the on-chain engine executes only after the depositary confirms the NAV. Yield distributed proportionally to all shareholders.

4
Redeem Shares (ERC-4626)
ERC-4626

ERC-7540 asyncRedeem(shares) — investor requests redemption (T+1 settlement window). ERC-4626 ensures fair value based on current NAV. The async pattern (ERC-7540) is required because vanilla ERC-4626 is synchronous and incompatible with T+1/T+2 fund settlement windows.

1
Investor completes KYC via IdentityRegistry
2
Asset management team updates NAV via oracle
3
YieldDistributionEngine accrues yield automatically
4
Investor redeems shares for pro-rata assets
TMMF → TMF Transition Flow

Investors can transition from low-risk TMMF to higher-risk TMF. This is how banks offer product upselling: start with a safe money market fund, then transition to a higher-yield mutual fund as the investor's risk appetite increases.

Investor holds TMMF shares (low risk, stable NAV €1.0000, ~4.5% yield)
Investor requests TMF transition via requestTMFTransition(tmfContract, tmmfAmount)
TMMF burns shares and TMF contract mints TMF shares based on TMMF NAV
Investor now holds TMF shares (higher risk, variable NAV, higher potential yield ~6-8%)
NAV Conversion Example
Investor holds: 100 TMMF shares × €1.0000 NAV = €100.00 value
TMF NAV: €1.0500 (variable, market-driven)
TMF shares received: €100.00 ÷ €1.0500 = 95.24 shares
— Atomic swap in single transaction, no counterparty risk (ERC-3643 transfer restrictions apply)
TMMF (Money Market)
• Low risk, aims to maintain stable NAV (€1.0000)
• Stable NAV (€1.0000)
• ~4.5% annual yield
• Daily liquidity
TMF (Mutual Fund)
• Higher risk, higher return
• Variable NAV (market-driven)
• ~6-8% annual yield (target)
• Redemption T+2 per UCITS rules

Fund Details

Fund Type Money Market Fund (TMMF)
Regulation MMFR 2017/1131 — LVNAV
Minimum Investment €100
MMFR Note: MMFR LVNAV is available to both retail and institutional investors. Retail share classes can have low minimums (€100 shown here for demo); institutional share classes typically require €100K+. Under MMFR, eligible assets must be government securities, repos, or high-quality commercial paper with maturity <397 days.
Current NAV €1.0000
NAV Type LVNAV (Low Volatility)
24h NAV Fluctuation ±0.0001%
Daily Yield Accrual ~0.0123%
Annual Yield ~4.5%
Yield Distribution Daily as dividend
NAV Updates Daily oracle push (12:00 CET cutoff)
Transition To TMF (Higher Yield)
Intraday NAV: Unlike traditional MMFs (T+1 NAV), Tokenize TMMF updates NAV intraday via oracle. Orders before 12:00 CET get same-day NAV; after 12:00 CET get next-day NAV.
Yield accrual: ERC-4626 accumulating model — share/asset ratio increases over time as yield accrues. No rebasing, no cash distributions. Your share balance stays the same, but each share is worth slightly more.
Liquidity caveat: Subject to fund prospectus terms and applicable UCITS/AIFMD redemption gates.

NAV Update Simulation

Simulate how the asset management team updates the NAV and distributes yield.

TMMF NAV History (last 50 updates) €1.000000

Tokenized Mutual Fund (TMF)

In Plain English

This is like a mutual fund — higher risk but higher reward (~6-8% target). Your money is invested in bonds and other assets, so the value goes up and down. It's like having a professionally managed investment portfolio that you can buy instantly — redemption is subject to a T+2 cooldown period (per UCITS rules). Banks offer this as a next step after TMMF: start with the safe savings account, then move to this for higher returns as you get more comfortable with investing.

Higher-risk mutual fund with variable NAV. Structured as an AIF (Alternative Investment Fund) under AIFMD, or UCITS for retail investors — subject to MiFID II suitability requirements. Built on a layered ERC standard stack: ERC-3643/T-REX (permissioned shell), ERC-4626 (vault accounting), ERC-7540 (async redemption for T+2 settlement), ERC-1643 (prospectus/KID/KIID anchoring). Supervised by FSMA under the Belgian Act of 11 December 2025 transposing MiCA (Wet van 11 december 2025 betreffende de markten voor cryptoactiva).

Industry Reference: How Banks Offer TMF (Tokenized Mutual Funds)
BNY Mellon + Goldman Sachs (July 2025) — Launched the first U.S. tokenized money market fund platform. Goldman issues shares in its Blueprint money market fund. BNY handles custody and investor onboarding. Tokens ("Fundshare") recorded on Goldman's private blockchain (GS DAP). Major firms including BlackRock, Fidelity, and Federated Hermes joined the rollout.
UBS uMINT (November 2024) — First tokenized investment fund from UBS Asset Management. Built on Ethereum + Polygon. Uses Chainlink Digital Transfer Agent (DTA) for compliance. Distributed via DigiFT (regulated on-chain fund distributor).
JPMorgan Onyx (2025) — Launched its first tokenized money market fund. Onyx Digital Assets platform handles billions in tokenized short-term investments. Leverages blockchain for real-time settlement and reduced counterparty risk.
Key Pattern: Tokenized mutual funds are structured as traditional regulated funds (UCITS/AIFMD) with blockchain as the settlement layer. The token is a digital representation of fund shares, not a new asset class. Compliance (KYC/AML, investor accreditation) is handled off-chain by the fund administrator or transfer agent. The blockchain provides real-time settlement, 24/7/365 transferability among approved investors, and automated dividend distribution.

Architecture Flow — TMF (ERC-4626 Vault)

Standards used: ERC-3643/T-REX (permissioned shell + ONCHAINID), ERC-4626 (vault accounting), ERC-7540 (async redemption), ERC-1643 (prospectus/KID anchoring), FATF Travel Rule (KYC-gated), oracle price feeds (variable NAV).

1
KYC + Accreditation Check
On-Chain

IdentityRegistry.checkCompliance() — FATF Travel Rule: investor must be verified + accredited (higher threshold than TMMF).

2
Variable NAV Update (Oracle)
Oracle Feed

NAV updated daily via Chainlink-style push oracle: authorized oracle submitter (asset management team) calls updateNAV(newNAV). Circuit breaker: if NAV hasn't been updated in 48 hours, all deposits/redeems freeze automatically. NAV is market-driven (more volatile than TMMF). ERC-4626: getNAV() returns current share value.

3
Purchase TMF Shares (ERC-4626)
ERC-4626

Direct: TMF.purchaseWithEURTokens() — restricted to EUR tokens (MiCA CASP compliance). USDC requires separate authorization.

From TMMF: requestTMFTransition() — burns TMMF shares, mints TMF shares based on NAV ratio.

4
Yield Distribution
ERC-4626

YieldDistributionEngine distributes yield (~6-8% target) proportionally to all TMF shareholders.

5
Redeem Shares (ERC-4626)
ERC-4626

vault.redeem(shares) — investor redeems for pro-rata assets. ERC-4626 assumes immediate redemption, so lock-up is implemented via a withdrawal queue pattern: investor calls requestRedeem(shares) → 2-day cooldown → executeRedeem() releases assets. This satisfies UCITS T+2 redemption rules while using the ERC-4626 vault interface.

1
Investor completes KYC via IdentityRegistry
2
Asset management team updates TMF NAV via oracle
3
Investor purchases TMF shares with EUR tokens or USDC
4
Investor redeems shares for pro-rata assets
Transition from TMMF to TMF

Banks offer product upselling: start with low-risk TMMF, then transition to higher-yield TMF. This is how retail banks guide customers from savings accounts to investment products.

Hold TMMF
€1.0000 NAV
requestTMFTransition
burn + mint
Get TMF
Variable NAV
NAV Conversion Math
You hold
100 TMMF shares × €1.0000 = €100.00
TMF NAV = €1.05
€100.00 ÷ €1.05 = 95.24 TMF shares
Cross-Contract Trust Model

How does TMMF trust TMF to burn its shares? The TMF contract address is whitelisted in the TMMF contract's authorizedTransitions[] array. Only the TMF contract can call burnFromTMMF(tmmfShares) on the TMMF contract. This is a one-way trust: TMMF trusts TMF to burn TMMF shares, and TMF trusts TMMF to verify the user has approved the transfer. The TMF contract address is immutable once set at deployment — no admin can change it. This prevents phishing attacks where a malicious contract impersonates TMF.

TMMF (Money Market)
• Low risk, aims to maintain stable NAV (€1.0000)
• Stable NAV (€1.0000)
• ~4.5% annual yield
• Daily liquidity
TMF (Mutual Fund)
• Higher risk, higher return
• Variable NAV (market-driven)
• ~6-8% annual yield (target)
• Redemption T+2 per UCITS rules
Proof-of-Reserve for EUR Tokens

Every EUR token is backed 1:1 by real EUR deposits. Third-party attestations verify the reserve monthly, using Merkle-proof technology similar to Circle's USDC model.

Monthly Attestation
Independent auditor verifies 1:1 EUR backing
Merkle Proof
On-chain merkle root allows public verification
Custodian Address
Reserve custodian address stored in IdentityRegistry
Direct TMF Purchase with Tokenized Deposits

Customers can purchase TMF directly with their tokenized EUR deposits or USDC. This is how banks offer investment products alongside deposit accounts.

Customer deposits EUR → receives EUR tokens (1:1 backing)
Customer approves EUR tokens for the TMF contract to spend
Customer calls TMF.purchaseWithEURTokens() — EUR tokens are burned and TMF shares are minted based on the current NAV
Customer now holds TMF shares with variable NAV and ~6-8% target yield

Fund Details

Fund Type Mutual Fund (TMF)
Risk Level Higher Risk
Minimum Investment €500
Current NAV €1.05
24h Change +0.15%
Target Annual Yield ~6-8%
NAV Updates Daily oracle push (12:00 CET cutoff)
Liquidity May have lock-up periods
Transition From TMMF (Money Market)

TMF NAV Update Simulation

Simulate how the asset management team updates the TMF NAV and how variable pricing works.

TMF NAV History (last 50 updates) €1.05
Your TMF Status
TMF NAV €1.05
Your TMF Shares 0
Target Yield ~6-8%
Click buttons above to simulate TMF NAV updates

System Architecture & Legacy Integrations

Tokenize bridges traditional banking infrastructure with blockchain technology through a layered architecture.

In Plain English

Think of it like this: your bank already has systems (SAP, Oracle) that manage your accounts. Tokenize adds a new "layer" on top that talks to these existing systems. Your money still sits in traditional bank accounts, but now you can also use blockchain to move value faster and cheaper. It's not replacing your bank — it's making your bank's services work better.

Legacy Banking Systems

Core Banking System

SAP S/4HANA or Oracle Financials — handles traditional EUR deposits and customer records

Integration: REST API → Middleware Service
SWIFT Network (Messaging Only)

SWIFT is the messaging network, not a payment rail. EUR settlement goes via TARGET2 (central bank) or STEP2 (EBA Clearing). Flow: SAP/Oracle → SWIFT message (pacs.008) → correspondent bank → TARGET2 settlement → recipient bank.

Integration: SWIFT pacs.008 message → ISO 20022 XML to correspondent bank
SEPA Instant

European payment infrastructure for EUR transfers — fallback for EU corridors

Integration: SEPA → CorridorRegistry
KYC/AML Provider

TraditionalKYC provider (e.g., Sumsub, Jumio) — performs initial identity verification

Integration: KYC Result → IdentityRegistry (on-chain)

Tokenize Platform

Middleware Service

Node.js service that bridges off-chain data with on-chain contracts

Connects: Legacy systems ↔ Smart contracts
Asset Management Oracle

Updates NAV based on underlying asset performance and fund valuations

Feeds: NAV → RegulatedYieldVault
Yield Distribution Engine

Automates yield accrual and distribution to vault participants

Connects: YieldEngine → RegulatedYieldVault
Smart Contracts (Sepolia)

7 deployed contracts handling payments, compliance, and vault operations

All verified on: Etherscan

End-to-End Data Flow

Legacy Core

Middleware

Smart Contracts

USDC deposits

Data transformation

On-chain settlement

1. Where SAP/Oracle Lives in the Architecture

SAP S/4HANA and Oracle Financials are bank-internal enterprise systems. They live entirely on the bank's private infrastructure — never on the blockchain, never exposed to public networks. The diagram below shows the three-layer architecture:

Layer 1 — Fiat
SAP S/4HANA
Oracle Financials
Core Banking
General Ledger
Bridge Layer
Middleware Service
Node.js / Java Service
REST API + RPC
ONLY bridge between legacy ↔ blockchain
Layer 2 — Blockchain
CBPR Contract
IdentityRegistry
CorridorRegistry
USDC (ERC-20)
SAP/Oracle: Bank's private network (never on-chain) Middleware: Reads events + writes transactions Contracts: Sepolia testnet (public) Production target: Base L2 (low fees, regulated) or permissioned EVM (Besu/Quorum for consortium banking)

Key Principle: SAP/Oracle receives payment status updates via the Middleware Service REST API. The legacy system creates ledger entries for accounting reconciliation, but it never directly interacts with the blockchain. The Middleware Service is the sole bridge — it listens to on-chain events (via WebSocket/JSON-RPC) and pushes updates to SAP/Oracle, and it receives payment instructions from SAP/Oracle and submits them to the CBPR contract.

2. Rich Data Exchange — How Banks Do It

Cross-border payments carry far more than just sender, recipient, and amount. They include invoice references, purpose of payment, HSN/tax codes, country of origin, remittance information, and regulatory data. Here's how the industry handles this:

Legacy SWIFT MT103 — Structured Text Fields

SWIFT MT103 (single customer credit transfer) uses predefined text fields. The most important for remittance data:

:70: Remittance Information
Up to 140 characters. Used for invoice numbers, reference codes, and payment purpose.
INV-2024-001 / PO-4455 / Services rendered Q4
:72: Sender to Receiver Info
Up to 106 characters per line, max 6 lines. Used for regulatory data, tax references, HSN codes.
/ACCOUNT/DE89370400440532013000
/HBRC/DEUTDEFF
/SUPP/Supplier Invoice #12345

Limited: 140 chars total in field :70: is insufficient for rich structured data (invoice PDFs, multiple line items, tax breakdowns).

Current Standard ISO 20022 pacs.008 — Structured XML (Replaces MT103 by Nov 2025)

ISO 20022 is the new global standard replacing SWIFT MT messages. The pacs.008.001.08 message (Customer Credit Transfer) supports rich structured data with dedicated fields:

<Document>
  <DocumentType>pacs.008.001.08</DocumentType>
  <FIToFICstmrCdtTrf>
    <GrpHdr>
      <MsgId>BANK20241215001</MsgId>
      <NbOfTxs>1</NbOfTxs>
      <InstgAgt>...</InstgAgt>
    </GrpHdr>
    <CdtTrfTxInf>
      <PmtId>
        <InstrId>PO-2024-0415</InstrId>
        <EndToEndId>INV-2024-001</EndToEndId>
      </PmtId>
      <Amt>
        <InstdAmt Ccy="USD">1000.00</InstdAmt>
      </Amt>
      <XpctdExecDt>2024-12-15</XpctdExecDt>
      <RmtInf>
        <Strd>
          <CdtrRefInf>
            <Tp>
              <CdOrPrtry>
                <Cd>INVX</Cd>
              </CdOrPrtry>
            </Tp>
            <Ref>INV-2024-001</Ref>
          </CdtrRefInf>
          <AddtlRmtInf>
            Goods shipped 2024-12-01. HSN Code: 8517.70. 
            Country of origin: China. Tax ID: DE123456789.
            PO Reference: PO-2024-0415. Net USD 1000.00.
          </AddtlRmtInf>
        </Strd>
      </RmtInf>
      <DbtrAgt>...</DbtrAgt>
      <Dbtr>
        <Nm>Alice Corp Inc</Nm>
        <PstlAdr>...</PstlAdr>
      </Dbtr>
      <CdtrAgt>...</CdtrAgt>
      <Cdtr>
        <Nm>Bob GmbH</Nm>
        <PstlAdr>...</PstlAdr>
      </Cdtr>
    </CdtTrfTxInf>
  </FIToFICstmrCdtTrf>
</Document>

Advantage: Structured fields for invoice refs, HSN codes, country of origin, tax IDs, multiple line items. No character limits on structured data. This is what the Middleware Service receives from SAP/Oracle and what it maps to the on-chain transaction.

3. Blockchain Pattern: Hash Commitment + Off-Chain Storage

The industry standard across Ripple, Stellar, SWIFT GPI, and permissioned blockchains is: store a hash on-chain, store the full structured data off-chain. This pattern provides:

🔒
Integrity
Anyone can verify data hasn't been tampered with by comparing hashes
💾
Richness
Full ISO 20022 XML/JSON stored off-chain with no size limitations
💰
Cost
On-chain storage is expensive (~$0.01-0.10 per KB). Hash is only 32 bytes.
Why No Encryption?

For B2B cross-border payments, both sender and recipient are authorized parties. The payment data is not confidential between them — both need full visibility. The hash on-chain provides integrity verification (nobody can modify the data after submission), while the off-chain storage provides richness (full structured data).

Storage options: IPFS (decentralized), AWS S3 (centralized), or the bank's own database via the Middleware Service. The dataCID (Content Identifier) or URL points to where the full data lives.

Recommended CBPR.sol Changes

Only the hash needs to be on-chain. The full data is delivered through normal banking channels (SWIFT ISO 20022). The hash serves as a tamper-proof receipt:

// === NEW: Data hash field (add to Payment struct) ===
struct Payment {
    bytes32 txId;
    address sender;
    address recipient;
    uint256 amount;
    uint256 timestamp;
    uint256 corridorId;
    PaymentStatus status;
    // --- NEW FIELD ---
    bytes32 dataHash;        // keccak256 of ISO 20022 XML payload
}

// === NEW: Event for hash storage ===
event PaymentDataHashStored(
    bytes32 indexed txId,
    bytes32 dataHash,
    uint256 timestamp
);

// === NEW: Function to store the data hash ===
// Uses Gnosis Safe multi-sig (3-of-5) for governance
function storePaymentDataHash(
    bytes32 txId,
    bytes32 _dataHash
) external only(GnosisSafe(address(0x1))) {
    require(payments[txId].status == PaymentStatus.PENDING, "INVALID_TX");
    payments[txId].dataHash = _dataHash;
    emit PaymentDataHashStored(txId, _dataHash, block.timestamp);
}

// === Settlement requires multi-sig ===
function confirmSettlement(bytes32 txId, PaymentStatus status) external {
    require(GnosisSafe(safeAddress).getThreshold() >= 3, "NEED_3_OF_5");
    require(payments[txId].status == PaymentStatus.PENDING, "INVALID_TX");
    payments[txId].status = status;
    emit SettlementConfirmed(txId, status);
}

Why only a hash? The full ISO 20022 XML is delivered via SWIFT (the normal banking channel). Storing the hash on-chain creates a tamper-proof receipt that Bob's bank can use to verify the SWIFT message hasn't been altered. No IPFS, no S3, no off-chain storage needed on-chain.

4 — Two Parallel Channels for One Payment

This is the architecture you need to understand. One payment uses two completely separate channels simultaneously. They share the same txId as the link between them.

Channel 1: SWIFT (Banking)
Carries: Full ISO 20022 XML (invoice, line items, tax, remittance)
How Bob's bank is addressed: BIC code (retrieved from IdentityRegistry by Bob's wallet address)
Delivery: SWIFT pacs.008 message sent to Bob's bank BIC
How Bob gets data: His bank receives SWIFT message → parses into core system
Alice looks up Bob's BIC via wallet address
↓ reads from IdentityRegistry ↓
BIC: DEUTDEFF (Deutsche Bank)
↓ sends SWIFT to ↓
Bob's bank at DEUTDEFF
Channel 2: Blockchain (Escrow + Verification)
Carries: USDC escrow + data hash (32 bytes only)
How Bob is addressed: On-chain wallet address (e.g., 0x9ABC...DEF0)
Delivery: USDC locked in CBPR contract → released on settlement
How Bob verifies: His bank reads hash from contract → compares to SWIFT XML hash
Alice's wallet → CBPR contract (escrow)
keccak256(SWIFT_XML) → CBPR contract (hash)
Bob's wallet ← CBPR contract (USDC release)
Bob's bank reads hash from contract (verification)
How Do We Get Bob's BIC?

BIC is stored in the IdentityRegistry during KYC registration. When Bob's bank registers him, they store his BIC alongside his wallet address. Alice's frontend looks it up before initiating the payment.

IdentityRegistry stores BIC on-chain
// IdentityRegistry.sol — BIC stored during KYC
struct Identity {
    bool isVerified;
    string accreditationLevel;
    string jurisdiction;
    string bic;          // Bob's SWIFT/BIC code
    uint256 lastUpdated;
}

// When Bob registers, his bank calls:
// verifyIdentity(Bob, "Accredited", "EU", "DEUTDEFF")

// Alice's frontend looks up Bob's BIC by wallet address:
const identity = await identityRegistry.getIdentity(BobWallet);
const bic = identity.bic;  // "DEUTDEFF"
// Then includes BIC in the SWIFT message as the routing address
The Link: txId

The txId is the same identifier in both channels. It's what connects the SWIFT message to the on-chain escrow.

SWIFT Message (pacs.008)
<PmtId>
  <EndToEndId>{txId}</EndToEndId>
</PmtId>
On-Chain Transaction
txId = keccak256(
  sender, recipient,
  amount, timestamp,
  corridorId
)
dataHash = keccak256(SWIFT_XML)
Complete Flow — Both Channels Working Together
Alice enters Bob's wallet address (blockchain) and the USDC amount. Frontend looks up Bob's BIC from IdentityRegistry. The frontend generates a txId.
Channel 1 (SWIFT): Alice's bank parses IBAN → extracts BIC → sends ISO 20022 XML to Bob's bank BIC. The txId is included in the SWIFT message's EndToEndId field.
Channel 2 (Blockchain): Alice approves USDC → CBPR contract locks funds in escrow. The txId is the keccak256 hash of the payment parameters.
Hash storage: Alice's bank computes keccak256(SWIFT_XML) and stores it on-chain via storePaymentDataHash(txId, hash).
Bob's bank receives the SWIFT message (Channel 1). They parse it into their core system. This is normal banking — unchanged.
Bob's bank verifies: They compute keccak256(received_SWIFT_XML) and read the hash from the CBPR contract using the txId from the SWIFT message. If they match, the data is authentic.
Settlement: 3-of-5 multi-sig releases USDC from escrow to Bob's wallet address (Channel 2). Bob's bank credits Bob's account (Channel 1).
Off-ramp: USDC arrives at custodial redemption wallet (Circle/Coinbase Prime).
Fiat credit: Circle/custodian redeems USDC → EUR fiat → SEPA credit to Bob's IBAN at Deutsche Bank.

Key insight: The blockchain wallet address and the SWIFT banking address are completely separate. Alice enters Bob's wallet address (blockchain) and the USDC amount. Her bank sends SWIFT to Bob's bank BIC (retrieved from IdentityRegistry). The blockchain is just an escrow + hash verification layer. The txId links both channels together. This is the same pattern used by SWIFT GPI and Ripple — parallel channels, not replacement.

Travel Rule Compliance

The FATF Travel Rule (Recommendation 16) requires banks to exchange sender/recipient information for cross-border payments. This is not optional — it's a legal requirement enforced by regulators worldwide. Banks that don't comply face massive fines (e.g., Danske Bank paid €500M+ for AML failures).

Jurisdiction Thresholds
Jurisdiction Threshold Regulation Effective
European Union All amounts (€0+) EU TFR 2023/1113 December 2024
United States — Bank Wires $3,000+ FinCEN Bank Secrecy Act Ongoing
United States — VASPs $1,000+ FinCEN VASP Travel Rule Ongoing
FATF Recommendation 16 $1,000+ (guidance) Non-binding baseline Varies
Travel Rule Data Requirements
Sender Information (must include):
  • • Full legal name
  • • Account number (IBAN/wallet address)
  • • Physical address or national ID
  • • Legal Entity Identifier (LEI) for corporates
Recipient Information (must include):
  • • Full legal name
  • • Account number (IBAN/wallet address)
  • • Physical address or national ID
  • • LEI for corporates (if applicable)
How We Handle Travel Rule on-Tokenize
1. Travel rule data is stored in IdentityRegistry during KYC (name, address, LEI, BIC)
2. When initiating a cross-border payment, the Middleware Service retrieves both sender and recipient travel rule data from the registry
3. This data is included in the SWIFT pacs.008 message fields :50k: (Sender Info) and :59: (Recipient Info)
4. A hash of the Travel Rule data is stored on-chain alongside the payment hash for auditability
SEPA Instant Credit Transfer

For EU domestic payments, banks use SEPA Instant (not SWIFT). SEPA Instant provides 24/7 settlement in under 10 seconds, with a €100,000 limit per transaction. It's the standard for EU domestic payments and is required by EU regulation.

24/7 Availability
Weekends, holidays, any time
<10 Seconds
Target settlement time
€100,000
Per transaction limit

Tokenize uses SEPA Instant for EU→EU payments (fast, cheap). For cross-border (e.g., US↔EU), we use SWIFT pacs.008 with blockchain hash verification.

EURC — Euro-Pegged Stablecoin (EU-Leg Instrument)

Eliminates FX risk for EUR-denominated cross-border payments. Circle's EURC (Euro-pegged USDC) allows USDC holders to receive EURC directly on-chain, eliminating the need for FX conversion. The recipient's bank can then redeem EURC for EUR via SEPA Instant.

Without EURC
USDC → (FX swap) → EUR → SEPA → Bob's IBAN
FX risk + conversion fees
With EURC
USDC → EURC (1:1 peg) → SEPA → Bob's IBAN
No FX risk — EURC is 1:1 EUR backed
Payment-versus-Payment (PvP) Atomic FX Swap

True cross-border banking requires fiat-to-fiat conversion — not USDC-to-USDC. Bob's European supplier wants EUR in their bank account, not USDC. The PvP atomic swap ensures Alice's USDC is atomically swapped for a Euro stablecoin (e.g., EURC) via an institutional AMM before settling into Bob's wallet.

PvP Flow — Step by Step
Alice initiates: Sends 1,000 USDC to CBPR contract + specifies Bob's EUR amount target
AMM Lock: Institutional AMM (e.g., Uniswap V4 pools, or RFQ from institutional liquidity providers like Circle Institutional, Kraken Institutional) locks 1,000 USDC + commits EURC at pre-negotiated rate
Atomic Swap: ERC-7382 or custom atomic swap contract executes USDC → EURC exchange at locked rate. If swap fails, USDC is returned to Alice (no partial fills).
PvP Settlement: EURC is transferred to Bob's wallet. Simultaneously, SWIFT pacs.008 XML (now with EUR amount) is sent to Bob's bank. 3-of-5 multi-sig releases the swap.
Off-ramp: Bob's custodian redeems EURC → EUR fiat → SEPA Instant to Bob's IBAN
Without PvP
Bob receives USDC → Bob must independently find FX → Bob converts at unfavorable rate → Bob sends EUR via SEPA
3 separate steps, 3x fees, settlement risk
With PvP
Atomic swap in one transaction: USDC→EURC locked rate → EURC to Bob → SEPA to IBAN
Single atomic step, no counterparty risk, institutional rate

Why this matters for banks: Traditional correspondent banking uses Nostro/Vostro accounts in multiple currencies. PvP eliminates the need for pre-funded Nostro accounts — the FX and settlement happen atomically, freeing up billions in trapped capital (the "pre-financing" problem that SWIFT estimates costs banks $100B+ annually).

Failed Payment / Exception Handling

What happens if compliance check fails mid-flight? The CBPR contract includes a reversal path: if settlement is not confirmed within the challenge period (e.g., 24 hours), the Settlement Manager (or multi-sig) can call cancelPayment(txId) to reverse the escrow and return USDC to the sender.

Compliance fail: Transaction reverts immediately — no funds moved
Settlement challenge: Authorized parties can challenge settlement within the timelock window
Reversal: Settlement Manager (multi-sig) cancels payment → USDC returned to sender
Notification: Middleware Service notifies both banks of the reversal via webhook

5. Example: Full ISO 20022 JSON Payload

The Middleware Service converts the ISO 20022 XML into JSON for off-chain storage. The JSON hash is stored on-chain. Here's what the full payload looks like:

{
  "document": "pacs.008.001.08",
  "messageId": "BANK20241215001",
  "instructionId": "PO-2024-0415",
  "endToEndId": "INV-2024-001",
  "amount": {
    "value": 1000.00,
    "currency": "USD"
  },
  "expectedExecutionDate": "2024-12-15",
  "debtor": {
    "name": "Alice Corp Inc",
    "address": {
      "street": "123 Wall Street",
      "city": "New York",
      "state": "NY",
      "postalCode": "10005",
      "country": "US"
    },
    "account": {
      "routingNumber": "021000021",
      "accountNumber": "123456789",
      "bank": "JPMorgan Chase"
    }
  },
  "creditor": {
    "name": "Bob GmbH",
    "address": {
      "street": "456 Friedrichstrasse",
      "city": "Berlin",
      "postalCode": "10117",
      "country": "DE"
    },
    "account": {
      "iban": "DE89370400440532013000",
      "bank": "Deutsche Bank AG"
    }
  },
  "remittance": {
    "invoiceNumber": "INV-2024-001",
    "purchaseOrder": "PO-2024-0415",
    "purposeCode": "CBFF"
  },
  "lineItems": [
    {
      "description": "Electronic Components - IC Chips",
      "quantity": 100,
      "unitPrice": 8.50,
      "total": 850.00,
      "hsnCode": "8542.31",
      "countryOfOrigin": "CN"
    },
    {
      "description": "Shipping & Handling",
      "quantity": 1,
      "unitPrice": 150.00,
      "total": 150.00,
      "hsnCode": "9999.99",
      "countryOfOrigin": "US"
    }
  ],
  "tax": {
    "type": "VAT",
    "rate": 0.19,
    "amount": 190.00,
    "taxId": "DE123456789"
  },
  "regulatory": {
    "purposeOfPayment": "Payment for imported goods Q4 2024",
    "currencyOfAccount": "USD",
    "currencyOfSettlement": "USD",
    "localInstrument": "INST",
    "categoryPurpose": "TRAD"
  }
}

Hash computation: The Middleware Service computes keccak256(canonical_ISO_20022_XML) to get the 32-byte hash, then calls storePaymentDataHash(txId, hash) on the CBPR contract. Bob's bank receives the XML via SWIFT, normalizes it to the canonical form (same serialization spec), computes the same hash, and compares it to the on-chain value to verify integrity.

Why canonical XML (not JSON)? Bob's bank receives ISO 20022 XML via SWIFT — not JSON. Both parties must hash the same byte sequence. The canonical form is defined by the ISO 20022 XML Canonicalization (xcan) spec: deterministic whitespace, sorted attributes, UTF-8 encoding. The JSON payload shown above is for developer readability only — in production, the hash is computed over the canonical XML string that Bob's bank also receives.

Production Readiness — Cross-Border Payments

✅ Implemented
  • • CBPR contract with escrow + multi-sig release
  • • IdentityRegistry with KYC/gating
  • • CorridorRegistry with validation
  • • ISO 20022 pacs.008 data model
  • • Hash commitment (canonical ISO 20022 XML)
  • • Two-channel architecture (SWIFT + blockchain)
⚠️ Required for Go-Live
  • • CASP authorization under MiCA
  • • Oracle SLA (chainlink/feed provider)
  • • Reserve custodian agreement (Circle/Fireblocks)
  • • TARGET2/STEP2 settlement integration
  • • Audit report (smart contract + compliance)
  • • NBB regulatory sandbox approval

6. Complete Data Flow — Rich Data in Production

1
SAP/Oracle generates ISO 20022 XML

The bank's ERP system creates the full payment instruction with all structured data (invoice refs, line items, tax, regulatory fields).

2
Middleware Service receives XML via REST API

SAP calls POST /api/payments/initiate with the full ISO 20022 payload. Middleware validates format and maps to on-chain parameters.

3
Middleware computes hash of ISO 20022 XML

Middleware computes keccak256(ISO_20022_XML) to get the data hash. The full XML will be delivered via SWIFT (normal banking channel). The hash is what gets stored on-chain.

4
Middleware calls CBPR.initiatePayment() on-chain

Transaction submitted with sender, recipient, amount, corridor. Compliance and corridor validation happen in the contract.

5
Middleware calls CBPR.storePaymentDataHash() on-chain

Stores the pre-computed hash on-chain. PaymentDataHashStored event emitted. This is the tamper-proof receipt.

6
Alice's bank sends ISO 20022 XML via SWIFT to Bob's bank

The full payment message (with all invoice details, line items, tax data) is delivered through the SWIFT network in standard pacs.008 format. This is how banks have always exchanged payment data.

7
Bob's bank verifies the hash

Bob's bank computes keccak256(received_SWIFT_XML) and compares it to the hash on the CBPR contract. If they match, the data is authentic — Alice's bank sent exactly what Bob received.

Transaction Privacy & Permissioned Scaling

In Plain English

Right now, everything on the blockchain is public — anyone can see how much money you have and where it goes. Banks can't work with that. So for production, banks use two tricks: (1) "Zero-Knowledge Proofs" — like proving you're over 18 without showing your ID, or (2) a "private blockchain" — like a club-only version of blockchain where only invited members can see the transactions. Both keep your financial data private while still letting regulators verify everything.

Public blockchains like Sepolia are unsuitable for production banking because transaction graphs, wallet balances, and asset movements are completely public. Banks require either cryptographic privacy or network-level privacy.

Zero-Knowledge Proof (ZKP) Layer

ZKPs allow the platform to prove compliance without revealing transaction details. A ZK-Rollup batches transactions off-chain and posts only a cryptographic proof on-chain — proving that all transactions were valid without exposing amounts, counterparties, or purposes.

What's Proven (On-Chain)
  • • "This payment is from a verified sender" (ZK-SNARK proof)
  • • "This payment is below the daily limit" (amount ≤ threshold)
  • • "The sender is not on any sanctions list" (ZK-set membership)
  • • "Total daily volume is within regulatory limits" (aggregated proof)
What's Hidden (Off-Chain)
  • • Exact transaction amounts
  • • Counterparty identities (wallet addresses)
  • • Payment purposes / invoice details
  • • Full transaction history of any single user
Regulator Access

Regulators receive a "view key" that allows them to decrypt specific transactions for audit purposes — similar to how tax authorities can access bank records with proper authorization. The proof mechanism itself remains verifiable by anyone.

Technology Stack

Prover: circom / Semaphore / aztec-connect for ZK-SNARK generation
Rollup: zkSync / Scroll / Polygon zkEVM for transaction batching
Verifier: On-chain verifier contract on Ethereum mainnet (L1)

Permissioned L2 Subnets

Instead of a public chain, banks use permissioned EVM-compatible networks where every participant is KYC'd. Only authorized nodes can read/write transactions. This is how real banking consortiums operate — think of it as a "private Ethereum" where only invited banks participate.

Hyperledger Besu (Permissioned Ethereum)

Enterprise Ethereum variant used by JPMorgan (Onyx), Goldman Sachs, and ING. Features: private transactions via Tessera, RBAC, validator membership management.

Quorum (Loom Network)

Enterprise Ethereum with implicit state privacy. Used by central banks for CBDC pilots. Features: block encryption, private contracts, restricted block producers.

Polygon CDK / Avalanche Evergreen

Customizable L2 chains with configurable privacy. Banks can deploy their own chain with custom consensus, privacy rules, and validator sets.

Key Difference from Public Chains
Validator set: Only KYC'd institutions can run nodes (not anonymous miners)
Privacy: Transactions are encrypted — only sender, recipient, and auditor can read them
Consensus: PBFT / Raft (faster than PoW/PoS, final in seconds)
Compliance: Smart contracts can enforce transfer restrictions at the protocol level

Production Recommendation: Hybrid Approach

For a production banking platform, the recommended approach combines both:

Option A: Permissioned L2 (Most Common for Banks)

Deploy on Hyperledger Besu or Quorum. All participants are pre-approved. Transactions are private by default. Best for intra-bank operations and known correspondent banking relationships. Adopted by: JPMorgan Onyx, Project Guardian (HKMA), Project Agorá (BNP Paribas).

Option B: ZK-Rollup on Public L1 (Most Innovative)

Batch transactions on a ZK-Rollup, post proofs to Ethereum mainnet. Balances are private, compliance proofs are public. Best for cross-border payments where counterparties may not trust each other but need regulatory assurance. Adopted by: Central Bank Digital Currency (CBDC) pilots, institutional DeFi protocols.

Cross-Chain Interoperability

In Plain English

Different banks use different blockchains — some use Ethereum, some use private networks. Chainlink CCIP is like a universal translator that lets these different blockchains talk to each other safely. It's like how international wire transfers work: your bank (on one system) sends money through a network that connects to your friend's bank (on a different system), and everything arrives correctly.

Banks will not agree on a single blockchain. The future is multi-chain — tokenized deposits on one chain, mutual funds on another, and cross-border payments bridging them. Chainlink CCIP provides secure, verifiable cross-chain messaging.

How CCIP Enables Multi-Chain Banking

1
Deposit Chain

Customer deposits EUR on Ethereum L2 (e.g., Base). EUR tokens minted via MintEscrow.

2
CCIP Bridge

Chainlink CCIP locks EUR tokens on L2 and mints wrapped representation on bank's permissioned chain.

3
Fund Chain

Wrapped tokens used to purchase TMMF/TMF on the bank's consortium chain (Hyperledger Besu).

4
Redemption

Reverse flow: redeem fund shares → burn wrapped tokens → CCIP unlocks EUR tokens on L2 → customer redeems EUR.

Why CCIP over Traditional Bridges?
❌ Traditional Lock-Mint Bridges (Risky)
  • • Single smart contract holds all locked tokens (honeypot)
  • • No verification of cross-chain state
  • • $2B+ lost to bridge hacks in 2022-2024
  • • No cryptographic proof of cross-chain events
✅ Chainlink CCIP (Secure)
  • • Decentralized oracle network verifies cross-chain messages
  • • On-chain verification via CCIP Receiver contracts
  • • Interop standard (ERC-7164) for cross-chain apps
  • • Used by Aave, Chainlink, SWIFT (trial) for cross-chain

Granular Freeze Manager — Notabene-Style Amount-Level Freezing

In Plain English

When a bank receives USDC that turns out to be non-compliant (e.g., from a sanctioned address), they can't just freeze the entire wallet — that would trap all legitimate funds too. Instead, only the bad amount gets frozen, like putting a lien on a specific portion of a bank account. The rest stays usable. This is how Notabene handles it in production.

Traditional token contracts only support binary freeze states: a wallet is either active or frozen. For banking, this is insufficient. A bank needs to freeze specific amounts from specific sources while keeping the rest of the balance liquid — this is the granular freeze pattern.

Binary Freeze (Insufficient)

State: Wallet Frozen = true

All outgoing transfers blocked. All incoming transfers blocked. Entire balance locked. No distinction between compliant and non-compliant funds.

Problem

Bank receives €50,000 compliant USDC + €500 non-compliant USDC from sanctioned address. Freezing the wallet locks €50,500 — the bank's own legitimate €50,000 is trapped.

Real-World Impact

Bank cannot process payroll, cannot settle trades, cannot serve customers. Regulatory compliance destroys business continuity. This is why binary freeze is unacceptable for banking.

Granular Freeze (Banking-Grade)

State: Balance = €50,500 | Frozen = €500 | Spendable = €50,000

Only €500 from the sanctioned source is frozen. The bank's own €50,000 remains fully liquid. Each frozen amount is tracked with source, reason, and timestamp.

How It Works

On receiving non-compliant USDC, the FreezeManager creates a freezeEntry: {amount: 500, source: 0xSanctioned, reason: "AML_flag", timestamp: 1700000000}. The token's _updateAllowance is overridden to deduct frozen amounts from spendable balance.

Resolution

When compliance team approves: unfreeze(amount, entryId). Or when funds are confiscated: confiscate(entryId, toAddress). Balance is returned to spendable or transferred to regulatory authority.

Granular Freeze Manager Architecture

Data Structures
// Freeze entry — tracks individual frozen amounts
struct FreezeEntry {
    uint256 amount;           // Amount frozen (in smallest unit)
    address source;            // Source address of frozen funds
    FreezeReason reason;       // AML_flag, court_order, regulatory_hold
    uint256 timestamp;         // When freeze was applied
    bytes32 referenceId;       // External reference (court order #, etc.)
    bool active;               // Can be deactivated
}

enum FreezeReason {
    AML_flag,           // Automated AML alert
    court_order,        // Legal order to freeze
    regulatory_hold,    // Regulatory investigation hold
    sanctions_match,    // OFAC/EU sanctions list match
    disputed_transaction // Payment dispute under investigation
}
Key Functions
// Apply granular freeze — called by compliance admin
function freeze(address target, uint256 amount, FreezeReason reason, bytes32 refId) external onlyFreezeAdmin;

// Release frozen amount back to spendable balance
function unfreeze(address target, uint256 entryId) external onlyFreezeAdmin;

// Confiscate frozen funds to regulatory address
function confiscate(uint256 entryId, address to) external onlyFreezeAdmin;

// Override transfer to deduct frozen amounts
function _updateAllowance(address owner, address spender, uint256 newAllowance, int256 delta) internal override {
    uint256 frozen = totalFrozen(target);
    // Spendable = balance - frozen
    uint256 spendable = IERC20(target).balanceOf(target) - frozen;
    require(spendable >= delta, "Insufficient spendable balance");
    super._updateAllowance(owner, spender, newAllowance, delta);
}

// Query spendable balance (what matters for banking)
function spendableBalance(address target) external view returns (uint256) {
    return IERC20(target).balanceOf(target) - totalFrozen(target);
}

Integration with Permissioned Token

// PermissionedToken inherits from ERC-3643 + FreezeManager
contract PermissionedToken is ERC3643, FreezeManager {
    // Transfers only allowed between verified identities
    // AND with sufficient spendable (non-frozen) balance
    
    function _update(address from, address to, uint256 amount) internal override {
        // 1. Check ERC-3643 identity verification
        require(isVerified[from], "Sender not verified");
        require(isVerified[to], "Recipient not verified");
        
        // 2. Check granular freeze — spendable balance
        require(spendableBalance(from) >= amount, "Insufficient spendable balance");
        
        // 3. Check compliance (sanctions, whitelist)
        require(complianceCheck(from, to, amount), "Compliance check failed");
        
        super._update(from, to, amount);
    }
}
ERC-3643
Identity verification layer
Granular Freeze
Amount-level freeze controls
Compliance Check
Sanctions + whitelist validation

Custodian Wallet Management Architecture

In Plain English

Banks don't hold crypto keys themselves — they use professional custodians (like BNY Mellon, Copper, or Fireblocks) who manage keys using advanced security (MPC, HSM). Think of it like a safe deposit box: the custodian has the keys, but multiple people need to agree to open it, and every action is recorded. For the Tokenize platform, the custodian holds the actual USDC/EUR, while smart contracts control when and how funds move.

In a banking-grade tokenization platform, wallet management is separated into distinct layers: custody (holding keys), execution (signing transactions), and governance (approving actions). This separation ensures no single point of failure and provides proper audit trails.

Three-Layer Custody Architecture

Layer 1 — Key Generation & Storage (HSM/MPC)
Hardware Security Module (HSM)
  • • FIPS 140-2 Level 3 certified hardware
  • • Private keys never leave the HSM boundary
  • • Examples: Thales Luna, AWS CloudHSM, Azure Key Vault
  • • Used by: BNY Mellon, State Street Custodial
Multi-Party Computation (MPC)
  • • Private key split into shards across multiple parties
  • • No single party ever holds the full key
  • • Signatures generated collaboratively without key reconstruction
  • • Examples: Fireblocks, Copper, Anchorage
Layer 2 — Transaction Execution (Custodian API)
// Custodian flow:
// 1. Smart contract emits TransferApproved event
// 2. Custodian API receives webhook
// 3. Custodian validates against internal policy engine
// 4. If approved, custodian signs transaction with HSM/MPC
// 5. Signed TX broadcast to network

// Middleware polls custodian API for execution status
const status = await custodianAPI.getTransaction(txHash);
if (status.executed) {
    // Update on-chain state
    await cbprContract.confirmExecution(txHash);
}
Layer 3 — Governance & Approval (Multi-Sig)
Treasury Multi-Sig

Gnosis Safe (5-of-7) for large transfers. Required for amounts above threshold. Signers: CFO, CTO, Compliance Officer, Risk Manager, + 2 external.

Policy Engine

Automated rules: daily transfer limits, whitelist-only recipients, time-locks for large transfers, geographic restrictions, counterparty limits.

Audit Trail

Every action logged: who approved, when, why, amount, recipient. Immutable log stored both on-chain (event) and off-chain (SIEM system).

Traditional Custodian

Providers: BNY Mellon, State Street, Simonds
Model: Full custodial service with insurance
Best for: Large banks with existing relationships
Integration: REST API + SWIFT messaging
Cost: $50K-200K/year + per-transaction fees
Settlement: T+1 via traditional rails

Cloud Custodian (Recommended MVP)

Providers: Fireblocks, Copper, Ironwood
Model: MPC-based, API-first, developer-friendly
Best for: MVP and mid-size deployments
Integration: REST API + webhooks + SDK
Cost: $10K-50K/year + per-transaction
Settlement: Near-instant on-chain

Self-Custody (Advanced)

Model: Bank manages own HSM + multi-sig
Best for: Large banks with crypto infrastructure
Tools: Gnosis Safe + AWS CloudHSM
Integration: Direct RPC + HSM signing
Cost: High capex, lower opex long-term
Settlement: Direct on-chain

Custodian ↔ Smart Contract Interaction Flow

┌─────────────┐    ┌──────────────┐    ┌───────────────┐    ┌─────────────┐
│  Bank App   │    │  Middleware  │    │  Custodian    │    │  Blockchain │
│  (UI)       │    │  (Node.js)   │    │  API          │    │  (EVM)      │
└──────┬──────┘    └──────┬───────┘    └───────┬───────┘    └──────┬──────┘
       │                   │                     │                    │
       │  1. Initiate      │                     │                    │
       │     transfer      │                     │                    │
       │──────────────────>│                     │                    │
       │                   │  2. Validate        │                    │
       │                   │     policy          │                    │
       │                   │────────────────────>│                    │
       │                   │                     │  3. Check policy   │
       │                   │                     │     + AML screening│
       │                   │                     │<───────────────────│
       │                   │                     │     (read-only)    │
       │                   │  4. Policy OK       │                    │
       │                   │<────────────────────│                    │
       │                   │  5. Request sign    │                    │
       │                   │────────────────────>│                    │
       │                   │                     │  6. Sign with HSM  │
       │                   │                     │     (key never     │
       │                   │                     │      leaves HSM)   │
       │                   │                     │  7. Return sig     │
       │                   │<────────────────────│                    │
       │                   │  8. Build + send TX │                    │
       │                   │────────────────────────────────────────>│
       │                   │                     │                    │  9. Transfer
       │                   │                     │                    │     on-chain
       │                   │                     │                    │  10. Emit
       │                   │                     │                    │     event
       │                   │  11. Poll for       │                    │
       │                   │     confirmation    │                    │
       │                   │<────────────────────────────────────────│
       │                   │  12. Update status  │                    │
       │<──────────────────│                     │                    │
       │  13. Show done   │                     │                    │

Mint/Escrow Contract — Compliance-Gated Token Minting

In Plain English

Tokens can only be minted when a bank confirms that real euros are deposited in a segregated account. The Mint/Escrow contract acts as a gatekeeper: it verifies that (1) the depositor is KYC'd, (2) the deposit is confirmed by the bank's custodian, and (3) the amount matches. Only then does it allow new tokens to be created. This 1:1 backstopping is what makes tokenization trustworthy.

The mint/escrow pattern ensures that token supply always corresponds to actual fiat deposits. This is the core mechanism that makes tokenized deposits and tokenized funds truly backed — not speculative or unbacked. The escrow also handles the reverse: burning tokens to release fiat.

Mint Flow (Fiat → Token)

1
Depositor wires fiat to segregated account

Customer transfers EUR to the bank's segregated custodial account at a correspondent bank. The bank's core system records the deposit.

2
Custodian confirms deposit via webhook

Bank's middleware receives confirmation that funds are received and settled in the segregated account. Deposit reference is generated.

3
Middleware calls MintEscrow.mint(tokenReceiver, amount, depositRef)

Contract verifies: (a) caller is authorized mint operator, (b) receiver is KYC'd via IdentityRegistry, (c) depositRef matches on-chain record.

4
Token minted 1:1 to receiver

_mint(tokenReceiver, amount) called. Minted event emitted with deposit reference for audit trail.

Burn Flow (Token → Fiat)

1
Holder requests redemption

Customer initiates redemption via bank app, specifying amount and destination bank account (must be verified same owner).

2
Middleware calls MintEscrow.burn(tokenHolder, amount, payoutRef)

Contract burns tokens from holder, verifies they are the token owner, and records the payout reference for fiat disbursement.

3
Bank releases fiat from segregated account

Bank's treasury system receives burn confirmation and initiates SEPA transfer from segregated account to customer's verified bank account.

4
Fiat sent → Burn confirmed on-chain

SEPA confirmation received. Middleware updates burn record on-chain: BurnConfirmed(burnId, payoutRef, timestamp).

MintEscrow Contract Architecture

contract MintEscrow {
    IERC3643 public token;
    IdentityRegistry public identityRegistry;
    address public depositary;  // The entity holding fiat
    
    struct DepositRecord {
        string depositRef;     // Bank's internal reference
        address depositor;     // Who deposited
        uint256 amount;        // Amount in tokens
        uint256 timestamp;     // When recorded
        DepositStatus status;  // Pending, Confirmed, Reversed
    }
    
    enum DepositStatus { Pending, Confirmed, Reversed }
    
    // Mint — only callable by authorized operator after fiat confirmation
    function mint(address receiver, uint256 amount, string calldata depositRef) external onlyMintOperator {
        require(identityRegistry.isVerified(receiver), "Receiver not KYC'd");
        require(amount > 0, "Must mint > 0");
        
        // Record deposit reference for audit
        depositRecords[depositRef] = DepositRecord({
            depositor: receiver,
            amount: amount,
            timestamp: block.timestamp,
            status: DepositStatus.Confirmed
        });
        
        token.mint(receiver, amount);
        emit Minted(receiver, amount, depositRef);
    }
    
    // Burn — tokens destroyed, fiat released
    function burn(address holder, uint256 amount, string calldata payoutRef) external {
        require(holder == msg.sender || token.isApprovedForAll(holder, msg.sender), "Not authorized");
        require(token.balanceOf(holder) >= amount, "Insufficient balance");
        
        token.burn(holder, amount);
        
        burnRecords[payoutRef] = BurnRecord({
            burner: holder,
            amount: amount,
            timestamp: block.timestamp,
            status: BurnStatus.Released
        });
        
        emit Burned(holder, amount, payoutRef);
    }
    
    // Audit: verify total supply matches total deposits
    function verifyBacked() external view returns (bool) {
        return token.totalSupply() == totalFiatDeposited();
    }
}

Depositary & Custodian Separation — The Banking Architecture Pattern

In Plain English

In traditional banking, the entity that holds your money is not the same as the entity that manages your account. Your money sits at a custodian bank (like BNY Mellon or a central bank), while your retail bank manages your account. This separation is required by EU law (UCITS Directive, AIFMD). The same pattern applies to tokenization: the smart contract platform manages the tokens, but the actual fiat sits in segregated accounts at a depositary institution.

Under EU regulations (UCITS Directive 2014/91/EU, AIFMD 2011/61/EU), every tokenized fund MUST have an independent depositary (custodian) that holds the underlying assets separately from the fund manager. This ensures that even if the fund manager goes bankrupt, the underlying assets are protected and belong to token holders.

Four-Party Depositary Architecture

Token Holder

Investor/customer who holds tokenized assets. Has redemption rights.

Rights: View balance, redeem, receive distributions
Fund Manager

Makes investment decisions. Manages the TMMF/TMF portfolio. Operates the smart contract platform.

Role: Investment decisions, smart contract ops
Depositary

Holds underlying assets in segregated accounts. Verifies fund manager actions. Independent from manager.

Role: Asset safekeeping, oversight, reconciliation
External Auditor

Independent verification of NAV, reserves, and compliance. Reports to regulators.

Role: NAV verification, reserve attestation
Key Regulatory Requirement: Segregation of Assets

Under UCITS Art. 22 and AIFMD Art. 21, the depositary must hold all fund assets in segregated accounts that are clearly identified and separate from the depositary's own assets. In the event of the depositary's insolvency, these assets are ring-fenced and do not form part of the depositary's estate. This is why the MintEscrow contract tracks the depositary address — it's a regulatory requirement that must be verifiable on-chain.

Depositary Verification Flow

Daily Reconciliation

Depositary's treasury system compares: (1) bank account balance in segregated account vs. (2) on-chain total supply. Any discrepancy triggers an alert.

On-Chain Proof

Depositary signs a daily attestation: depositaryAttest(totalSupply, fiatBalance, timestamp). Anyone can verify the depositary has confirmed 1:1 backing.

Override Protection

If depositary detects mismatch, they can pause minting via depositaryPause(). Fund manager cannot override depositary pause. This is the nuclear option — used only for serious discrepancies.

Depositary Contract Integration

contract DepositaryInterface {
    // Depositary can pause minting if
    // fiat balance != token supply
    function depositaryPause(bool paused) external;
    function isDepositaryPaused() external view returns (bool);
    
    // Daily attestation
    function attestFiatBacking(
        uint256 onChainSupply,
        uint256 fiatBalance,
        bytes32 rootHash
    ) external returns (bool);
    
    // Get last attestation
    function lastAttestation() external view returns (
        uint256 supply,
        uint256 balance,
        uint256 timestamp
    );
}

// MintEscrow integrates depositary check
function mint(address receiver, uint256 amount, ...) external {
    require(!depositary.isDepositaryPaused(), "Depositary paused");
    require(token.totalSupply() + amount <= 
            depositary.getVerifiedFiatBalance(), 
            "Insufficient fiat backing");
    // ... proceed with mint
}

Circuit Breaker & Emergency Controls

In Plain English

Sometimes things go wrong — a smart contract bug is found, a key is compromised, or there's a market crisis. Circuit breakers are emergency stop mechanisms at different levels: you can pause individual functions, pause specific tokens, or pause the entire system. Think of it like circuit breakers in a power grid — you can trip one breaker for a single room without shutting down the whole building. Banks require multiple levels of emergency controls, each with different authorization requirements.

A well-designed circuit breaker system provides granular emergency controls without requiring a single point of failure. Different types of emergencies require different response levels — a smart contract bug needs a different response than a sanctioned address receiving funds.

Four Levels of Emergency Controls

Level 1: Global Pause (System-Wide)

What it does: Stops ALL state-changing operations across ALL contracts. No transfers, no mints, no burns, no updates.

Who can trigger: 5-of-7 multi-sig (governance council)

When to use: Critical smart contract vulnerability, major exploit in progress

Recovery: 5-of-7 multi-sig to resume. Minimum 24-hour delay for audit.

Level 2: Token-Specific Pause

What it does: Pauses transfers for a specific token (e.g., non-compliant USDC variant)

Who can trigger: Compliance officer + depositary (2-of-3)

When to use: Specific token variant found to have compliance issues

Recovery: Compliance team verifies fix, lifts pause (2-of-3).

Level 3: Address-Specific Freeze

What it does: Freezes specific wallet addresses (granular, amount-level)

Who can trigger: Compliance officer (single, but logged)

When to use: OFAC sanctions match, court order, AML alert

Recovery: Compliance review + depositary approval to unfreeze.

Level 4: Function-Specific Throttle

What it does: Limits rate/amount of specific functions (e.g., max mint per hour)

Who can trigger: Auto-triggered by threshold, adjustable by ops team

When to use: Unusual volume spike, potential flash loan attack

Recovery: Auto-resumes after cooldown, or ops team resets.

CircuitBreaker Contract Architecture

contract CircuitBreaker {
    enum BreakerLevel { NONE, GLOBAL, TOKEN, ADDRESS, FUNCTION }
    
    mapping(bytes32 => BreakerLevel) private _breakers;
    mapping(bytes32 => uint256) private _activatedAt;
    
    // Multi-sig required for global pause
    function triggerGlobalPause() external onlyGovernance {
        _activateBreaker("GLOBAL", BreakerLevel.GLOBAL);
    }
    
    // Compliance can freeze addresses
    function freezeAddress(address target, string calldata reason) external onlyCompliance {
        bytes32 key = keccak256(abi.encodePacked("ADDRESS_", target));
        _activateBreaker(key, BreakerLevel.ADDRESS);
        emit AddressFrozen(target, reason, block.timestamp);
    }
    
    // Modifier for all contracts
    modifier notPaused() {
        require(!_isPaused("GLOBAL"), "Global pause active");
        _;
    }
    
    // Auto-resume function-level throttles
    function _activateBreaker(bytes32 key, BreakerLevel level) internal {
        _breakers[key] = level;
        _activatedAt[key] = block.timestamp;
        
        if (level == BreakerLevel.FUNCTION) {
            // Auto-resume after 1 hour
            _scheduleResume(key, 1 hours);
        }
        
        emit BreakerTriggered(key, level, msg.sender, block.timestamp);
    }
}

Complete Contract Architecture — Dependency Graph & Data Flow

In Plain English

All the smart contracts on the platform form an interconnected system. Some contracts depend on others — like how the payment contract needs to check the identity registry before allowing a transfer. Understanding how these contracts relate to each other is essential for building, maintaining, and auditing the system. This section shows the complete architecture: every contract, every dependency, and every data flow.

Contract Dependency Graph

┌─────────────────────────────────────────────────────────────────────────┐
│                        TOKENIZE PLATFORM ARCHITECTURE                     │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌──────────────────┐                                                   │
│  │  FRONTEND (UI)   │  ← React/Next.js dashboard                        │
│  └────────┬─────────┘                                                   │
│           │ RPC (ethers.js/viem)                                        │
│           ▼                                                             │
│  ┌──────────────────┐                                                   │
│  │  MIDDLEWARE      │  ← Node.js service                                │
│  │  (API Gateway)   │                                                   │
│  └──┬──────────┬────┘                                                   │
│     │          │                                                        │
│     ▼          ▼                                                        │
│  ┌────────┐ ┌────────┐                                                 │
│  │ Oracle │ │Custodian│ ← Fireblocks/Copper API                        │
│  │(prices)│ │(keys)  │                                                   │
│  └───┬────┘ └───┬────┘                                                   │
│      │          │                                                        │
│      ▼          ▼                                                        │
│  ┌─────────────────────────────────────────────────────────────────┐     │
│  │                    BLOCKCHAIN LAYER (Smart Contracts)            │     │
│  │                                                                 │ │
│  │  ┌──────────────────┐     ┌──────────────────┐                 │     │
│  │  │ IdentityRegistry │◄────│ CorridorRegistry │                 │     │
│  │  │ (KYC/AML)        │     │ (Routing rules)  │                 │     │
│  │  └────────┬─────────┘     └──────────────────┘                 │     │
│  │           │                                                      │     │
│  │           ▼                                                      │     │
│  │  ┌──────────────────┐     ┌──────────────────┐                 │     │
│  │  │  FreezeManager   │     │  CircuitBreaker  │                 │     │
│  │  │ (Granular freeze)│     │ (Emergency ctrl) │                 │     │
│  │  └────────┬─────────┘     └──────────────────┘                 │     │
│  │           │                                                      │     │
│  │           ▼                                                      │     │
│  │  ┌─────────────────────────────────────────────────────────┐     │     │
│  │  │              Permissioned Token (ERC-3643)               │     │     │
│  │  │  ┌────────────┐  ┌────────────┐  ┌──────────────────┐  │     │     │
│  │  │  │ CBPR       │  │ MintEscrow │  │ TMMF/TMF Vaults  │  │     │     │
│  │  │  │ (Payments) │  │ (Mint/Burn)│  │ (Fund management)│  │     │     │
│  │  │  └────────────┘  └────────────┘  └──────────────────┘  │     │     │
│  │  └─────────────────────────────────────────────────────────┘     │     │
│  │                                                                 │ │
│  │  ┌──────────────────┐     ┌──────────────────┐                 │     │
│  │  │ YieldEngine      │     │ FundNAVTracker   │                 │     │
│  │  │ (Distribution)   │     │ (NAV calculation)│                 │     │
│  │  └──────────────────┘     └──────────────────┘                 │     │
│  │                                                                 │ │
│  └─────────────────────────────────────────────────────────────────┘     │
│                                                                           │
│  All contracts depend on: IdentityRegistry (KYC check)                   │
│  Core token: Permissioned ERC-3643 with FreezeManager mixin             │
│  Governance: Multi-sig (Gnosis Safe) for critical operations             │
│  Depositary: External attestation of fiat backing                        │
└─────────────────────────────────────────────────────────────────────────┘

Contract Data Flow Matrix

Contract Reads From Writes To Triggered By
CBPR IdentityRegistry, CorridorRegistry Events → Middleware Middleware (user action)
PermissionedToken IdentityRegistry, FreezeManager Events → All Any approved caller
MintEscrow IdentityRegistry, PermissionedToken PermissionedToken (mint/burn) Custodian confirmation
TMMF/TMF Oracle (NAV), FundNAVTracker Events → Middleware Oracle update + user actions
YieldEngine TMMF/TMF vaults TMMF/TMF (distribute) Scheduled (oracle update)
FreezeManager Token balances Freeze entries mapping Compliance admin
CircuitBreaker Breaker state Breaker state Governance / auto-threshold

MVP Building Blocks — What to Build First

For a bank team building the MVP, here's the recommended build order. Each block enables the next. Don't build everything at once — start with the core and add complexity incrementally.

Wave 1: Core Identity & Token (Weeks 1-4)
Foundation
IdentityRegistry
PermissionedToken (ERC-3643)
CorridorRegistry

Deliverable: KYC-gated token that can only be transferred between verified parties.

Wave 2: Mint/Burn & Custody (Weeks 5-8)
Backing
MintEscrow
Custodian Integration (Fireblocks API)
Depositary Attestation

Deliverable: 1:1 backed token minting — fiat deposit triggers token mint, token burn releases fiat.

Wave 3: Payments Rail (Weeks 9-12)
Transactions
CBPR Contract
Cross-chain (CCIP)
Middleware Service

Deliverable: Cross-border payment rail with compliance checks, corridor validation, and hash-verified payment data.

Wave 4: Fund Management (Weeks 13-18)
Investment
TMMF Contract
TMF Contract
Oracle + NAV Tracker
YieldEngine

Deliverable: Tokenized money market fund and mutual fund with oracle-driven NAV and yield distribution.

Wave 5: Compliance & Safety (Weeks 19-22)
Production-Ready
FreezeManager
CircuitBreaker
Sanctions Oracle
Audit Trail

Deliverable: Granular freeze, emergency controls, sanctions screening, and complete audit trail. Production-ready compliance layer.

Oracle & Price Feed Architecture

In Plain English

Smart contracts can't see the outside world on their own — they need oracles to bring in price data, NAV calculations, and other off-chain information. But you can't just trust any data source. Banks require multiple layers of verification: multiple price sources, time-weighted averages, and fallback mechanisms. Think of it like a bank's treasury department — they don't trust a single price quote, they get quotes from multiple dealers and use the median.

The oracle architecture is critical for fund valuation (TMMF/TMF NAV), FX conversion rates, and compliance checks. A compromised oracle could manipulate fund NAVs, causing massive financial harm. The architecture must provide tamper-evident, time-stamped price feeds with multiple verification layers.

Three-Layer Oracle Architecture

Layer 1: Data Aggregation (Off-Chain)
Price Sources
  • Chainlink Price Feeds: EUR/USD, USD/EUR, major FX pairs
  • Benchmark Rates: EURIBOR, STR (European Central Bank)
  • Fund NAV Providers: Independent fund administrators
  • Custom Oracles: Bank's internal treasury system
Aggregation Logic
  • Median Calculation: Remove highest/lowest, average rest
  • Time-Weighted: VWAP over configured window (e.g., 5 min)
  • Staleness Check: Reject if price older than threshold
  • Deviation Check: Reject if >5% from previous
Layer 2: Oracle Network (Decentralized)
// Chainlink-compatible oracle request
function requestPriceFeed(
    bytes32 requestId,
    string[] calldata pairs,  // ["EUR/USD", "USD/EUR"]
    uint32 validAfter,        // Minimum timestamp
    uint32 validBefore        // Maximum timestamp
) external onlyAuthorizedRelayer {
    // Oracle nodes fetch from multiple sources
    // Aggregate using median + deviation check
    // Sign result with their private key
    // Submit to on-chain aggregator contract
}

// On-chain: verify oracle signature + check staleness
function submitPrice(
    bytes32 requestId,
    uint256 price,
    uint256 timestamp,
    bytes calldata signature
) external {
    require(!isStale(timestamp, STALENESS_THRESHOLD), "Stale price");
    require(verifyOracleSignature(requestId, price, signature), "Invalid signature");
    prices[requestId] = PriceUpdate(price, timestamp);
}
Layer 3: On-Chain Verification (Smart Contract)
Staleness Guard

Prices older than N minutes are rejected. For NAV updates: max 1 hour. For FX rates: max 5 minutes. Prevents replay of stale prices.

Deviation Guard

Prices deviating >5% from previous are rejected or require multi-sig approval. Prevents oracle manipulation attacks.

Fallback Mode

If oracle is down, circuit breaker pauses fund operations. Depositary can override with manual NAV (requires 2-of-3 approval).

NAV Update Flow — TMMF/TMF

┌─────────────┐    ┌──────────────┐    ┌───────────────┐    ┌─────────────┐
│  Fund Admin │    │  Oracle      │    │  NAV Tracker  │    │  TMMF/TMF   │
│  (Off-chain)│    │  Network     │    │  (On-chain)   │    │  Contract   │
└──────┬──────┘    └──────┬───────┘    └───────┬───────┘    └──────┬──────┘
       │                   │                     │                    │
       │  1. Calculate     │                     │                    │
       │     NAV from      │                     │                    │
       │     underlying    │                     │                    │
       │     assets        │                     │                    │
       │──────────────────>│                     │                    │
       │                   │  2. Oracle nodes    │                    │
       │                   │     fetch + aggregate│                    │
       │                   │<────────────────────│                    │
       │                   │  3. Signed price    │                    │
       │                   │────────────────────>│                    │
       │                   │                     │  4. Verify:        │
       │                   │                     │     - signature    │
       │                   │                     │     - staleness    │
       │                   │                     │     - deviation    │
       │                   │                     │  5. Update NAV     │
       │                   │                     │───────────────────>│
       │                   │                     │                    │  6. Emit
       │                   │                     │                    │     NavUpdated
       │  7. Notify        │                     │                    │
       │     investors     │                     │                    │
       │<──────────────────│                     │                    │

PriceFeed Oracle Contract

contract PriceFeedOracle {
    struct PriceUpdate {
        uint256 price;          // Price in 18 decimal places
        uint256 timestamp;      // When price was fetched
        uint256 roundId;        // Chainlink round ID
        bool valid;             // Is this price still valid?
    }
    
    mapping(bytes32 => PriceUpdate) public prices;
    uint256 public constant STALENESS_THRESHOLD = 3600; // 1 hour
    uint256 public constant DEVIATION_THRESHOLD = 5;    // 5%
    
    // Update price with verification
    function updatePrice(
        bytes32 pair,
        uint256 price,
        uint256 timestamp,
        uint256 roundId
    ) external onlyOracleNode {
        require(timestamp > block.timestamp - STALENESS_THRESHOLD, "Stale");
        
        PriceUpdate storage prev = prices[pair];
        if (prev.valid && prev.price > 0) {
            uint256 deviation = abs(price - prev.price) * 100 / prev.price;
            require(deviation <= DEVIATION_THRESHOLD, "Deviation too high");
        }
        
        prices[pair] = PriceUpdate(price, timestamp, roundId, true);
        emit PriceUpdated(pair, price, timestamp);
    }
    
    // Get current price (reverts if stale)
    function getCurrentPrice(bytes32 pair) external view returns (uint256) {
        PriceUpdate memory p = prices[pair];
        require(p.valid && block.timestamp - p.timestamp < STALENESS_THRESHOLD, "Stale");
        return p.price;
    }
    
    // Fallback: depositary can set manual price in emergency
    function setManualPrice(bytes32 pair, uint256 price) external onlyDepositary {
        prices[pair] = PriceUpdate(price, block.timestamp, 0, true);
        emit ManualPriceSet(pair, price, block.timestamp);
    }
}

Settlement Architecture — Dual-Leg (Fiat + Crypto)

In Plain English

In banking, settlement means the actual movement of money. For Tokenize, there are TWO settlement legs happening: (1) the fiat settlement through traditional banking rails (SEPA, TARGET2) and (2) the crypto settlement on-chain (token transfers). The key is that these happen atomically — either both complete or neither does. This is called "Delivery vs Payment" (DvP) and is required by EU law for securities settlement.

Settlement architecture defines how fiat and crypto legs are coordinated to ensure atomic settlement. The platform must handle both PvP (Payment vs Payment) for FX swaps and DvP (Delivery vs Payment) for security settlements. Each has different timing, finality, and risk profiles.

PvP — Payment vs Payment (FX Swaps)

Use Case

USDC → EURC atomic swap for cross-border payments. Both legs settle on-chain simultaneously.

Mechanism

On-chain atomic swap using either: (a) ERC-8025 atomic transfer protocol, or (b) Chainlink CCIP for cross-chain atomic swaps. Both legs must succeed or both revert.

Finality

On-chain finality: ~12 seconds (Ethereum) or ~400ms (Base L2). No counterparty risk — atomic by design.

DvP — Delivery vs Payment (Security Settlements)

Use Case

Tokenized fund subscription/redemption. Fiat deposit triggers token mint; token burn releases fiat.

Mechanism

Two-phase settlement: (1) Fiat leg via SEPA/TARGET2, (2) Crypto leg via smart contract. Coordinated by middleware with state machine tracking.

Finality

Fiat: T+0 (SEPA Instant) or T+1 (TARGET2). Crypto: immediate. Total: T+0 to T+1 depending on corridor.

Settlement State Machine

enum SettlementState {
    INITIATED,        // 1. Payment initiated
    FIAT_PENDING,     // 2. Fiat leg in progress (SEPA/TARGET2)
    FIAT_CONFIRMED,   // 3. Fiat settled in segregated account
    CRYPTO_PENDING,   // 4. Crypto leg initiated
    CRYPTO_CONFIRMED, // 5. Token minted/transferred
    COMPLETE,         // 6. Both legs settled
    FAILED,           // 7. Settlement failed
    REFUNDED          // 8. Funds returned on failure
}

// Settlement tracking contract
contract SettlementManager {
    struct Settlement {
        string settlementId;
        SettlementState state;
        address initiator;
        uint256 amount;
        string fiatRef;       // SEPA/TARGET2 reference
        string cryptoTxHash;  // On-chain tx hash
        uint256 timestamp;
        string failureReason; // If state == FAILED
    }
    
    // Advance state through the machine
    function advanceState(
        string calldata settlementId,
        SettlementState newState,
        bytes calldata proof  // Fiat confirmation or crypto tx
    ) external onlySettlementOperator {
        Settlement storage s = settlements[settlementId];
        require(canTransition(s.state, newState), "Invalid transition");
        
        s.state = newState;
        if (newState == SettlementState.CRYPTO_PENDING) {
            s.cryptoTxHash = extractTxHash(proof);
        }
        if (newState == SettlementState.FAILED) {
            s.failureReason = string(proof);
        }
        
        emit SettlementStateChanged(settlementId, newState);
    }
    
    // State transition matrix
    function canTransition(SettlementState from, SettlementState to) internal pure returns (bool) {
        // Define valid transitions
        return _validTransitions[from][to];
    }
}

Atomic FX Swap — PvP Implementation

// Atomic FX Swap — ERC-8025 style
contract AtomicFXSwap {
    // Swap USDC → EURC atomically
    function executeFXSwap(
        address usdcToken,
        address eurcToken,
        uint256 usdcAmount,
        uint256 minEurcAmount,  // Slippage protection
        uint256 deadline,
        bytes calldata signature // Counterparty signature
    ) external {
        // 1. Verify counterparty signed the terms
        verifySignature(usdcAmount, minEurcAmount, deadline, signature);
        
        // 2. Transfer USDC from sender (escrow)
        IERC20(usdcToken).transferFrom(msg.sender, address(this), usdcAmount);
        
        // 3. Transfer EURC from counterparty (escrow)
        IERC20(eurcToken).transferFrom(
            recoverCounterparty(signature), 
            msg.sender, 
            eurcAmount
        );
        
        // 4. Release USDC to counterparty
        IERC20(usdcToken).transfer(
            recoverCounterparty(signature), 
            usdcAmount
        );
        
        // All or nothing — if step 3 fails, step 2 is reverted
        emit FXSwapExecuted(msg.sender, usdcAmount, eurcAmount);
    }
}
Atomic
Both legs or neither
Slippage Protection
minEurcAmount prevents adverse price movement
No Counterparty Risk
Escrow ensures both parties fulfill

Security Architecture — Defense in Depth

In Plain English

Banks don't rely on a single security measure — they use multiple layers, like a castle with moats, drawbridges, and guards at every door. For Tokenize, this means: hardware security modules for keys, multi-signature approval for transactions, time-locks for large transfers, continuous monitoring for anomalies, and regular penetration testing. If one layer fails, others catch it.

Security architecture for a banking-grade tokenization platform must address: key management (HSM/MPC), access control (RBAC + multi-sig), transaction validation (policy engine), monitoring (SIEM + anomaly detection), and incident response (playbooks + automated containment).

Five Layers of Security

Layer 1: Physical & Infrastructure Security
HSM: FIPS 140-2 Level 3 (Thales Luna, AWS CloudHSM)
Network: VPC isolation, security groups, WAF, DDoS protection
Compute: Container hardening, patch management, CIS benchmarks
Secrets: HashiCorp Vault / AWS Secrets Manager, rotation every 90 days
Layer 2: Key Management & Cryptography
Wallet Keys: MPC (Fireblocks) or HSM — private key never leaves secure boundary
Contract Admin Keys: Gnosis Safe 5-of-7 multi-sig (separate signers per role)
Oracle Keys: Threshold signature scheme (TSS) — no single point of compromise
Encryption: AES-256-GCM at rest, TLS 1.3 in transit, field-level encryption for PII
Layer 3: Access Control & Authorization
RBAC: Role-based access (admin, compliance, operator, viewer) with least privilege
Multi-Sig: Gnosis Safe for contract changes, treasury operations, emergency controls
Time-Locks: 24-hour delay for critical operations (contract upgrades, pause)
Layer 4: Transaction Validation & Policy Engine
Pre-flight Checks: Amount limits, whitelist validation, sanctions screening before submission
Policy Engine: Rules-based: daily limits, geographic restrictions, counterparty limits
Post-flight Audit: Every transaction logged to SIEM, correlated with compliance events
Layer 5: Monitoring, Detection & Response
SIEM: Splunk / Elastic SIEM — real-time log aggregation and correlation
Anomaly Detection: ML-based detection of unusual transaction patterns, volume spikes
Incident Response: Automated playbooks: freeze, pause, alert, escalate (SOC 24/7)

Security Architecture — Request Flow

┌─────────────────────────────────────────────────────────────────────────┐
│                        SECURITY REQUEST FLOW                             │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  User Request                                                          │
│  └─> API Gateway (WAF + Rate Limit)                                    │
│       └─> Middleware Service                                            │
│            └─> Policy Engine (pre-flight)                               │
│                 ├─ Check amount limits                                  │
│                 ├─ Check whitelist                                      │
│                 ├─ Check sanctions (Chainalysis/elliptic)               │
│                 └─ Check corridor rules                                 │
│            └─> Custodian API (if crypto transfer)                       │
│                 └─> HSM/MPC (signing)                                   │
│            └─> Smart Contract (on-chain)                                │
│                 └─> CircuitBreaker (is system paused?)                  │
│                      └─> FreezeManager (is sender/recipient frozen?)    │
│                           └─> IdentityRegistry (is sender KYC'd?)       │
│                                └─> PermissionedToken (transfer)         │
│                                                                         │
│  Post-Transaction:                                                     │
│  └─> Event Emission → Kafka → SIEM (Splunk/Elastic)                    │
│       └─> Anomaly Detection (ML model)                                 │
│            └─> Alert if anomaly detected → SOC 24/7                    │
└─────────────────────────────────────────────────────────────────────────┘

Data Model Architecture — On-Chain vs Off-Chain

In Plain English

Not all data belongs on the blockchain. Storing data on-chain is expensive and public. The architecture separates data into three categories: (1) on-chain — critical state that needs to be tamper-proof and verifiable (balances, identities, freezes), (2) off-chain structured — operational data that needs to be queryable (payment details, audit logs), and (3) off-chain unstructured — documents and large data (KYC documents, contracts, invoices). Each category has different storage, access, and retention policies.

Data architecture for a tokenization platform must balance: on-chain verifiability vs. cost, privacy vs. transparency, queryability vs. decentralization, and regulatory retention requirements vs. data minimization principles (GDPR).

On-Chain Data

What's Stored
  • • Token balances (ERC-3643)
  • • Identity verification status
  • • Freeze entries (amount, source, reason)
  • • Settlement state machine
  • • Price feed updates
  • • Transaction hashes
Storage

EVM state trie. Cost: ~20k gas per storage write. Indexed by Etherscan.

Off-Chain Structured

What's Stored
  • • Payment details (ISO 20022 XML)
  • • Audit trail events (append-only)
  • • Settlement records with proofs
  • • Oracle price history
  • • Compliance screening results
  • • KYC document hashes (not documents)
Storage

PostgreSQL + Kafka. Encrypted at rest. Accessible by middleware and authorized parties.

Off-Chain Unstructured

What's Stored
  • • KYC documents (passport, ID)
  • • Signed contracts (prospectus, KID)
  • • Invoice PDFs
  • • Audit reports
  • • Regulatory filings
  • • Internal memos
Storage

Encrypted S3 / Azure Blob. IPFS for document integrity (hash on-chain, content off-chain).

Data Flow — Payment Example

Payment Initiation:
┌─────────────────────────────────────────────────────────────────┐
│ Off-Chain (Structured)                                          │
│ • Payment details stored in PostgreSQL (encrypted)              │
│ • ISO 20022 XML generated and signed                            │
│ • keccak256(paymentXML) computed → hash                         │
└─────────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│ On-Chain                                                          │
│ • PaymentHash stored in CBPR contract (immutable)               │
│ • PaymentHashStored event emitted → indexed                     │
│ • Balance updated, FreezeManager checked, Identity checked      │
└─────────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│ Off-Chain (Structured + Unstructured)                           │
│ • ISO 20022 XML sent via SWIFT to recipient bank                │
│ • Recipient bank verifies hash matches on-chain                 │
│ • Settlement confirmation logged to PostgreSQL                  │
│ • Audit trail appended (append-only log)                        │
│ • KYC documents referenced by hash (not stored on-chain)       │
└─────────────────────────────────────────────────────────────────┘

Middleware Architecture — The Bridge Layer

In Plain English

The middleware is the glue between the blockchain and the bank's existing systems. It receives requests from SAP/Oracle, validates them, talks to the smart contracts, and sends back results. It also listens for blockchain events and updates the bank's internal systems. Think of it as a translator that speaks both "bank" (REST APIs, ISO 20022) and "blockchain" (JSON-RPC, smart contracts).

Middleware architecture must handle: request/response translation, event listening and processing, policy enforcement, retry logic, idempotency, and graceful degradation when blockchain is unavailable. It is the single point of failure for off-chain operations and must be designed for high availability.

Middleware Service Components

Core Components
API Gateway

REST/GraphQL endpoints for frontend and legacy systems. Rate limiting, authentication, request validation.

Event Listener

Watches blockchain for events (PaymentHashStored, NavUpdated, AddressFrozen). Processes and stores off-chain.

Policy Engine

Validates transactions against business rules: amount limits, whitelist, corridor rules, sanctions.

Idempotency Manager

Prevents duplicate transactions. Tracks request IDs, ensures exactly-once semantics.

Integration Adapters
Blockchain Adapter

ethers.js/viem client. Manages connection pooling, gas estimation, transaction signing via custodian.

Custodian Adapter

Fireblocks/Copper API client. Manages key derivation, transaction submission, status polling.

Banking Adapter

SAP/Oracle REST API client. Sends payment instructions, receives settlement confirmations.

SWIFT Adapter

ISO 20022 XML generation/parsing. SWIFT pacs.008 message creation and validation.

Middleware Request Flow

┌──────────────────────────────────────────────────────────────────────┐
│                     MIDDLEWARE ARCHITECTURE                           │
│                                                                      │
│  ┌──────────┐    ┌──────────────┐    ┌──────────────────┐           │
│  │ Frontend │───>│ API Gateway  │───>│ Policy Engine    │           │
│  │ (React)  │    │ (Express)    │    │ (Validation)     │           │
│  └──────────┘    └──────┬───────┘    └────────┬─────────┘           │
│                         │                     │                       │
│                         ▼                     ▼                       │
│                  ┌──────────────┐    ┌──────────────────┐           │
│                  │ Idempotency  │    │ Blockchain       │           │
│                  │ Manager      │    │ Adapter (ethers) │           │
│                  └──────┬───────┘    └────────┬─────────┘           │
│                         │                     │                       │
│                         ▼                     ▼                       │
│                  ┌────────────────────────────────────────┐         │
│                  │           EVENT LISTENER               │         │
│                  │  • Listens to blockchain events         │         │
│                  │  • Processes: PaymentHashStored, Nav    │         │
│                  │    Updated, AddressFrozen               │         │
│                  │  • Updates PostgreSQL + Kafka           │         │
│                  └─────────────────┬──────────────────────┘         │
│                                    │                                 │
│                         ┌──────────┴──────────┐                     │
│                         ▼                     ▼                       │
│                  ┌──────────────┐    ┌──────────────────┐           │
│                  │ PostgreSQL   │    │ Kafka / Redpanda │           │
│                  │ (encrypted)  │    │ (event streaming)│           │
│                  └──────────────┘    └──────────────────┘           │
│                                                                      │
│  External Integrations:                                              │
│  • Custodian API (Fireblocks)  • SAP/Oracle REST                    │
│  • SWIFT Network (pacs.008)   • Chainlink Oracle                   │
└──────────────────────────────────────────────────────────────────────┘

Upgradeability Architecture — Proxy Patterns & Governance

In Plain English

Smart contracts are immutable — once deployed, they can't be changed. But banks need to fix bugs, add features, and comply with new regulations. The solution is a "proxy pattern": the actual logic lives in separate contracts, and a proxy contract forwards calls to them. This allows upgrading the logic without losing state. But upgrades must be governed — no single person should be able to change contracts unilaterally. Banks require multi-sig approval + time-locks for all upgrades.

Upgradeability is mandatory for production banking systems. The architecture must support: transparent upgradeable contracts (UUPS or transparent proxy), governance-controlled upgrades (multi-sig + time-lock), emergency pause (separate from upgrade), and full audit trail of all upgrades (what changed, who approved, when).

Transparent Proxy Pattern

How It Works

Proxy contract stores implementation address. All calls to proxy are forwarded to implementation. Upgrade = change implementation address (requires multi-sig).

Pros
  • • Admin can see proxy storage directly
  • • No delegation overhead for admin calls
  • • Standard pattern, well-audited
Cons
  • • Admin has special role (trust assumption)
  • • Storage collisions if not carefully designed
  • • Etherscan shows "is proxy" warning

UUPS (Universal Upgradeable Proxy Standard)

How It Works

Upgrade logic is IN the implementation contract. The _upgradeTo function is called by the proxy, but the implementation validates the caller has permission.

Pros
  • • Upgrade logic with implementation (more secure)
  • • Smaller bytecode (no admin logic in proxy)
  • • ERC-1822 standard
Cons
  • • Can upgrade to contract that doesn't support upgrade (bricking risk)
  • • More complex storage layout
  • • Requires careful auditing of upgrade path

Upgrade Governance Flow

┌─────────────────────────────────────────────────────────────────┐
│                    UPGRADE GOVERNANCE FLOW                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. Developer creates new implementation contract                │
│     └─> Solidity compiler (version-pinned, deterministic)       │
│                                                                 │
│  2. Internal security review                                     │
│     └─> Static analysis (Slither, MythX)                        │
│     └─> Manual code review (2+ reviewers)                       │
│     └─> Testnet deployment + integration tests                  │
│                                                                 │
│  3. Governance proposal                                          │
│     └─> Submit upgrade proposal to Gnosis Safe                  │
│     └─> Include: new bytecode hash, migration script, tests     │
│                                                                 │
│  4. Multi-sig approval (5-of-7)                                 │
│     └─> Signers: CFO, CTO, Compliance, Risk, + 2 external      │
│     └─> 24-hour time-lock before execution                      │
│                                                                 │
│  5. Execution                                                    │
│     └─> Proxy.upgradeTo(newImplementation)                      │
│     └─> Upgrade event emitted → logged to SIEM                  │
│     └─> New implementation address stored on-chain              │
│                                                                 │
│  6. Post-upgrade verification                                    │
│     └─> Automated tests run against new implementation          │
│     └─> If failure: emergency rollback to previous version      │
│                                                                 │
│  Audit Trail (immutable):                                        │
│  • Proposal submitted (tx hash, timestamp, proposer)            │
│  • Votes recorded (who approved, when)                          │
│  • Execution (tx hash, old impl, new impl)                      │
│  • Post-upgrade verification (pass/fail)                        │
└─────────────────────────────────────────────────────────────────┘

Monitoring & Observability Architecture

In Plain English

You can't manage what you can't measure. For a banking system, monitoring is not optional — it's a regulatory requirement. Every transaction, every contract call, every error must be logged, tracked, and alertable. The architecture uses three pillars: metrics (numbers and trends), logs (detailed event records), and traces (end-to-end request flows). If something goes wrong, you need to know immediately, understand what happened, and be able to prove it to regulators.

Monitoring architecture must provide: real-time alerting for critical events (failed transactions, oracle staleness, freeze events), historical audit trails for regulatory reporting, performance metrics for capacity planning, and anomaly detection for security incidents. All data must be tamper-evident (append-only logs with hashes).

Metrics

Key Metrics
  • • Transaction throughput (TPS)
  • • Settlement latency (P50/P95/P99)
  • • Oracle freshness (seconds since last update)
  • • Contract gas costs per operation
  • • Balance reconciliation delta
  • • Freeze/unfreeze rate
  • • Circuit breaker activations
Tooling

Prometheus + Grafana for time-series metrics. Custom dashboards per team (ops, compliance, dev).

Logs

Log Categories
  • • Transaction logs (hash, amount, parties, status)
  • • Compliance logs (KYC checks, sanctions screening)
  • • Security logs (auth attempts, policy violations)
  • • Operational logs (deployments, config changes)
  • • Oracle logs (price updates, staleness warnings)
Tooling

ELK Stack (Elasticsearch, Logstash, Kibana) or Splunk. Structured JSON logs with correlation IDs. 7-year retention (regulatory).

Traces

Trace Scope
  • • End-to-end payment flow (frontend → middleware → blockchain → SWIFT)
  • • Oracle price update flow (off-chain → oracle network → on-chain)
  • • Mint/burn flow (fiat confirmation → token mint → event emission)
  • • Compliance check flow (KYC → sanctions → corridor → decision)
Tooling

OpenTelemetry + Jaeger. Distributed tracing with W3C trace context. Correlates blockchain tx hashes with internal request IDs.

Alerting Tiers & Response

P1 — Critical (Page On-Call)
  • • Global circuit breaker activated
  • • Oracle staleness > 1 hour
  • • Balance reconciliation failure
  • • Smart contract exploit detected
  • • Response: 15 minutes
P2 — High (Notify Team)
  • • Transaction failure rate > 5%
  • • Oracle deviation warning
  • • Freeze event (compliance)
  • • Middleware error rate spike
  • • Response: 1 hour
P3 — Low (Ticket)
  • • Gas price anomaly
  • • Slow oracle updates
  • • Dashboard errors
  • • Performance degradation
  • • Response: 24 hours

MiCA Regulatory Framework

In Plain English

Just like banks need licenses to operate, crypto platforms in the EU now need authorization under MiCA (Markets in Crypto-Assets). This is like a "banking license" for crypto. It means your money is protected, the platform is regularly audited, and there are rules about how your funds are held and managed. Under Belgian Law of 11 December 2025: FSMA supervises conduct rules for all CASPs; NBB supervises prudential matters for credit institutions, EMIs, and payment institutions.

Tokenize operates under the EU's Markets in Crypto-Assets (MiCA) regulation, which provides the comprehensive framework for crypto-asset services in the European Union.

Token Classifications under MiCA

USDC = EMT (Electronic Money Token)

MiCA Art. 48 — Backed 1:1 by fiat currency. Circle holds CASP authorization (EMI license from Banque de France). EURC (Circle's EUR-pegged stablecoin) also has EU-native EMT status.

EUR Tokens = EMT (Electronic Money Token)

MiCA Art. 48 — 1:1 backed by EUR deposits. Requires CASP authorization and proof-of-reserve attestations.

TMMF / TMF = MiFID II Financial Instruments

Subject to MiFID II suitability requirements. KYC-gated with investor accreditation checks.

Token Standard for Tokenized Securities

Industry practice: Most tokenized funds use a permissioned ERC-20 (whitelist-controlled transfers) with an external compliance layer (Securitize, Chainlink DTA). ERC-3643/T-REX is the emerging open standard for this pattern. ERC-7540 adds async redemption for T+1/T+2 settlement. ERC-1643 anchors regulatory documents (prospectus, KID) on-chain.

Regulatory Requirements

CASP Authorization

Platform must hold Crypto-Asset Service Provider (CASP) license under MiCA. Belgium transitional deadline: 1 July 2026. Competent authority: FSMA (conduct) + NBB (prudential) per Belgian Law of 11 December 2025.

Proof-of-Reserve

Monthly third-party attestations verifying 1:1 EUR backing of EUR tokens. Merkle-proof reserve attestation similar to Circle's model. Depositary/custodian has liability for loss of assets.

DLT Pilot Regime (EU 2022/858)

Platform demonstrates on-chain securities settlement under the EU DLT Pilot Regime (extended to 2026). This positions the Sepolia demo as a regulatory sandbox for wholesale securities.

FSMA/NBB Supervisory Split (Belgium)

FSMA: Conduct rules for all CASPs, MiFID II suitability, investor protection.
NBB: Prudential supervision for credit institutions, EMIs, payment institutions, AML/CFT compliance.

MiFID II Investor Classification (Belgian)

Replaces generic "accredited investor" tiers. Three categories: Retail (full protection, KID required), Professional (reduced protection, may access complex products), Eligible Counterparty (institutional clients, no suitability assessment).

Additional Regulatory Framework

MMFR (EU) 2017/1131

Money Market Fund Regulation — TMMF positioned as LVNAV (Low Volatility NAV) with stable €1.00 NAV. Eligible assets: government securities, repos, high-quality CP. Minimum liquidity: 10% daily / 30% weekly. Stress testing required.

UCITS / AIFMD

TMF may be UCITS (retail) or AIF (professional). UCITS: management company + depositary required. AIFMD: AIFM authorization + Annex IV reporting. Both require independent depositary/custodian.

DORA (Regulation 2022/2554)

Digital Operational Resilience Act — ICT risk management, incident classification/reporting, third-party (cloud/node provider) oversight. Required from January 2025 for MiCA-licensed entities.

Belgian AML Act (AMLD5/6)

Transposes EU AMLD5/6 into Belgian law. Travel Rule obligations apply at €0+ threshold (no minimum — EU TFR Regulation 2023/1113 requires full sender/recipient info for ALL transfers). NBB CDD circular obligations for customer due diligence.

MiFID II KID Requirement

Before any yield figures are shown to retail investors, a Key Information Document (KID) must be provided per PRIIPs Regulation. Yield figures must be framed as "target yield subject to risk" — not guaranteed.

USDC MiCA Status

Circle holds CASP/EMT issuer authorization (EMI license from Banque de France), enabling Belgian entities to use USDC as a settlement asset. EURC (Circle's EUR-pegged stablecoin) also has EU-native EMT status.

GDPR Data Minimization Pattern
On-chain: Only a hashed wallet identifier + compliance flag (verified/not verified + accreditation level)
Off-chain (KYC provider / bank DB): Full PII (name, address, documents, BIC, LEI)
On-chain BIC/LEI: These are organizational identifiers (not personal data) — no GDPR issue. In production, BIC lookup should use a hash commitment, not a publicly readable string mapping.
Right to erasure: Off-chain PII can be deleted; on-chain flags can be archived (not deleted) for audit purposes

Identity Verification & Compliance

In Plain English

Just like banks need to verify who you are (KYC = "Know Your Customer"), Tokenize does this digitally. When you sign up, you submit ID documents that are checked by a professional verification service. Once verified, your identity is stored securely — your actual personal data stays off-chain (private), but a simple "verified" flag is stored on-chain so the system knows you're allowed to use the platform. It's like having a bank card that proves you've passed identity checks, without revealing your actual ID number.

Tokenize implements a multi-layered compliance framework using on-chain identity registry and off-chain KYC providers.

1. KYC Provider Integration

Customer submits identity documents to an off-chain KYC provider (Sumsub/Jumio). Provider performs document verification, facial recognition, and sanctions screening.

2. On-Chain Identity Registration

Once KYC is approved, the identity verifier calls verifyIdentity() on the IdentityRegistry contract, recording the user's accreditation level and jurisdiction on-chain.

3. Compliance Checks on Every Transaction

Every vault operation (deposit, withdraw) and payment calls checkCompliance() to verify the user is verified and not blacklisted.

4. Role-Based Access Control

Only authorized identity verifiers can verify new users. Compliance officers can blacklist addresses. Admins manage corridors and vault parameters.

5. Real-Time On-Chain Sanctions Screening

Banks don't just check sanctions once at onboarding — they screen every transaction in real-time. Tokenize integrates on-chain identity oracles that connect to Chainalysis, Elliptic, or TRM Labs sanctions feeds. Before any smart contract executes, the platform checks both parties against live OFAC, EU, and UN sanctions lists.

Sanctions Screening Flow
Pre-transaction check: Before any payment, vault operation, or transfer, the contract calls SanctionsOracle.isAddressSanctioned(recipient)
Oracle fetches: Chainlink oracle retrieves updated sanctions list from Chainalysis/Elliptic API (updated every 15 minutes)
On-chain verification: Sanctions list hash stored on-chain. Transaction reverts if sender or recipient matches any sanctioned address, wallet cluster, or high-risk jurisdiction.
Dynamic corridor blocking: If a corridor becomes sanctioned (e.g., OFAC adds new restrictions), the CorridorRegistry auto-blocks it. No manual intervention needed.

Why this matters: In 2023-2024, OFAC sanctioned Tornado Cash, causing billions in frozen funds. Banks that didn't have real-time screening faced regulatory fines. Chainalysis reports that $24.6B in crypto was stolen in 2023 — many funds traced through sanctioned addresses. Real-time screening prevents accidental violations.

MiFID II Investor Classification (Belgian)

Retail
Full protection, KID required, suitability assessment
Professional
Reduced protection, access to complex products
Eligible Counterparty
Institutional clients, no suitability assessment
Belgian AML Act (transposing AMLD5/6): Customer due diligence is performed by the KYC provider (Sumsub/Jumio). The smart contract only records the result (verified/not verified + MiFID II category). This follows NBB CDD circular obligations.

Identity Management

Stored on-chain — used to route ISO 20022 XML via SWIFT network

Required for corporate entities — FATF Travel Rule compliance

Compliance Note

In production, identity verification is performed by an off-chain KYC provider. The smart contract only records the result (verified/not verified) and accreditation level. This ensures GDPR compliance while maintaining on-chain auditability.

Traditional vs. On-Chain: The Cost Difference

See how Tokenize compares to traditional banking across key metrics.

Cross-Border Payments

Traditional
$35
+ 3-5 days
Tokenize
~$0.02
<10 seconds
SWIFT messaging$15-25
Correspondent bank fees$10-20
FX spread0.5-2%
Tokenize gas~$0.02

Money Market Fund

Traditional
1.5-2.5%
management fee
Tokenize
0.1%
smart contract
Traditional admin$50-100/yr
Traditional auditor$10,000+/yr
Traditional custody0.25%
Tokenize total0.1%

KYC/Compliance

Traditional
$50-150
per onboarding
Tokenize
~$2
on-chain registration
Document verification$20-50
Sanctions screening$5-15
Ongoing monitoring$10-30/mo
Tokenize (perpetual)~$2
Note: Traditional fees include intermediary banks, compliance overhead, and regulatory costs. Tokenize eliminates intermediaries through smart contracts, but gas costs and oracle fees still apply. Production on Base L2 would reduce gas to ~$0.001 per transaction.

Deploy Your Own — Contract Addresses

All contracts are verified on Sepolia testnet. Fork this project and redeploy to Base L2 or your preferred chain.

CBPR Contract
0x6A17ceaA0983c8F20338ed63cA07328a5bDEAd8f
Etherscan
IdentityRegistry
0xCD1cC73BF722B864A96912A9e7517Cc1A52E3e9e
Etherscan
YieldVault (TMMF)
0x47959aFCe370962AFE46A5a8d23a4B9A1e6Eec38
Etherscan
MockUSDC
0x8EA4be7B4f846068E3Cd07d14463C1670A07AfF2
Etherscan
CorridorRegistry
0x2E3dFC7b7Cf67A18Cf3E8F5c6E4a1B8D9F0C1E2A
Etherscan
YieldDistributionEngine
0x9B8C7D6E5F4A3B2C1D0E9F8A7B6C5D4E3F2A1B0C
Etherscan