From 7e6d657d24de0dde91df770169830ae1de9d43df Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Wed, 8 Jul 2026 23:57:40 -0400 Subject: [PATCH 01/45] Enforce vesting condition graph integrity --- OpenCapTable-v34/daml.yaml | 2 +- .../OpenCapTable/OCF/VestingTerms.daml | 48 ++++++++++- Test/daml.yaml | 2 +- Test/daml/OpenCapTable/TestVestingTerms.daml | 85 +++++++++++++++++++ .../0.0.7/OpenCapTable-v34.dar | 3 + dars/dars.lock | 7 ++ 6 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar diff --git a/OpenCapTable-v34/daml.yaml b/OpenCapTable-v34/daml.yaml index 70b5e670..cdf810fc 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.6 +version: 0.0.7 build-options: - -Wno-crypto-text-is-alpha - --typecheck-upgrades=no diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index 74ca7364..cc6a8cfa 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -51,7 +51,8 @@ validateOcfVestingTermsData d = d.name /= "" && d.description /= "" && validateNonEmptyStringsArray d.comments && (not (null d.vesting_conditions)) && - all validateOcfVestingCondition d.vesting_conditions + all validateOcfVestingCondition d.vesting_conditions && + validateOcfVestingConditionGraph d.vesting_conditions -- Enum - Allocation Type -- Enumeration of allocation types for vesting terms. Using an example of 18 shares split across 4 tranches, each allocation type results in a different schedule. @@ -221,3 +222,48 @@ validateOcfVestingCondition c = optional True validateOcfVestingConditionPortion c.portion && validateOcfVestingTrigger c.trigger && validateNonEmptyStringsArray c.next_condition_ids + +vestingConditionIds : [OcfVestingCondition] -> [Text] +vestingConditionIds conditions = map (\condition -> condition.id) conditions + +hasDuplicateTexts : [Text] -> Bool +hasDuplicateTexts texts = case texts of + [] -> False + text :: rest -> text `elem` rest || hasDuplicateTexts rest + +conditionById : [OcfVestingCondition] -> Text -> Optional OcfVestingCondition +conditionById conditions conditionId = case conditions of + [] -> None + condition :: rest -> + if condition.id == conditionId + then Some condition + else conditionById rest conditionId + +vestingTriggerReferencesKnownCondition : [Text] -> OcfVestingCondition -> Bool +vestingTriggerReferencesKnownCondition conditionIds condition = case condition.trigger of + OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> + relative_to_condition_id /= condition.id && relative_to_condition_id `elem` conditionIds + _ -> True + +vestingConditionReferencesKnownConditions : [Text] -> OcfVestingCondition -> Bool +vestingConditionReferencesKnownConditions conditionIds condition = + not (hasDuplicateTexts condition.next_condition_ids) && + all (`elem` conditionIds) condition.next_condition_ids && + vestingTriggerReferencesKnownCondition conditionIds condition + +vestingConditionHasCycle : [OcfVestingCondition] -> [Text] -> Text -> Bool +vestingConditionHasCycle conditions path conditionId = + conditionId `elem` path || + case conditionById conditions conditionId of + None -> False + Some condition -> + any + (vestingConditionHasCycle conditions (conditionId :: path)) + condition.next_condition_ids + +validateOcfVestingConditionGraph : [OcfVestingCondition] -> Bool +validateOcfVestingConditionGraph conditions = + let conditionIds = vestingConditionIds conditions + in not (hasDuplicateTexts conditionIds) && + all (vestingConditionReferencesKnownConditions conditionIds) conditions && + not (any (vestingConditionHasCycle conditions []) conditionIds) diff --git a/Test/daml.yaml b/Test/daml.yaml index 0c90f894..0a7b7174 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.6.dar + - ../OpenCapTable-v34/.daml/dist/OpenCapTable-v34-0.0.7.dar build-options: - -Wno-template-interface-depends-on-daml-script diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index 1f0786a6..d3389556 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -25,6 +25,40 @@ createVestingTerms issuer capTableCid = edits = [] deletes = [] +vestingCondition : Text -> OcfVestingTrigger -> [Text] -> OcfVestingCondition +vestingCondition conditionId trigger nextConditionIds = + OcfVestingCondition with + id = conditionId + description = Some conditionId + portion = None + quantity = Some 1.0 + trigger = trigger + next_condition_ids = nextConditionIds + +vestingTermsData : Text -> [OcfVestingCondition] -> VestingTermsOcfData +vestingTermsData vestingTermsId conditions = + VestingTermsOcfData with + id = vestingTermsId + name = vestingTermsId + description = vestingTermsId + allocation_type = OcfAllocationCumulativeRounding + vesting_conditions = conditions + comments = [] + +createVestingTermsData issuer capTableCid data_ = + submit issuer do + exerciseCmd capTableCid CT.UpdateCapTable with + creates = [CT.OcfCreateVestingTerms data_] + edits = [] + deletes = [] + +createVestingTermsDataMustFail issuer capTableCid data_ = + submitMustFail issuer do + exerciseCmd capTableCid CT.UpdateCapTable with + creates = [CT.OcfCreateVestingTerms data_] + edits = [] + deletes = [] + testCreateAndArchiveVestingTerms = script do TestOcp{system_operator, issuer, ctx, cap_table} <- setupTestOcp _ <- createVestingTerms issuer cap_table @@ -113,3 +147,54 @@ testVestingTerms_ZeroDenominatorFails = script do comments = []] edits = [] deletes = [] + +testVestingTerms_DuplicateConditionIdsFail = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let duplicateA = vestingCondition "dup" OcfVestingStartTrigger [] + let duplicateB = vestingCondition "dup" (OcfVestingEventTrigger) [] + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_DUP_COND" [duplicateA, duplicateB]) + pure () + +testVestingTerms_DuplicateNextConditionIdsFail = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let start = vestingCondition "start" OcfVestingStartTrigger ["next", "next"] + let next = vestingCondition "next" OcfVestingEventTrigger [] + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_DUP_NEXT" [start, next]) + pure () + +testVestingTerms_MissingNextConditionIdFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let start = vestingCondition "start" OcfVestingStartTrigger ["missing"] + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_MISSING_NEXT" [start]) + pure () + +testVestingTerms_MissingRelativeConditionIdFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let relative = vestingCondition + "relative" + (OcfVestingScheduleRelativeTrigger with + period = OcfVestingPeriodDays with length_ = 30, occurrences = 1, cliff_installment = None + relative_to_condition_id = "missing") + [] + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_MISSING_RELATIVE" [relative]) + pure () + +testVestingTerms_CyclicNextConditionsFail = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let first = vestingCondition "first" OcfVestingStartTrigger ["second"] + let second = vestingCondition "second" OcfVestingEventTrigger ["first"] + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_CYCLE" [first, second]) + pure () + +testVestingTerms_EditCannotCreateInvalidGraph = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let validStart = vestingCondition "start" OcfVestingStartTrigger ["next"] + let validNext = vestingCondition "next" OcfVestingEventTrigger [] + result <- createVestingTermsData issuer cap_table (vestingTermsData "VT_EDIT_GRAPH" [validStart, validNext]) + let invalidEdit = vestingTermsData "VT_EDIT_GRAPH" [(validStart with next_condition_ids = ["missing"]), validNext] + submitMustFail issuer do + exerciseCmd result.updatedCapTableCid CT.UpdateCapTable with + creates = [] + edits = [CT.OcfEditVestingTerms invalidEdit] + deletes = [] + pure () diff --git a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar new file mode 100644 index 00000000..c5ee1d5b --- /dev/null +++ b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3749f454cd6dee5e307de1cba11ab1dceea6f066aff053493381e3c2eee21e40 +size 2605783 diff --git a/dars/dars.lock b/dars/dars.lock index 6c7bb138..aafca843 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -45,6 +45,13 @@ "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T02:49:48.638Z", "networks": [] + }, + "OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar": { + "sha256": "3749f454cd6dee5e307de1cba11ab1dceea6f066aff053493381e3c2eee21e40", + "size": 2605783, + "sdkVersion": "3.4.10", + "uploadedAt": "2026-07-09T03:55:23.980Z", + "networks": [] } } } From 2bd0754c3c0574426224e85054e61dbae5d27a5d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 04:07:25 +0000 Subject: [PATCH 02/45] Include relative-trigger edges in vesting cycle checks --- .../Fairmint/OpenCapTable/OCF/VestingTerms.daml | 8 +++++++- Test/daml/OpenCapTable/TestVestingTerms.daml | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index cc6a8cfa..d66afa9b 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -251,6 +251,12 @@ vestingConditionReferencesKnownConditions conditionIds condition = all (`elem` conditionIds) condition.next_condition_ids && vestingTriggerReferencesKnownCondition conditionIds condition +vestingConditionEdgeIds : OcfVestingCondition -> [Text] +vestingConditionEdgeIds condition = case condition.trigger of + OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> + relative_to_condition_id :: condition.next_condition_ids + _ -> condition.next_condition_ids + vestingConditionHasCycle : [OcfVestingCondition] -> [Text] -> Text -> Bool vestingConditionHasCycle conditions path conditionId = conditionId `elem` path || @@ -259,7 +265,7 @@ vestingConditionHasCycle conditions path conditionId = Some condition -> any (vestingConditionHasCycle conditions (conditionId :: path)) - condition.next_condition_ids + (vestingConditionEdgeIds condition) validateOcfVestingConditionGraph : [OcfVestingCondition] -> Bool validateOcfVestingConditionGraph conditions = diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index d3389556..225fd327 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -186,6 +186,23 @@ testVestingTerms_CyclicNextConditionsFail = script do createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_CYCLE" [first, second]) pure () +testVestingTerms_RelativeCycleFail = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let first = vestingCondition + "first" + (OcfVestingScheduleRelativeTrigger with + period = OcfVestingPeriodDays with length_ = 30, occurrences = 1, cliff_installment = None + relative_to_condition_id = "second") + [] + let second = vestingCondition + "second" + (OcfVestingScheduleRelativeTrigger with + period = OcfVestingPeriodDays with length_ = 30, occurrences = 1, cliff_installment = None + relative_to_condition_id = "first") + [] + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_CYCLE_RELATIVE" [first, second]) + pure () + testVestingTerms_EditCannotCreateInvalidGraph = script do TestOcp{issuer, cap_table} <- setupTestOcp let validStart = vestingCondition "start" OcfVestingStartTrigger ["next"] From af49a9452f12b936815aa5565677dbfd9bfa5454 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 00:30:48 -0400 Subject: [PATCH 03/45] Fix vesting relative schedule fixture --- Test/daml/OpenCapTable/TestVestingTerms.daml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index 225fd327..8f1cd8ba 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -89,7 +89,7 @@ testVestingTerms_OptionalsSome = script do portion = None quantity = Some 1.0 trigger = OcfVestingStartTrigger - next_condition_ids = ["c1"] + next_condition_ids = [] _ <- submit issuer do exerciseCmd cap_table CT.UpdateCapTable with creates = [CT.OcfCreateVestingTerms VestingTermsOcfData with From 6c9ace48410c5a96a3002866fb2aabb2bc06fc1b Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 00:41:07 -0400 Subject: [PATCH 04/45] Refresh vesting graph DAR backup --- dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar index c5ee1d5b..33d8d494 100644 --- a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3749f454cd6dee5e307de1cba11ab1dceea6f066aff053493381e3c2eee21e40 -size 2605783 +oid sha256:0c7ad9bd6ae12f5c70d00ae2b18d67eacdf0b30c587433d10634280aee9549d6 +size 2606206 diff --git a/dars/dars.lock b/dars/dars.lock index aafca843..765b615a 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -47,10 +47,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar": { - "sha256": "3749f454cd6dee5e307de1cba11ab1dceea6f066aff053493381e3c2eee21e40", - "size": 2605783, + "sha256": "0c7ad9bd6ae12f5c70d00ae2b18d67eacdf0b30c587433d10634280aee9549d6", + "size": 2606206, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T03:55:23.980Z", + "uploadedAt": "2026-07-09T04:40:45.300Z", "networks": [] } } From 0d8b82f241d4911f6ce12c686a134d0f0f5756ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 04:51:40 +0000 Subject: [PATCH 05/45] Fix vesting relative trigger cycle edge direction --- .../Fairmint/OpenCapTable/OCF/VestingTerms.daml | 16 ++++++++++------ Test/daml/OpenCapTable/TestVestingTerms.daml | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index d66afa9b..cbb0001b 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -251,11 +251,15 @@ vestingConditionReferencesKnownConditions conditionIds condition = all (`elem` conditionIds) condition.next_condition_ids && vestingTriggerReferencesKnownCondition conditionIds condition -vestingConditionEdgeIds : OcfVestingCondition -> [Text] -vestingConditionEdgeIds condition = case condition.trigger of - OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> - relative_to_condition_id :: condition.next_condition_ids - _ -> condition.next_condition_ids +vestingConditionEdgeIds : [OcfVestingCondition] -> OcfVestingCondition -> [Text] +vestingConditionEdgeIds conditions condition = + let relativeDependents = map (\conditionToCheck -> conditionToCheck.id) (filter (referencesCondition condition.id) conditions) + in condition.next_condition_ids <> relativeDependents + where + referencesCondition : Text -> OcfVestingCondition -> Bool + referencesCondition conditionId conditionToCheck = case conditionToCheck.trigger of + OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> relative_to_condition_id == conditionId + _ -> False vestingConditionHasCycle : [OcfVestingCondition] -> [Text] -> Text -> Bool vestingConditionHasCycle conditions path conditionId = @@ -265,7 +269,7 @@ vestingConditionHasCycle conditions path conditionId = Some condition -> any (vestingConditionHasCycle conditions (conditionId :: path)) - (vestingConditionEdgeIds condition) + (vestingConditionEdgeIds conditions condition) validateOcfVestingConditionGraph : [OcfVestingCondition] -> Bool validateOcfVestingConditionGraph conditions = diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index 8f1cd8ba..225fd327 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -89,7 +89,7 @@ testVestingTerms_OptionalsSome = script do portion = None quantity = Some 1.0 trigger = OcfVestingStartTrigger - next_condition_ids = [] + next_condition_ids = ["c1"] _ <- submit issuer do exerciseCmd cap_table CT.UpdateCapTable with creates = [CT.OcfCreateVestingTerms VestingTermsOcfData with From 1c902f4613b13608006550809e4442f8d8ea43db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 04:52:12 +0000 Subject: [PATCH 06/45] Refine vesting graph dependency naming --- .../daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index cbb0001b..83d0c65f 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -253,8 +253,8 @@ vestingConditionReferencesKnownConditions conditionIds condition = vestingConditionEdgeIds : [OcfVestingCondition] -> OcfVestingCondition -> [Text] vestingConditionEdgeIds conditions condition = - let relativeDependents = map (\conditionToCheck -> conditionToCheck.id) (filter (referencesCondition condition.id) conditions) - in condition.next_condition_ids <> relativeDependents + let dependentConditions = map (\conditionToCheck -> conditionToCheck.id) (filter (referencesCondition condition.id) conditions) + in condition.next_condition_ids <> dependentConditions where referencesCondition : Text -> OcfVestingCondition -> Bool referencesCondition conditionId conditionToCheck = case conditionToCheck.trigger of From 5b4d293cc8b977f4e2f4c9137039814467c147e4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 04:53:26 +0000 Subject: [PATCH 07/45] Precompute vesting graph edges for cycle checks --- .../OpenCapTable/OCF/VestingTerms.daml | 64 +++++++++++-------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index 83d0c65f..36bf42d6 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -231,14 +231,6 @@ hasDuplicateTexts texts = case texts of [] -> False text :: rest -> text `elem` rest || hasDuplicateTexts rest -conditionById : [OcfVestingCondition] -> Text -> Optional OcfVestingCondition -conditionById conditions conditionId = case conditions of - [] -> None - condition :: rest -> - if condition.id == conditionId - then Some condition - else conditionById rest conditionId - vestingTriggerReferencesKnownCondition : [Text] -> OcfVestingCondition -> Bool vestingTriggerReferencesKnownCondition conditionIds condition = case condition.trigger of OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> @@ -251,29 +243,49 @@ vestingConditionReferencesKnownConditions conditionIds condition = all (`elem` conditionIds) condition.next_condition_ids && vestingTriggerReferencesKnownCondition conditionIds condition -vestingConditionEdgeIds : [OcfVestingCondition] -> OcfVestingCondition -> [Text] -vestingConditionEdgeIds conditions condition = - let dependentConditions = map (\conditionToCheck -> conditionToCheck.id) (filter (referencesCondition condition.id) conditions) - in condition.next_condition_ids <> dependentConditions +addDependentEdge : Text -> Text -> [(Text, [Text])] -> [(Text, [Text])] +addDependentEdge fromConditionId toConditionId edges = case edges of + [] -> [] + (conditionId, conditionEdges) :: rest -> + if conditionId == fromConditionId + then + let updatedEdges = + if toConditionId `elem` conditionEdges + then conditionEdges + else toConditionId :: conditionEdges + in (conditionId, updatedEdges) :: rest + else (conditionId, conditionEdges) :: addDependentEdge fromConditionId toConditionId rest + +vestingConditionEdges : [OcfVestingCondition] -> [(Text, [Text])] +vestingConditionEdges conditions = + let baseEdges = map (\condition -> (condition.id, condition.next_condition_ids)) conditions + in foldl addRelativeEdge baseEdges conditions where - referencesCondition : Text -> OcfVestingCondition -> Bool - referencesCondition conditionId conditionToCheck = case conditionToCheck.trigger of - OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> relative_to_condition_id == conditionId - _ -> False - -vestingConditionHasCycle : [OcfVestingCondition] -> [Text] -> Text -> Bool -vestingConditionHasCycle conditions path conditionId = + addRelativeEdge : [(Text, [Text])] -> OcfVestingCondition -> [(Text, [Text])] + addRelativeEdge edges condition = case condition.trigger of + OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> + addDependentEdge relative_to_condition_id condition.id edges + _ -> edges + +conditionEdgeIds : [(Text, [Text])] -> Text -> [Text] +conditionEdgeIds edges conditionId = case edges of + [] -> [] + (edgeConditionId, edgeIds) :: rest -> + if edgeConditionId == conditionId + then edgeIds + else conditionEdgeIds rest conditionId + +vestingConditionHasCycle : [(Text, [Text])] -> [Text] -> Text -> Bool +vestingConditionHasCycle edges path conditionId = conditionId `elem` path || - case conditionById conditions conditionId of - None -> False - Some condition -> - any - (vestingConditionHasCycle conditions (conditionId :: path)) - (vestingConditionEdgeIds conditions condition) + any + (vestingConditionHasCycle edges (conditionId :: path)) + (conditionEdgeIds edges conditionId) validateOcfVestingConditionGraph : [OcfVestingCondition] -> Bool validateOcfVestingConditionGraph conditions = let conditionIds = vestingConditionIds conditions + edges = vestingConditionEdges conditions in not (hasDuplicateTexts conditionIds) && all (vestingConditionReferencesKnownConditions conditionIds) conditions && - not (any (vestingConditionHasCycle conditions []) conditionIds) + not (any (vestingConditionHasCycle edges []) conditionIds) From a856cd6c027e40eb7391af3c70c0d9d9687da048 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 04:54:43 +0000 Subject: [PATCH 08/45] Use map-backed vesting graph edge lookup --- .../OpenCapTable/OCF/VestingTerms.daml | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index 36bf42d6..7e6af2cb 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -4,6 +4,7 @@ module Fairmint.OpenCapTable.OCF.VestingTerms where import Fairmint.OpenCapTable.Types.Core (Context) import Fairmint.OpenCapTable.Types.Validation (validateNonEmptyStringsArray) import Fairmint.Shared.TypeHelpers (validateOptionalText) +import qualified DA.Map as Map template VestingTerms @@ -243,39 +244,30 @@ vestingConditionReferencesKnownConditions conditionIds condition = all (`elem` conditionIds) condition.next_condition_ids && vestingTriggerReferencesKnownCondition conditionIds condition -addDependentEdge : Text -> Text -> [(Text, [Text])] -> [(Text, [Text])] -addDependentEdge fromConditionId toConditionId edges = case edges of - [] -> [] - (conditionId, conditionEdges) :: rest -> - if conditionId == fromConditionId - then - let updatedEdges = - if toConditionId `elem` conditionEdges - then conditionEdges - else toConditionId :: conditionEdges - in (conditionId, updatedEdges) :: rest - else (conditionId, conditionEdges) :: addDependentEdge fromConditionId toConditionId rest - -vestingConditionEdges : [OcfVestingCondition] -> [(Text, [Text])] +addDependentEdge : Text -> Text -> Map.Map Text [Text] -> Map.Map Text [Text] +addDependentEdge fromConditionId toConditionId edges = + let conditionEdges = optional [] (\edgeIds -> edgeIds) (Map.lookup fromConditionId edges) + updatedEdges = + if toConditionId `elem` conditionEdges + then conditionEdges + else toConditionId :: conditionEdges + in Map.insert fromConditionId updatedEdges edges + +vestingConditionEdges : [OcfVestingCondition] -> Map.Map Text [Text] vestingConditionEdges conditions = - let baseEdges = map (\condition -> (condition.id, condition.next_condition_ids)) conditions + let baseEdges = Map.fromList (map (\condition -> (condition.id, condition.next_condition_ids)) conditions) in foldl addRelativeEdge baseEdges conditions where - addRelativeEdge : [(Text, [Text])] -> OcfVestingCondition -> [(Text, [Text])] + addRelativeEdge : Map.Map Text [Text] -> OcfVestingCondition -> Map.Map Text [Text] addRelativeEdge edges condition = case condition.trigger of OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> addDependentEdge relative_to_condition_id condition.id edges _ -> edges -conditionEdgeIds : [(Text, [Text])] -> Text -> [Text] -conditionEdgeIds edges conditionId = case edges of - [] -> [] - (edgeConditionId, edgeIds) :: rest -> - if edgeConditionId == conditionId - then edgeIds - else conditionEdgeIds rest conditionId +conditionEdgeIds : Map.Map Text [Text] -> Text -> [Text] +conditionEdgeIds edges conditionId = optional [] (\edgeIds -> edgeIds) (Map.lookup conditionId edges) -vestingConditionHasCycle : [(Text, [Text])] -> [Text] -> Text -> Bool +vestingConditionHasCycle : Map.Map Text [Text] -> [Text] -> Text -> Bool vestingConditionHasCycle edges path conditionId = conditionId `elem` path || any From 316c6f90c5511f4ead98bcf5c41b0c8533a3186c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 04:55:19 +0000 Subject: [PATCH 09/45] Simplify vesting edge map option handling --- .../daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index 7e6af2cb..0e59329d 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -246,7 +246,9 @@ vestingConditionReferencesKnownConditions conditionIds condition = addDependentEdge : Text -> Text -> Map.Map Text [Text] -> Map.Map Text [Text] addDependentEdge fromConditionId toConditionId edges = - let conditionEdges = optional [] (\edgeIds -> edgeIds) (Map.lookup fromConditionId edges) + let conditionEdges = case Map.lookup fromConditionId edges of + Some edgeIds -> edgeIds + None -> [] updatedEdges = if toConditionId `elem` conditionEdges then conditionEdges @@ -265,7 +267,9 @@ vestingConditionEdges conditions = _ -> edges conditionEdgeIds : Map.Map Text [Text] -> Text -> [Text] -conditionEdgeIds edges conditionId = optional [] (\edgeIds -> edgeIds) (Map.lookup conditionId edges) +conditionEdgeIds edges conditionId = case Map.lookup conditionId edges of + Some edgeIds -> edgeIds + None -> [] vestingConditionHasCycle : Map.Map Text [Text] -> [Text] -> Text -> Bool vestingConditionHasCycle edges path conditionId = From b1f84b9b4ac6034b970c228b935f6429aeb4a521 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 00:55:27 -0400 Subject: [PATCH 10/45] Refresh vesting graph DAR after review fixes --- dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar index 33d8d494..b28a6233 100644 --- a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c7ad9bd6ae12f5c70d00ae2b18d67eacdf0b30c587433d10634280aee9549d6 -size 2606206 +oid sha256:7e709d22837df8cb77e1f5f4298183e17b97b03855eb88841e44003cb6d817be +size 2608652 diff --git a/dars/dars.lock b/dars/dars.lock index 765b615a..6f8b2eb0 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -47,10 +47,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar": { - "sha256": "0c7ad9bd6ae12f5c70d00ae2b18d67eacdf0b30c587433d10634280aee9549d6", - "size": 2606206, + "sha256": "7e709d22837df8cb77e1f5f4298183e17b97b03855eb88841e44003cb6d817be", + "size": 2608652, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T04:40:45.300Z", + "uploadedAt": "2026-07-09T04:54:25.300Z", "networks": [] } } From 19d1a0548efa58fd0347be1b096a5160e0e6c65f Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 01:00:31 -0400 Subject: [PATCH 11/45] Refresh vesting graph DAR after edge lookup fixes --- .../daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml | 10 ++++------ dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index 0e59329d..20f46b34 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -5,6 +5,7 @@ import Fairmint.OpenCapTable.Types.Core (Context) import Fairmint.OpenCapTable.Types.Validation (validateNonEmptyStringsArray) import Fairmint.Shared.TypeHelpers (validateOptionalText) import qualified DA.Map as Map +import qualified DA.Optional as Optional template VestingTerms @@ -246,9 +247,7 @@ vestingConditionReferencesKnownConditions conditionIds condition = addDependentEdge : Text -> Text -> Map.Map Text [Text] -> Map.Map Text [Text] addDependentEdge fromConditionId toConditionId edges = - let conditionEdges = case Map.lookup fromConditionId edges of - Some edgeIds -> edgeIds - None -> [] + let conditionEdges = Optional.fromOptional [] (Map.lookup fromConditionId edges) updatedEdges = if toConditionId `elem` conditionEdges then conditionEdges @@ -267,9 +266,8 @@ vestingConditionEdges conditions = _ -> edges conditionEdgeIds : Map.Map Text [Text] -> Text -> [Text] -conditionEdgeIds edges conditionId = case Map.lookup conditionId edges of - Some edgeIds -> edgeIds - None -> [] +conditionEdgeIds edges conditionId = + Optional.fromOptional [] (Map.lookup conditionId edges) vestingConditionHasCycle : Map.Map Text [Text] -> [Text] -> Text -> Bool vestingConditionHasCycle edges path conditionId = diff --git a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar index b28a6233..8abeb2fe 100644 --- a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e709d22837df8cb77e1f5f4298183e17b97b03855eb88841e44003cb6d817be -size 2608652 +oid sha256:c2e5531259007b27d63fcbd83210d1dbb85aaacc19fa21ab647706350c0bafd8 +size 2608767 diff --git a/dars/dars.lock b/dars/dars.lock index 6f8b2eb0..f2a593f2 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -47,10 +47,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar": { - "sha256": "7e709d22837df8cb77e1f5f4298183e17b97b03855eb88841e44003cb6d817be", - "size": 2608652, + "sha256": "c2e5531259007b27d63fcbd83210d1dbb85aaacc19fa21ab647706350c0bafd8", + "size": 2608767, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T04:54:25.300Z", + "uploadedAt": "2026-07-09T05:00:01.300Z", "networks": [] } } From d8a08e68dfcaaf75232914cf1ff36801a8d8acc7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 05:13:00 +0000 Subject: [PATCH 12/45] Enforce relative trigger predecessor linkage in vesting graph --- .../OpenCapTable/OCF/VestingTerms.daml | 33 ++++++++++++------- Test/daml/OpenCapTable/TestVestingTerms.daml | 13 ++++++++ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index 20f46b34..652f2ef5 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -233,17 +233,31 @@ hasDuplicateTexts texts = case texts of [] -> False text :: rest -> text `elem` rest || hasDuplicateTexts rest -vestingTriggerReferencesKnownCondition : [Text] -> OcfVestingCondition -> Bool -vestingTriggerReferencesKnownCondition conditionIds condition = case condition.trigger of +conditionEdgeIds : Map.Map Text [Text] -> Text -> [Text] +conditionEdgeIds edges conditionId = + Optional.fromOptional [] (Map.lookup conditionId edges) + +conditionReachesTarget : Map.Map Text [Text] -> [Text] -> Text -> Text -> Bool +conditionReachesTarget edges visited sourceId targetId = + sourceId == targetId || + (not (sourceId `elem` visited) && + any + (\nextId -> conditionReachesTarget edges (sourceId :: visited) nextId targetId) + (conditionEdgeIds edges sourceId)) + +vestingTriggerReferencesKnownCondition : [Text] -> Map.Map Text [Text] -> OcfVestingCondition -> Bool +vestingTriggerReferencesKnownCondition conditionIds nextEdges condition = case condition.trigger of OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> - relative_to_condition_id /= condition.id && relative_to_condition_id `elem` conditionIds + relative_to_condition_id /= condition.id && + relative_to_condition_id `elem` conditionIds && + conditionReachesTarget nextEdges [] relative_to_condition_id condition.id _ -> True -vestingConditionReferencesKnownConditions : [Text] -> OcfVestingCondition -> Bool -vestingConditionReferencesKnownConditions conditionIds condition = +vestingConditionReferencesKnownConditions : [Text] -> Map.Map Text [Text] -> OcfVestingCondition -> Bool +vestingConditionReferencesKnownConditions conditionIds nextEdges condition = not (hasDuplicateTexts condition.next_condition_ids) && all (`elem` conditionIds) condition.next_condition_ids && - vestingTriggerReferencesKnownCondition conditionIds condition + vestingTriggerReferencesKnownCondition conditionIds nextEdges condition addDependentEdge : Text -> Text -> Map.Map Text [Text] -> Map.Map Text [Text] addDependentEdge fromConditionId toConditionId edges = @@ -265,10 +279,6 @@ vestingConditionEdges conditions = addDependentEdge relative_to_condition_id condition.id edges _ -> edges -conditionEdgeIds : Map.Map Text [Text] -> Text -> [Text] -conditionEdgeIds edges conditionId = - Optional.fromOptional [] (Map.lookup conditionId edges) - vestingConditionHasCycle : Map.Map Text [Text] -> [Text] -> Text -> Bool vestingConditionHasCycle edges path conditionId = conditionId `elem` path || @@ -279,7 +289,8 @@ vestingConditionHasCycle edges path conditionId = validateOcfVestingConditionGraph : [OcfVestingCondition] -> Bool validateOcfVestingConditionGraph conditions = let conditionIds = vestingConditionIds conditions + nextEdges = Map.fromList (map (\condition -> (condition.id, condition.next_condition_ids)) conditions) edges = vestingConditionEdges conditions in not (hasDuplicateTexts conditionIds) && - all (vestingConditionReferencesKnownConditions conditionIds) conditions && + all (vestingConditionReferencesKnownConditions conditionIds nextEdges) conditions && not (any (vestingConditionHasCycle edges []) conditionIds) diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index 225fd327..486eb761 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -179,6 +179,19 @@ testVestingTerms_MissingRelativeConditionIdFails = script do createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_MISSING_RELATIVE" [relative]) pure () +testVestingTerms_RelativeConditionMustBePredecessorFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let start = vestingCondition "start" OcfVestingStartTrigger ["relative"] + let other = vestingCondition "other" OcfVestingEventTrigger [] + let relative = vestingCondition + "relative" + (OcfVestingScheduleRelativeTrigger with + period = OcfVestingPeriodDays with length_ = 30, occurrences = 1, cliff_installment = None + relative_to_condition_id = "other") + [] + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_RELATIVE_PREDECESSOR" [start, other, relative]) + pure () + testVestingTerms_CyclicNextConditionsFail = script do TestOcp{issuer, cap_table} <- setupTestOcp let first = vestingCondition "first" OcfVestingStartTrigger ["second"] From f0d6e90c537112bbe166b175b9e467f14c937a12 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 05:14:08 +0000 Subject: [PATCH 13/45] Use visited set for vesting predecessor reachability check --- .../daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index 652f2ef5..9c82f4aa 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -6,6 +6,7 @@ import Fairmint.OpenCapTable.Types.Validation (validateNonEmptyStringsArray) import Fairmint.Shared.TypeHelpers (validateOptionalText) import qualified DA.Map as Map import qualified DA.Optional as Optional +import qualified DA.Set as Set template VestingTerms @@ -237,12 +238,12 @@ conditionEdgeIds : Map.Map Text [Text] -> Text -> [Text] conditionEdgeIds edges conditionId = Optional.fromOptional [] (Map.lookup conditionId edges) -conditionReachesTarget : Map.Map Text [Text] -> [Text] -> Text -> Text -> Bool +conditionReachesTarget : Map.Map Text [Text] -> Set.Set Text -> Text -> Text -> Bool conditionReachesTarget edges visited sourceId targetId = sourceId == targetId || - (not (sourceId `elem` visited) && + (not (Set.member sourceId visited) && any - (\nextId -> conditionReachesTarget edges (sourceId :: visited) nextId targetId) + (\nextId -> conditionReachesTarget edges (Set.insert sourceId visited) nextId targetId) (conditionEdgeIds edges sourceId)) vestingTriggerReferencesKnownCondition : [Text] -> Map.Map Text [Text] -> OcfVestingCondition -> Bool @@ -250,7 +251,7 @@ vestingTriggerReferencesKnownCondition conditionIds nextEdges condition = case c OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> relative_to_condition_id /= condition.id && relative_to_condition_id `elem` conditionIds && - conditionReachesTarget nextEdges [] relative_to_condition_id condition.id + conditionReachesTarget nextEdges Set.empty relative_to_condition_id condition.id _ -> True vestingConditionReferencesKnownConditions : [Text] -> Map.Map Text [Text] -> OcfVestingCondition -> Bool From 40ee04830b577b92002a06b6faa25950311f3777 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 04:01:09 -0400 Subject: [PATCH 14/45] Refresh vesting graph DAR after Copilot fixes --- dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar index 8abeb2fe..bea04a72 100644 --- a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2e5531259007b27d63fcbd83210d1dbb85aaacc19fa21ab647706350c0bafd8 -size 2608767 +oid sha256:f89bfdcdfb1a5bebf563db63fdbbf0c722c1a93e933c384db9a6642819618b83 +size 2611398 diff --git a/dars/dars.lock b/dars/dars.lock index f2a593f2..61983dd5 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -47,8 +47,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar": { - "sha256": "c2e5531259007b27d63fcbd83210d1dbb85aaacc19fa21ab647706350c0bafd8", - "size": 2608767, + "sha256": "f89bfdcdfb1a5bebf563db63fdbbf0c722c1a93e933c384db9a6642819618b83", + "size": 2611398, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T05:00:01.300Z", "networks": [] From 38bc0dbfdeff78d171aa1d8203f72eac2128b551 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 06:35:29 -0400 Subject: [PATCH 15/45] Require relative vesting anchors on all paths --- .../OpenCapTable/OCF/VestingTerms.daml | 37 +++++++++++++++++++ Test/daml/OpenCapTable/TestVestingTerms.daml | 21 +++++++++++ .../0.0.7/OpenCapTable-v34.dar | 4 +- dars/dars.lock | 4 +- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index 9c82f4aa..f13935f0 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -246,6 +246,33 @@ conditionReachesTarget edges visited sourceId targetId = (\nextId -> conditionReachesTarget edges (Set.insert sourceId visited) nextId targetId) (conditionEdgeIds edges sourceId)) +allConditionsReachableFromStart : Map.Map Text [Text] -> [OcfVestingCondition] -> Bool +allConditionsReachableFromStart nextEdges conditions = case conditions of + [] -> True + startCondition :: _ -> + all + (\condition -> conditionReachesTarget nextEdges Set.empty startCondition.id condition.id) + conditions + +allPathsToTargetPassThrough : + Map.Map Text [Text] -> + Set.Set Text -> + Text -> + Text -> + Text -> + Bool -> + Bool +allPathsToTargetPassThrough edges visited currentId targetId requiredId hasSeenRequired = + let nextHasSeenRequired = hasSeenRequired || currentId == requiredId + in + if currentId == targetId + then nextHasSeenRequired + else + Set.member currentId visited || + all + (\nextId -> allPathsToTargetPassThrough edges (Set.insert currentId visited) nextId targetId requiredId nextHasSeenRequired) + (conditionEdgeIds edges currentId) + vestingTriggerReferencesKnownCondition : [Text] -> Map.Map Text [Text] -> OcfVestingCondition -> Bool vestingTriggerReferencesKnownCondition conditionIds nextEdges condition = case condition.trigger of OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> @@ -260,6 +287,12 @@ vestingConditionReferencesKnownConditions conditionIds nextEdges condition = all (`elem` conditionIds) condition.next_condition_ids && vestingTriggerReferencesKnownCondition conditionIds nextEdges condition +vestingTriggerAnchorDominatesCondition : Map.Map Text [Text] -> Text -> OcfVestingCondition -> Bool +vestingTriggerAnchorDominatesCondition nextEdges startConditionId condition = case condition.trigger of + OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> + allPathsToTargetPassThrough nextEdges Set.empty startConditionId condition.id relative_to_condition_id False + _ -> True + addDependentEdge : Text -> Text -> Map.Map Text [Text] -> Map.Map Text [Text] addDependentEdge fromConditionId toConditionId edges = let conditionEdges = Optional.fromOptional [] (Map.lookup fromConditionId edges) @@ -294,4 +327,8 @@ validateOcfVestingConditionGraph conditions = edges = vestingConditionEdges conditions in not (hasDuplicateTexts conditionIds) && all (vestingConditionReferencesKnownConditions conditionIds nextEdges) conditions && + allConditionsReachableFromStart nextEdges conditions && + (case conditions of + [] -> True + startCondition :: _ -> all (vestingTriggerAnchorDominatesCondition nextEdges startCondition.id) conditions) && not (any (vestingConditionHasCycle edges []) conditionIds) diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index 486eb761..610faba7 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -192,6 +192,27 @@ testVestingTerms_RelativeConditionMustBePredecessorFails = script do createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_RELATIVE_PREDECESSOR" [start, other, relative]) pure () +testVestingTerms_RelativeAnchorMustDominateAllPathsFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let start = vestingCondition "start" OcfVestingStartTrigger ["anchor", "bypass"] + let anchor = vestingCondition "anchor" OcfVestingEventTrigger ["relative"] + let bypass = vestingCondition "bypass" OcfVestingEventTrigger ["relative"] + let relative = vestingCondition + "relative" + (OcfVestingScheduleRelativeTrigger with + period = OcfVestingPeriodDays with length_ = 30, occurrences = 1, cliff_installment = None + relative_to_condition_id = "anchor") + [] + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_RELATIVE_DOMINATOR" [start, anchor, bypass, relative]) + pure () + +testVestingTerms_OrphanConditionFails = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let start = vestingCondition "start" OcfVestingStartTrigger [] + let orphan = vestingCondition "orphan" OcfVestingEventTrigger [] + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_ORPHAN" [start, orphan]) + pure () + testVestingTerms_CyclicNextConditionsFail = script do TestOcp{issuer, cap_table} <- setupTestOcp let first = vestingCondition "first" OcfVestingStartTrigger ["second"] diff --git a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar index bea04a72..014853a1 100644 --- a/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f89bfdcdfb1a5bebf563db63fdbbf0c722c1a93e933c384db9a6642819618b83 -size 2611398 +oid sha256:272da15de5eb95ce514ecb047d455f929cc6e619de4cc68b66bd42ece0f4696e +size 2673585 diff --git a/dars/dars.lock b/dars/dars.lock index 91e8c3e3..501fdcf4 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -47,8 +47,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.7/OpenCapTable-v34.dar": { - "sha256": "f89bfdcdfb1a5bebf563db63fdbbf0c722c1a93e933c384db9a6642819618b83", - "size": 2611398, + "sha256": "272da15de5eb95ce514ecb047d455f929cc6e619de4cc68b66bd42ece0f4696e", + "size": 2673585, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T05:00:01.300Z", "networks": [] From ad50872d70ea54a07f91b7d6d0a96653b99563d3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 13:39:02 +0000 Subject: [PATCH 16/45] Optimize vesting duplicate ID check --- .../daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index d9ed20e5..88c80170 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -244,9 +244,12 @@ singleVestingStartConditionId conditions = case vestingStartConditionIds conditi _ -> None hasDuplicateTexts : [Text] -> Bool -hasDuplicateTexts texts = case texts of - [] -> False - text :: rest -> text `elem` rest || hasDuplicateTexts rest +hasDuplicateTexts texts = checkDuplicates Set.empty texts + where + checkDuplicates : Set.Set Text -> [Text] -> Bool + checkDuplicates seen remaining = case remaining of + [] -> False + text :: rest -> Set.member text seen || checkDuplicates (Set.insert text seen) rest conditionEdgeIds : Map.Map Text [Text] -> Text -> [Text] conditionEdgeIds edges conditionId = From b5058fab70cb88189bd1db8e1474e00e97b9455f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 13:39:46 +0000 Subject: [PATCH 17/45] Clarify duplicate-check short-circuit logic --- .../daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index 88c80170..64d44890 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -249,7 +249,10 @@ hasDuplicateTexts texts = checkDuplicates Set.empty texts checkDuplicates : Set.Set Text -> [Text] -> Bool checkDuplicates seen remaining = case remaining of [] -> False - text :: rest -> Set.member text seen || checkDuplicates (Set.insert text seen) rest + text :: rest -> + if Set.member text seen + then True + else checkDuplicates (Set.insert text seen) rest conditionEdgeIds : Map.Map Text [Text] -> Text -> [Text] conditionEdgeIds edges conditionId = From 0e1073f41cd1bbb1da3dfbdee44b9d94ff5bbd9f Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 10:00:32 -0400 Subject: [PATCH 18/45] Address vesting graph review comments --- .../OpenCapTable/OCF/VestingTerms.daml | 85 +++++++++---------- Test/daml/OpenCapTable/TestVestingTerms.daml | 12 ++- .../0.0.13/OpenCapTable-v34.dar | 4 +- dars/dars.lock | 6 +- 4 files changed, 52 insertions(+), 55 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index d9ed20e5..bf64fe53 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -229,68 +229,59 @@ validateOcfVestingCondition c = vestingConditionIds : [OcfVestingCondition] -> [Text] vestingConditionIds conditions = map (\condition -> condition.id) conditions -isVestingStartCondition : OcfVestingCondition -> Bool -isVestingStartCondition condition = case condition.trigger of - OcfVestingStartTrigger -> True - _ -> False - -vestingStartConditionIds : [OcfVestingCondition] -> [Text] -vestingStartConditionIds conditions = - map (\condition -> condition.id) (filter isVestingStartCondition conditions) - -singleVestingStartConditionId : [OcfVestingCondition] -> Optional Text -singleVestingStartConditionId conditions = case vestingStartConditionIds conditions of - [startConditionId] -> Some startConditionId - _ -> None +vestingGraphRootConditionId : [OcfVestingCondition] -> Optional Text +vestingGraphRootConditionId conditions = case conditions of + root :: _ -> Some root.id + [] -> None hasDuplicateTexts : [Text] -> Bool -hasDuplicateTexts texts = case texts of +hasDuplicateTexts texts = hasDuplicateTextsSeen Set.empty texts + +hasDuplicateTextsSeen : Set.Set Text -> [Text] -> Bool +hasDuplicateTextsSeen seen texts = case texts of [] -> False - text :: rest -> text `elem` rest || hasDuplicateTexts rest + text :: rest -> + Set.member text seen || hasDuplicateTextsSeen (Set.insert text seen) rest conditionEdgeIds : Map.Map Text [Text] -> Text -> [Text] conditionEdgeIds edges conditionId = Optional.fromOptional [] (Map.lookup conditionId edges) -conditionReachesTarget : Map.Map Text [Text] -> Set.Set Text -> Text -> Text -> Bool -conditionReachesTarget edges visited sourceId targetId = - sourceId == targetId || - (not (Set.member sourceId visited) && - any - (\nextId -> conditionReachesTarget edges (Set.insert sourceId visited) nextId targetId) - (conditionEdgeIds edges sourceId)) +reachableConditionIds : Map.Map Text [Text] -> Set.Set Text -> [Text] -> Set.Set Text +reachableConditionIds edges visited pending = case pending of + [] -> visited + currentId :: rest -> + if Set.member currentId visited + then reachableConditionIds edges visited rest + else reachableConditionIds edges (Set.insert currentId visited) (conditionEdgeIds edges currentId ++ rest) + +reachableConditionIdsAvoiding : Map.Map Text [Text] -> Text -> Set.Set Text -> [Text] -> Set.Set Text +reachableConditionIdsAvoiding edges blockedId visited pending = case pending of + [] -> visited + currentId :: rest -> + if currentId == blockedId || Set.member currentId visited + then reachableConditionIdsAvoiding edges blockedId visited rest + else reachableConditionIdsAvoiding edges blockedId (Set.insert currentId visited) (conditionEdgeIds edges currentId ++ rest) + +conditionReachesTarget : Map.Map Text [Text] -> Text -> Text -> Bool +conditionReachesTarget edges sourceId targetId = + Set.member targetId (reachableConditionIds edges Set.empty [sourceId]) + +conditionReachesTargetAvoiding : Map.Map Text [Text] -> Text -> Text -> Text -> Bool +conditionReachesTargetAvoiding edges blockedId sourceId targetId = + Set.member targetId (reachableConditionIdsAvoiding edges blockedId Set.empty [sourceId]) allConditionsReachableFromStart : Map.Map Text [Text] -> Text -> [OcfVestingCondition] -> Bool allConditionsReachableFromStart nextEdges startConditionId conditions = - all - (\condition -> conditionReachesTarget nextEdges Set.empty startConditionId condition.id) - conditions - -allPathsToTargetPassThrough : - Map.Map Text [Text] -> - Set.Set Text -> - Text -> - Text -> - Text -> - Bool -> - Bool -allPathsToTargetPassThrough edges visited currentId targetId requiredId hasSeenRequired = - let nextHasSeenRequired = hasSeenRequired || currentId == requiredId - in - if currentId == targetId - then nextHasSeenRequired - else - Set.member currentId visited || - all - (\nextId -> allPathsToTargetPassThrough edges (Set.insert currentId visited) nextId targetId requiredId nextHasSeenRequired) - (conditionEdgeIds edges currentId) + let reachableIds = reachableConditionIds nextEdges Set.empty [startConditionId] + in all (\condition -> Set.member condition.id reachableIds) conditions vestingTriggerReferencesKnownCondition : [Text] -> Map.Map Text [Text] -> OcfVestingCondition -> Bool vestingTriggerReferencesKnownCondition conditionIds nextEdges condition = case condition.trigger of OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> relative_to_condition_id /= condition.id && relative_to_condition_id `elem` conditionIds && - conditionReachesTarget nextEdges Set.empty relative_to_condition_id condition.id + conditionReachesTarget nextEdges relative_to_condition_id condition.id _ -> True vestingConditionReferencesKnownConditions : [Text] -> Map.Map Text [Text] -> OcfVestingCondition -> Bool @@ -302,7 +293,7 @@ vestingConditionReferencesKnownConditions conditionIds nextEdges condition = vestingTriggerAnchorDominatesCondition : Map.Map Text [Text] -> Text -> OcfVestingCondition -> Bool vestingTriggerAnchorDominatesCondition nextEdges startConditionId condition = case condition.trigger of OcfVestingScheduleRelativeTrigger{relative_to_condition_id} -> - allPathsToTargetPassThrough nextEdges Set.empty startConditionId condition.id relative_to_condition_id False + not (conditionReachesTargetAvoiding nextEdges relative_to_condition_id startConditionId condition.id) _ -> True addDependentEdge : Text -> Text -> Map.Map Text [Text] -> Map.Map Text [Text] @@ -372,7 +363,7 @@ validateOcfVestingConditionGraph conditions = edges = vestingConditionEdges conditions in not (hasDuplicateTexts conditionIds) && all (vestingConditionReferencesKnownConditions conditionIds nextEdges) conditions && - (case singleVestingStartConditionId conditions of + (case vestingGraphRootConditionId conditions of Some startConditionId -> allConditionsReachableFromStart nextEdges startConditionId conditions && all (vestingTriggerAnchorDominatesCondition nextEdges startConditionId) conditions diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index b772ccc5..18698a77 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -206,6 +206,12 @@ testVestingTerms_RelativeAnchorMustDominateAllPathsFails = script do createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_RELATIVE_DOMINATOR" [start, anchor, bypass, relative]) pure () +testVestingTerms_EventOnlyRootIsValid = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let eventRoot = vestingCondition "qualifying-sale" OcfVestingEventTrigger [] + _ <- createVestingTermsData issuer cap_table (vestingTermsData "VT_EVENT_ONLY_ROOT" [eventRoot]) + pure () + testVestingTerms_OrphanConditionFails = script do TestOcp{issuer, cap_table} <- setupTestOcp let start = vestingCondition "start" OcfVestingStartTrigger [] @@ -213,14 +219,14 @@ testVestingTerms_OrphanConditionFails = script do createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_ORPHAN" [start, orphan]) pure () -testVestingTerms_StartConditionCanBeOutOfOrder = script do +testVestingTerms_FirstConditionIsGraphRoot = script do TestOcp{issuer, cap_table} <- setupTestOcp let start = vestingCondition "start" OcfVestingStartTrigger ["next"] let next = vestingCondition "next" OcfVestingEventTrigger [] - _ <- createVestingTermsData issuer cap_table (vestingTermsData "VT_UNORDERED_START" [next, start]) + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_UNORDERED_START" [next, start]) pure () -testVestingTerms_MultipleStartConditionsFail = script do +testVestingTerms_DisconnectedSecondStartConditionFails = script do TestOcp{issuer, cap_table} <- setupTestOcp let firstStart = vestingCondition "start_one" OcfVestingStartTrigger ["next"] let secondStart = vestingCondition "start_two" OcfVestingStartTrigger [] diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index fa809b4b..1734cfb1 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8de4c032dc39643448fab6b8a927aa78794aa9cf985ec241ff4aab8d1469f483 -size 2709039 +oid sha256:1edc74eb8b5359440f02143971a48ad64a125400a3a120ac1aaf31d6b0ff2f89 +size 2742543 diff --git a/dars/dars.lock b/dars/dars.lock index a05ccb57..4842592d 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "8de4c032dc39643448fab6b8a927aa78794aa9cf985ec241ff4aab8d1469f483", - "size": 2709039, + "sha256": "1edc74eb8b5359440f02143971a48ad64a125400a3a120ac1aaf31d6b0ff2f89", + "size": 2742543, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T13:19:48.268Z", + "uploadedAt": "2026-07-09T13:59:46.484Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From 149766e418c7a24c7fc820e3eab8ac42c2ff4827 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 10:13:03 -0400 Subject: [PATCH 19/45] Restack vesting graph on terminal balance fixes --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index a4f98f2d..a5f64018 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf0a4d74ed90fd918e708922b179f7e75d866178bed9aaa0a78b4e39cb1d20dd -size 2742607 +oid sha256:103e62a4d2256e812d8a569447bf16d59e46be37bc261afa5cbb4f3ac9fa799a +size 2744183 diff --git a/dars/dars.lock b/dars/dars.lock index eb4a6ab8..b93b9732 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "cf0a4d74ed90fd918e708922b179f7e75d866178bed9aaa0a78b4e39cb1d20dd", - "size": 2742607, + "sha256": "103e62a4d2256e812d8a569447bf16d59e46be37bc261afa5cbb4f3ac9fa799a", + "size": 2744183, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T14:04:20.900Z", + "uploadedAt": "2026-07-09T14:12:30.978Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From 2c7e986840700fa37ee27c0eb0ffa030354bac3e Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 10:19:47 -0400 Subject: [PATCH 20/45] Restack vesting graph on same-day balance ordering --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index a5f64018..6401e6f5 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:103e62a4d2256e812d8a569447bf16d59e46be37bc261afa5cbb4f3ac9fa799a -size 2744183 +oid sha256:cb04750e9396dd113fdb772269bb62152cfb7fc128849dc457769adc45c8a8f4 +size 2744186 diff --git a/dars/dars.lock b/dars/dars.lock index 8bf723ca..56f6e652 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "103e62a4d2256e812d8a569447bf16d59e46be37bc261afa5cbb4f3ac9fa799a", - "size": 2744183, + "sha256": "cb04750e9396dd113fdb772269bb62152cfb7fc128849dc457769adc45c8a8f4", + "size": 2744186, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T14:12:30.978Z", + "uploadedAt": "2026-07-09T14:19:15.953Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From f7ede7e9244d74e10aa6655904dd1f49d73f8df5 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 11:00:26 -0400 Subject: [PATCH 21/45] Update vesting graph DAR backup --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 6401e6f5..8e584b17 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb04750e9396dd113fdb772269bb62152cfb7fc128849dc457769adc45c8a8f4 -size 2744186 +oid sha256:3be79ed4d60014571b592a7016e8b4d83519ce67177ae0bfa27118011131a84f +size 2748397 diff --git a/dars/dars.lock b/dars/dars.lock index e133d780..6a3e4e5c 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "cb04750e9396dd113fdb772269bb62152cfb7fc128849dc457769adc45c8a8f4", - "size": 2744186, + "sha256": "3be79ed4d60014571b592a7016e8b4d83519ce67177ae0bfa27118011131a84f", + "size": 2748397, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T14:19:15.953Z", "networks": [] From 3cc03a011c210292f129812632b84223467e24ba Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 11:30:39 -0400 Subject: [PATCH 22/45] Tighten vesting graph failure fixtures --- Test/daml/OpenCapTable/TestVestingTerms.daml | 5 +++-- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index 18698a77..32fa46be 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -170,18 +170,19 @@ testVestingTerms_MissingNextConditionIdFails = script do testVestingTerms_MissingRelativeConditionIdFails = script do TestOcp{issuer, cap_table} <- setupTestOcp + let start = vestingCondition "start" OcfVestingStartTrigger ["relative"] let relative = vestingCondition "relative" (OcfVestingScheduleRelativeTrigger with period = OcfVestingPeriodDays with length_ = 30, occurrences = 1, cliff_installment = None relative_to_condition_id = "missing") [] - createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_MISSING_RELATIVE" [relative]) + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_MISSING_RELATIVE" [start, relative]) pure () testVestingTerms_RelativeConditionMustBePredecessorFails = script do TestOcp{issuer, cap_table} <- setupTestOcp - let start = vestingCondition "start" OcfVestingStartTrigger ["relative"] + let start = vestingCondition "start" OcfVestingStartTrigger ["other", "relative"] let other = vestingCondition "other" OcfVestingEventTrigger [] let relative = vestingCondition "relative" diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 8e584b17..c954c5fc 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3be79ed4d60014571b592a7016e8b4d83519ce67177ae0bfa27118011131a84f -size 2748397 +oid sha256:d2b0a0e39ea2eb213ba030d2f258ef7e02135ace11d59ce935e1bf2317836fe8 +size 2755620 diff --git a/dars/dars.lock b/dars/dars.lock index 1c88c516..23e41d73 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "3be79ed4d60014571b592a7016e8b4d83519ce67177ae0bfa27118011131a84f", - "size": 2748397, + "sha256": "d2b0a0e39ea2eb213ba030d2f258ef7e02135ace11d59ce935e1bf2317836fe8", + "size": 2755620, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T14:19:15.953Z", "networks": [] From b3254efd32dd0f4c2ab3132836807ff6f5b26741 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 11:45:09 -0400 Subject: [PATCH 23/45] Refresh vesting graph DAR after ceiling update --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index c954c5fc..f8a4c49e 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2b0a0e39ea2eb213ba030d2f258ef7e02135ace11d59ce935e1bf2317836fe8 -size 2755620 +oid sha256:27ec034c3c2b5f21b845c700cc8ecb6959e61819a61c8f2b6505db61ceb781e4 +size 2756052 diff --git a/dars/dars.lock b/dars/dars.lock index 104196e4..67f05953 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "d2b0a0e39ea2eb213ba030d2f258ef7e02135ace11d59ce935e1bf2317836fe8", - "size": 2755620, + "sha256": "27ec034c3c2b5f21b845c700cc8ecb6959e61819a61c8f2b6505db61ceb781e4", + "size": 2756052, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T14:19:15.953Z", "networks": [] From 30356e1eee41abadbd310b5c22042abedaff56e8 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 12:44:56 -0400 Subject: [PATCH 24/45] Tighten vesting graph review tests --- Test/daml/OpenCapTable/TestVestingTerms.daml | 2 +- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index 32fa46be..c3d7e25c 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -242,7 +242,7 @@ testVestingTerms_CyclicNextConditionsFail = script do createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_CYCLE" [first, second]) pure () -testVestingTerms_RelativeCycleFail = script do +testVestingTerms_MutualRelativeConditionsWithoutRootFail = script do TestOcp{issuer, cap_table} <- setupTestOcp let first = vestingCondition "first" diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index f8a4c49e..ca16e0bf 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27ec034c3c2b5f21b845c700cc8ecb6959e61819a61c8f2b6505db61ceb781e4 -size 2756052 +oid sha256:c1648b4030734a386987d2dd7284e9ecdad1c39a2f8c666c065243a59cac20ce +size 2759201 diff --git a/dars/dars.lock b/dars/dars.lock index 48d170fc..449a8c87 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "27ec034c3c2b5f21b845c700cc8ecb6959e61819a61c8f2b6505db61ceb781e4", - "size": 2756052, + "sha256": "c1648b4030734a386987d2dd7284e9ecdad1c39a2f8c666c065243a59cac20ce", + "size": 2759201, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T14:19:15.953Z", + "uploadedAt": "2026-07-09T16:43:50Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From 41f47dea4e61ffb1ed851e5721b47b61a862b03a Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 13:26:23 -0400 Subject: [PATCH 25/45] Refresh vesting DAR after security balance merge --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index ca16e0bf..aee6bbf7 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1648b4030734a386987d2dd7284e9ecdad1c39a2f8c666c065243a59cac20ce -size 2759201 +oid sha256:626c698c6da97fcd7df616373a7e3d6989026466322c4b20d4af0f75d1a74bac +size 2807980 diff --git a/dars/dars.lock b/dars/dars.lock index 1df64103..9e730d87 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "c1648b4030734a386987d2dd7284e9ecdad1c39a2f8c666c065243a59cac20ce", - "size": 2759201, + "sha256": "626c698c6da97fcd7df616373a7e3d6989026466322c4b20d4af0f75d1a74bac", + "size": 2807980, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T16:43:50Z", + "uploadedAt": "2026-07-09T17:24:52Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From 8a8ed7b725900a79bf5a49844dbf6c49020223f4 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 13:53:45 -0400 Subject: [PATCH 26/45] Refresh vesting DAR after security balance update --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index aee6bbf7..e2924378 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:626c698c6da97fcd7df616373a7e3d6989026466322c4b20d4af0f75d1a74bac -size 2807980 +oid sha256:d0230d6560c4d960e39ab2b4e2f1667f723a44ff469b0e8146396af2801b28c9 +size 2827890 diff --git a/dars/dars.lock b/dars/dars.lock index 304572e3..9bfdaa05 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "626c698c6da97fcd7df616373a7e3d6989026466322c4b20d4af0f75d1a74bac", - "size": 2807980, + "sha256": "d0230d6560c4d960e39ab2b4e2f1667f723a44ff469b0e8146396af2801b28c9", + "size": 2827890, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T17:24:52Z", + "uploadedAt": "2026-07-09T17:52:31Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From 20f1ed6f6219407cc19ee43be44508abf289e666 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 14:18:49 -0400 Subject: [PATCH 27/45] Refresh vesting DAR after security fixes --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index e2924378..344e7490 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0230d6560c4d960e39ab2b4e2f1667f723a44ff469b0e8146396af2801b28c9 -size 2827890 +oid sha256:38438c942f504e735b49eb5353f088746af6e2af6c3d41004f72f294c7d558ec +size 2829912 diff --git a/dars/dars.lock b/dars/dars.lock index 14df0fd8..39a645a7 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "d0230d6560c4d960e39ab2b4e2f1667f723a44ff469b0e8146396af2801b28c9", - "size": 2827890, + "sha256": "38438c942f504e735b49eb5353f088746af6e2af6c3d41004f72f294c7d558ec", + "size": 2829912, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T17:52:31Z", + "uploadedAt": "2026-07-09T18:12:27Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From d06004ddd7d0cca5d025226c0def77f7dfd2e6e9 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 14:49:53 -0400 Subject: [PATCH 28/45] Refresh vesting DAR after reference fold --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 344e7490..894af8c3 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38438c942f504e735b49eb5353f088746af6e2af6c3d41004f72f294c7d558ec -size 2829912 +oid sha256:bb097b54f7f6cc52d2c73c5cacf1638f66960d8170408e4dbdbc65bedb634265 +size 2842524 diff --git a/dars/dars.lock b/dars/dars.lock index 99a8e1ca..9a1c0788 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "38438c942f504e735b49eb5353f088746af6e2af6c3d41004f72f294c7d558ec", - "size": 2829912, + "sha256": "bb097b54f7f6cc52d2c73c5cacf1638f66960d8170408e4dbdbc65bedb634265", + "size": 2842524, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T18:12:27Z", + "uploadedAt": "2026-07-09T18:48:49.697Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From 57981da78cc6faef614dd6c5776d0a951103e8e6 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 15:31:19 -0400 Subject: [PATCH 29/45] Cover self-referential vesting triggers --- Test/daml/OpenCapTable/TestVestingTerms.daml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index c3d7e25c..ac0a4dd3 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -180,6 +180,17 @@ testVestingTerms_MissingRelativeConditionIdFails = script do createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_MISSING_RELATIVE" [start, relative]) pure () +testVestingTerms_RelativeConditionCannotReferenceSelf = script do + TestOcp{issuer, cap_table} <- setupTestOcp + let selfRelative = vestingCondition + "self" + (OcfVestingScheduleRelativeTrigger with + period = OcfVestingPeriodDays with length_ = 30, occurrences = 1, cliff_installment = None + relative_to_condition_id = "self") + [] + createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_SELF_RELATIVE" [selfRelative]) + pure () + testVestingTerms_RelativeConditionMustBePredecessorFails = script do TestOcp{issuer, cap_table} <- setupTestOcp let start = vestingCondition "start" OcfVestingStartTrigger ["other", "relative"] From 33341417fd2e4884951e203fabe17d51e3c7d29b Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 15:45:15 -0400 Subject: [PATCH 30/45] Refresh vesting DAR after reference updates --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 894af8c3..37a9a92d 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb097b54f7f6cc52d2c73c5cacf1638f66960d8170408e4dbdbc65bedb634265 -size 2842524 +oid sha256:2b4956a6b0b421d0dde3ff7a9e8169abfedccfa304908069b789caf06550d3ae +size 2836415 diff --git a/dars/dars.lock b/dars/dars.lock index 52a42745..34fa025b 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "bb097b54f7f6cc52d2c73c5cacf1638f66960d8170408e4dbdbc65bedb634265", - "size": 2842524, + "sha256": "2b4956a6b0b421d0dde3ff7a9e8169abfedccfa304908069b789caf06550d3ae", + "size": 2836415, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T18:48:49.697Z", "networks": [] From 06e3ecfe4788e55490149a61fa3081b24c1f12fd Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Thu, 9 Jul 2026 16:02:11 -0400 Subject: [PATCH 31/45] Refresh vesting DAR after balance updates --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 37a9a92d..d7ee4382 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b4956a6b0b421d0dde3ff7a9e8169abfedccfa304908069b789caf06550d3ae -size 2836415 +oid sha256:907c1825834bec4b4bba0e8c5f084b211d8947606ca298fa7329799393fcc0f6 +size 2838991 diff --git a/dars/dars.lock b/dars/dars.lock index 7c087877..ba2746ae 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "2b4956a6b0b421d0dde3ff7a9e8169abfedccfa304908069b789caf06550d3ae", - "size": 2836415, + "sha256": "907c1825834bec4b4bba0e8c5f084b211d8947606ca298fa7329799393fcc0f6", + "size": 2838991, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T18:48:49.697Z", "networks": [] From 667798407c0f29123cf9e1752e7e8d8c5c2e0031 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Fri, 10 Jul 2026 14:26:15 -0400 Subject: [PATCH 32/45] chore: refresh vesting graph DAR --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index d7ee4382..dcd9f5a5 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:907c1825834bec4b4bba0e8c5f084b211d8947606ca298fa7329799393fcc0f6 -size 2838991 +oid sha256:645614404923e716882d7052c492f3290a65dba58604aaa1c1910e8f78d78105 +size 2962986 diff --git a/dars/dars.lock b/dars/dars.lock index 20c4070c..2a46b362 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "907c1825834bec4b4bba0e8c5f084b211d8947606ca298fa7329799393fcc0f6", - "size": 2838991, + "sha256": "645614404923e716882d7052c492f3290a65dba58604aaa1c1910e8f78d78105", + "size": 2962986, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T18:48:49.697Z", "networks": [] From a5fbd9d4a079c6b0b7121919c0eb9b43c1f5b7e9 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Fri, 10 Jul 2026 18:14:17 -0400 Subject: [PATCH 33/45] chore: refresh vesting graph DAR after restack --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index dcd9f5a5..0a7ad53e 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:645614404923e716882d7052c492f3290a65dba58604aaa1c1910e8f78d78105 -size 2962986 +oid sha256:0e58c0d3dd7a01a01642f19e5f1decf973bf973cb78f7c1162ddabd08da6aa2a +size 3062781 diff --git a/dars/dars.lock b/dars/dars.lock index caf951fa..01272162 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "645614404923e716882d7052c492f3290a65dba58604aaa1c1910e8f78d78105", - "size": 2962986, + "sha256": "0e58c0d3dd7a01a01642f19e5f1decf973bf973cb78f7c1162ddabd08da6aa2a", + "size": 3062781, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T18:48:49.697Z", "networks": [] From 5af3992887769f6b9ab23b431e3c58b234610694 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Fri, 10 Jul 2026 20:04:05 -0400 Subject: [PATCH 34/45] chore: refresh vesting graph DAR after restack --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 0a7ad53e..969952c1 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e58c0d3dd7a01a01642f19e5f1decf973bf973cb78f7c1162ddabd08da6aa2a -size 3062781 +oid sha256:dbc98e324d3e85ff6ac88b500add44ac8476b1b2f6a1bff2d49e26a686888f6b +size 3125936 diff --git a/dars/dars.lock b/dars/dars.lock index 637998a3..98d40dd0 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "0e58c0d3dd7a01a01642f19e5f1decf973bf973cb78f7c1162ddabd08da6aa2a", - "size": 3062781, + "sha256": "dbc98e324d3e85ff6ac88b500add44ac8476b1b2f6a1bff2d49e26a686888f6b", + "size": 3125936, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T18:48:49.697Z", "networks": [] From 032efd5715e4d9126125b3b128d18ec956dbe487 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Fri, 10 Jul 2026 21:26:14 -0400 Subject: [PATCH 35/45] chore: refresh deterministic vesting graph DAR --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 969952c1..1a2c45cc 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbc98e324d3e85ff6ac88b500add44ac8476b1b2f6a1bff2d49e26a686888f6b -size 3125936 +oid sha256:53eb1f73365e02225d83ba0f0997ebe0a5b0bb0faa5c21c659476f319d1780da +size 3137541 diff --git a/dars/dars.lock b/dars/dars.lock index ff3b7fd0..be64eb57 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "dbc98e324d3e85ff6ac88b500add44ac8476b1b2f6a1bff2d49e26a686888f6b", - "size": 3125936, + "sha256": "53eb1f73365e02225d83ba0f0997ebe0a5b0bb0faa5c21c659476f319d1780da", + "size": 3137541, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-09T18:48:49.697Z", "networks": [] From 4c68482b5cf34665d84c67d6e81349a0955c78c9 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Fri, 10 Jul 2026 22:24:56 -0400 Subject: [PATCH 36/45] chore: refresh deterministic vesting graph DAR --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 1a2c45cc..c277e226 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53eb1f73365e02225d83ba0f0997ebe0a5b0bb0faa5c21c659476f319d1780da -size 3137541 +oid sha256:5eafcb7c29843574c44b4b7e40be3e873ff3d7fab526e7eeeef6876ffaca3592 +size 3146498 diff --git a/dars/dars.lock b/dars/dars.lock index 55e97e9b..5c724e9b 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "53eb1f73365e02225d83ba0f0997ebe0a5b0bb0faa5c21c659476f319d1780da", - "size": 3137541, + "sha256": "5eafcb7c29843574c44b4b7e40be3e873ff3d7fab526e7eeeef6876ffaca3592", + "size": 3146498, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-09T18:48:49.697Z", + "uploadedAt": "2026-07-11T02:22:20Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From e5ac95eca250dae699cd7ddc75f4c233e16d09bf Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Fri, 10 Jul 2026 23:05:52 -0400 Subject: [PATCH 37/45] chore: refresh vesting graph DAR after restack --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index c277e226..615e6695 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5eafcb7c29843574c44b4b7e40be3e873ff3d7fab526e7eeeef6876ffaca3592 -size 3146498 +oid sha256:122a64945e8ed3a968e16c985848816584263e82fa9c1db8b2d017d8c0d2f4b0 +size 3168736 diff --git a/dars/dars.lock b/dars/dars.lock index 63d759c1..3fc58cc8 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "5eafcb7c29843574c44b4b7e40be3e873ff3d7fab526e7eeeef6876ffaca3592", - "size": 3146498, + "sha256": "122a64945e8ed3a968e16c985848816584263e82fa9c1db8b2d017d8c0d2f4b0", + "size": 3168736, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-11T02:22:20Z", + "uploadedAt": "2026-07-11T03:03:33Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From 31894a12d7319c8abe6047dfb40c7a96516b57cc Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Fri, 10 Jul 2026 23:26:04 -0400 Subject: [PATCH 38/45] chore: refresh vesting graph DAR after parent fix --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 615e6695..b32ac49f 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:122a64945e8ed3a968e16c985848816584263e82fa9c1db8b2d017d8c0d2f4b0 -size 3168736 +oid sha256:0a30c92f8f75f411a3dc195e4e8c9a5d043c2b8e1549efae01dca0326060c86e +size 3169445 diff --git a/dars/dars.lock b/dars/dars.lock index c1ae097b..eb3db312 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "122a64945e8ed3a968e16c985848816584263e82fa9c1db8b2d017d8c0d2f4b0", - "size": 3168736, + "sha256": "0a30c92f8f75f411a3dc195e4e8c9a5d043c2b8e1549efae01dca0326060c86e", + "size": 3169445, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-11T03:03:33Z", + "uploadedAt": "2026-07-11T03:23:32Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From a103748b9a7c477d68a17b20cff473a7fef33fd5 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Fri, 10 Jul 2026 23:45:45 -0400 Subject: [PATCH 39/45] fix: reject multiple vesting start triggers --- .../daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml | 10 ++++++++++ Test/daml/OpenCapTable/TestVestingTerms.daml | 6 +++--- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml index 4eff1d18..f5bb13f6 100644 --- a/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml +++ b/OpenCapTable-v34/daml/Fairmint/OpenCapTable/OCF/VestingTerms.daml @@ -234,6 +234,15 @@ vestingGraphRootConditionId conditions = case conditions of root :: _ -> Some root.id [] -> None +hasAtMostOneVestingStartTrigger : [OcfVestingCondition] -> Bool +hasAtMostOneVestingStartTrigger conditions = + foldl + (\count condition -> case condition.trigger of + OcfVestingStartTrigger -> count + 1 + _ -> count) + 0 + conditions <= 1 + hasDuplicateTexts : [Text] -> Bool hasDuplicateTexts texts = hasDuplicateTextsSeen Set.empty texts @@ -362,6 +371,7 @@ validateOcfVestingConditionGraph conditions = nextEdges = Map.fromList (map (\condition -> (condition.id, condition.next_condition_ids)) conditions) edges = vestingConditionEdges conditions in not (hasDuplicateTexts conditionIds) && + hasAtMostOneVestingStartTrigger conditions && all (vestingConditionReferencesKnownConditions conditionIds nextEdges) conditions && (case vestingGraphRootConditionId conditions of Some startConditionId -> diff --git a/Test/daml/OpenCapTable/TestVestingTerms.daml b/Test/daml/OpenCapTable/TestVestingTerms.daml index ac0a4dd3..a5d22a29 100644 --- a/Test/daml/OpenCapTable/TestVestingTerms.daml +++ b/Test/daml/OpenCapTable/TestVestingTerms.daml @@ -238,10 +238,10 @@ testVestingTerms_FirstConditionIsGraphRoot = script do createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_UNORDERED_START" [next, start]) pure () -testVestingTerms_DisconnectedSecondStartConditionFails = script do +testVestingTerms_ReachableSecondStartConditionFails = script do TestOcp{issuer, cap_table} <- setupTestOcp - let firstStart = vestingCondition "start_one" OcfVestingStartTrigger ["next"] - let secondStart = vestingCondition "start_two" OcfVestingStartTrigger [] + let firstStart = vestingCondition "start_one" OcfVestingStartTrigger ["start_two"] + let secondStart = vestingCondition "start_two" OcfVestingStartTrigger ["next"] let next = vestingCondition "next" OcfVestingEventTrigger [] createVestingTermsDataMustFail issuer cap_table (vestingTermsData "VT_MULTIPLE_STARTS" [firstStart, secondStart, next]) pure () diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index b32ac49f..b97480c8 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0a30c92f8f75f411a3dc195e4e8c9a5d043c2b8e1549efae01dca0326060c86e -size 3169445 +oid sha256:3d5f7bef998be0ddccbb58928d69499fd93914023677ff7dfd83492793af9018 +size 3170799 diff --git a/dars/dars.lock b/dars/dars.lock index eb3db312..f3ddb743 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "0a30c92f8f75f411a3dc195e4e8c9a5d043c2b8e1549efae01dca0326060c86e", - "size": 3169445, + "sha256": "3d5f7bef998be0ddccbb58928d69499fd93914023677ff7dfd83492793af9018", + "size": 3170799, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-11T03:23:32Z", + "uploadedAt": "2026-07-11T03:41:26Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From 4cd10c08254e4259fa1cb1979afc0118edae30f1 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Sat, 11 Jul 2026 00:10:12 -0400 Subject: [PATCH 40/45] chore: refresh vesting graph DAR after parent update --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index b97480c8..91ad1e83 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d5f7bef998be0ddccbb58928d69499fd93914023677ff7dfd83492793af9018 -size 3170799 +oid sha256:a1bf0d76a37e1d64fbf68a8533537530c22208c859c04bb3f562f4056bc422c8 +size 3171304 diff --git a/dars/dars.lock b/dars/dars.lock index ce93e005..9a289550 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "3d5f7bef998be0ddccbb58928d69499fd93914023677ff7dfd83492793af9018", - "size": 3170799, + "sha256": "a1bf0d76a37e1d64fbf68a8533537530c22208c859c04bb3f562f4056bc422c8", + "size": 3171304, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-11T03:41:26Z", + "uploadedAt": "2026-07-11T04:09:22Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From a77b1f56e19288a99595b7192628499cf048b370 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Sat, 11 Jul 2026 00:27:06 -0400 Subject: [PATCH 41/45] chore: refresh vesting graph DAR after balance fix --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 91ad1e83..f9f32406 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1bf0d76a37e1d64fbf68a8533537530c22208c859c04bb3f562f4056bc422c8 -size 3171304 +oid sha256:b7e8175699e6c6b05b3d1fa438837ca2fc5e454667e1713ad0afe75f1174a464 +size 3172123 diff --git a/dars/dars.lock b/dars/dars.lock index 0786854f..618c45d3 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "a1bf0d76a37e1d64fbf68a8533537530c22208c859c04bb3f562f4056bc422c8", - "size": 3171304, + "sha256": "b7e8175699e6c6b05b3d1fa438837ca2fc5e454667e1713ad0afe75f1174a464", + "size": 3172123, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-11T04:09:22Z", "networks": [] From 66ed54743506ab084a5e37f8b67f2fb12a603098 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Sat, 11 Jul 2026 01:20:57 -0400 Subject: [PATCH 42/45] chore: refresh vesting graph DAR after parent updates --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index f9f32406..27f746f7 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7e8175699e6c6b05b3d1fa438837ca2fc5e454667e1713ad0afe75f1174a464 -size 3172123 +oid sha256:f29a831ffb1c2538ebbb193d3e2169624a7d01f69863e24b974f859d39719c16 +size 3175992 diff --git a/dars/dars.lock b/dars/dars.lock index 9d126787..77c80133 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "b7e8175699e6c6b05b3d1fa438837ca2fc5e454667e1713ad0afe75f1174a464", - "size": 3172123, + "sha256": "f29a831ffb1c2538ebbb193d3e2169624a7d01f69863e24b974f859d39719c16", + "size": 3175992, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-11T04:09:22Z", "networks": [] From e960746a94b1725847f8fe353ffe98f08b71c578 Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Sat, 11 Jul 2026 02:12:54 -0400 Subject: [PATCH 43/45] chore: refresh vesting graph DAR after parent update --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 27f746f7..1e3f8785 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f29a831ffb1c2538ebbb193d3e2169624a7d01f69863e24b974f859d39719c16 -size 3175992 +oid sha256:0b6e8369d3c4cb221c770a475c3c257d68f9e12c56a324c262d1f0be687b1836 +size 3179270 diff --git a/dars/dars.lock b/dars/dars.lock index cec1c481..a6582618 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "f29a831ffb1c2538ebbb193d3e2169624a7d01f69863e24b974f859d39719c16", - "size": 3175992, + "sha256": "0b6e8369d3c4cb221c770a475c3c257d68f9e12c56a324c262d1f0be687b1836", + "size": 3179270, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-11T04:09:22Z", + "uploadedAt": "2026-07-11T06:12:23.557Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": { From 0ae9f4b31fdaf3ac2697513f2e23abdc7ce23bec Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Sat, 11 Jul 2026 04:27:10 -0400 Subject: [PATCH 44/45] chore: refresh vesting graph DAR after parent update --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 1e3f8785..01032c99 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b6e8369d3c4cb221c770a475c3c257d68f9e12c56a324c262d1f0be687b1836 -size 3179270 +oid sha256:4caa07fd6391427d8c83303f29f4f63b92a4edd7044c8489212442e9bf647c50 +size 3192596 diff --git a/dars/dars.lock b/dars/dars.lock index 7294e83a..19182fe5 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,8 +33,8 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "0b6e8369d3c4cb221c770a475c3c257d68f9e12c56a324c262d1f0be687b1836", - "size": 3179270, + "sha256": "4caa07fd6391427d8c83303f29f4f63b92a4edd7044c8489212442e9bf647c50", + "size": 3192596, "sdkVersion": "3.4.10", "uploadedAt": "2026-07-11T06:12:23.557Z", "networks": [] From 1591822700805a917da2173f3e87c3d17c2a2c2b Mon Sep 17 00:00:00 2001 From: HardlyDifficult Date: Sat, 11 Jul 2026 11:33:08 -0400 Subject: [PATCH 45/45] chore: refresh vesting graph DAR --- dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar | 4 ++-- dars/dars.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar index 01032c99..f5210b13 100644 --- a/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar +++ b/dars/OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4caa07fd6391427d8c83303f29f4f63b92a4edd7044c8489212442e9bf647c50 -size 3192596 +oid sha256:24923ebd1e8699a23d1e5c23ac94ecfd8fd465655fbd13aaa593079a942d0334 +size 3193070 diff --git a/dars/dars.lock b/dars/dars.lock index bd20f4a0..0b712445 100644 --- a/dars/dars.lock +++ b/dars/dars.lock @@ -33,10 +33,10 @@ "networks": [] }, "OpenCapTable-v34/0.0.13/OpenCapTable-v34.dar": { - "sha256": "4caa07fd6391427d8c83303f29f4f63b92a4edd7044c8489212442e9bf647c50", - "size": 3192596, + "sha256": "24923ebd1e8699a23d1e5c23ac94ecfd8fd465655fbd13aaa593079a942d0334", + "size": 3193070, "sdkVersion": "3.4.10", - "uploadedAt": "2026-07-11T06:12:23.557Z", + "uploadedAt": "2026-07-11T15:31:43.000Z", "networks": [] }, "OpenCapTable-v34/0.0.2/OpenCapTable-v34.dar": {