Cartographie des articles MiCA

Cartographie complète article par article du Règlement (UE) 2023/1114 — Marchés de crypto-actifs.

Source : Règlement (UE) 2023/1114|En vigueur: 29 juin 2023|Entièrement applicable: 30 décembre 2024


Référence rapide — Seuils et délais clés

Les chiffres essentiels de MiCA que tout implémenteur doit connaître

ArticleSeuil / Délai
Art. 4(2)Exemption de livre blanc : ≤ 1 000 000 EUR sur 12 mois
Art. 4(2)Exemption par État membre : < 150 personnes par État membre
Art. 8(5)Notification du livre blanc : ≥ 20 JOURS OUVRABLES avant publication
Art. 10(1)Publication du résultat de l’offre : dans les 20 JOURS OUVRABLES suivant la fin de la souscription
Art. 12(2)Livre blanc modifié : notifié ≥ 7 JOURS OUVRABLES avant publication
Art. 13(1)Délai de rétractation des détenteurs de détail : 14 JOURS CALENDAIRES
Art. 13(2)Délai de remboursement : 14 JOURS à compter de la notification de la rétractation
Art. 14(3)Offre annulée : fonds restitués dans les 25 JOURS CALENDAIRES
Art. 20(2)Évaluation de l’agrément d’un émetteur d’ART : 60 JOURS OUVRABLES
Art. 35(1)Plancher de fonds propres ART : 350 000 EUR
Art. 35(1)Fonds propres ART : 2 % de la réserve moyenne sur 6 mois
Art. 45(5)Fonds propres ART d’importance significative : 3 % de la réserve moyenne
Art. 36(4)Dépôts ART auprès d’établissements de crédit : ≥ 30 % par monnaie de référence
Art. 45(7)Dépôts ART d’importance significative : ≥ 60 % par monnaie de référence
Art. 43ART d’importance significative : ≥ 3 critères sur 7
Art. 43Seuil de détenteurs : > 10 000 000
Art. 43Seuil de valeur : > 5 000 000 000 EUR
Art. 49(4)Remboursement EMT : à tout moment, au pair, sans frais
Art. 51(11)Notification du livre blanc EMT : ≥ 20 JOURS OUVRABLES avant publication
Art. 54(a)Fonds reçus pour des EMT : ≥ 30 % déposés auprès d’établissements de crédit
Art. 63(9)Évaluation de l’agrément d’un PSCA : 40 JOURS OUVRABLES
Art. 67(1)(a), Annex IVPSCA catégorie 1 : 50 000 EUR
Art. 67(1)(a), Annex IVPSCA catégorie 2 : 125 000 EUR
Art. 67(1)(a), Annex IVPSCA catégorie 3 : 150 000 EUR
Art. 68(9)Conservation des enregistrements des PSCA : 5 ANS
Art. 70(3)Fonds des clients placés auprès d’un établissement de crédit ou d’une banque centrale avant la fin du jour ouvrable suivant
Art. 75(5)Relevé de position (conservation) : au moins tous les 3 MOIS
Art. 81(12)Réexamen de l’adéquation : au moins tous les 2 ANS

Cartographie article par article

Titre II — Crypto-actifs autres que les ART et les EMT — Art. 4–15

Art. 4

Offre au public de crypto-actifs

Voir le POC

Une personne ne peut offrir au public dans l’Union des crypto-actifs (autres que des ART ou des EMT) que si elle est une personne morale, a rédigé, notifié et publié un livre blanc sur les crypto-actifs et respecte les obligations des offreurs — sauf exemption de l’art. 4(2) ou exclusion de l’art. 4(3).

Obligations
  • L’offreur doit être une personne morale (art. 4(1)(a))
  • Rédiger un livre blanc sur les crypto-actifs (art. 6)
  • Notifier le livre blanc à l’autorité compétente au moins 20 JOURS OUVRABLES avant sa publication (art. 8(5))
  • Publier le livre blanc sur le site internet de l’offreur (art. 9)
  • Exemptions (art. 4(2)) : moins de 150 personnes par État membre, 1 000 000 EUR au plus sur 12 mois, ou investisseurs qualifiés uniquement
Seuils clés

Seuil d’exemption (art. 4(2)(b)): ≤ 1 000 000 EUR sur 12 mois

Exemption par État membre (art. 4(2)(a)): < 150 personnes par État membre

Notification à l’autorité compétente (art. 8(5)): ≥ 20 JOURS OUVRABLES avant publication

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

Contenu et forme du livre blanc sur les crypto-actifs (+ annexe I)

Le livre blanc doit contenir les informations énumérées à l’art. 6(1) et à l’annexe I : offreur, émetteur et exploitant de la plate-forme de négociation, projet, offre, crypto-actif, droits et obligations, technologie sous-jacente, risques et principales incidences négatives sur le climat et l’environnement.

Obligations
  • Informations sur l’offreur ou la personne qui demande l’admission à la négociation, l’émetteur et l’exploitant de la plate-forme de négociation (art. 6(1)(a) à (c) ; annexe I, parties A à C)
  • Informations sur le projet de crypto-actif (art. 6(1)(d) ; annexe I, partie D)
  • Informations sur l’offre au public ou l’admission à la négociation (art. 6(1)(e) ; annexe I, partie E)
  • Informations sur le crypto-actif, les droits et obligations, la technologie sous-jacente (art. 6(1)(f) à (h) ; annexe I, parties F à H)
  • Risques (art. 6(1)(i) ; annexe I, partie I)
  • Principales incidences négatives du mécanisme de consensus sur le climat et l’environnement (art. 6(1)(j))
  • Déclarations obligatoires, notamment que le livre blanc n’a pas été approuvé par une autorité compétente (art. 6(3) à (6))
  • Résumé bref, en langage non technique (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

Droit de rétractation (détenteurs de détail)

Voir le POC

Les détenteurs de détail qui achètent directement auprès de l’offreur, ou auprès d’un PSCA qui place pour son compte, peuvent se rétracter dans un délai de 14 jours calendaires à compter de leur accord d’achat ; tous les paiements sont remboursés dans les 14 jours suivant la notification de la rétractation.

Obligations
  • Droit de rétractation dans un délai de 14 JOURS CALENDAIRES à compter de la date de l’accord d’achat (art. 13(1))
  • Sans frais, sans coûts et sans avoir à motiver sa décision (art. 13(1))
  • Rembourser tous les paiements, y compris les frais, dans les 14 jours suivant l’information (art. 13(2))
  • Informer sur le droit de rétractation dans le livre blanc (art. 13(3))
  • Inapplicable lorsque les crypto-actifs étaient admis à la négociation avant l’achat (art. 13(4))
Seuils clés

Délai de rétractation: 14 JOURS CALENDAIRES à compter de l’accord d’achat

Délai de remboursement: 14 JOURS à compter de la notification de la rétractation

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"]),
})

Titre III — Jetons se référant à un ou des actifs (ART) — Art. 16–47

Art. 35

Exigences de fonds propres des émetteurs d’ART

Voir le POC

Les émetteurs d’ART disposent à tout moment de fonds propres au moins égaux au plus élevé des montants suivants : 350 000 EUR, 2 % du montant moyen de la réserve d’actifs, ou un quart des frais généraux fixes de l’année précédente. Les ART d’importance significative appliquent 3 % (art. 45(5)).

Obligations
  • Fonds propres ≥ MAX(350 000 EUR, 2 % de la réserve moyenne, ¼ des frais généraux fixes) (art. 35(1))
  • ART d’importance significative (art. 45(5)) : 3 % au lieu de 2 %
  • Fonds propres constitués des éléments et instruments de fonds propres de base de catégorie 1 (art. 35(2))
  • Réserve moyenne = montants en fin de journée calendaire sur les six mois précédents (art. 35(1), deuxième alinéa)
  • L’autorité compétente peut exiger jusqu’à 20 % de plus que le montant de l’art. 35(1)(b) (art. 35(3))
Seuils clés

Plancher minimal: 350 000 EUR

Pourcentage standard: 2 % de la réserve moyenne (6 mois)

Pourcentage pour un ART d’importance significative: 3 % de la réserve moyenne

Frais généraux fixes (art. 35(1)(c)): ¼ des frais généraux fixes de l’année précédente

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

Réserve d’actifs — composition, conservation et investissement

Voir le POC

Les émetteurs d’ART maintiennent une réserve d’actifs juridiquement et opérationnellement séparée, évaluée aux prix de marché et au moins égale aux créances des détenteurs, conservée par un dépositaire et investie uniquement dans des instruments très liquides. Les niveaux minimaux de dépôts sont fixés par les normes techniques de réglementation de l’ABE, dans les limites prévues par le règlement.

Obligations
  • Constituer et maintenir une réserve couvrant les actifs de référence et les risques de liquidité liés au remboursement (art. 36(1))
  • Ségrégation juridique et opérationnelle par rapport au patrimoine de l’émetteur (art. 36(2) et (3))
  • Dépôts auprès d’établissements de crédit ≥ 30 % du montant référencé dans chaque monnaie officielle (art. 36(4)(d)) ; ≥ 60 % pour les ART d’importance significative (art. 45(7)(b))
  • Valeur totale de la réserve ≥ créances des détenteurs, aux prix de marché (art. 36(7))
  • Conservation par un PSCA, un établissement de crédit ou une entreprise d’investissement dans les 5 jours ouvrables suivant l’émission (art. 37(3))
  • Éviter la concentration des dépositaires et des actifs de réserve (art. 37(1)(d) et (e))
  • Investir uniquement dans des instruments financiers très liquides à risque de marché, de crédit et de concentration minimal (art. 38(1))
  • Audit indépendant tous les six mois (art. 36(9)) ; publication de la composition de la réserve au moins une fois par mois (art. 30(1))
Seuils clés

Dépôts minimaux (art. 36(4)(d)): ≥ 30 % par monnaie de référence

Dépôts minimaux, ART d’importance significative (art. 45(7)(b)): ≥ 60 % par monnaie de référence

Délai de conservation (art. 37(3)): 5 JOURS OUVRABLES après l’émission

Audit indépendant (art. 36(9)): Tous les 6 mois

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 — droit de remboursement et interdiction d’accorder des intérêts

Voir le POC

Les détenteurs disposent à tout moment d’un droit de remboursement, payé en fonds correspondant à la valeur de marché des actifs de référence ou par la livraison de ces actifs, selon une politique de remboursement fixée par l’émetteur. Le remboursement est gratuit et aucun intérêt ne peut être accordé.

Obligations
  • Droit de remboursement À TOUT MOMENT à l’égard de l’émetteur (art. 39(1))
  • Remboursement en fonds à la valeur de marché des actifs de référence, ou par livraison des actifs (art. 39(2))
  • La politique de remboursement fixe les conditions, périodes et délais (art. 39(2)(a)) — MiCA ne fixe aucun délai
  • Le remboursement n’est soumis à aucuns frais (art. 39(3))
  • Les émetteurs et les PSCA n’accordent pas d’intérêts, y compris sous forme d’avantages liés à la durée de détention (art. 40)
Seuils clés

Délai de remboursement: Fixé par la politique de remboursement de l’émetteur (art. 39(2)(a))

Frais de remboursement: Aucuns (art. 39(3))

Intérêts / rendement: INTERDITS (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),
})

Titre IV — Jetons de monnaie électronique (EMT) — Art. 48–58

Art. 49

Émission et possibilité de remboursement de jetons de monnaie électronique

Voir le POC

Les EMT sont émis au pair dès réception des fonds et doivent être remboursés à tout moment et au pair, en fonds autres que de la monnaie électronique, à la demande du détenteur. Le remboursement est gratuit.

Obligations
  • Les détenteurs disposent d’une créance sur l’émetteur (art. 49(2))
  • Émission AU PAIR dès réception des fonds (art. 49(3))
  • Remboursement À TOUT MOMENT et AU PAIR, en fonds autres que de la monnaie électronique (art. 49(4))
  • Indiquer clairement les conditions de remboursement dans le livre blanc (art. 49(5))
  • Le remboursement n’est soumis à aucuns frais (art. 49(6))
  • Au moins 30 % des fonds reçus déposés sur des comptes distincts auprès d’établissements de crédit (art. 54(a))
Seuils clés

Délai de remboursement: À tout moment (art. 49(4)) — MiCA ne fixe aucun délai de traitement

Taux de change: Au pair (1:1)

Frais: Aucuns (art. 49(6))

Dépôts auprès d’établissements de crédit (art. 54(a)): ≥ 30 % des fonds reçus

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

Interdiction de verser des intérêts

Voir le POC

Ni les émetteurs d’EMT ni les PSCA fournissant des services liés aux EMT ne peuvent accorder d’intérêts. Toute rémunération ou tout avantage lié à la durée de détention est considéré comme un intérêt.

Obligations
  • INTERDIT : intérêts accordés par l’émetteur sur des EMT (art. 50(1))
  • INTERDIT : intérêts accordés par un PSCA fournissant des services liés aux EMT (art. 50(2))
  • Toute rémunération ou tout avantage lié à la durée de détention est traité comme un intérêt (art. 50(3))
  • Y compris les compensations nettes ou remises ayant un effet équivalent, de l’émetteur ou de tiers (art. 50(3))
Seuils clés

Intérêts / rendement: INTERDITS

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,
  }
}

Titre V — Prestataires de services sur crypto-actifs (PSCA) — Art. 59–85

Art. 67

Exigences prudentielles des PSCA

Voir le POC

Les PSCA disposent à tout moment de garanties prudentielles au moins égales au plus élevé des montants suivants : le capital minimal permanent de l’annexe IV pour leurs services, ou un quart des frais généraux fixes de l’année précédente — sous forme de fonds propres, d’une police d’assurance, ou des deux.

Obligations
  • Garanties prudentielles ≥ MAX(minimum de l’annexe IV, ¼ des frais généraux fixes de l’année précédente) (art. 67(1))
  • Catégorie 1 (50 000 EUR) : conseil, gestion de portefeuille, réception et transmission, exécution, placement, transfert
  • Catégorie 2 (125 000 EUR) : services de catégorie 1 + conservation, échange contre des fonds ou d’autres crypto-actifs
  • Catégorie 3 (150 000 EUR) : services de catégorie 2 + exploitation d’une plate-forme de négociation
  • Forme : fonds propres CET1, police d’assurance, ou une combinaison des deux (art. 67(4))
Seuils clés

Minimum catégorie 1 (annexe IV): 50 000 EUR

Minimum catégorie 2 (annexe IV): 125 000 EUR

Minimum catégorie 3 (annexe IV): 150 000 EUR

Calcul alternatif (art. 67(1)(b)): ¼ des frais généraux fixes de l’année précédente

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

Procédures de traitement des réclamations

Voir le POC

Les PSCA mettent en place des procédures de réclamation efficaces, transparentes et gratuites, tiennent un registre de toutes les réclamations et les instruisent de manière diligente et équitable. MiCA ne fixe lui-même aucun délai ; les normes techniques de réglementation adoptées au titre de l’art. 71(5) le plafonnent à 2 mois à compter de la réception de la réclamation (art. 6(2) du règlement délégué (UE) 2025/294).

Obligations
  • Établir et publier des procédures de réclamation efficaces et transparentes (art. 71(1))
  • GRATUITES pour les clients (art. 71(2))
  • Informer les clients, fournir un modèle de réclamation, enregistrer toutes les réclamations et les mesures prises (art. 71(3))
  • Instruire de manière diligente et équitable ; communiquer le résultat dans un délai raisonnable (art. 71(4))
  • Communiquer la décision dans les 2 MOIS suivant la réception de la réclamation (art. 6(2) du règlement délégué (UE) 2025/294)
  • Dans les situations exceptionnelles où ce n’est pas possible, informer le client des raisons du retard et de la date de la décision (art. 6(3) du règlement délégué (UE) 2025/294)
  • Conserver les enregistrements des services et activités pendant 5 ANS (art. 68(9))
Seuils clés

Délai de réponse: « Délai raisonnable » (art. 71(4)) ; aucun délai fixe dans MiCA lui-même

Délai maximal de décision (NTR réclamations): 2 MOIS à compter de la réception (art. 6(2) du règlement délégué (UE) 2025/294)

SLA indicatif (POC): 5 / 15 / 35 JOURS OUVRABLES

Conservation (art. 68(9)): 5 ANS

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

Évaluation de l’adéquation (conseil et gestion de portefeuille)

Voir le POC

Les PSCA qui fournissent des conseils ou une gestion de portefeuille évaluent l’adéquation en fonction des connaissances et de l’expérience du client, de ses objectifs d’investissement, y compris sa tolérance au risque, et de sa situation financière, y compris sa capacité à supporter des pertes.

Obligations
  • Obtenir les informations nécessaires avant le service (art. 81(1) et (8)) :
  • (a) Connaissances et expérience en matière d’investissement, y compris en crypto-actifs
  • (b) Objectifs d’investissement, y compris la tolérance au risque
  • (c) Situation financière, y compris la capacité à supporter des pertes
  • Ne pas recommander ni gérer lorsque le service n’est pas adéquat (art. 81(11))
  • Réexaminer l’adéquation pour chaque client au moins tous les deux ans (art. 81(12))
  • Fournir un rapport d’adéquation sous format électronique pour le conseil (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))
}

Titre VI — Prévention et interdiction des abus de marché — Art. 86–92

Art. 89

Interdiction des opérations d’initiés

Voir le POC

Nul ne peut utiliser une information privilégiée pour acquérir ou céder des crypto-actifs, ni recommander ou inciter autrui à le faire. L’information privilégiée est définie à l’art. 87 ; la divulgation illicite est interdite par l’art. 90.

Obligations
  • INTERDIT : acquérir ou céder des crypto-actifs en utilisant une information privilégiée (art. 89)
  • INTERDIT : recommander ou inciter autrui à effectuer une opération sur la base d’une information privilégiée (art. 89)
  • INTERDIT : divulguer illicitement une information privilégiée hors de l’exercice normal de ses fonctions (art. 90)
  • Information privilégiée = précise, non publique, susceptible d’influencer sensiblement les prix (art. 87)
  • Les émetteurs rendent publiques les informations privilégiées dès que possible (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

Interdiction des manipulations de marché

Voir le POC

Nul ne peut effectuer ou tenter d’effectuer des manipulations de marché : signaux faux ou trompeurs, fixation des prix à un niveau artificiel, procédés fictifs ou trompeurs, diffusion de fausses informations (art. 91(2) et (3)).

Obligations
  • INTERDIT : transactions ou ordres donnant des signaux faux ou trompeurs, p. ex. transactions fictives (wash trading) (art. 91(2)(a))
  • INTERDIT : fixer les prix à un niveau anormal ou artificiel (art. 91(2)(a))
  • INTERDIT : procédés fictifs ou toute autre forme de tromperie ou d’artifice (art. 91(2)(b))
  • INTERDIT : passer, annuler ou modifier des ordres pour créer de faux signaux, p. ex. layering/spoofing (art. 91(3)(b))
  • INTERDIT : diffuser des informations fausses ou trompeuses, y compris des rumeurs (art. 91(2)(c))
  • Les personnes qui organisent ou exécutent à titre professionnel des transactions détectent et déclarent les soupçons sans délai (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
}

Règlement (UE) 2023/1114 — Règlement sur les marchés de crypto-actifs (MiCA)

CELEX:32023R1114 · Les documents sont conservés 5 ans conformément à l'art. 75 · Entièrement applicable à partir du: 30 décembre 2024