Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8f498c3
Enforce global security id uniqueness
HardlyDifficult Jul 9, 2026
69cae78
Merge remote-tracking branch 'origin/codex/ocf-vesting-graph-integrit…
HardlyDifficult Jul 9, 2026
019d401
Refresh security id DAR after vesting merge
HardlyDifficult Jul 9, 2026
f1c8eee
Merge remote-tracking branch 'origin/codex/ocf-vesting-graph-integrit…
HardlyDifficult Jul 9, 2026
b0c4766
Refresh security id DAR after vesting update
HardlyDifficult Jul 9, 2026
3b83a24
Merge remote-tracking branch 'origin/codex/ocf-vesting-graph-integrit…
HardlyDifficult Jul 9, 2026
bb52fcd
Refresh security id DAR after vesting fixes
HardlyDifficult Jul 9, 2026
7a105ca
Merge remote-tracking branch 'origin/codex/ocf-vesting-graph-integrit…
HardlyDifficult Jul 9, 2026
dfa0f14
Refresh security id DAR after reference fold
HardlyDifficult Jul 9, 2026
0126fdb
Enforce transaction lifecycle dates
HardlyDifficult Jul 9, 2026
1ae9713
Validate final security ID uniqueness
HardlyDifficult Jul 9, 2026
70b1f1d
Merge remote-tracking branch 'origin/codex/ocf-vesting-graph-integrit…
HardlyDifficult Jul 9, 2026
5fd583a
Refresh security ID DAR after reference updates
HardlyDifficult Jul 9, 2026
6b3f649
Merge remote-tracking branch 'origin/codex/ocf-security-id-uniqueness…
HardlyDifficult Jul 9, 2026
f27eec6
Refresh lifecycle DAR after reference updates
HardlyDifficult Jul 9, 2026
9139d35
Merge remote-tracking branch 'origin/codex/ocf-vesting-graph-integrit…
HardlyDifficult Jul 9, 2026
133300b
Refresh security ID DAR after vesting updates
HardlyDifficult Jul 9, 2026
d644372
Merge remote-tracking branch 'origin/codex/ocf-security-id-uniqueness…
HardlyDifficult Jul 9, 2026
e6a0e8c
Refresh lifecycle DAR after security updates
HardlyDifficult Jul 9, 2026
d08558b
Expand lifecycle date validation coverage
HardlyDifficult Jul 9, 2026
603d9dd
fix: close lifecycle validation gaps
HardlyDifficult Jul 10, 2026
5121feb
Merge commit 'a5fbd9d' into codex/ocf-security-id-uniqueness
HardlyDifficult Jul 10, 2026
bae63d4
feat: enforce lifecycle successor ID uniqueness
HardlyDifficult Jul 10, 2026
227cbb3
Merge commit 'bae63d4' into codex/ocf-transaction-lifecycle-dates
HardlyDifficult Jul 10, 2026
0901de0
Merge commit '8b1992f' into codex/ocf-security-id-uniqueness
HardlyDifficult Jul 10, 2026
97a5fd0
Merge commit '0901de0' into codex/ocf-transaction-lifecycle-dates
HardlyDifficult Jul 10, 2026
8fadb10
Merge remote-tracking branch 'origin/codex/ocf-vesting-graph-integrit…
HardlyDifficult Jul 11, 2026
48872c5
Merge remote-tracking branch 'origin/codex/ocf-vesting-graph-integrit…
HardlyDifficult Jul 11, 2026
98118c2
chore: refresh lifecycle DAR after parent update
HardlyDifficult Jul 11, 2026
3305146
Merge remote-tracking branch 'origin/codex/ocf-vesting-graph-integrit…
HardlyDifficult Jul 11, 2026
c6726ec
chore: refresh lifecycle DAR after parent update
HardlyDifficult Jul 11, 2026
36866de
Merge remote-tracking branch 'origin/codex/ocf-vesting-graph-integrit…
HardlyDifficult Jul 11, 2026
1a042c5
chore: refresh lifecycle date DAR
HardlyDifficult Jul 11, 2026
4d90aa7
fix: require exact convertible successor dates
HardlyDifficult Jul 11, 2026
a0306fa
Validate approval dates against event dates
HardlyDifficult Jul 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion OpenCapTable-v34/daml.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion Test/daml.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
181 changes: 181 additions & 0 deletions Test/daml/OpenCapTable/TestApprovalDateConsistency.daml
Original file line number Diff line number Diff line change
@@ -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 ()
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down
4 changes: 2 additions & 2 deletions Test/daml/OpenCapTable/TestStockPlanPoolAdjustment.daml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down
Loading
Loading