MiCA-Artikel-Zuordnung

Vollständige Artikel-für-Artikel Code-Zuordnung der Verordnung (EU) 2023/1114 — Märkte für Krypto-Assets.

Quelle: Verordnung (EU) 2023/1114|In Kraft: 29. Juni 2023|Vollständig anwendbar: 30. Dezember 2024


Kurzreferenz — Wichtige Schwellenwerte und Fristen

Die wesentlichen MiCA-Zahlen, die jeder Implementierer kennen muss

ArtikelSchwellenwert / Frist
Art. 4(2)Ausnahme vom Whitepaper: ≤ 1 000 000 EUR in 12 Monaten
Art. 4(2)Ausnahme je Mitgliedstaat: < 150 Personen je Mitgliedstaat
Art. 8(5)Übermittlung des Whitepapers: ≥ 20 ARBEITSTAGE vor Veröffentlichung
Art. 10(1)Veröffentlichung des Angebotsergebnisses: innerhalb von 20 ARBEITSTAGEN nach Ende der Zeichnungsfrist
Art. 12(2)Geändertes Whitepaper: ≥ 7 ARBEITSTAGE vor Veröffentlichung übermittelt
Art. 13(1)Widerrufsfrist für Kleinanleger: 14 KALENDERTAGE
Art. 13(2)Erstattungsfrist: 14 TAGE ab der Widerrufsmitteilung
Art. 14(3)Annulliertes Angebot: Rückzahlung innerhalb von 25 KALENDERTAGEN
Art. 20(2)Prüfung des Zulassungsantrags eines ART-Emittenten: 60 ARBEITSTAGE
Art. 35(1)Mindesteigenmittel ART: 350 000 EUR
Art. 35(1)Eigenmittel ART: 2 % der durchschnittlichen Reserve über 6 Monate
Art. 45(5)Eigenmittel signifikanter ART: 3 % der durchschnittlichen Reserve
Art. 36(4)ART-Einlagen bei Kreditinstituten: ≥ 30 % je Referenzwährung
Art. 45(7)Einlagen signifikanter ART: ≥ 60 % je Referenzwährung
Art. 43Signifikante ART: ≥ 3 von 7 Kriterien
Art. 43Schwelle Inhaber: > 10 000 000
Art. 43Schwelle Wert: > 5 000 000 000 EUR
Art. 49(4)Rücktausch von EMT: jederzeit, zum Nennwert, gebührenfrei
Art. 51(11)Übermittlung des EMT-Whitepapers: ≥ 20 ARBEITSTAGE vor Veröffentlichung
Art. 54(a)Geldbeträge für EMT: ≥ 30 % bei Kreditinstituten hinterlegt
Art. 63(9)Prüfung des Zulassungsantrags eines Anbieters von Kryptowerte-Dienstleistungen: 40 ARBEITSTAGE
Art. 67(1)(a), Annex IVKlasse 1: 50 000 EUR
Art. 67(1)(a), Annex IVKlasse 2: 125 000 EUR
Art. 67(1)(a), Annex IVKlasse 3: 150 000 EUR
Art. 68(9)Aufbewahrung der Aufzeichnungen: 5 JAHRE
Art. 70(3)Kundengelder bis zum Ende des folgenden Geschäftstags bei einem Kreditinstitut oder einer Zentralbank platziert
Art. 75(5)Aufstellung der Positionen (Verwahrung): mindestens alle 3 MONATE
Art. 81(12)Überprüfung der Eignung: mindestens alle 2 JAHRE

Artikel-für-Artikel Zuordnung

Titel II — Andere Kryptowerte als ART oder EMT — Art. 4–15

Art. 4

Öffentliche Angebote von Kryptowerten

POC ansehen

Kryptowerte (außer ART oder EMT) darf in der Union nur öffentlich anbieten, wer eine juristische Person ist, ein Kryptowerte-Whitepaper erstellt, übermittelt und veröffentlicht hat und die Pflichten der Anbieter erfüllt — es sei denn, eine Ausnahme nach Art. 4(2) oder ein Ausschluss nach Art. 4(3) greift.

Pflichten
  • Der Anbieter muss eine juristische Person sein (Art. 4(1)(a))
  • Ein Kryptowerte-Whitepaper erstellen (Art. 6)
  • Das Whitepaper mindestens 20 ARBEITSTAGE vor der Veröffentlichung der zuständigen Behörde übermitteln (Art. 8(5))
  • Das Whitepaper auf der Website des Anbieters veröffentlichen (Art. 9)
  • Ausnahmen (Art. 4(2)): weniger als 150 Personen je Mitgliedstaat, höchstens 1 000 000 EUR in 12 Monaten oder ausschließlich qualifizierte Anleger
Wichtige Schwellenwerte

Ausnahmeschwelle (Art. 4(2)(b)): ≤ 1 000 000 EUR in 12 Monaten

Ausnahme je Mitgliedstaat (Art. 4(2)(a)): < 150 Personen je Mitgliedstaat

Übermittlung an die Behörde (Art. 8(5)): ≥ 20 ARBEITSTAGE vor Veröffentlichung

Art. 4 — TypeScript / ZodTypeScript
import { z } from "zod"

const TargetAudienceEnum = z.enum([
  "general_public",        // full Art. 4(1) requirements
  "limited_distribution",  // Art. 4(2)(a): < 150 persons per Member State
  "qualified_investors",   // Art. 4(2)(c): addressed to and holdable only by QIs
  "free_distribution",     // Art. 4(3)(a): Title II does not apply
  "mining_reward",         // Art. 4(3)(b)
  "existing_utility",      // Art. 4(3)(c): good or service exists or is in operation
  "limited_network",       // Art. 4(3)(d)
])

const OfferingDataSchema = z.object({
  offerorIsLegalEntity: z.boolean(),                          // Art. 4(1)(a)
  totalConsiderationEUR_12months: z.number().nonnegative(),   // Art. 4(2)(b): ≤ EUR 1,000,000
  targetAudience: TargetAudienceEnum,
  personsPerMemberState: z.number().int().nonnegative(),      // Art. 4(2)(a)
  holdingRestrictedToQualifiedInvestors: z.boolean(),         // Art. 4(2)(c)
  freeOfferAgainstDataOrFees: z.boolean(),  // Art. 4(3), second subparagraph: then not "free"
  utilityGoodOrServiceExists: z.boolean(),  // Art. 4(3)(c)
  intendsAdmissionToTrading: z.boolean(),   // Art. 4(4): no exemption applies
})

function checkOfferingEligibility(data: OfferingData, today: Date): {
  offerPermitted: boolean          // Art. 4(1)(a): legal persons only
  whitepaperRequired: boolean      // Art. 4(1)(b)–(d) unless Art. 4(2) or 4(3)
  exemptionBasis: string | null    // e.g. "Art. 4(2)(b)"
  earliestPublicationDate?: string // notified today + 20 working days (Art. 8(5))
  limitedNetworkNotificationRequired: boolean // Art. 4(3), third subparagraph
  violations: string[]
}
Art. 6

Inhalt und Form des Kryptowerte-Whitepapers (+ Anhang I)

Das Whitepaper muss die in Art. 6(1) und Anhang I genannten Informationen enthalten: Anbieter, Emittent und Betreiber der Handelsplattform, Projekt, Angebot, Kryptowert, Rechte und Pflichten, zugrunde liegende Technologie, Risiken sowie die wichtigsten nachteiligen Auswirkungen auf Klima und Umwelt.

Pflichten
  • Angaben zum Anbieter oder zur die Zulassung zum Handel beantragenden Person, zum Emittenten und zum Betreiber der Handelsplattform (Art. 6(1)(a)–(c); Anhang I, Teile A–C)
  • Angaben zum Kryptowerte-Projekt (Art. 6(1)(d); Anhang I, Teil D)
  • Angaben zum öffentlichen Angebot oder zur Zulassung zum Handel (Art. 6(1)(e); Anhang I, Teil E)
  • Angaben zum Kryptowert, zu Rechten und Pflichten und zur zugrunde liegenden Technologie (Art. 6(1)(f)–(h); Anhang I, Teile F–H)
  • Risiken (Art. 6(1)(i); Anhang I, Teil I)
  • Wichtigste nachteilige Auswirkungen des Konsensmechanismus auf Klima und Umwelt (Art. 6(1)(j))
  • Pflichterklärungen, u. a. dass das Whitepaper von keiner zuständigen Behörde genehmigt wurde (Art. 6(3)–(6))
  • Kurze Zusammenfassung in nicht fachsprachlicher Form (Art. 6(7))
Art. 6 — TypeScript / ZodTypeScript
import { z } from "zod"

const LEI_REGEX = /^[A-Z0-9]{18}[0-9]{2}$/

const IssuerSchema = z.object({
  legalName:        z.string().min(1),
  legalForm:        z.string().min(1),
  lei:              z.string().regex(LEI_REGEX).optional(),
  registeredAddress: z.object({
    street:  z.string(),
    city:    z.string(),
    country: z.string().length(2),
    postcode: z.string(),
  }),
  ncaNotified:      z.string().length(2),  // MS where NCA notified
  managementBody:   z.array(z.object({
    name:  z.string(),
    role:  z.string(),
    dob:   z.string().date().optional(),
  })).min(1),
  websiteUrl:       z.string().url(),
  financialStatements: z.string().url().optional(),
})

const ConsensusMechanismEnum = z.enum([
  "PoS", "PoW", "dPoS", "PoA", "DAG", "other"
])

const WhitePaperSchema = z.object({
  // Metadata
  version:         z.string().default("1.0"),
  language:        z.string().default("en"),
  publicationDate: z.string().datetime().optional(),
  documentHash:    z.string().length(64).optional(), // SHA-256 hex

  // Art. 6(1)(a)–(b); Annex I, Parts A–B
  offeror:  IssuerSchema,
  issuer:   IssuerSchema.optional(), // if different from the offeror

  // Art. 6(1)(d); Annex I, Part D — Project
  reasonForOffer:     z.string().min(50),
  useOfProceeds:      z.string().min(50),
  technologyDescription: z.string().min(100),

  // Art. 6(1)(f)–(h); Annex I, Parts F–H — Crypto-asset, rights, technology
  tokenName:          z.string().min(1),
  tokenSymbol:        z.string().max(10),
  tokenType:          z.enum(["utility", "payment", "other_crypto_asset"]),
  totalSupply:        z.number().positive(),
  issuanceSchedule:   z.string(),
  distributionPlan:   z.array(z.object({
    recipient:    z.string(),
    amount:       z.number(),
    vestingMonths: z.number().int().nonnegative(),
    percentage:   z.number().min(0).max(100),
  })),
  holderRights:       z.array(z.string()).min(1),
  holderObligations:  z.array(z.string()),
  transferable:       z.boolean(),
  dltProtocol:        z.string(),
  smartContractAddress: z.string().optional(),
  smartContractAuditUrl: z.string().url().optional(),

  // Art. 6(1)(i); Annex I, Part I — Risks
  risks: z.object({
    offerRisks:      z.array(z.string()).min(1), // Annex I, Part I, point 1
    issuerRisks:     z.array(z.string()),        // point 2 (if issuer ≠ offeror)
    cryptoAssetRisks: z.array(z.string()).min(1), // point 3
    projectRisks:    z.array(z.string()).min(1), // point 4
    technologyRisks: z.array(z.string()).min(1), // point 5, with mitigation measures
  }),

  // Art. 6(1)(j) — Climate and environment-related adverse impacts
  consensusMechanism: ConsensusMechanismEnum,
  climateImpactDisclosure: z.string().optional(),
  annualEnergyKWh:    z.number().nonnegative().optional(),
  carbonFootprintTons: z.number().nonnegative().optional(),
})

// Compliance validator
function validateWhitePaper(wp: WhitePaper): {
  valid: boolean
  missingFields: string[]
  warnings: string[]
} {
  const missing: string[] = []
  const warnings: string[] = []

  // Art. 6(1)(j) applies whatever the consensus mechanism
  if (!wp.climateImpactDisclosure) {
    missing.push("Principal adverse impacts on the climate of the consensus mechanism (Art. 6(1)(j))")
  }
  if (!wp.smartContractAuditUrl) {
    warnings.push("Smart contract audit URL recommended")
  }
  if (wp.distributionPlan.reduce((s, d) => s + d.percentage, 0) !== 100) {
    missing.push("Distribution plan percentages must sum to 100%")
  }
  return { valid: missing.length === 0, missingFields: missing, warnings }
}
Art. 13

Widerrufsrecht (Kleinanleger)

POC ansehen

Kleinanleger, die direkt beim Anbieter oder bei einem für ihn platzierenden Anbieter von Kryptowerte-Dienstleistungen kaufen, können innerhalb von 14 Kalendertagen ab ihrer Kaufvereinbarung widerrufen; alle Zahlungen werden innerhalb von 14 Tagen nach der Widerrufsmitteilung erstattet.

Pflichten
  • Widerruf innerhalb von 14 KALENDERTAGEN ab dem Tag der Kaufvereinbarung (Art. 13(1))
  • Ohne Gebühren, ohne Kosten und ohne Angabe von Gründen (Art. 13(1))
  • Alle Zahlungen einschließlich Entgelten innerhalb von 14 Tagen nach Kenntnis erstatten (Art. 13(2))
  • Im Whitepaper über das Widerrufsrecht informieren (Art. 13(3))
  • Gilt nicht, wenn die Kryptowerte vor dem Kauf bereits zum Handel zugelassen waren (Art. 13(4))
Wichtige Schwellenwerte

Widerrufsfrist: 14 KALENDERTAGE ab der Kaufvereinbarung

Erstattungsfrist: 14 TAGE ab der Widerrufsmitteilung

Art. 13 — TypeScript / ZodTypeScript
import { z } from "zod"
import { addDays } from "date-fns"

const PurchaseSchema = z.object({
  purchaseId:      z.string().uuid(),
  purchaserId:     z.string(),
  offeringId:      z.string(),
  purchaseDate:    z.string().datetime(),
  whitepaperPublicationDate: z.string().datetime(),
  amountEUR:       z.number().positive(),
  tokenAmount:     z.number().positive(),
  transactionCostEUR: z.number().nonnegative(),
  isRetailPurchaser: z.boolean(),
  admittedToTradingBeforePurchase: z.boolean(), // Art. 13(4) exclusion
})

function getWithdrawalDeadline(purchase: Purchase): Date {
  // Art. 13(1): 14 calendar days from the agreement to purchase
  return addDays(new Date(purchase.purchaseDate), 14)
}

function getRefundDeadline(withdrawalNoticeDate: Date): Date {
  // 14 calendar days from date offeror is informed (Art. 13(2))
  return addDays(withdrawalNoticeDate, 14)
}

const WithdrawalSchema = z.object({
  withdrawalId:    z.string().uuid(),
  purchaseId:      z.string().uuid(),
  noticeDate:      z.string().datetime(),
  deadline:        z.string().datetime(),
  refundDue:       z.number(), // amountEUR + transactionCostEUR
  refundDeadline:  z.string().datetime(),
  status:          z.enum(["open", "withdrawn", "deadline_passed", "refunded"]),
})

Titel III — Vermögenswertereferenzierte Token (ART) — Art. 16–47

Art. 35

Eigenmittelanforderungen für Emittenten von ART

POC ansehen

Emittenten von ART verfügen jederzeit über Eigenmittel in Höhe von mindestens dem höchsten der folgenden Beträge: 350 000 EUR, 2 % des durchschnittlichen Betrags der Vermögenswertreserve oder ein Viertel der fixen Gemeinkosten des Vorjahres. Für signifikante ART gelten 3 % (Art. 45(5)).

Pflichten
  • Eigenmittel ≥ MAX(350 000 EUR, 2 % der durchschnittlichen Reserve, ¼ der fixen Gemeinkosten) (Art. 35(1))
  • Signifikante ART (Art. 45(5)): 3 % statt 2 %
  • Eigenmittel aus Posten und Instrumenten des harten Kernkapitals (Art. 35(2))
  • Durchschnittliche Reserve = Beträge am Ende jedes Kalendertags über die vorangegangenen sechs Monate (Art. 35(1), Unterabsatz 2)
  • Die zuständige Behörde kann bis zu 20 % mehr als den Betrag nach Art. 35(1)(b) verlangen (Art. 35(3))
Wichtige Schwellenwerte

Mindestbetrag: 350 000 EUR

Standardsatz: 2 % der durchschnittlichen Reserve (6 Monate)

Satz für signifikante ART: 3 % der durchschnittlichen Reserve

Fixe Gemeinkosten (Art. 35(1)(c)): ¼ der fixen Gemeinkosten des Vorjahres

Art. 35 — TypeScript / ZodTypeScript
import { z } from "zod"

// Daily reserve snapshot for 6-month rolling average
const ReserveSnapshotSchema = z.object({
  date:           z.string().date(),
  totalReserveEUR: z.number().nonnegative(),
})

function calculateRequiredOwnFunds(
  dailySnapshots: ReserveSnapshot[],       // end of each calendar day, preceding 6 months
  isSignificant: boolean,
  fixedOverheadsPrecedingYearEUR: number
): {
  averageReserve: number
  percentageRequirement: number    // 2% (Art. 35(1)(b)) or 3% (Art. 45(5))
  calculatedRequirement: number    // avg * pct
  overheadRequirement: number      // ¼ of fixed overheads (Art. 35(1)(c))
  requiredOwnFunds: number         // highest of the three limbs
  breachThreshold: number          // POC early warning at 110% (not a MiCA value)
} {
  const avg = dailySnapshots.reduce((s, d) => s + d.totalReserveEUR, 0)
              / dailySnapshots.length
  const pct = isSignificant ? 0.03 : 0.02
  const calculated = avg * pct
  const overheads = fixedOverheadsPrecedingYearEUR / 4
  // Art. 35(1): at least the highest of (a) EUR 350,000, (b) and (c)
  const required = Math.max(350_000, calculated, overheads)
  return {
    averageReserve: avg,
    percentageRequirement: pct,
    calculatedRequirement: calculated,
    overheadRequirement: overheads,
    requiredOwnFunds: required,
    breachThreshold: required * 1.1,
  }
}
Art. 36–38

Vermögenswertreserve — Zusammensetzung, Verwahrung und Anlage

POC ansehen

Emittenten von ART halten eine rechtlich und operativ getrennte Vermögenswertreserve, bewertet zu Marktpreisen und mindestens in Höhe der Forderungen der Inhaber, verwahrt und nur in hochliquide Instrumente angelegt. Die Mindesteinlagen legen technische Regulierungsstandards der EBA innerhalb der in der Verordnung festgelegten Untergrenzen fest.

Pflichten
  • Eine Reserve bilden und halten, die die Risiken der referenzierten Vermögenswerte und die Liquiditätsrisiken des Rücktauschs abdeckt (Art. 36(1))
  • Rechtliche und operative Trennung vom Vermögen des Emittenten (Art. 36(2)–(3))
  • Einlagen bei Kreditinstituten ≥ 30 % des referenzierten Betrags je amtlicher Währung (Art. 36(4)(d)); ≥ 60 % für signifikante ART (Art. 45(7)(b))
  • Gesamtwert der Reserve ≥ Forderungen der Inhaber, zu Marktpreisen (Art. 36(7))
  • Verwahrung durch einen Anbieter von Kryptowerte-Dienstleistungen, ein Kreditinstitut oder eine Wertpapierfirma innerhalb von 5 Arbeitstagen nach der Ausgabe (Art. 37(3))
  • Konzentration bei Verwahrern und Reservevermögen vermeiden (Art. 37(1)(d)–(e))
  • Nur in hochliquide Finanzinstrumente mit minimalem Markt-, Kredit- und Konzentrationsrisiko anlegen (Art. 38(1))
  • Unabhängige Prüfung alle sechs Monate (Art. 36(9)); Veröffentlichung der Reservezusammensetzung mindestens monatlich (Art. 30(1))
Wichtige Schwellenwerte

Mindesteinlagen (Art. 36(4)(d)): ≥ 30 % je Referenzwährung

Mindesteinlagen, signifikante ART (Art. 45(7)(b)): ≥ 60 % je Referenzwährung

Verwahrungsfrist (Art. 37(3)): 5 ARBEITSTAGE nach der Ausgabe

Unabhängige Prüfung (Art. 36(9)): Alle 6 Monate

Art. 36–38 — TypeScript / ZodTypeScript
import { z } from "zod"

// Asset categories modelled by the POC. Art. 38(1) only allows highly liquid
// financial instruments specified by EBA RTS; the list below is a POC assumption.
const AssetCategoryEnum = z.enum([
  "deposit_credit_institution",  // counts towards Art. 36(4)(d) / 45(7)(b)
  "ucits_money_market_fund",
  "eu_government_bond",
  "central_bank_deposit",        // not a deposit in a credit institution
])

const ReserveAssetSchema = z.object({
  assetId:      z.string().uuid(),
  category:     AssetCategoryEnum,
  institution:  z.string(),
  currency:     z.string().length(3),  // ISO 4217
  marketValueEUR: z.number().nonnegative(), // market prices (Art. 36(7))
  custodian:    z.string(),            // Art. 37(3): CASP, credit institution or investment firm
  verifiedAt:   z.string().datetime(),
})

const ReserveStateSchema = z.object({
  snapshotDate:        z.string().datetime(),
  referenceCurrency:   z.string().length(3),
  holderClaimsEUR:     z.number().nonnegative(), // aggregate claims of holders (Art. 36(7))
  assets:              z.array(ReserveAssetSchema),
})

function validateReserveCompliance(state: ReserveState, isSignificant: boolean) {
  const total = state.assets.reduce((s, a) => s + a.marketValueEUR, 0)
  const deposits = state.assets
    .filter(a => a.category === "deposit_credit_institution" && a.currency === state.referenceCurrency)
    .reduce((s, a) => s + a.marketValueEUR, 0)
  // Floors: ≥ 30% (Art. 36(4)(d)), ≥ 60% for significant ARTs (Art. 45(7)(b));
  // the exact amounts are set by EBA RTS within these floors
  const minDeposits = isSignificant ? 0.60 : 0.30

  // Art. 37(1)(d)–(e): avoid concentration; 10% is an illustrative POC policy limit
  const byInstitution: Record<string, number> = {}
  state.assets.forEach(a => {
    byInstitution[a.institution] = (byInstitution[a.institution] || 0) + a.marketValueEUR
  })
  const maxConcentration = Math.max(...Object.values(byInstitution)) / total

  return {
    deposits_min:  { pass: deposits / total >= minDeposits, actual: deposits / total, required: minDeposits },
    concentration: { pass: maxConcentration <= 0.10, maxSingleInstitution: maxConcentration },
    // Art. 36(7): aggregate value at market prices ≥ aggregate claims of holders
    full_coverage: { pass: total >= state.holderClaimsEUR, coverageRatio: total / state.holderClaimsEUR },
  }
}
Art. 39–40

ART — Recht auf Rücktausch und Verbot der Gewährung von Zinsen

POC ansehen

Inhaber haben jederzeit ein Recht auf Rücktausch, erfüllt durch Zahlung eines Geldbetrags in Höhe des Marktwerts der referenzierten Vermögenswerte oder durch deren Lieferung, nach einer vom Emittenten festgelegten Rücktauschpolitik. Der Rücktausch ist gebührenfrei, und es dürfen keine Zinsen gewährt werden.

Pflichten
  • Recht auf Rücktausch JEDERZEIT gegenüber dem Emittenten (Art. 39(1))
  • Rücktausch in Geldbeträgen zum Marktwert der referenzierten Vermögenswerte oder durch deren Lieferung (Art. 39(2))
  • Die Rücktauschpolitik legt Bedingungen, Fristen und Zeitrahmen fest (Art. 39(2)(a)) — MiCA setzt keine Frist
  • Der Rücktausch ist gebührenfrei (Art. 39(3))
  • Emittenten und Anbieter von Kryptowerte-Dienstleistungen gewähren keine Zinsen, auch keine an die Haltedauer geknüpften Vorteile (Art. 40)
Wichtige Schwellenwerte

Rücktauschfrist: Laut Rücktauschpolitik des Emittenten (Art. 39(2)(a))

Rücktauschgebühr: Keine (Art. 39(3))

Zinsen / Rendite: VERBOTEN (Art. 40)

Art. 39–40 — TypeScript / ZodTypeScript
import { z } from "zod"
import { addBusinessDays } from "date-fns"

const ARTRedemptionSchema = z.object({
  requestId:       z.string().uuid(),
  holderId:        z.string(),
  tokenAmount:     z.number().positive(),
  requestedAt:     z.string().datetime(),
  mode:            z.enum(["reference_assets", "fiat_equivalent"]),
  destinationAccount: z.string(),
  marketValueEUR:  z.number().optional(),
  feeEUR:          z.number().nonnegative(), // Art. 39(3): 0, except a recovery-plan
                                             // liquidity fee under Art. 46(1)(a)
  netAmountEUR:    z.number().optional(),
  workingDayDeadline: z.string().datetime(),
  status:          z.enum([
    "pending",
    "processing",
    "completed",
    "rejected",
    "deadline_breached"
  ]),
})

function getARTRedemptionDeadline(requestDate: Date, policyWorkingDays: number): Date {
  // Timeframe defined in the issuer's redemption policy (Art. 39(2)(a))
  return addBusinessDays(requestDate, policyWorkingDays)
}

// Art. 40(3): any remuneration or benefit related to the holding period is interest,
// including net compensation or discounts with an equivalent effect
const InterestProhibitionSchema = z.object({
  tokenId:              z.string(),
  holderAddress:        z.string(),
  interestPaid:         z.literal(0),
  holdingPeriodBenefits: z.literal(0),
  equivalentDiscounts:  z.literal(0),
})

Titel IV — E-Geld-Token (EMT) — Art. 48–58

Art. 49

Ausgabe und Rücktauschbarkeit von E-Geld-Token

POC ansehen

EMT werden bei Entgegennahme eines Geldbetrags zum Nennwert ausgegeben und müssen auf Verlangen des Inhabers jederzeit und zum Nennwert in Geldbeträgen, die kein E-Geld sind, zurückgetauscht werden. Der Rücktausch ist gebührenfrei.

Pflichten
  • Inhaber haben eine Forderung gegenüber dem Emittenten (Art. 49(2))
  • Ausgabe ZUM NENNWERT bei Entgegennahme eines Geldbetrags (Art. 49(3))
  • Rücktausch JEDERZEIT und ZUM NENNWERT, in Geldbeträgen, die kein E-Geld sind (Art. 49(4))
  • Rücktauschbedingungen im Whitepaper deutlich angeben (Art. 49(5))
  • Der Rücktausch ist gebührenfrei (Art. 49(6))
  • Mindestens 30 % der entgegengenommenen Geldbeträge auf getrennten Konten bei Kreditinstituten (Art. 54(a))
Wichtige Schwellenwerte

Rücktauschzeitpunkt: Jederzeit (Art. 49(4)) — MiCA setzt keine Bearbeitungsfrist

Umtauschkurs: Nennwert (1:1)

Gebühren: Keine (Art. 49(6))

Einlagen bei Kreditinstituten (Art. 54(a)): ≥ 30 % der entgegengenommenen Geldbeträge

Art. 49 — TypeScript / ZodTypeScript
import { z } from "zod"
import { addBusinessDays, isAfter } from "date-fns"

const EMTRedemptionSchema = z.object({
  requestId:       z.string().uuid(),
  holderId:        z.string(),
  tokenAmount:     z.number().positive(),
  referenceCurrency: z.string().length(3),
  requestedAt:     z.string().datetime(),
  // PAR VALUE: 1 token = 1 unit of fiat
  parValuePerToken: z.literal(1),
  totalFiatAmount: z.number(), // = tokenAmount * 1
  feeEUR:          z.number().min(0).max(0), // Must be 0
  netAmount:       z.number(), // = totalFiatAmount (no deduction)
  destinationIBAN: z.string().regex(/^[A-Z]{2}[0-9]{2}[A-Z0-9]{4,30}$/),
  deadline:        z.string().datetime(), // issuer SLA (MiCA: "at any time")
  status:          z.enum([
    "pending",
    "processing",
    "completed",
    "sla_breached"
  ]),
})

function createEMTRedemption(
  tokenAmount: number,
  currency: string,
  requestDate: Date
): EMTRedemption {
  const deadline = addBusinessDays(requestDate, 1) // issuer policy, not a MiCA figure
  return {
    requestId: crypto.randomUUID(),
    tokenAmount,
    referenceCurrency: currency,
    parValuePerToken: 1,
    totalFiatAmount: tokenAmount * 1, // Par value
    feeEUR: 0,
    netAmount: tokenAmount, // Full amount, no fees
    deadline: deadline.toISOString(),
    status: "pending",
  }
}

function checkSLABreach(redemption: EMTRedemption): boolean {
  return redemption.status === "pending" && 
         isAfter(new Date(), new Date(redemption.deadline))
}
Art. 50

Verbot der Gewährung von Zinsen

POC ansehen

Weder Emittenten von EMT noch Anbieter von Kryptowerte-Dienstleistungen, die Dienstleistungen im Zusammenhang mit EMT erbringen, dürfen Zinsen gewähren. Jede an die Haltedauer geknüpfte Vergütung oder jeder sonstige Vorteil gilt als Zins.

Pflichten
  • VERBOTEN: Zinsgewährung durch Emittenten auf EMT (Art. 50(1))
  • VERBOTEN: Zinsgewährung durch Anbieter von Kryptowerte-Dienstleistungen im Zusammenhang mit EMT (Art. 50(2))
  • Jede an die Haltedauer geknüpfte Vergütung oder jeder sonstige Vorteil gilt als Zins (Art. 50(3))
  • Einschließlich Nettovergütungen oder Rabatten mit gleicher Wirkung, vom Emittenten oder von Dritten (Art. 50(3))
Wichtige Schwellenwerte

Zinsen / Rendite: VERBOTEN

Art. 50 — TypeScript / ZodTypeScript
import { z } from "zod"

// Art. 50(3): any remuneration or other benefit related to the length of time
// a holder holds the EMT is interest (incl. equivalent net compensation or discounts)
const EMTYieldComplianceSchema = z.object({
  tokenId:         z.string(),
  periodStart:     z.string().date(),
  periodEnd:       z.string().date(),
  interestPaid:           z.literal(0), // Art. 50(1) issuer, Art. 50(2) CASP
  holdingPeriodRewards:   z.literal(0), // Art. 50(3)
  equivalentCompensation: z.literal(0), // Art. 50(3): from the issuer or third parties
})

// Compliance check function
function validateArt50Compliance(
  tokenId: string,
  transactions: Transaction[]
): {
  compliant: boolean
  violations: string[]
} {
  const violations: string[] = []
  
  // Payments to holders computed from how long they held the EMT
  const yieldTransactions = transactions.filter(tx =>
    tx.type === "interest" ||
    (tx.type === "reward" && tx.basedOnHoldingPeriod) ||
    (tx.type === "discount" && tx.basedOnHoldingPeriod)
  )

  if (yieldTransactions.length > 0) {
    violations.push(
      `Art. 50 violation: ${yieldTransactions.length} yield-bearing transactions detected`
    )
  }

  return {
    compliant: violations.length === 0,
    violations,
  }
}

Titel V — Anbieter von Kryptowerte-Dienstleistungen (CASP) — Art. 59–85

Art. 67

Aufsichtsrechtliche Anforderungen an Anbieter von Kryptowerte-Dienstleistungen

POC ansehen

Anbieter von Kryptowerte-Dienstleistungen verfügen jederzeit über aufsichtsrechtliche Sicherheitsvorkehrungen in Höhe mindestens des höheren der beiden Beträge: des permanenten Mindestkapitals nach Anhang IV für ihre Dienstleistungen oder eines Viertels der fixen Gemeinkosten des Vorjahres — als Eigenmittel, Versicherungspolice oder beides.

Pflichten
  • Sicherheitsvorkehrungen ≥ MAX(Mindestkapital nach Anhang IV, ¼ der fixen Gemeinkosten des Vorjahres) (Art. 67(1))
  • Klasse 1 (50 000 EUR): Beratung, Portfolioverwaltung, Annahme und Übermittlung, Ausführung, Platzierung, Transfer
  • Klasse 2 (125 000 EUR): Dienstleistungen der Klasse 1 + Verwahrung, Tausch gegen Geldbeträge oder andere Kryptowerte
  • Klasse 3 (150 000 EUR): Dienstleistungen der Klasse 2 + Betrieb einer Handelsplattform
  • Form: CET1-Eigenmittel, Versicherungspolice oder eine Kombination (Art. 67(4))
Wichtige Schwellenwerte

Mindestbetrag Klasse 1 (Anhang IV): 50 000 EUR

Mindestbetrag Klasse 2 (Anhang IV): 125 000 EUR

Mindestbetrag Klasse 3 (Anhang IV): 150 000 EUR

Alternative Berechnung (Art. 67(1)(b)): ¼ der fixen Gemeinkosten des Vorjahres

Art. 67 — TypeScript / ZodTypeScript
import { z } from "zod"

const CASPServiceEnum = z.enum([
  // Class 1 — EUR 50,000 (Annex IV)
  "advice",
  "portfolio_management",
  "reception_transmission",
  "execution",
  "placing",
  "transfer",
  // Class 2 — EUR 125,000
  "exchange_fiat",
  "exchange_crypto",
  "custody",
  // Class 3 — EUR 150,000
  "trading_platform",
])

// Annex IV — permanent minimum capital (Art. 67(1)(a))
const TIER_MINIMUMS = {
  tier1: 50_000,
  tier2: 125_000,
  tier3: 150_000,
} as const

const SERVICE_TIERS: Record<z.infer<typeof CASPServiceEnum>, keyof typeof TIER_MINIMUMS> = {
  advice: "tier1",
  reception_transmission: "tier1",
  execution: "tier1",
  placing: "tier1",
  transfer: "tier1",
  portfolio_management: "tier1",
  exchange_fiat: "tier2",
  exchange_crypto: "tier2",
  custody: "tier2",
  trading_platform: "tier3",
}

function calculateCASPOwnFunds(
  services: z.infer<typeof CASPServiceEnum>[],
  annualFixedOverhead: number
): {
  highestTier: keyof typeof TIER_MINIMUMS
  tierMinimum: number
  quarterOverhead: number
  requiredOwnFunds: number
} {
  // Determine highest tier from selected services
  const tiers = services.map(s => SERVICE_TIERS[s])
  const highestTier = tiers.includes("tier3") ? "tier3"
    : tiers.includes("tier2") ? "tier2" : "tier1"

  const tierMinimum = TIER_MINIMUMS[highestTier]
  const quarterOverhead = annualFixedOverhead / 4 // Art. 67(1)(b)

  return {
    highestTier,
    tierMinimum,
    quarterOverhead,
    requiredOwnFunds: Math.max(tierMinimum, quarterOverhead),
  }
}
Art. 71

Beschwerdeverfahren

POC ansehen

Anbieter von Kryptowerte-Dienstleistungen unterhalten wirksame, transparente und kostenlose Beschwerdeverfahren, führen Aufzeichnungen über alle Beschwerden und prüfen diese zeitnah und fair. MiCA selbst setzt keine feste Frist; die nach Art. 71(5) erlassenen technischen Regulierungsstandards begrenzen sie auf 2 Monate ab Eingang der Beschwerde (Art. 6(2) der Delegierten Verordnung (EU) 2025/294).

Pflichten
  • Wirksame und transparente Beschwerdeverfahren festlegen und veröffentlichen (Art. 71(1))
  • KOSTENLOS für Kunden (Art. 71(2))
  • Kunden informieren, eine Beschwerdevorlage bereitstellen, alle Beschwerden und Maßnahmen aufzeichnen (Art. 71(3))
  • Zeitnah und fair prüfen; das Ergebnis innerhalb eines angemessenen Zeitraums mitteilen (Art. 71(4))
  • Die Entscheidung innerhalb von 2 MONATEN nach Eingang der Beschwerde mitteilen (Art. 6(2) der Delegierten Verordnung (EU) 2025/294)
  • Ist dies in Ausnahmefällen nicht möglich, den Kunden über die Gründe der Verzögerung und den Zeitpunkt der Entscheidung informieren (Art. 6(3) der Delegierten Verordnung (EU) 2025/294)
  • Aufzeichnungen über Dienstleistungen und Tätigkeiten 5 JAHRE aufbewahren (Art. 68(9))
Wichtige Schwellenwerte

Antwortfrist: „Angemessener Zeitraum“ (Art. 71(4)); keine feste Frist in MiCA selbst

Höchstfrist für die Entscheidung (RTS Beschwerden): 2 MONATE ab Eingang (Art. 6(2) der Delegierten Verordnung (EU) 2025/294)

Beispielhafte Service-Level (POC): 5 / 15 / 35 ARBEITSTAGE

Aufbewahrung (Art. 68(9)): 5 JAHRE

Art. 71 — TypeScript / ZodTypeScript
import { z } from "zod"
import { addBusinessDays, addMonths, differenceInBusinessDays, isAfter } from "date-fns"

const ComplaintSchema = z.object({
  complaintId:      z.string().uuid(),
  clientId:         z.string(),
  submittedAt:      z.string().datetime(),
  subject:          z.string().min(10),
  description:      z.string().min(50),
  // SLA tracking (internal policy — MiCA requires "timely" handling)
  ackDeadline:      z.string().datetime(), // +5 business days
  ackSentAt:        z.string().datetime().optional(),
  responseDeadline: z.string().datetime(), // +15 business days
  extendedDeadline: z.string().datetime().optional(), // +35 if extended, capped at decisionDeadline
  // Regulatory cap: decision within 2 months of receipt (RTS 2025/294)
  decisionDeadline: z.string().datetime(),
  extensionReason:  z.string().optional(),
  responseSentAt:   z.string().datetime().optional(),
  // Status
  status: z.enum([
    "received",
    "acknowledged",
    "under_review",
    "extended",
    "resolved",
    "sla_breached"
  ]),
  // Retention: 5 years (Art. 68(9))
  retentionUntil:   z.string().datetime().optional(),
})

function createComplaint(clientId: string, subject: string, description: string): Complaint {
  const now = new Date()
  return {
    complaintId: crypto.randomUUID(),
    clientId,
    submittedAt: now.toISOString(),
    subject,
    description,
    ackDeadline: addBusinessDays(now, 5).toISOString(),
    responseDeadline: addBusinessDays(now, 15).toISOString(),
    decisionDeadline: addMonths(now, 2).toISOString(),
    status: "received",
  }
}

function checkSLAStatus(complaint: Complaint): {
  ackOverdue: boolean
  responseOverdue: boolean
  decisionOverdue: boolean // inform the client of the reasons and the decision date
  daysUntilAck: number
  daysUntilResponse: number
} {
  const now = new Date()
  const ackDeadline = new Date(complaint.ackDeadline)
  const responseDeadline = new Date(
    complaint.extendedDeadline || complaint.responseDeadline
  )

  return {
    ackOverdue: !complaint.ackSentAt && isAfter(now, ackDeadline),
    responseOverdue: !complaint.responseSentAt && isAfter(now, responseDeadline),
    decisionOverdue:
      !complaint.responseSentAt && isAfter(now, new Date(complaint.decisionDeadline)),
    daysUntilAck: differenceInBusinessDays(ackDeadline, now),
    daysUntilResponse: differenceInBusinessDays(responseDeadline, now),
  }
}
Art. 81

Beurteilung der Eignung (Beratung und Portfolioverwaltung)

POC ansehen

Anbieter von Kryptowerte-Dienstleistungen, die Beratung oder Portfolioverwaltung erbringen, beurteilen die Eignung anhand der Kenntnisse und Erfahrungen des Kunden, seiner Anlageziele einschließlich Risikotoleranz und seiner finanziellen Verhältnisse einschließlich der Fähigkeit, Verluste zu tragen.

Pflichten
  • Vor der Dienstleistung die erforderlichen Informationen einholen (Art. 81(1), (8)):
  • (a) Kenntnisse und Erfahrungen mit Anlagen, auch in Kryptowerten
  • (b) Anlageziele einschließlich Risikotoleranz
  • (c) Finanzielle Verhältnisse einschließlich der Fähigkeit, Verluste zu tragen
  • Keine Empfehlung und keine Verwaltung, wenn die Dienstleistung nicht geeignet ist (Art. 81(11))
  • Die Eignung für jeden Kunden mindestens alle zwei Jahre überprüfen (Art. 81(12))
  • Bei Beratung einen Eignungsbericht in elektronischer Form bereitstellen (Art. 81(13))
Art. 81 — TypeScript / ZodTypeScript
import { z } from "zod"

const KnowledgeAssessmentSchema = z.object({
  yearsOfExperience: z.number().int().min(0),
  cryptoTypesTraded: z.array(z.enum([
    "bitcoin", "ethereum", "stablecoins", "defi", "nfts", "other"
  ])),
  understandsVolatility: z.boolean(),
  understandsPrivateKeys: z.boolean(),
  previousLosses: z.boolean(),
  selfAssessedLevel: z.enum(["novice", "intermediate", "advanced"]),
})

const FinancialSituationSchema = z.object({
  annualIncomeEUR: z.number().nonnegative(),
  liquidAssetsEUR: z.number().nonnegative(),
  totalLiabilitiesEUR: z.number().nonnegative(),
  monthlyExpensesEUR: z.number().nonnegative(),
  emergencyFundMonths: z.number().int().min(0),
  dependents: z.number().int().min(0),
})

const InvestmentObjectivesSchema = z.object({
  purpose: z.enum([
    "capital_growth",
    "income_generation",
    "speculation",
    "hedging",
    "diversification"
  ]),
  timeHorizon: z.enum([
    "less_than_1_year",
    "1_to_3_years",
    "3_to_5_years",
    "more_than_5_years"
  ]),
  riskTolerance: z.enum(["low", "medium", "high"]),
  maxPortfolioAllocation: z.number().min(0).max(100),
})

const LossCapacitySchema = z.object({
  maxAcceptableLossPct: z.number().min(0).max(100),
  canAffordTotalLoss: z.boolean(),
  impactOnLifestyle: z.enum(["none", "minor", "significant", "severe"]),
})

const SuitabilityAssessmentSchema = z.object({
  assessmentId:    z.string().uuid(),
  clientId:        z.string(),
  assessedAt:      z.string().datetime(),
  knowledge:       KnowledgeAssessmentSchema,
  financialSituation: FinancialSituationSchema,
  objectives:      InvestmentObjectivesSchema,
  lossCapacity:    LossCapacitySchema,
  suitabilityScore: z.number().min(0).max(100),
  recommendation:  z.enum(["suitable", "potentially_suitable", "not_suitable"]),
  warnings:        z.array(z.string()),
  nextReviewDue:   z.string().datetime(), // At least every two years (Art. 81(12))
})

function calculateSuitabilityScore(assessment: SuitabilityAssessment): number {
  let score = 50 // Base score

  // Knowledge adjustments
  if (assessment.knowledge.yearsOfExperience >= 3) score += 15
  if (assessment.knowledge.understandsVolatility) score += 10

  // Financial health adjustments
  const netWorth = assessment.financialSituation.liquidAssetsEUR 
    - assessment.financialSituation.totalLiabilitiesEUR
  if (netWorth > 100_000) score += 10
  if (assessment.financialSituation.emergencyFundMonths >= 6) score += 10

  // Risk tolerance alignment
  if (assessment.objectives.riskTolerance === "low") score -= 15
  if (assessment.lossCapacity.canAffordTotalLoss) score += 10

  return Math.max(0, Math.min(100, score))
}

Titel VI — Verhinderung und Verbot von Marktmissbrauch — Art. 86–92

Art. 89

Verbot von Insidergeschäften

POC ansehen

Niemand darf Insiderinformationen nutzen, um Kryptowerte zu erwerben oder zu veräußern, oder anderen dies empfehlen oder sie dazu verleiten. Insiderinformationen sind in Art. 87 definiert; die unrechtmäßige Offenlegung verbietet Art. 90.

Pflichten
  • VERBOTEN: Erwerb oder Veräußerung von Kryptowerten unter Nutzung von Insiderinformationen (Art. 89)
  • VERBOTEN: anderen auf Grundlage von Insiderinformationen Geschäfte empfehlen oder sie dazu verleiten (Art. 89)
  • VERBOTEN: unrechtmäßige Offenlegung von Insiderinformationen außerhalb der normalen Ausübung der Tätigkeit (Art. 90)
  • Insiderinformation = präzise, nicht öffentlich, geeignet, die Kurse erheblich zu beeinflussen (Art. 87)
  • Emittenten veröffentlichen Insiderinformationen so bald wie möglich (Art. 88)
Art. 89 — TypeScript / ZodTypeScript
import { z } from "zod"

const InsideInformationSchema = z.object({
  informationId:   z.string().uuid(),
  cryptoAssetId:   z.string(),
  description:     z.string().min(20),
  // Criteria for "inside information"
  isPrecise:       z.boolean(),     // Specific enough to conclude price effect
  isNonPublic:     z.boolean(),     // Not yet disclosed to market
  isPriceSensitive: z.boolean(),    // Would likely affect price if disclosed
  discoveredAt:    z.string().datetime(),
  disclosedAt:     z.string().datetime().optional(),
  source:          z.enum([
    "issuer_employee",
    "casp_employee",
    "advisor",
    "third_party",
    "technical_discovery"
  ]),
})

const InsiderTradeCheckSchema = z.object({
  tradeId:         z.string().uuid(),
  traderId:        z.string(),
  cryptoAssetId:   z.string(),
  tradeTimestamp:  z.string().datetime(),
  direction:       z.enum(["buy", "sell"]),
  amount:          z.number().positive(),
  // Compliance fields
  hadInsideInfo:   z.boolean(),
  insideInfoIds:   z.array(z.string().uuid()),
  complianceCheck: z.enum([
    "clear",           // No inside info
    "flagged",         // Potential violation
    "confirmed_breach" // Verified Art. 89 breach
  ]),
})

function checkInsiderTrade(
  trade: Trade,
  activeInsideInfo: InsideInformation[]
): {
  violation: boolean
  matchingInfo: InsideInformation[]
  recommendedAction: string
} {
  const matching = activeInsideInfo.filter(info =>
    info.cryptoAssetId === trade.cryptoAssetId &&
    info.isPrecise && info.isNonPublic && info.isPriceSensitive &&
    !info.disclosedAt // Still non-public
  )

  return {
    violation: matching.length > 0,
    matchingInfo: matching,
    recommendedAction: matching.length > 0
      ? "HALT_TRADE_AND_REPORT_TO_NCA"
      : "PROCEED",
  }
}
Art. 91

Verbot der Marktmanipulation

POC ansehen

Niemand darf Marktmanipulation betreiben oder dies versuchen: falsche oder irreführende Signale, Sicherung eines künstlichen Kursniveaus, Vorspiegelung falscher Tatsachen oder Verbreitung falscher Informationen (Art. 91(2)–(3)).

Pflichten
  • VERBOTEN: Geschäfte oder Aufträge mit falschen oder irreführenden Signalen, z. B. Scheingeschäfte (Wash Trading) (Art. 91(2)(a))
  • VERBOTEN: Kurse auf einem anormalen oder künstlichen Niveau sichern (Art. 91(2)(a))
  • VERBOTEN: fiktive Vorrichtungen oder sonstige Kunstgriffe oder Formen der Täuschung (Art. 91(2)(b))
  • VERBOTEN: Erteilen, Stornieren oder Ändern von Aufträgen, um falsche Signale zu setzen, z. B. Layering/Spoofing (Art. 91(3)(b))
  • VERBOTEN: falsche oder irreführende Informationen verbreiten, einschließlich Gerüchten (Art. 91(2)(c))
  • Wer beruflich Geschäfte vermittelt oder ausführt, muss Verdachtsfälle aufdecken und unverzüglich melden (Art. 92(1))
Art. 91 — TypeScript / ZodTypeScript
import { z } from "zod"

const ManipulationTypeEnum = z.enum([
  "wash_trading",
  "layering",
  "spoofing",
  "pump_and_dump",
  "coordinated_trading",
  "false_information",
])

const SuspiciousPatternSchema = z.object({
  patternId:       z.string().uuid(),
  detectedAt:      z.string().datetime(),
  cryptoAssetId:   z.string(),
  manipulationType: ManipulationTypeEnum,
  confidence:      z.number().min(0).max(1),
  indicators:      z.array(z.string()),
  involvedAddresses: z.array(z.string()),
  volumeAffected:  z.number().nonnegative(),
  priceImpactPct:  z.number(),
  status:          z.enum([
    "detected",
    "under_review",
    "confirmed",
    "dismissed",
    "reported_to_nca"
  ]),
})

// Wash trading detection
function detectWashTrading(
  trades: Trade[],
  timeWindowMinutes: number = 60
): SuspiciousPattern[] {
  const patterns: SuspiciousPattern[] = []
  
  // Group trades by address pairs
  const addressPairs = new Map<string, Trade[]>()
  trades.forEach(trade => {
    const key = [trade.fromAddress, trade.toAddress].sort().join("|")
    if (!addressPairs.has(key)) addressPairs.set(key, [])
    addressPairs.get(key)!.push(trade)
  })

  // Check for circular patterns
  addressPairs.forEach((pairTrades, key) => {
    if (pairTrades.length >= 3) {
      const buys = pairTrades.filter(t => t.direction === "buy")
      const sells = pairTrades.filter(t => t.direction === "sell")
      
      if (buys.length > 0 && sells.length > 0) {
        patterns.push({
          patternId: crypto.randomUUID(),
          detectedAt: new Date().toISOString(),
          cryptoAssetId: pairTrades[0].cryptoAssetId,
          manipulationType: "wash_trading",
          confidence: 0.8,
          indicators: [
            "Circular trading between same addresses",
            `${pairTrades.length} trades in ${timeWindowMinutes} minutes`,
          ],
          involvedAddresses: key.split("|"),
          volumeAffected: pairTrades.reduce((s, t) => s + t.amount, 0),
          priceImpactPct: 0,
          status: "detected",
        })
      }
    }
  })

  return patterns
}

Verordnung (EU) 2023/1114 — Verordnung über Märkte für Krypto-Assets (MiCA)

CELEX:32023R1114 · Unterlagen werden gemäß Art. 75 5 Jahre aufbewahrt · Vollständig anwendbar ab dem: 30. Dezember 2024