diff --git a/OpenCapTable-v34/daml.yaml b/OpenCapTable-v34/daml.yaml index a8cb9483..5a2ffed7 100644 --- a/OpenCapTable-v34/daml.yaml +++ b/OpenCapTable-v34/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.4.10 name: OpenCapTable-v34 source: daml -version: 0.0.13 +version: 0.0.14 build-options: - -Wno-crypto-text-is-alpha - --typecheck-upgrades=no diff --git a/Test/daml.yaml b/Test/daml.yaml index 16f002f3..533768e2 100644 --- a/Test/daml.yaml +++ b/Test/daml.yaml @@ -7,6 +7,6 @@ dependencies: - daml-stdlib - daml-script data-dependencies: - - ../OpenCapTable-v34/.daml/dist/OpenCapTable-v34-0.0.13.dar + - ../OpenCapTable-v34/.daml/dist/OpenCapTable-v34-0.0.14.dar build-options: - -Wno-template-interface-depends-on-daml-script diff --git a/Test/daml/OpenCapTable/TestApprovalDateConsistency.daml b/Test/daml/OpenCapTable/TestApprovalDateConsistency.daml new file mode 100644 index 00000000..659800b1 --- /dev/null +++ b/Test/daml/OpenCapTable/TestApprovalDateConsistency.daml @@ -0,0 +1,181 @@ +module OpenCapTable.TestApprovalDateConsistency where + +import qualified Fairmint.OpenCapTable.CapTable as CT +import Fairmint.OpenCapTable.OCF.IssuerAuthorizedSharesAdjustment (IssuerAuthorizedSharesAdjustmentOcfData(..)) +import Fairmint.OpenCapTable.OCF.StockClassAuthorizedSharesAdjustment (StockClassAuthorizedSharesAdjustmentOcfData(..)) +import Fairmint.OpenCapTable.OCF.StockPlanPoolAdjustment (StockPlanPoolAdjustmentOcfData(..)) +import Fairmint.OpenCapTable.OCF.Valuation (ValuationOcfData(..), OcfValuationType(..)) +import Fairmint.OpenCapTable.Types.Monetary (OcfMonetary(..)) +import OpenCapTable.Setup +import OpenCapTable.TestHelpers + ( addDefaultStakeholder + , addDefaultStockClass + , addPrerequisites + , convertibleSuccessorIssuance + , defaultStockIssuance + , defaultStockPlan + , equityCompensationSuccessorIssuance + , warrantSuccessorIssuance + ) +import qualified DA.Date as DA +import DA.Date (Month(..)) +import qualified DA.Time as DT +import Daml.Script + +jan01 : Time +jan01 = DT.time (DA.date 2024 Jan 01) 0 0 0 + +jan02 : Time +jan02 = DT.time (DA.date 2024 Jan 02) 0 0 0 + +assertCreateFails : Party -> ContractId CT.CapTable -> CT.OcfCreateData -> Script () +assertCreateFails issuer capTable createData = do + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [createData] + edits = [] + deletes = [] + pure () + +convertibleWithLateBoardApproval : CT.OcfCreateData +convertibleWithLateBoardApproval = + case convertibleSuccessorIssuance "CV-LATE-BOARD" "CSEC-LATE-BOARD" "SH-1" jan01 100.0 of + CT.OcfCreateConvertibleIssuance issuance -> + CT.OcfCreateConvertibleIssuance (issuance with board_approval_date = Some jan02) + _ -> error "Expected convertible issuance" + +equityCompensationWithLateStockholderApproval : CT.OcfCreateData +equityCompensationWithLateStockholderApproval = + case equityCompensationSuccessorIssuance "EC-LATE-STOCKHOLDER" "ECSEC-LATE-STOCKHOLDER" "SH-1" jan01 100.0 of + CT.OcfCreateEquityCompensationIssuance issuance -> + CT.OcfCreateEquityCompensationIssuance (issuance with stockholder_approval_date = Some jan02) + _ -> error "Expected equity compensation issuance" + +warrantWithLateStockholderApproval : CT.OcfCreateData +warrantWithLateStockholderApproval = + case warrantSuccessorIssuance "WR-LATE-STOCKHOLDER" "WSEC-LATE-STOCKHOLDER" "SH-1" jan01 100.0 of + CT.OcfCreateWarrantIssuance issuance -> + CT.OcfCreateWarrantIssuance (issuance with stockholder_approval_date = Some jan02) + _ -> error "Expected warrant issuance" + +issuerAdjustment : Text -> Optional Time -> Optional Time -> IssuerAuthorizedSharesAdjustmentOcfData +issuerAdjustment adjustmentId boardApprovalDate stockholderApprovalDate = + IssuerAuthorizedSharesAdjustmentOcfData with + id = adjustmentId + date = jan01 + issuer_id = "ISSUER_1" + new_shares_authorized = 200_000_000.0 + board_approval_date = boardApprovalDate + stockholder_approval_date = stockholderApprovalDate + comments = [] + +stockClassAdjustment : Optional Time -> Optional Time -> StockClassAuthorizedSharesAdjustmentOcfData +stockClassAdjustment boardApprovalDate stockholderApprovalDate = + StockClassAuthorizedSharesAdjustmentOcfData with + id = "SC-ADJ-LATE-APPROVAL" + date = jan01 + stock_class_id = "SC_COMMON" + new_shares_authorized = 2_000_000.0 + board_approval_date = boardApprovalDate + stockholder_approval_date = stockholderApprovalDate + comments = [] + +stockPlanAdjustment : Optional Time -> Optional Time -> StockPlanPoolAdjustmentOcfData +stockPlanAdjustment boardApprovalDate stockholderApprovalDate = + StockPlanPoolAdjustmentOcfData with + id = "PLAN-ADJ-LATE-APPROVAL" + date = jan01 + stock_plan_id = "PLAN-APPROVAL-DATES" + shares_reserved = 1_200.0 + board_approval_date = boardApprovalDate + stockholder_approval_date = stockholderApprovalDate + comments = [] + +valuation : Optional Time -> Optional Time -> ValuationOcfData +valuation boardApprovalDate stockholderApprovalDate = + ValuationOcfData with + id = "VALUATION-LATE-APPROVAL" + effective_date = jan01 + price_per_share = OcfMonetary with amount = 1.0, currency = "USD" + stock_class_id = "SC_COMMON" + valuation_type = OcfValuationType409A + comments = [] + board_approval_date = boardApprovalDate + provider = None + stockholder_approval_date = stockholderApprovalDate + +testApprovalDateConsistency_ConvertibleLateBoardApprovalFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStakeholder issuer cap_table + assertCreateFails issuer capTable convertibleWithLateBoardApproval + +testApprovalDateConsistency_EquityCompensationLateStockholderApprovalFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStakeholder issuer cap_table + assertCreateFails issuer capTable equityCompensationWithLateStockholderApproval + +testApprovalDateConsistency_IssuerAdjustmentLateBoardApprovalFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + assertCreateFails issuer cap_table (CT.OcfCreateIssuerAuthorizedSharesAdjustment (issuerAdjustment "ISSUER-ADJ-LATE-BOARD" (Some jan02) None)) + +testApprovalDateConsistency_StockClassAdjustmentLateStockholderApprovalFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStockClass issuer cap_table + assertCreateFails issuer capTable (CT.OcfCreateStockClassAuthorizedSharesAdjustment (stockClassAdjustment None (Some jan02))) + +testApprovalDateConsistency_StockIssuanceLateBoardApprovalFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + let issuance = (defaultStockIssuance "STOCK-LATE-BOARD" "SSEC-LATE-BOARD" "SH-1" "SC_COMMON") with + board_approval_date = Some jan02 + assertCreateFails issuer capTable (CT.OcfCreateStockIssuance issuance) + +testApprovalDateConsistency_StockPlanAdjustmentLateStockholderApprovalFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStockClass issuer cap_table + result <- submit issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateStockPlan (defaultStockPlan "PLAN-APPROVAL-DATES" "SC_COMMON")] + edits = [] + deletes = [] + assertCreateFails issuer result.updatedCapTableCid (CT.OcfCreateStockPlanPoolAdjustment (stockPlanAdjustment None (Some jan02))) + +testApprovalDateConsistency_ValuationLateBoardApprovalFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStockClass issuer cap_table + assertCreateFails issuer capTable (CT.OcfCreateValuation (valuation (Some jan02) None)) + +testApprovalDateConsistency_WarrantLateStockholderApprovalFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStakeholder issuer cap_table + assertCreateFails issuer capTable warrantWithLateStockholderApproval + +testApprovalDateConsistency_ApprovalsOnTransactionDateSucceed = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + let issuance = (defaultStockIssuance "STOCK-SAME-DAY-APPROVAL" "SSEC-SAME-DAY-APPROVAL" "SH-1" "SC_COMMON") with + board_approval_date = Some jan01 + stockholder_approval_date = Some jan01 + + _ <- submit issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateStockIssuance issuance] + edits = [] + deletes = [] + pure () + +testApprovalDateConsistency_EditIsRevalidated = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let validAdjustment = issuerAdjustment "ISSUER-ADJ-EDIT-APPROVAL" (Some jan01) None + result <- submit issuer do + exerciseCmd cap_table CT.UpdateCapTable with + creates = [CT.OcfCreateIssuerAuthorizedSharesAdjustment validAdjustment] + edits = [] + deletes = [] + + submitMustFail issuer do + exerciseCmd result.updatedCapTableCid CT.UpdateCapTable with + creates = [] + edits = [CT.OcfEditIssuerAuthorizedSharesAdjustment (validAdjustment with board_approval_date = Some jan02)] + deletes = [] + pure () diff --git a/Test/daml/OpenCapTable/TestIssuerAuthorizedSharesAdjustment.daml b/Test/daml/OpenCapTable/TestIssuerAuthorizedSharesAdjustment.daml index c7f4356f..8f8be129 100644 --- a/Test/daml/OpenCapTable/TestIssuerAuthorizedSharesAdjustment.daml +++ b/Test/daml/OpenCapTable/TestIssuerAuthorizedSharesAdjustment.daml @@ -66,8 +66,8 @@ testIssuerAuthorizedSharesAdjustment_OptionalsSome = script do date = DT.time (DA.date 2024 Jan 02) 0 0 0 issuer_id = "ISSUER_1" new_shares_authorized = 2500.0 - board_approval_date = Some (DT.time (DA.date 2024 Jan 03) 0 0 0) - stockholder_approval_date = Some (DT.time (DA.date 2024 Jan 04) 0 0 0) + board_approval_date = Some (DT.time (DA.date 2024 Jan 01) 0 0 0) + stockholder_approval_date = Some (DT.time (DA.date 2024 Jan 02) 0 0 0) comments = ["Increase"]] edits = [] deletes = [] diff --git a/Test/daml/OpenCapTable/TestStockClassAuthorizedSharesAdjustment.daml b/Test/daml/OpenCapTable/TestStockClassAuthorizedSharesAdjustment.daml index bab22c9e..6ab01af1 100644 --- a/Test/daml/OpenCapTable/TestStockClassAuthorizedSharesAdjustment.daml +++ b/Test/daml/OpenCapTable/TestStockClassAuthorizedSharesAdjustment.daml @@ -74,8 +74,8 @@ testCreateAndArchiveStockClassAuthorizedSharesAdjustmentBuiltIn = script do date = DT.time (DA.date 2024 Jan 02) 0 0 0 stock_class_id = "SC_COMMON_2" new_shares_authorized = 1_500_000.0 - board_approval_date = Some (DT.time (DA.date 2024 Jan 03) 0 0 0) - stockholder_approval_date = Some (DT.time (DA.date 2024 Jan 05) 0 0 0) + board_approval_date = Some (DT.time (DA.date 2024 Jan 01) 0 0 0) + stockholder_approval_date = Some (DT.time (DA.date 2024 Jan 02) 0 0 0) comments = ["Authorized change"]] edits = [] deletes = [] diff --git a/Test/daml/OpenCapTable/TestStockPlanPoolAdjustment.daml b/Test/daml/OpenCapTable/TestStockPlanPoolAdjustment.daml index 2f9f8ed5..acff98a7 100644 --- a/Test/daml/OpenCapTable/TestStockPlanPoolAdjustment.daml +++ b/Test/daml/OpenCapTable/TestStockPlanPoolAdjustment.daml @@ -53,8 +53,8 @@ testStockPlanPoolAdjustment_OptionalsSome = script do id = "TX_STOCK_PLAN_POOL_ADJ_2" date = DT.time (DA.date 2024 Jan 02) 0 0 0 stock_plan_id = "PLAN_1" - board_approval_date = Some (DT.time (DA.date 2024 Jan 03) 0 0 0) - stockholder_approval_date = Some (DT.time (DA.date 2024 Jan 04) 0 0 0) + board_approval_date = Some (DT.time (DA.date 2024 Jan 01) 0 0 0) + stockholder_approval_date = Some (DT.time (DA.date 2024 Jan 02) 0 0 0) shares_reserved = 1750.0 comments = ["Top up"]] edits = [] diff --git a/Test/daml/OpenCapTable/TestTransactionLifecycleDates.daml b/Test/daml/OpenCapTable/TestTransactionLifecycleDates.daml new file mode 100644 index 00000000..0fe3bc2d --- /dev/null +++ b/Test/daml/OpenCapTable/TestTransactionLifecycleDates.daml @@ -0,0 +1,359 @@ +module OpenCapTable.TestTransactionLifecycleDates where + +import qualified Fairmint.OpenCapTable.CapTable as CT +import Fairmint.OpenCapTable.OCF.ConvertibleAcceptance (ConvertibleAcceptanceOcfData(..)) +import Fairmint.OpenCapTable.OCF.ConvertibleTransfer (ConvertibleTransferOcfData(..)) +import Fairmint.OpenCapTable.OCF.EquityCompensationAcceptance (EquityCompensationAcceptanceOcfData(..)) +import Fairmint.OpenCapTable.OCF.EquityCompensationRepricing (EquityCompensationRepricingOcfData(..)) +import Fairmint.OpenCapTable.OCF.EquityCompensationTransfer (EquityCompensationTransferOcfData(..)) +import Fairmint.OpenCapTable.OCF.StockAcceptance (StockAcceptanceOcfData(..)) +import Fairmint.OpenCapTable.OCF.StockReissuance (StockReissuanceOcfData(..)) +import Fairmint.OpenCapTable.OCF.StockRetraction (StockRetractionOcfData(..)) +import Fairmint.OpenCapTable.OCF.StockTransfer (StockTransferOcfData(..)) +import Fairmint.OpenCapTable.OCF.VestingAcceleration (VestingAccelerationOcfData(..)) +import Fairmint.OpenCapTable.OCF.WarrantAcceptance (WarrantAcceptanceOcfData(..)) +import Fairmint.OpenCapTable.OCF.WarrantTransfer (WarrantTransferOcfData(..)) +import Fairmint.OpenCapTable.Types.Monetary (OcfMonetary(..)) +import OpenCapTable.Setup +import OpenCapTable.TestHelpers + ( addConvertibleIssuance + , addDefaultStakeholder + , addEquityCompensationIssuance + , addPrerequisites + , addStockIssuance + , addWarrantIssuance + , convertibleSuccessorIssuance + , createStockIssuanceWith + , defaultStockIssuance + , equityCompensationRelease + , stockCancellationOn + ) +import qualified DA.Date as DA +import DA.Date (Month(..)) +import qualified DA.Time as DT +import Daml.Script + +dec31 : Time +dec31 = DT.time (DA.date 2023 Dec 31) 0 0 0 + +jan02 : Time +jan02 = DT.time (DA.date 2024 Jan 02) 0 0 0 + +jan03 : Time +jan03 = DT.time (DA.date 2024 Jan 03) 0 0 0 + +usd : Decimal -> OcfMonetary +usd amount = OcfMonetary with amount = amount, currency = "USD" + +stockTransfer : Text -> Text -> Text -> StockTransferOcfData +stockTransfer transferId sourceSecurityId resultingSecurityId = StockTransferOcfData with + id = transferId + date = jan02 + security_id = sourceSecurityId + quantity = 10.0 + resulting_security_ids = [resultingSecurityId] + balance_security_id = None + consideration_text = None + comments = [] + +convertibleTransfer : Text -> Text -> Text -> ConvertibleTransferOcfData +convertibleTransfer transferId sourceSecurityId resultingSecurityId = ConvertibleTransferOcfData with + id = transferId + date = jan02 + security_id = sourceSecurityId + amount = usd 100.0 + resulting_security_ids = [resultingSecurityId] + balance_security_id = None + consideration_text = None + comments = [] + +warrantTransfer : Text -> Text -> Text -> WarrantTransferOcfData +warrantTransfer transferId sourceSecurityId resultingSecurityId = WarrantTransferOcfData with + id = transferId + date = jan02 + security_id = sourceSecurityId + quantity = 10.0 + resulting_security_ids = [resultingSecurityId] + balance_security_id = None + consideration_text = None + comments = [] + +equityCompensationTransfer : Text -> Text -> Text -> EquityCompensationTransferOcfData +equityCompensationTransfer transferId sourceSecurityId resultingSecurityId = EquityCompensationTransferOcfData with + id = transferId + date = jan02 + security_id = sourceSecurityId + quantity = 10.0 + resulting_security_ids = [resultingSecurityId] + balance_security_id = None + consideration_text = None + comments = [] + +testTransactionLifecycleDates_StockAcceptanceBeforeIssuanceFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addStockIssuance issuer capTable "TX-STOCK-SOURCE" "SEC-STOCK-SOURCE" "SH-1" "SC_COMMON" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateStockAcceptance StockAcceptanceOcfData with + id = "TX-STOCK-ACCEPT-BEFORE" + date = dec31 + security_id = "SEC-STOCK-SOURCE" + comments = []] + edits = [] + deletes = [] + pure () + +testTransactionLifecycleDates_ConvertibleAcceptanceBeforeIssuanceFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStakeholder issuer cap_table + capTable <- addConvertibleIssuance issuer capTable "TX-CV-SOURCE" "SEC-CV-SOURCE" "SH-1" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateConvertibleAcceptance ConvertibleAcceptanceOcfData with + id = "TX-CV-ACCEPT-BEFORE" + date = dec31 + security_id = "SEC-CV-SOURCE" + comments = []] + edits = [] + deletes = [] + pure () + +testTransactionLifecycleDates_WarrantAcceptanceBeforeIssuanceFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStakeholder issuer cap_table + capTable <- addWarrantIssuance issuer capTable "TX-WR-SOURCE" "SEC-WR-SOURCE" "SH-1" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateWarrantAcceptance WarrantAcceptanceOcfData with + id = "TX-WR-ACCEPT-BEFORE" + date = dec31 + security_id = "SEC-WR-SOURCE" + comments = []] + edits = [] + deletes = [] + pure () + +testTransactionLifecycleDates_EquityCompensationAcceptanceBeforeIssuanceFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addEquityCompensationIssuance issuer capTable "TX-EC-SOURCE" "SEC-EC-SOURCE" "SH-1" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateEquityCompensationAcceptance EquityCompensationAcceptanceOcfData with + id = "TX-EC-ACCEPT-BEFORE" + date = dec31 + security_id = "SEC-EC-SOURCE" + comments = []] + edits = [] + deletes = [] + pure () + +testTransactionLifecycleDates_StockTransferResultBeforeTransferFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addStockIssuance issuer capTable "TX-STOCK-SOURCE" "SEC-STOCK-SOURCE" "SH-1" "SC_COMMON" + capTable <- addStockIssuance issuer capTable "TX-STOCK-RESULT" "SEC-STOCK-RESULT" "SH-1" "SC_COMMON" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateStockTransfer (stockTransfer "TX-STOCK-TRANSFER-LATE" "SEC-STOCK-SOURCE" "SEC-STOCK-RESULT")] + edits = [] + deletes = [] + pure () + +testTransactionLifecycleDates_ConvertibleTransferResultBeforeTransferFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStakeholder issuer cap_table + capTable <- addConvertibleIssuance issuer capTable "TX-CV-SOURCE" "SEC-CV-SOURCE" "SH-1" + capTable <- addConvertibleIssuance issuer capTable "TX-CV-RESULT" "SEC-CV-RESULT" "SH-1" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateConvertibleTransfer (convertibleTransfer "TX-CV-TRANSFER-LATE" "SEC-CV-SOURCE" "SEC-CV-RESULT")] + edits = [] + deletes = [] + pure () + +testTransactionLifecycleDates_ConvertibleTransferResultAfterTransferFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStakeholder issuer cap_table + capTable <- addConvertibleIssuance issuer capTable "TX-CV-AFTER-SOURCE" "SEC-CV-AFTER-SOURCE" "SH-1" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = + [ convertibleSuccessorIssuance "TX-CV-AFTER-RESULT" "SEC-CV-AFTER-RESULT" "SH-1" jan03 100.0 + , CT.OcfCreateConvertibleTransfer + (convertibleTransfer "TX-CV-AFTER-TRANSFER" "SEC-CV-AFTER-SOURCE" "SEC-CV-AFTER-RESULT") + ] + edits = [] + deletes = [] + pure () + +testTransactionLifecycleDates_WarrantTransferResultBeforeTransferFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addDefaultStakeholder issuer cap_table + capTable <- addWarrantIssuance issuer capTable "TX-WR-SOURCE" "SEC-WR-SOURCE" "SH-1" + capTable <- addWarrantIssuance issuer capTable "TX-WR-RESULT" "SEC-WR-RESULT" "SH-1" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateWarrantTransfer (warrantTransfer "TX-WR-TRANSFER-LATE" "SEC-WR-SOURCE" "SEC-WR-RESULT")] + edits = [] + deletes = [] + pure () + +testTransactionLifecycleDates_EquityCompensationTransferResultBeforeTransferFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addEquityCompensationIssuance issuer capTable "TX-EC-SOURCE" "SEC-EC-SOURCE" "SH-1" + capTable <- addEquityCompensationIssuance issuer capTable "TX-EC-RESULT" "SEC-EC-RESULT" "SH-1" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateEquityCompensationTransfer (equityCompensationTransfer "TX-EC-TRANSFER-LATE" "SEC-EC-SOURCE" "SEC-EC-RESULT")] + edits = [] + deletes = [] + pure () + +testTransactionLifecycleDates_StockCancellationBalanceBeforeCancellationFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addStockIssuance issuer capTable "TX-STOCK-CANCEL-SOURCE" "SEC-STOCK-CANCEL-SOURCE" "SH-1" "SC_COMMON" + capTable <- createStockIssuanceWith issuer capTable + ((defaultStockIssuance "TX-STOCK-CANCEL-BALANCE" "SEC-STOCK-CANCEL-BALANCE" "SH-1" "SC_COMMON") with + date = dec31 + quantity = 90.0) + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = + [ CT.OcfCreateStockCancellation + ((stockCancellationOn "TX-STOCK-CANCEL-LATE" "SEC-STOCK-CANCEL-SOURCE" 10.0 jan02) with + balance_security_id = Some "SEC-STOCK-CANCEL-BALANCE") + ] + edits = [] + deletes = [] + +testTransactionLifecycleDates_EquityCompensationReleaseResultBeforeSettlementFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addEquityCompensationIssuance issuer capTable "TX-EC-RELEASE-SOURCE" "SEC-EC-RELEASE-SOURCE" "SH-1" + capTable <- createStockIssuanceWith issuer capTable + ((defaultStockIssuance "TX-EC-RELEASE-RESULT" "SEC-EC-RELEASE-RESULT" "SH-1" "SC_COMMON") with + date = jan02 + quantity = 10.0) + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = + [ CT.OcfCreateEquityCompensationRelease + ((equityCompensationRelease "TX-EC-RELEASE-LATE" "SEC-EC-RELEASE-SOURCE" jan02 (DT.time (DA.date 2024 Jan 03) 0 0 0) 10.0) with + resulting_security_ids = ["SEC-EC-RELEASE-RESULT"]) + ] + edits = [] + deletes = [] + +testTransactionLifecycleDates_StockReissuanceResultBeforeTransactionFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addStockIssuance issuer capTable "TX-REISSUE-SOURCE" "SEC-REISSUE-SOURCE" "SH-1" "SC_COMMON" + capTable <- addStockIssuance issuer capTable "TX-REISSUE-RESULT" "SEC-REISSUE-RESULT" "SH-1" "SC_COMMON" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateStockReissuance StockReissuanceOcfData with + id = "TX-REISSUE-LATE" + date = jan02 + security_id = "SEC-REISSUE-SOURCE" + resulting_security_ids = ["SEC-REISSUE-RESULT"] + split_transaction_id = None + reason_text = None + comments = []] + edits = [] + deletes = [] + +testTransactionLifecycleDates_StockRetractionBeforeIssuanceFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addStockIssuance issuer capTable "TX-RETRACTION-SOURCE" "SEC-RETRACTION-SOURCE" "SH-1" "SC_COMMON" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateStockRetraction StockRetractionOcfData with + id = "TX-RETRACTION-BEFORE" + date = dec31 + security_id = "SEC-RETRACTION-SOURCE" + reason_text = "Predates its source issuance" + comments = []] + edits = [] + deletes = [] + +testTransactionLifecycleDates_EquityCompensationRepricingBeforeIssuanceFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addEquityCompensationIssuance issuer capTable "TX-REPRICE-SOURCE" "SEC-REPRICE-SOURCE" "SH-1" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateEquityCompensationRepricing EquityCompensationRepricingOcfData with + id = "TX-REPRICE-BEFORE" + date = dec31 + security_id = "SEC-REPRICE-SOURCE" + new_exercise_price = usd 1.0 + comments = []] + edits = [] + deletes = [] + +testTransactionLifecycleDates_WrongTypeStockOutputFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addStockIssuance issuer capTable "TX-WRONG-OUTPUT-SOURCE" "SEC-WRONG-OUTPUT-SOURCE" "SH-1" "SC_COMMON" + capTable <- addConvertibleIssuance issuer capTable "TX-WRONG-OUTPUT" "SEC-WRONG-OUTPUT" "SH-1" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateStockTransfer (stockTransfer "TX-WRONG-OUTPUT-TRANSFER" "SEC-WRONG-OUTPUT-SOURCE" "SEC-WRONG-OUTPUT")] + edits = [] + deletes = [] + +testTransactionLifecycleDates_ReleaseSettlementBeforeTransactionFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addEquityCompensationIssuance issuer capTable "TX-RELEASE-ORDER-SOURCE" "SEC-RELEASE-ORDER-SOURCE" "SH-1" + capTable <- createStockIssuanceWith issuer capTable + ((defaultStockIssuance "TX-RELEASE-ORDER-RESULT" "SEC-RELEASE-ORDER-RESULT" "SH-1" "SC_COMMON") with + date = jan02 + quantity = 10.0) + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = + [ CT.OcfCreateEquityCompensationRelease + ((equityCompensationRelease "TX-RELEASE-ORDER" "SEC-RELEASE-ORDER-SOURCE" jan03 jan02 10.0) with + resulting_security_ids = ["SEC-RELEASE-ORDER-RESULT"]) + ] + edits = [] + deletes = [] + +testTransactionLifecycleDates_VestingAccelerationBeforeIssuanceFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + capTable <- addPrerequisites issuer cap_table + capTable <- addStockIssuance issuer capTable "TX-VESTING-SOURCE" "SEC-VESTING-SOURCE" "SH-1" "SC_COMMON" + + submitMustFail issuer do + exerciseCmd capTable CT.UpdateCapTable with + creates = [CT.OcfCreateVestingAcceleration VestingAccelerationOcfData with + id = "TX-VESTING-ACCELERATION-BEFORE" + date = dec31 + security_id = "SEC-VESTING-SOURCE" + quantity = 10.0 + reason_text = "Predates its source issuance" + comments = []] + edits = [] + deletes = [] diff --git a/dars/OpenCapTable-v34/0.0.14/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.14/OpenCapTable-v34.dar new file mode 100644 index 00000000..825ebacd --- /dev/null +++ b/dars/OpenCapTable-v34/0.0.14/OpenCapTable-v34.dar @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:099c610b1248e1ef312cb15b0715e791088671c70ac13f44e7e103b22a20d88c +size 3235156 diff --git a/dars/dars.lock b/dars/dars.lock index 0b712445..aab88f15 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -39,6 +39,13 @@ "uploadedAt": "2026-07-11T15:31:43.000Z", "networks": [] }, + "OpenCapTable-v34/0.0.14/OpenCapTable-v34.dar": { + "sha256": "099c610b1248e1ef312cb15b0715e791088671c70ac13f44e7e103b22a20d88c", + "size": 3235156, + "sdkVersion": "3.4.10", + "uploadedAt": "2026-07-11T16:30:30.000Z", + "networks": [] + }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { "sha256": "2ce462b8afcb1bcdbe351c56b0a47de478477f3c655da00e41cb397f63e997d6", "size": 2446238, diff --git a/scripts/codegen/templates/CapTable.daml.template b/scripts/codegen/templates/CapTable.daml.template index ec9aae8b..0a0a93d9 100644 --- a/scripts/codegen/templates/CapTable.daml.template +++ b/scripts/codegen/templates/CapTable.daml.template @@ -106,6 +106,13 @@ toMaps ct = CapTableMaps with stock_issuances_by_security_id = ct.stock_issuances_by_security_id warrant_issuances_by_security_id = ct.warrant_issuances_by_security_id +securityIdExists : CapTableMaps -> Text -> Bool +securityIdExists maps securityId = + isSome (Map.lookup securityId maps.convertible_issuances_by_security_id) || + isSome (Map.lookup securityId maps.equity_compensation_issuances_by_security_id) || + isSome (Map.lookup securityId maps.stock_issuances_by_security_id) || + isSome (Map.lookup securityId maps.warrant_issuances_by_security_id) + securityIdsInFinalMaps : CapTableMaps -> Update [Text] securityIdsInFinalMaps maps = do convertibleSecurityIds <- foldlA @@ -3339,6 +3346,18 @@ validateOptionalStockClassReference label maps stockClassId = case stockClassId Some id -> validateStockClassReference label maps id None -> pure () +assertDateOnOrAfter : Text -> Time -> Text -> Time -> Update () +assertDateOnOrAfter label eventDate referenceLabel referenceDate = + assertMsg + (label <> " date " <> show eventDate <> " cannot precede " <> referenceLabel <> " date " <> show referenceDate) + (eventDate >= referenceDate) + +assertOptionalApprovalDateOnOrBefore : Text -> Text -> Optional Time -> Text -> Time -> Update () +assertOptionalApprovalDateOnOrBefore label approvalLabel approvalDate eventLabel eventDate = + case approvalDate of + Some date -> assertDateOnOrAfter (label <> " " <> eventLabel) eventDate (label <> " " <> approvalLabel) date + None -> pure () + validateStockClassConversionRightReferences : CapTableMaps -> Update () validateStockClassConversionRightReferences maps = mapA_ @@ -3425,6 +3444,406 @@ validateStockIssuanceReferences maps = validateOptionalReference "Stock issuance vesting terms" maps.vesting_terms issuance.issuance_data.vesting_terms_id) (Map.values maps.stock_issuances) +validateStockSourceTransactionDate : CapTableMaps -> Text -> Time -> Text -> Update () +validateStockSourceTransactionDate maps label transactionDate securityId = + case Map.lookup securityId maps.stock_issuances_by_security_id of + Some issuanceCid -> do + issuance <- fetch issuanceCid + assertDateOnOrAfter label transactionDate ("stock issuance " <> issuance.issuance_data.id) issuance.issuance_data.date + None -> pure () + +validateConvertibleSourceTransactionDate : CapTableMaps -> Text -> Time -> Text -> Update () +validateConvertibleSourceTransactionDate maps label transactionDate securityId = + case Map.lookup securityId maps.convertible_issuances_by_security_id of + Some issuanceCid -> do + issuance <- fetch issuanceCid + assertDateOnOrAfter label transactionDate ("convertible issuance " <> issuance.issuance_data.id) issuance.issuance_data.date + None -> pure () + +validateWarrantSourceTransactionDate : CapTableMaps -> Text -> Time -> Text -> Update () +validateWarrantSourceTransactionDate maps label transactionDate securityId = + case Map.lookup securityId maps.warrant_issuances_by_security_id of + Some issuanceCid -> do + issuance <- fetch issuanceCid + assertDateOnOrAfter label transactionDate ("warrant issuance " <> issuance.issuance_data.id) issuance.issuance_data.date + None -> pure () + +validateEquityCompensationSourceTransactionDate : CapTableMaps -> Text -> Time -> Text -> Update () +validateEquityCompensationSourceTransactionDate maps label transactionDate securityId = + case Map.lookup securityId maps.equity_compensation_issuances_by_security_id of + Some issuanceCid -> do + issuance <- fetch issuanceCid + assertDateOnOrAfter label transactionDate ("equity compensation issuance " <> issuance.issuance_data.id) issuance.issuance_data.date + None -> pure () + +validateStockOutputDate : CapTableMaps -> Text -> Time -> Text -> Update () +validateStockOutputDate maps label transactionDate securityId = + case Map.lookup securityId maps.stock_issuances_by_security_id of + Some issuanceCid -> do + issuance <- fetch issuanceCid + assertDateOnOrAfter (label <> " output stock issuance " <> issuance.issuance_data.id) issuance.issuance_data.date label transactionDate + None -> + assertMsg + (label <> " output security is not a stock issuance: " <> securityId) + (not (securityIdExists maps securityId)) + +validateConvertibleOutputDate : CapTableMaps -> Text -> Time -> Text -> Update () +validateConvertibleOutputDate maps label transactionDate securityId = + case Map.lookup securityId maps.convertible_issuances_by_security_id of + Some issuanceCid -> do + issuance <- fetch issuanceCid + assertMsg + (label <> " output convertible issuance date mismatch for " <> securityId <> ": expected " <> show transactionDate <> ", found " <> show issuance.issuance_data.date) + (issuance.issuance_data.date == transactionDate) + None -> + assertMsg + (label <> " output security is not a convertible issuance: " <> securityId) + (not (securityIdExists maps securityId)) + +validateWarrantOutputDate : CapTableMaps -> Text -> Time -> Text -> Update () +validateWarrantOutputDate maps label transactionDate securityId = + case Map.lookup securityId maps.warrant_issuances_by_security_id of + Some issuanceCid -> do + issuance <- fetch issuanceCid + assertDateOnOrAfter (label <> " output warrant issuance " <> issuance.issuance_data.id) issuance.issuance_data.date label transactionDate + None -> + assertMsg + (label <> " output security is not a warrant issuance: " <> securityId) + (not (securityIdExists maps securityId)) + +validateEquityCompensationOutputDate : CapTableMaps -> Text -> Time -> Text -> Update () +validateEquityCompensationOutputDate maps label transactionDate securityId = + case Map.lookup securityId maps.equity_compensation_issuances_by_security_id of + Some issuanceCid -> do + issuance <- fetch issuanceCid + assertDateOnOrAfter (label <> " output equity compensation issuance " <> issuance.issuance_data.id) issuance.issuance_data.date label transactionDate + None -> + assertMsg + (label <> " output security is not an equity compensation issuance: " <> securityId) + (not (securityIdExists maps securityId)) + +validateVestingSourceTransactionDate : CapTableMaps -> Text -> Time -> Text -> Update () +validateVestingSourceTransactionDate maps label transactionDate securityId = + case Map.lookup securityId maps.stock_issuances_by_security_id of + Some _ -> validateStockSourceTransactionDate maps label transactionDate securityId + None -> case Map.lookup securityId maps.warrant_issuances_by_security_id of + Some _ -> validateWarrantSourceTransactionDate maps label transactionDate securityId + None -> case Map.lookup securityId maps.equity_compensation_issuances_by_security_id of + Some _ -> validateEquityCompensationSourceTransactionDate maps label transactionDate securityId + None -> pure () + +validateOptionalStockOutputDate : CapTableMaps -> Text -> Time -> Optional Text -> Update () +validateOptionalStockOutputDate maps label transactionDate securityIdOpt = case securityIdOpt of + Some securityId -> validateStockOutputDate maps label transactionDate securityId + None -> pure () + +validateOptionalConvertibleOutputDate : CapTableMaps -> Text -> Time -> Optional Text -> Update () +validateOptionalConvertibleOutputDate maps label transactionDate securityIdOpt = case securityIdOpt of + Some securityId -> validateConvertibleOutputDate maps label transactionDate securityId + None -> pure () + +validateOptionalWarrantOutputDate : CapTableMaps -> Text -> Time -> Optional Text -> Update () +validateOptionalWarrantOutputDate maps label transactionDate securityIdOpt = case securityIdOpt of + Some securityId -> validateWarrantOutputDate maps label transactionDate securityId + None -> pure () + +validateOptionalEquityCompensationOutputDate : CapTableMaps -> Text -> Time -> Optional Text -> Update () +validateOptionalEquityCompensationOutputDate maps label transactionDate securityIdOpt = case securityIdOpt of + Some securityId -> validateEquityCompensationOutputDate maps label transactionDate securityId + None -> pure () + +validateStockLifecycleDates : CapTableMaps -> Update () +validateStockLifecycleDates maps = do + mapA_ + (\acceptanceCid -> do + acceptance <- fetch acceptanceCid + validateStockSourceTransactionDate maps ("Stock acceptance " <> acceptance.acceptance_data.id) acceptance.acceptance_data.date acceptance.acceptance_data.security_id) + (Map.values maps.stock_acceptances) + + mapA_ + (\cancellationCid -> do + cancellation <- fetch cancellationCid + let label = "Stock cancellation " <> cancellation.cancellation_data.id + validateStockSourceTransactionDate maps label cancellation.cancellation_data.date cancellation.cancellation_data.security_id + validateOptionalStockOutputDate maps label cancellation.cancellation_data.date cancellation.cancellation_data.balance_security_id) + (Map.values maps.stock_cancellations) + + mapA_ + (\repurchaseCid -> do + repurchase <- fetch repurchaseCid + let label = "Stock repurchase " <> repurchase.repurchase_data.id + validateStockSourceTransactionDate maps label repurchase.repurchase_data.date repurchase.repurchase_data.security_id + validateOptionalStockOutputDate maps label repurchase.repurchase_data.date repurchase.repurchase_data.balance_security_id) + (Map.values maps.stock_repurchases) + + mapA_ + (\transferCid -> do + transfer <- fetch transferCid + let label = "Stock transfer " <> transfer.transfer_data.id + validateStockSourceTransactionDate maps label transfer.transfer_data.date transfer.transfer_data.security_id + validateOptionalStockOutputDate maps label transfer.transfer_data.date transfer.transfer_data.balance_security_id + mapA_ (validateStockOutputDate maps label transfer.transfer_data.date) transfer.transfer_data.resulting_security_ids) + (Map.values maps.stock_transfers) + + mapA_ + (\conversionCid -> do + conversion <- fetch conversionCid + let label = "Stock conversion " <> conversion.conversion_data.id + validateStockSourceTransactionDate maps label conversion.conversion_data.date conversion.conversion_data.security_id + validateOptionalStockOutputDate maps label conversion.conversion_data.date conversion.conversion_data.balance_security_id + mapA_ (validateStockOutputDate maps label conversion.conversion_data.date) conversion.conversion_data.resulting_security_ids) + (Map.values maps.stock_conversions) + + mapA_ + (\retractionCid -> do + retraction <- fetch retractionCid + validateStockSourceTransactionDate maps ("Stock retraction " <> retraction.retraction_data.id) retraction.retraction_data.date retraction.retraction_data.security_id) + (Map.values maps.stock_retractions) + + mapA_ + (\reissuanceCid -> do + reissuance <- fetch reissuanceCid + let label = "Stock reissuance " <> reissuance.reissuance_data.id + validateStockSourceTransactionDate maps label reissuance.reissuance_data.date reissuance.reissuance_data.security_id + mapA_ (validateStockOutputDate maps label reissuance.reissuance_data.date) reissuance.reissuance_data.resulting_security_ids) + (Map.values maps.stock_reissuances) + + mapA_ + (\consolidationCid -> do + consolidation <- fetch consolidationCid + let label = "Stock consolidation " <> consolidation.consolidation_data.id + mapA_ (validateStockSourceTransactionDate maps label consolidation.consolidation_data.date) consolidation.consolidation_data.security_ids + validateStockOutputDate maps label consolidation.consolidation_data.date consolidation.consolidation_data.resulting_security_id) + (Map.values maps.stock_consolidations) + +validateConvertibleLifecycleDates : CapTableMaps -> Update () +validateConvertibleLifecycleDates maps = do + mapA_ + (\acceptanceCid -> do + acceptance <- fetch acceptanceCid + validateConvertibleSourceTransactionDate maps ("Convertible acceptance " <> acceptance.acceptance_data.id) acceptance.acceptance_data.date acceptance.acceptance_data.security_id) + (Map.values maps.convertible_acceptances) + + mapA_ + (\cancellationCid -> do + cancellation <- fetch cancellationCid + let label = "Convertible cancellation " <> cancellation.cancellation_data.id + validateConvertibleSourceTransactionDate maps label cancellation.cancellation_data.date cancellation.cancellation_data.security_id + validateOptionalConvertibleOutputDate maps label cancellation.cancellation_data.date cancellation.cancellation_data.balance_security_id) + (Map.values maps.convertible_cancellations) + + mapA_ + (\transferCid -> do + transfer <- fetch transferCid + let label = "Convertible transfer " <> transfer.transfer_data.id + validateConvertibleSourceTransactionDate maps label transfer.transfer_data.date transfer.transfer_data.security_id + validateOptionalConvertibleOutputDate maps label transfer.transfer_data.date transfer.transfer_data.balance_security_id + mapA_ (validateConvertibleOutputDate maps label transfer.transfer_data.date) transfer.transfer_data.resulting_security_ids) + (Map.values maps.convertible_transfers) + + mapA_ + (\conversionCid -> do + conversion <- fetch conversionCid + let label = "Convertible conversion " <> conversion.conversion_data.id + validateConvertibleSourceTransactionDate maps label conversion.conversion_data.date conversion.conversion_data.security_id + validateOptionalConvertibleOutputDate maps label conversion.conversion_data.date conversion.conversion_data.balance_security_id + mapA_ (validateStockOutputDate maps label conversion.conversion_data.date) conversion.conversion_data.resulting_security_ids) + (Map.values maps.convertible_conversions) + + mapA_ + (\retractionCid -> do + retraction <- fetch retractionCid + validateConvertibleSourceTransactionDate maps ("Convertible retraction " <> retraction.retraction_data.id) retraction.retraction_data.date retraction.retraction_data.security_id) + (Map.values maps.convertible_retractions) + +validateWarrantLifecycleDates : CapTableMaps -> Update () +validateWarrantLifecycleDates maps = do + mapA_ + (\acceptanceCid -> do + acceptance <- fetch acceptanceCid + validateWarrantSourceTransactionDate maps ("Warrant acceptance " <> acceptance.acceptance_data.id) acceptance.acceptance_data.date acceptance.acceptance_data.security_id) + (Map.values maps.warrant_acceptances) + + mapA_ + (\cancellationCid -> do + cancellation <- fetch cancellationCid + let label = "Warrant cancellation " <> cancellation.cancellation_data.id + validateWarrantSourceTransactionDate maps label cancellation.cancellation_data.date cancellation.cancellation_data.security_id + validateOptionalWarrantOutputDate maps label cancellation.cancellation_data.date cancellation.cancellation_data.balance_security_id) + (Map.values maps.warrant_cancellations) + + mapA_ + (\transferCid -> do + transfer <- fetch transferCid + let label = "Warrant transfer " <> transfer.transfer_data.id + validateWarrantSourceTransactionDate maps label transfer.transfer_data.date transfer.transfer_data.security_id + validateOptionalWarrantOutputDate maps label transfer.transfer_data.date transfer.transfer_data.balance_security_id + mapA_ (validateWarrantOutputDate maps label transfer.transfer_data.date) transfer.transfer_data.resulting_security_ids) + (Map.values maps.warrant_transfers) + + mapA_ + (\exerciseCid -> do + exercise <- fetch exerciseCid + let label = "Warrant exercise " <> exercise.exercise_data.id + validateWarrantSourceTransactionDate maps label exercise.exercise_data.date exercise.exercise_data.security_id + mapA_ (validateStockOutputDate maps label exercise.exercise_data.date) exercise.exercise_data.resulting_security_ids) + (Map.values maps.warrant_exercises) + + mapA_ + (\retractionCid -> do + retraction <- fetch retractionCid + validateWarrantSourceTransactionDate maps ("Warrant retraction " <> retraction.retraction_data.id) retraction.retraction_data.date retraction.retraction_data.security_id) + (Map.values maps.warrant_retractions) + +validateEquityCompensationLifecycleDates : CapTableMaps -> Update () +validateEquityCompensationLifecycleDates maps = do + mapA_ + (\acceptanceCid -> do + acceptance <- fetch acceptanceCid + validateEquityCompensationSourceTransactionDate maps ("Equity compensation acceptance " <> acceptance.acceptance_data.id) acceptance.acceptance_data.date acceptance.acceptance_data.security_id) + (Map.values maps.equity_compensation_acceptances) + + mapA_ + (\cancellationCid -> do + cancellation <- fetch cancellationCid + let label = "Equity compensation cancellation " <> cancellation.cancellation_data.id + validateEquityCompensationSourceTransactionDate maps label cancellation.cancellation_data.date cancellation.cancellation_data.security_id + validateOptionalEquityCompensationOutputDate maps label cancellation.cancellation_data.date cancellation.cancellation_data.balance_security_id) + (Map.values maps.equity_compensation_cancellations) + + mapA_ + (\transferCid -> do + transfer <- fetch transferCid + let label = "Equity compensation transfer " <> transfer.transfer_data.id + validateEquityCompensationSourceTransactionDate maps label transfer.transfer_data.date transfer.transfer_data.security_id + validateOptionalEquityCompensationOutputDate maps label transfer.transfer_data.date transfer.transfer_data.balance_security_id + mapA_ (validateEquityCompensationOutputDate maps label transfer.transfer_data.date) transfer.transfer_data.resulting_security_ids) + (Map.values maps.equity_compensation_transfers) + + mapA_ + (\exerciseCid -> do + exercise <- fetch exerciseCid + let label = "Equity compensation exercise " <> exercise.exercise_data.id + validateEquityCompensationSourceTransactionDate maps label exercise.exercise_data.date exercise.exercise_data.security_id + mapA_ (validateStockOutputDate maps label exercise.exercise_data.date) exercise.exercise_data.resulting_security_ids) + (Map.values maps.equity_compensation_exercises) + + mapA_ + (\releaseCid -> do + release <- fetch releaseCid + let label = "Equity compensation release " <> release.release_data.id + validateEquityCompensationSourceTransactionDate maps label release.release_data.date release.release_data.security_id + assertDateOnOrAfter (label <> " settlement") release.release_data.settlement_date label release.release_data.date + mapA_ (validateStockOutputDate maps label release.release_data.settlement_date) release.release_data.resulting_security_ids) + (Map.values maps.equity_compensation_releases) + + mapA_ + (\repricingCid -> do + repricing <- fetch repricingCid + validateEquityCompensationSourceTransactionDate maps ("Equity compensation repricing " <> repricing.repricing_data.id) repricing.repricing_data.date repricing.repricing_data.security_id) + (Map.values maps.equity_compensation_repricings) + + mapA_ + (\retractionCid -> do + retraction <- fetch retractionCid + validateEquityCompensationSourceTransactionDate maps ("Equity compensation retraction " <> retraction.retraction_data.id) retraction.retraction_data.date retraction.retraction_data.security_id) + (Map.values maps.equity_compensation_retractions) + +validateVestingLifecycleDates : CapTableMaps -> Update () +validateVestingLifecycleDates maps = do + mapA_ + (\startCid -> do + start <- fetch startCid + validateVestingSourceTransactionDate maps ("Vesting start " <> start.vesting_data.id) start.vesting_data.date start.vesting_data.security_id) + (Map.values maps.vesting_starts) + + mapA_ + (\eventCid -> do + event <- fetch eventCid + validateVestingSourceTransactionDate maps ("Vesting event " <> event.vesting_data.id) event.vesting_data.date event.vesting_data.security_id) + (Map.values maps.vesting_events) + + mapA_ + (\accelerationCid -> do + acceleration <- fetch accelerationCid + validateVestingSourceTransactionDate maps ("Vesting acceleration " <> acceleration.acceleration_data.id) acceleration.acceleration_data.date acceleration.acceleration_data.security_id) + (Map.values maps.vesting_accelerations) + +validateTransactionLifecycleDates : CapTableMaps -> Update () +validateTransactionLifecycleDates maps = do + validateApprovalDateConsistency maps + validateStockLifecycleDates maps + validateConvertibleLifecycleDates maps + validateWarrantLifecycleDates maps + validateEquityCompensationLifecycleDates maps + validateVestingLifecycleDates maps + +validateApprovalDateConsistency : CapTableMaps -> Update () +validateApprovalDateConsistency maps = do + mapA_ + (\issuanceCid -> do + issuance <- fetch issuanceCid + let label = "Convertible issuance " <> issuance.issuance_data.id + assertOptionalApprovalDateOnOrBefore label "board approval" issuance.issuance_data.board_approval_date "transaction" issuance.issuance_data.date + assertOptionalApprovalDateOnOrBefore label "stockholder approval" issuance.issuance_data.stockholder_approval_date "transaction" issuance.issuance_data.date) + (Map.values maps.convertible_issuances) + + mapA_ + (\issuanceCid -> do + issuance <- fetch issuanceCid + let label = "Equity compensation issuance " <> issuance.issuance_data.id + assertOptionalApprovalDateOnOrBefore label "board approval" issuance.issuance_data.board_approval_date "transaction" issuance.issuance_data.date + assertOptionalApprovalDateOnOrBefore label "stockholder approval" issuance.issuance_data.stockholder_approval_date "transaction" issuance.issuance_data.date) + (Map.values maps.equity_compensation_issuances) + + mapA_ + (\adjustmentCid -> do + adjustment <- fetch adjustmentCid + let label = "Issuer authorized shares adjustment " <> adjustment.adjustment_data.id + assertOptionalApprovalDateOnOrBefore label "board approval" adjustment.adjustment_data.board_approval_date "transaction" adjustment.adjustment_data.date + assertOptionalApprovalDateOnOrBefore label "stockholder approval" adjustment.adjustment_data.stockholder_approval_date "transaction" adjustment.adjustment_data.date) + (Map.values maps.issuer_authorized_shares_adjustments) + + mapA_ + (\adjustmentCid -> do + adjustment <- fetch adjustmentCid + let label = "Stock class authorized shares adjustment " <> adjustment.adjustment_data.id + assertOptionalApprovalDateOnOrBefore label "board approval" adjustment.adjustment_data.board_approval_date "transaction" adjustment.adjustment_data.date + assertOptionalApprovalDateOnOrBefore label "stockholder approval" adjustment.adjustment_data.stockholder_approval_date "transaction" adjustment.adjustment_data.date) + (Map.values maps.stock_class_authorized_shares_adjustments) + + mapA_ + (\issuanceCid -> do + issuance <- fetch issuanceCid + let label = "Stock issuance " <> issuance.issuance_data.id + assertOptionalApprovalDateOnOrBefore label "board approval" issuance.issuance_data.board_approval_date "transaction" issuance.issuance_data.date + assertOptionalApprovalDateOnOrBefore label "stockholder approval" issuance.issuance_data.stockholder_approval_date "transaction" issuance.issuance_data.date) + (Map.values maps.stock_issuances) + + mapA_ + (\adjustmentCid -> do + adjustment <- fetch adjustmentCid + let label = "Stock plan pool adjustment " <> adjustment.adjustment_data.id + assertOptionalApprovalDateOnOrBefore label "board approval" adjustment.adjustment_data.board_approval_date "transaction" adjustment.adjustment_data.date + assertOptionalApprovalDateOnOrBefore label "stockholder approval" adjustment.adjustment_data.stockholder_approval_date "transaction" adjustment.adjustment_data.date) + (Map.values maps.stock_plan_pool_adjustments) + + mapA_ + (\valuationCid -> do + valuation <- fetch valuationCid + let label = "Valuation " <> valuation.valuation_data.id + assertOptionalApprovalDateOnOrBefore label "board approval" valuation.valuation_data.board_approval_date "effective" valuation.valuation_data.effective_date + assertOptionalApprovalDateOnOrBefore label "stockholder approval" valuation.valuation_data.stockholder_approval_date "effective" valuation.valuation_data.effective_date) + (Map.values maps.valuations) + + mapA_ + (\issuanceCid -> do + issuance <- fetch issuanceCid + let label = "Warrant issuance " <> issuance.issuance_data.id + assertOptionalApprovalDateOnOrBefore label "board approval" issuance.issuance_data.board_approval_date "transaction" issuance.issuance_data.date + assertOptionalApprovalDateOnOrBefore label "stockholder approval" issuance.issuance_data.stockholder_approval_date "transaction" issuance.issuance_data.date) + (Map.values maps.warrant_issuances) + data StockIssuanceShareNumberLot = StockIssuanceShareNumberLot with stock_class_id: Text issuance_id: Text @@ -6246,6 +6665,7 @@ template CapTable validateConfiguredReferences finalMaps validateFinalSecurityIdUniqueness finalMaps validateSuccessorSecurityIdContinuity finalMaps + validateTransactionLifecycleDates finalMaps validateStockBalanceSuccessorQuantities stockEventIndex finalMaps validateNonStockBalanceSuccessorQuantities stockEventIndex nonStockBalanceEventIndex finalMaps validateStockSecurityBalances stockEventIndex finalMaps