Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
4e07ce3
feat: enforce OCF reference integrity
HardlyDifficult Jul 9, 2026
167b4b9
Restack reference integrity on authorized share ceilings
HardlyDifficult Jul 9, 2026
9859c94
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 9, 2026
cdb3c7f
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 9, 2026
7a7c4be
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 9, 2026
ece7511
Restack reference integrity on share ceiling
HardlyDifficult Jul 9, 2026
4175b9e
Restack reference integrity on indexed share ceilings
HardlyDifficult Jul 9, 2026
45c6352
Address reference integrity review feedback
HardlyDifficult Jul 9, 2026
37674c1
Allow equity compensation same-batch reference edits
HardlyDifficult Jul 9, 2026
942fb17
Merge authorized ceiling base into reference integrity
HardlyDifficult Jul 9, 2026
6529ed3
Group reference integrity enforcement
HardlyDifficult Jul 9, 2026
9d96dcf
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 9, 2026
b2fcf46
Address reference integrity review comments
HardlyDifficult Jul 9, 2026
206ce52
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 9, 2026
ead5716
Clarify final issuance reference validation
HardlyDifficult Jul 9, 2026
0cc050c
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 9, 2026
3dc1d9c
Update reference integrity DAR backup
HardlyDifficult Jul 9, 2026
aa5a1d1
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 9, 2026
3273664
Refresh reference integrity DAR after base update
HardlyDifficult Jul 9, 2026
8ad8853
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 9, 2026
e5f08cc
Refresh reference integrity DAR after ceiling update
HardlyDifficult Jul 9, 2026
e862d6e
Revalidate configured references after deletes
HardlyDifficult Jul 9, 2026
6a512b7
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 9, 2026
25df21e
Refresh reference integrity after ceiling update
HardlyDifficult Jul 9, 2026
ef5a898
Validate stock plan class membership
HardlyDifficult Jul 9, 2026
9e49a9a
Enforce vesting transaction condition references
HardlyDifficult Jul 9, 2026
a6b5f6c
Validate equity plan stock class references
HardlyDifficult Jul 9, 2026
091e046
Test orphaned stock issuance references
HardlyDifficult Jul 10, 2026
a7b1197
fix: avoid partial vesting condition match
HardlyDifficult Jul 10, 2026
40f99b4
test: cover reference review edge cases
HardlyDifficult Jul 10, 2026
6565bf0
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 10, 2026
cda94f8
fix: align reference checks with ceiling parent
HardlyDifficult Jul 10, 2026
0dff01e
fix: close reference integrity review gaps
HardlyDifficult Jul 10, 2026
6a2ba88
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 10, 2026
600a672
Merge commit 'ac8a405ee15cff886fccfe6f4b3f784267955ef5' into codex/oc…
HardlyDifficult Jul 10, 2026
9d00073
chore: refresh reference integrity DAR
HardlyDifficult Jul 10, 2026
2c0c9ea
Merge branch 'codex/ocf-stock-class-share-ceiling' into codex/ocf-ref…
HardlyDifficult Jul 10, 2026
69f1755
test: align reference fixture with ceiling base
HardlyDifficult Jul 10, 2026
48ee919
Merge commit '22d0e24' into codex/ocf-reference-integrity-category
HardlyDifficult Jul 10, 2026
67fe05a
test: cover duplicate trigger IDs on edits
HardlyDifficult Jul 10, 2026
89a1c48
feat: enforce lifecycle successor references
HardlyDifficult Jul 10, 2026
9f352e8
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 10, 2026
5272fc8
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 11, 2026
4c0c5a2
chore: refresh reference integrity DAR after restack
HardlyDifficult Jul 11, 2026
feb1f62
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 11, 2026
7ff47b7
chore: refresh deterministic reference integrity DAR
HardlyDifficult Jul 11, 2026
df55f69
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 11, 2026
976ab4f
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 11, 2026
fc71c51
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 11, 2026
55aa332
Merge remote-tracking branch 'origin/codex/ocf-stock-class-share-ceil…
HardlyDifficult Jul 11, 2026
f4788cc
chore: refresh reference integrity DAR after parent fix
HardlyDifficult Jul 11, 2026
88ae4aa
docs: align stock plan fixture comment
HardlyDifficult Jul 11, 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.5
version: 0.0.6
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.5.dar
- ../OpenCapTable-v34/.daml/dist/OpenCapTable-v34-0.0.6.dar
build-options:
- -Wno-template-interface-depends-on-daml-script
152 changes: 152 additions & 0 deletions Test/daml/OpenCapTable/TestBalanceSecurityReferences.daml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
module OpenCapTable.TestBalanceSecurityReferences where

import qualified Fairmint.OpenCapTable.CapTable as CT
import Fairmint.OpenCapTable.OCF.ConvertibleCancellation (ConvertibleCancellationOcfData(..))
import Fairmint.OpenCapTable.OCF.EquityCompensationCancellation (EquityCompensationCancellationOcfData(..))
import Fairmint.OpenCapTable.OCF.StockCancellation (StockCancellationOcfData(..))
import Fairmint.OpenCapTable.OCF.WarrantCancellation (WarrantCancellationOcfData(..))
import Fairmint.OpenCapTable.Types.Monetary (OcfMonetary(..))
import OpenCapTable.Setup
import OpenCapTable.TestHelpers
( addDefaultConvertibleIssuance
, addDefaultEquityCompensationIssuance
, addDefaultStakeholder
, addDefaultStockIssuance
, addDefaultWarrantIssuance
, addPrerequisites
, defaultStockIssuance
, defaultTestDate
)
import Daml.Script

testBalanceSecurityReferences_MissingStockSuccessorFails = script do
TestOcp{issuer, cap_table} <- setupTestOcp
capTableCid <- addPrerequisites issuer cap_table
capTableCid <- addDefaultStockIssuance issuer capTableCid

submitMustFail issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateStockCancellation StockCancellationOcfData with
id = "TX-STOCK-MISSING-BALANCE"
date = defaultTestDate
quantity = 10.0
reason_text = "Partial cancellation"
security_id = "SEC-STOCK-1"
comments = []
balance_security_id = Some "SEC-STOCK-MISSING-BALANCE"]
edits = []
deletes = []

testBalanceSecurityReferences_MissingWarrantSuccessorFails = script do
TestOcp{issuer, cap_table} <- setupTestOcp
capTableCid <- addDefaultStakeholder issuer cap_table
capTableCid <- addDefaultWarrantIssuance issuer capTableCid

submitMustFail issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateWarrantCancellation WarrantCancellationOcfData with
id = "TX-WARRANT-MISSING-BALANCE"
date = defaultTestDate
quantity = 10.0
reason_text = "Partial cancellation"
security_id = "SEC-WR-1"
comments = []
balance_security_id = Some "SEC-WARRANT-MISSING-BALANCE"]
edits = []
deletes = []

testBalanceSecurityReferences_MissingConvertibleSuccessorFails = script do
TestOcp{issuer, cap_table} <- setupTestOcp
capTableCid <- addDefaultStakeholder issuer cap_table
capTableCid <- addDefaultConvertibleIssuance issuer capTableCid

submitMustFail issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateConvertibleCancellation ConvertibleCancellationOcfData with
id = "TX-CONVERTIBLE-MISSING-BALANCE"
amount = OcfMonetary with amount = 10.0, currency = "USD"
date = defaultTestDate
reason_text = "Partial cancellation"
security_id = "SEC-CV-1"
comments = []
balance_security_id = Some "SEC-CONVERTIBLE-MISSING-BALANCE"]
edits = []
deletes = []

testBalanceSecurityReferences_MissingEquityCompensationSuccessorFails = script do
TestOcp{issuer, cap_table} <- setupTestOcp
capTableCid <- addPrerequisites issuer cap_table
capTableCid <- addDefaultEquityCompensationIssuance issuer capTableCid

submitMustFail issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateEquityCompensationCancellation EquityCompensationCancellationOcfData with
id = "TX-EC-MISSING-BALANCE"
date = defaultTestDate
quantity = 10.0
reason_text = "Partial cancellation"
security_id = "SEC-EC-1"
comments = []
balance_security_id = Some "SEC-EC-MISSING-BALANCE"]
edits = []
deletes = []

testBalanceSecurityReferences_StockSuccessorCreatedInSameBatchSucceeds = script do
TestOcp{issuer, cap_table} <- setupTestOcp
capTableCid <- addPrerequisites issuer cap_table
capTableCid <- addDefaultStockIssuance issuer capTableCid
let balanceIssuance = (defaultStockIssuance
"TX-STOCK-BALANCE-SUCCESSOR"
"SEC-STOCK-BALANCE-SUCCESSOR"
"SH-1"
"SC_COMMON") with quantity = 90.0

_ <- submit issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates =
[ CT.OcfCreateStockIssuance balanceIssuance
, CT.OcfCreateStockCancellation StockCancellationOcfData with
id = "TX-STOCK-CANCELLATION-BALANCE-SUCCESSOR"
date = defaultTestDate
quantity = 10.0
reason_text = "Partial cancellation"
security_id = "SEC-STOCK-1"
comments = []
balance_security_id = Some "SEC-STOCK-BALANCE-SUCCESSOR"
]
edits = []
deletes = []
pure ()

testBalanceSecurityReferences_EditCanCreateStockSuccessorInSameBatch = script do
TestOcp{issuer, cap_table} <- setupTestOcp
capTableCid <- addPrerequisites issuer cap_table
capTableCid <- addDefaultStockIssuance issuer capTableCid
let cancellation = StockCancellationOcfData with
id = "TX-STOCK-EDIT-BALANCE"
date = defaultTestDate
quantity = 10.0
reason_text = "Partial cancellation"
security_id = "SEC-STOCK-1"
comments = []
balance_security_id = None

created <- submit issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateStockCancellation cancellation]
edits = []
deletes = []

let balanceIssuance = (defaultStockIssuance
"TX-STOCK-EDIT-BALANCE-SUCCESSOR"
"SEC-STOCK-EDIT-BALANCE-SUCCESSOR"
"SH-1"
"SC_COMMON") with quantity = 90.0

_ <- submit issuer do
exerciseCmd created.updatedCapTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateStockIssuance balanceIssuance]
edits = [CT.OcfEditStockCancellation (cancellation with
balance_security_id = Some "SEC-STOCK-EDIT-BALANCE-SUCCESSOR")]
deletes = []
pure ()
72 changes: 39 additions & 33 deletions Test/daml/OpenCapTable/TestConversionMechanisms.daml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Fairmint.OpenCapTable.Types.Monetary (OcfMonetary(..))
import Fairmint.OpenCapTable.Types.Stock (OcfInitialSharesAuthorized(..), OcfQuantitySourceType(..), OcfRatio(..), OcfStockClassType(..))
import OpenCapTable.HelpersTriggers (ocfTriggerElectiveAtWill)
import OpenCapTable.Setup
import OpenCapTable.TestHelpers (addDefaultStakeholder)
import OpenCapTable.TestHelpers (addDefaultStakeholder, defaultStockClass)

testTime : Time
testTime = DT.time (DA.date 2024 Jan 1) 0 0 0
Expand Down Expand Up @@ -392,22 +392,25 @@ testConversionMechanismRights_AllValidVariantsCreate = script do
capTableCid <- addDefaultStakeholder issuer cap_table
result1 <- submit issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateStockClass StockClassOcfData with
id = "SC_PREFERRED_ALL_CONVERSION_MECHANISMS"
name = "Preferred All Conversion Mechanisms"
class_type = OcfStockClassTypePreferred
default_id_prefix = "PAM-"
initial_shares_authorized = OcfInitialSharesNumeric 1_000_000.0
votes_per_share = 1.0
seniority = 2.0
board_approval_date = None
stockholder_approval_date = None
par_value = None
price_per_share = None
liquidation_preference_multiple = None
participation_cap_multiple = None
conversion_rights = validStockClassRights
comments = []]
creates =
[ CT.OcfCreateStockClass (defaultStockClass "SC_COMMON")
, CT.OcfCreateStockClass (StockClassOcfData with
id = "SC_PREFERRED_ALL_CONVERSION_MECHANISMS"
name = "Preferred All Conversion Mechanisms"
class_type = OcfStockClassTypePreferred
default_id_prefix = "PAM-"
initial_shares_authorized = OcfInitialSharesNumeric 1_000_000.0
votes_per_share = 1.0
seniority = 2.0
board_approval_date = None
stockholder_approval_date = None
par_value = None
price_per_share = None
liquidation_preference_multiple = None
participation_cap_multiple = None
conversion_rights = validStockClassRights
comments = [])
]
edits = []
deletes = []
result2 <- submit issuer do
Expand Down Expand Up @@ -460,22 +463,25 @@ testConversionMechanismRights_InvalidVariantsReject = script do
capTableCid <- addDefaultStakeholder issuer cap_table
stockControl <- submit issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateStockClass StockClassOcfData with
id = "SC_VALID_CONVERSION_MECHANISM_CONTROL"
name = "Valid Conversion Mechanism Control"
class_type = OcfStockClassTypePreferred
default_id_prefix = "VCM-"
initial_shares_authorized = OcfInitialSharesNumeric 1_000_000.0
votes_per_share = 1.0
seniority = 2.0
board_approval_date = None
stockholder_approval_date = None
par_value = None
price_per_share = None
liquidation_preference_multiple = None
participation_cap_multiple = None
conversion_rights = [stockClassRightWith OcfConversionMechanismRatioConversion None None (Some validRatio) None None None None None]
comments = []]
creates =
[ CT.OcfCreateStockClass (defaultStockClass "SC_COMMON")
, CT.OcfCreateStockClass (StockClassOcfData with
id = "SC_VALID_CONVERSION_MECHANISM_CONTROL"
name = "Valid Conversion Mechanism Control"
class_type = OcfStockClassTypePreferred
default_id_prefix = "VCM-"
initial_shares_authorized = OcfInitialSharesNumeric 1_000_000.0
votes_per_share = 1.0
seniority = 2.0
board_approval_date = None
stockholder_approval_date = None
par_value = None
price_per_share = None
liquidation_preference_multiple = None
participation_cap_multiple = None
conversion_rights = [stockClassRightWith OcfConversionMechanismRatioConversion None None (Some validRatio) None None None None None]
comments = [])
]
edits = []
deletes = []
submitMustFail issuer do
Expand Down
11 changes: 6 additions & 5 deletions Test/daml/OpenCapTable/TestConvertibleCancellation.daml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import qualified DA.Time as DT
import Daml.Script

-- Create a convertible issuance to cancel
createConvertibleIssuance issuer capTableCid securityId amount =
createConvertibleIssuance issuer capTableCid securityId amount issuanceDate =
submit issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateConvertibleIssuance ConvertibleIssuanceOcfData with
id = "TX_CONV_ISS_" <> securityId
date = DT.time (DA.date 2022 Jun 01) 0 0 0
date = issuanceDate
security_id = securityId
custom_id = "SAFE-1"
stakeholder_id = "SH-1"
Expand All @@ -38,7 +38,7 @@ createConvertibleIssuance issuer capTableCid securityId amount =
testConvertibleCancellation_Create = script do
TestOcp{system_operator, issuer, ctx, cap_table} <- setupTestOcp
capTableCid <- addDefaultStakeholder issuer cap_table
result <- createConvertibleIssuance issuer capTableCid "SEC-1" 25000.0
result <- createConvertibleIssuance issuer capTableCid "SEC-1" 25000.0 (DT.time (DA.date 2022 Jun 01) 0 0 0)
_ <- submit issuer do
exerciseCmd result.updatedCapTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateConvertibleCancellation ConvertibleCancellationOcfData with
Expand All @@ -56,9 +56,10 @@ testConvertibleCancellation_Create = script do
testConvertibleCancellation_PartialWithOptionals = script do
TestOcp{system_operator, issuer, ctx, cap_table} <- setupTestOcp
capTableCid <- addDefaultStakeholder issuer cap_table
result <- createConvertibleIssuance issuer capTableCid "SEC-2" 100000.0
result <- createConvertibleIssuance issuer capTableCid "SEC-2" 100000.0 (DT.time (DA.date 2022 Jun 01) 0 0 0)
balanceResult <- createConvertibleIssuance issuer result.updatedCapTableCid "SEC-CONV-PARTIAL-BAL" 75000.0 (DT.time (DA.date 2024 Jun 15) 0 0 0)
_ <- submit issuer do
exerciseCmd result.updatedCapTableCid CT.UpdateCapTable with
exerciseCmd balanceResult.updatedCapTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateConvertibleCancellation ConvertibleCancellationOcfData with
id = "TX_CONV_CANCEL_PARTIAL"
date = DT.time (DA.date 2024 Jun 15) 0 0 0
Expand Down
Loading
Loading