Skip to content

Contract Diagram

Cursor Agent edited this page Apr 8, 2026 · 11 revisions

OCP Contract Architecture

Contract Hierarchy

flowchart TB
    OcpFactory -->|AuthorizeIssuer| IssuerAuthorization
    IssuerAuthorization -->|CreateCapTable| CapTable
    CapTable -->|Edit| Issuer["Issuer (OCF object)"]
    CapTable -->|Create/Edit/Delete| OCF["OCF Objects & Transactions"]
Loading

CapTable manages all OCF contracts via Maps (OCF object ID → ContractId) for O(1) lookup. The OCF object ID is a business identifier (typically a GUID from the database), not the DAML ContractId which changes on each archive/recreate.

Contract Flow

sequenceDiagram
    actor SO as System Operator
    actor I as Issuer
    participant OcpFactory
    participant IssuerAuthorization
    participant Issuer
    participant CapTable
    participant OCF as OCF Contracts

    SO->>OcpFactory: Deploy (once)
    SO->>OcpFactory: AuthorizeIssuer(issuer)
    OcpFactory->>IssuerAuthorization: create

    I->>IssuerAuthorization: CreateCapTable(issuer_data)
    IssuerAuthorization->>Issuer: create
    IssuerAuthorization->>CapTable: create (with Issuer)

    I->>CapTable: UpdateCapTable(creates, edits, deletes)
    CapTable->>OCF: archive/create OCF contracts
Loading

Key Design Patterns

Pattern Description
Dual Signatories All contracts require both issuer and system_operator
Factory Chain OcpFactory → IssuerAuthorization → CapTable
State Management CapTable maintains Map Text (ContractId T) for O(1) lookup
Reference Validation CapTable validates referenced objects exist before creating (e.g., stakeholder must exist before stock issuance)
Archive + Recreate Edit = archive old contract + create new + update map
Issuer is Special Exactly one per CapTable, can only be edited (no delete)

File Structure

OpenCapTable-v34/daml/Fairmint/OpenCapTable/
├── OcpFactory.daml          # Factory contract
├── IssuerAuthorization.daml # Authorization contract  
├── CapTable.daml            # State management (GENERATED by codegen)
├── Types.daml               # Shared types & enums
└── OCF/                     # 47 OCF object contracts
    ├── Issuer.daml
    ├── Stakeholder.daml
    ├── StockClass.daml
    ├── StockIssuance.daml
    └── ...

scripts/codegen/
├── generate-captable.ts     # Generates CapTable.daml from OCF types
└── captable-config.yaml     # Reference validation configuration

Code Generation: CapTable.daml is generated by scripts/codegen/generate-captable.ts, which discovers OCF types from OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/ and generates the appropriate Maps and CRUD choices. Run npm run codegen:captable to regenerate.

NFT packages (separate from CapTable factory chain)

CapTable / OcpFactory flow above is unchanged. NFT contracts live in two DAML packages:

Package Role
NftApi-v01 Nft.Api.V1 — canonical Nft interface and types
NftReference-v01 Nft.Reference.V1 — reference registry, assets, metadata, receive authorization

npm run codegen runs scripts/merge-nft-iface-codegen.ts after both packages codegen: it copies Nft/Api from the API package into the reference package’s generated lib/ so the standalone reference tarball exports both Nft.Api and Nft.Reference (the merged root lib/ does the same for the NPM bundle).

Older OpenCapTableNftIface-v01 / OpenCapTableNft-v01 DAR backups under dars/ are unrelated to current source layout.

Equity certificate packages (separate from OcpFactory)

Independent of the factory chain above. EquityCertificate depends on EquityCertificateShared and NFT DARs.

Package Role
EquityCertificateShared Types (Types.daml), shared validation
EquityCertificate (EquityCertificate-v01/) Certificate, CertificateRegistry
flowchart LR
  ECS[EquityCertificateShared] --> EC[EquityCertificate]
  NFT[NftApi / NftReference] --> EC
Loading

See EquityCertificate-Module.

References

Clone this wiki locally