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
| Artikel | Schwellenwert / 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. 43 | Signifikante ART: ≥ 3 von 7 Kriterien |
| Art. 43 | Schwelle Inhaber: > 10 000 000 |
| Art. 43 | Schwelle 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 IV | Klasse 1: 50 000 EUR |
| Art. 67(1)(a), Annex IV | Klasse 2: 125 000 EUR |
| Art. 67(1)(a), Annex IV | Klasse 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
Öffentliche Angebote von Kryptowerten
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
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[]
}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))
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 }
}Widerrufsrecht (Kleinanleger)
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
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
Eigenmittelanforderungen für Emittenten von ART
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
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,
}
}Vermögenswertreserve — Zusammensetzung, Verwahrung und Anlage
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
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 — Recht auf Rücktausch und Verbot der Gewährung von Zinsen
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)
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
Ausgabe und Rücktauschbarkeit von E-Geld-Token
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
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))
}Verbot der Gewährung von Zinsen
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
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
Aufsichtsrechtliche Anforderungen an Anbieter von Kryptowerte-Dienstleistungen
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
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),
}
}Beschwerdeverfahren
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
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),
}
}Beurteilung der Eignung (Beratung und Portfolioverwaltung)
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))
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
Verbot von Insidergeschäften
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)
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",
}
}Verbot der Marktmanipulation
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))
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
}