Compliance Extensions
The Transfer Hook enforces the rules. Everything on this page extends those rules into credential lifecycle, emergency powers, jurisdictional adaptability, and regulatory reporting.
Overview
The SPL-2022 Transfer Hook is the enforcement core — five checks, executed by the Solana runtime on every transfer, with no bypass path. But compliance for regulated securities does not end at transfers. Credentials expire. Regulators issue subpoenas. Courts order seizures. Jurisdictions change their rules. Tax authorities demand filings.
Compliance extensions are the mechanisms that handle everything the Transfer Hook does not: the lifecycle of KYC credentials between transfers, the emergency powers that override normal operations under legal authority, the feature flags that let issuers adapt offering behavior without redeploying contracts, the jurisdictional rules that vary across regulatory regimes, and the reporting grain that turns on-chain state into regulatory filings.
None of these extensions weaken the Transfer Hook. They extend the compliance surface around it — covering the full regulatory lifecycle from credential issuance through investor exit and tax reporting.
Transfer Hook Extensions
The SPL-2022 Transfer Hook enforces five compliance checks on every security token transfer. These checks are executed by the Solana runtime itself — not by application logic, not by an API gateway, not by anything that can be bypassed. The five checks, in order:
- KYC Validity — Both sender and receiver must hold valid, unexpired KYC Credential NFTs with
aml_clear: trueandpep_clear: true. - Lock-Up Period — The sender's
InvestorPositionPDA must show alocked_untiltimestamp in the past. Reg D lock-ups are typically 6–12 months. - Jurisdiction Whitelist — The receiver's
jurisdiction_hashmust appear in the offering'sComplianceConfigallowed_jurisdictionslist. - Accreditation Tier — The receiver's
investor_classmust meet or exceed the offering's accreditation requirement. - Investor Count — If the receiver is a new investor, the offering's current investor count must be below
max_investors.
If any check fails, the entire transaction reverts. The tokens do not move. A ComplianceViolation event is emitted with the specific failure reason. See the Transfer Rules documentation for the complete enforcement mechanism, including the execution flow and the architectural guarantee that no transfer — from any program, including raw SPL Token calls and DEX interactions — can bypass these checks.
Everything that follows on this page builds on this foundation. The Transfer Hook is the floor. Compliance extensions are the rest of the building.
Credential Lifecycle
KYC Credential NFTs are not permanent. They carry an expires_at timestamp, and when that timestamp passes, the credential is treated identically to no credential at all — the Transfer Hook rejects any transfer involving an expired credential. This is by design: regulatory verification decays. An investor verified 18 months ago may have changed jurisdiction, lost accreditation status, or become a politically exposed person.
Expiration Tracking
The platform does not wait for expiration to cause a failed transfer. The KYC Grain proactively tracks credential expiration windows and initiates re-verification before credentials expire:
| Window | Action |
|---|---|
| 90 days before expiry | Informational notification sent to the investor. No restrictions applied. |
| 30 days before expiry | Re-verification workflow triggered. Investor receives instructions and a deadline. Existing credential remains valid. |
| 7 days before expiry | Escalation to the Broker-Dealer and Platform Operator. Warning displayed on investor dashboard. |
| Expiration (T+0) | Credential becomes invalid. Transfer Hook rejects all transfers involving this wallet. Distribution claims are blocked. Minting is blocked. |
Mid-Holding Expiration
When a credential expires while an investor holds tokens, the tokens are not seized, burned, or moved. The investor still owns them — ownership is a legal right that does not evaporate because a KYC check expired. What changes is the investor's ability to act on those tokens:
- Transfers out: Blocked. The Transfer Hook rejects any outgoing transfer from a wallet with an expired credential.
- Transfers in: Blocked. The Transfer Hook rejects any incoming transfer to a wallet with an expired credential.
- Distribution claims: Blocked. Unclaimed distributions accrue and are released once the credential is renewed.
- CrossConversion requests: Blocked. No conversion to or from traditional securities until re-verification is complete.
- Voting and governance: Unaffected. Token-weighted governance rights are tied to ownership, not credential status.
Once the investor completes re-verification and a fresh KYC Credential NFT is minted to their wallet, all capabilities are restored immediately. There is no grace period in either direction — invalid means invalid, valid means valid.
Credential Revocation
Separate from expiration, a credential can be actively revoked by a compliance officer. Revocation sets aml_clear or pep_clear to false on the credential, which causes the Transfer Hook to reject transfers even if the credential has not expired. Revocation is logged as a critical-severity audit event and requires a documented reason. Common triggers: updated sanctions list match, law enforcement request, adverse media screening hit.
Emergency Powers
Emergency powers are compliance safety valves — operations that override normal rules under legal authority. They exist because regulated securities operate within a legal system that can compel action. These are not everyday operations. Every invocation is logged, audited, and requires cryptographic proof of authorization.
Account Freezing
The freeze_account instruction locks an investor's position entirely — no transfers, no sales, no CrossConversions, no distribution claims — until the freeze is lifted.
| Aspect | Detail |
|---|---|
| Authorization | Requires Security Admin NFT from the Melusina Admin NFT system (level=Security). |
| Effect | Sets a frozen flag on the InvestorPosition PDA. The Transfer Hook checks this flag and rejects all outgoing transfers. |
| Unfreezing | Same authorization level. Both freeze and unfreeze reasons are logged to the audit trail. |
| Emergency Freeze | For high-urgency situations where the Security Admin NFT is unavailable, a 2-of-3 threshold signing ceremony can freeze an account. |
| Audit | Every freeze/unfreeze is logged with actor wallet, NFT role, timestamp, and reason. 7-year retention. |
Account freezing is a regulatory tool for AML/SAR compliance, court orders, and regulatory investigations. Every use requires a documented reason.
Forced Transfers
The force_transfer instruction moves tokens from one wallet to another without the sender's consent. It is the most restricted operation in the entire program — a power that exists solely for court-ordered transfers and regulatory enforcement actions.
| Requirement | Detail |
|---|---|
| Keyholder Threshold | 3-of-5 Master NFT keyholder threshold signing. Three separate keyholders, using hardware wallets, in three separate locations, must independently sign. |
| Court Order Hash | A SHA-256 hash of the court order document must be included in the instruction. This hash is stored on-chain permanently — cryptographic proof that a legal basis existed. |
| Parameters | from, to, amount, court_order_hash (SHA-256 of the court order document). |
| Compliance Bypass | Force transfer bypasses standard Transfer Hook checks (lock-up, jurisdiction, accreditation). The court order supersedes contract-level rules. The destination wallet's KYC status is still recorded. |
| Audit | Critical-severity audit event. All signing keyholders recorded. Court order hash stored immutably on-chain. Notification sent to all platform operators and the Trustee. |
Three keyholders must agree. A court order must be on record. The action is visible on-chain permanently. Maximum transparency, maximum auditability, maximum friction — by design.
Emergency Pause
All programs include a pause instruction gated by the Security Admin NFT. When invoked, the pause halts all transfer, minting, and distribution operations for a specific offering. This is a circuit-breaker for scenarios such as: a discovered vulnerability in a third-party integration, a regulatory halt order, or a disputed cap table state that requires reconciliation before trading resumes.
Pause is per-offering, not platform-wide. One offering can be paused while all others continue operating normally. Unpausing requires the same Security Admin NFT authorization and is logged identically.
Feature Flags
The ComplianceConfig PDA includes a features field — a 64-bit bitmask that controls which capabilities are enabled for a given offering. Feature flags allow issuers to enable or disable specific behaviors without redeploying or migrating the smart contract.
ComplianceConfig.features: u64 (bitmask)
├── Bit 0: PAUSE_TRADING // Halt all secondary transfers
├── Bit 1: RESTRICT_CROSSCONV // Disable CrossConversion for this offering
├── Bit 2: REQUIRE_ACCREDITATION // Enforce accredited investor check
├── Bit 3: ENFORCE_LOCKUP // Enforce lock-up period on transfers
├── Bit 4: ENABLE_DISTRIBUTIONS // Allow distribution claims
├── Bit 5: ENABLE_VOTING // Allow token-weighted governance
├── Bit 6: RESTRICT_FLOWBACK // Reg S flowback prevention
├── Bit 7: ENABLE_OTC_MATCHING // Allow OTC secondary trading
├── ...
└── Bit 63: RESERVED // Reserved for future use
How Feature Flags Are Checked
Each instruction that is gated by a feature flag reads the offering's ComplianceConfig PDA and performs a bitwise AND against the relevant flag. If the bit is not set, the instruction returns a FeatureDisabled error. This check happens before any other validation — a disabled feature fails fast, costs minimal compute, and produces a clear error.
// Pseudocode: feature flag check
let config = ComplianceConfig::load(offering_id)?;
if config.features & PAUSE_TRADING != 0 {
return Err(ComplianceError::TradingPaused);
}
// Proceed with transfer checks...
Modification Rules
Feature flags are modifiable by the Issuer with Platform Operator approval. Every modification is logged to the audit trail with the previous value, the new value, and the reason for the change. Certain flags — such as PAUSE_TRADING — can also be set via emergency powers (Security Admin NFT) without Issuer initiation, for regulatory halt scenarios.
The bitmask design supports up to 64 independent features. New capabilities can be added to the smart contract and gated behind unused bits without modifying existing flag assignments or requiring data migration.
Jurisdictional Adaptability
Securities regulations vary by jurisdiction — and a platform that only handles US Reg D and Reg S will not scale internationally. The compliance extensions are designed for jurisdictional adaptability: each offering carries its own jurisdiction configuration, and the framework supports regulatory regimes beyond US securities law.
Per-Offering Jurisdiction Whitelists
Every offering's ComplianceConfig PDA contains an allowed_jurisdictions list — SHA-256 hashes of ISO 3166-1 country codes. The Transfer Hook compares the receiver's jurisdiction_hash against this list on every transfer. The hashing preserves investor privacy: the blockchain does not reveal which country an investor is in.
| Regulatory Regime | Jurisdiction Configuration | Status |
|---|---|---|
| Reg D 506(b/c) | US-only. Only wallets with US jurisdiction hash can receive tokens. | Active |
| Reg S | Non-US only. US jurisdiction hash explicitly excluded. Flowback restrictions enforced via the RESTRICT_FLOWBACK feature flag during the distribution compliance period. |
Active |
| Dual Reg D + Reg S | Segregated token mints — separate US (Reg D) and non-US (Reg S) tranches, each with its own ComplianceConfig. Cross-tranche transfers blocked. |
Active |
| EU MiFID II | EU member state hashes whitelisted. Accreditation tier mapped to MiFID II investor classification (Retail, Professional, Eligible Counterparty). Requires additional credential fields for LEI and national ID scheme. | Planned |
| UK FCA | UK jurisdiction hash whitelisted post-Brexit, separate from EU. FCA investor categorization (Restricted, High Net Worth, Sophisticated, Professional) mapped to investor_class tiers. |
Planned |
| Singapore MAS | SG jurisdiction hash. MAS accredited investor threshold (SGD 2M net assets or SGD 300K annual income) mapped to accreditation tier. Capital Markets Services licence requirements enforced at the Broker NFT level. | Planned (APAC) |
| Hong Kong SFC | HK jurisdiction hash. SFC professional investor classification (HKD 8M portfolio threshold) mapped to investor_class. Type 1 / Type 9 licence requirements enforced at the platform operator level. |
Planned (APAC) |
| Restricted Jurisdictions | OFAC-sanctioned jurisdiction hashes are never included in any offering's whitelist. KYC Credential NFTs are never issued for sanctioned jurisdictions — double enforcement. | Active |
Future-Proofing
The jurisdiction model is deliberately generic: a whitelist of hashes, an accreditation tier enum, and a regulatory exemption enum. Adding a new regulatory regime does not require smart contract changes — it requires:
- Adding the new jurisdiction's country code hash to the relevant offerings'
allowed_jurisdictionslists. - Mapping the regime's investor classification to existing
investor_classtiers (or extending the enum if no existing tier fits). - Configuring the KYC Grain to perform the jurisdiction-specific verification workflow.
- Adding the regime's reporting requirements to the compliance-grain.
The smart contract enforces the rules. The off-chain grains handle the jurisdiction-specific logic. This separation means the on-chain program does not need to know anything about MiFID II or MAS regulations — it only needs to know whether a hash is in a list and whether a tier meets a threshold.
Audit & Reporting Extensions
Compliance is not just enforcement — it is reporting. The compliance-grain (a Go service in the Sandstorm actor framework) generates the regulatory filings and reports that securities law requires. These reports are derived from on-chain state and grain journal records — not from a separate database that might drift from the source of truth.
Regulatory Filings
| Report | Authority | Frequency | Description |
|---|---|---|---|
| Form D | SEC (EDGAR) | Per offering + annual amendment | Notice of exempt offering of securities. Generated as XML validated against the SEC EDGAR schema. Must be filed within 15 days of the first sale of securities. Annual amendments filed to update investor counts and amounts raised. |
| Blue Sky Filings | State regulators | Per state, per offering | State-level securities exemption filings. The compliance-grain tracks per-state exemptions, investor counts, and filing deadlines. States vary widely — some accept federal filing, others require separate state-specific forms. |
| AML/SAR | FinCEN | As needed | Suspicious Activity Reports. Automated flagging based on transaction patterns (unusual volume, rapid transfers near lock-up expiry, structuring patterns). Human compliance officer review before filing — the system flags, a person decides. |
| K-1 | IRS | Annual | Schedule K-1 (Partner's Share of Income) for LLC pass-through taxation. Generated from on-chain distribution records and cap table snapshots at tax year end. Each investor receives a K-1 reflecting their proportional share. |
| Reg S Compliance | SEC | Ongoing | Non-US investor tracking, flowback restriction enforcement, and distribution compliance period monitoring. Ensures tokens do not flow back to US wallets during the restricted period. |
| Cap Table Snapshots | Internal / Auditors | On demand | Ownership snapshots pulled directly from on-chain state. Immutable, verifiable, and exportable in standard formats for auditor consumption. |
Audit Trail
Every action across every grain and smart contract is logged to an append-only audit trail. This is not optional and cannot be disabled. The audit event structure:
AuditEvent {
id, // Unique event identifier
timestamp, // Precise event time
severity, // info | warning | critical
category, // auth | transfer | compliance | governance
actor_id, // Wallet address of the actor
actor_type, // NFT role (Operator, Trustee, Broker, etc.)
action, // What was done
resource, // What it was done to
resource_type, // Offering, investor, distribution, etc.
success, // Whether the action succeeded
error_message, // Failure reason (if applicable)
grain_id, // Which grain processed the action
offering_id, // Which offering was affected
series_id, // Which Series LLC
metadata // Additional context (JSON)
}
Seven-year retention — required by SEC regulations for broker-dealer and investment adviser records. Every audit event is written to the grain's append-only journal, encrypted at rest with AES-256, and replicated for durability. After the 7-year retention period, automated purge with legal hold override ensures data is retained only as long as legally required.
Audit Export
The compliance-grain supports full audit trail export in standard formats for external auditors, regulators, and legal counsel. Exports can be filtered by offering, date range, severity, category, and actor. The export includes cryptographic integrity proofs — an auditor can verify that no events have been tampered with or omitted from the export.
Grain journals support deterministic replay: given the same sequence of audit events, the grain reconstructs identical state. This is the disaster recovery mechanism — restore the journal, replay the events, verify the state. The log is the truth.