code wiki / (root) / nx_captable_lib.nx

nx_captable_lib.nx source

↩ module page · 108 lines · 5326 B

1// nx_captable_lib.nx -- ENTITY MANAGEMENT: capitalisation table arithmetic and corporate-authority limits. 2// The Carta/Athennian-class category we had at zero. A cap table is not a spreadsheet, it is a set of 3// hard corporate-law constraints, and two of them are violated constantly. 4// 5// u2605OVER-ISSUANCE IS VOID, NOT AN OVERDRAFT. A corporation may not issue more shares than its charter 6// AUTHORISES. Shares purportedly issued beyond that number are void -- not "issued pending an amendment", 7// not a rounding problem to fix at the next raise. A cap table that simply shows a larger issued figure 8// is asserting something the corporation had no power to do, so this refuses rather than reports. 9// 10// u2605OWNERSHIP DEPENDS ENTIRELY ON THE BASIS, AND THE BASIS IS USUALLY UNSTATED. The same holder is a 11// different percentage on an OUTSTANDING basis than on a FULLY DILUTED basis (which counts the option 12// pool, warrants and convertibles). Founders hear the outstanding number, investors model the diluted 13// one, and the gap is where disputes live. Both are computed here, separately and explicitly named -- 14// there is deliberately no single "ownership" function to call by accident. 15// 16// Percentages are in PER MILLE (0..1000) to stay in integer arithmetic; a permille figure is exact where 17// a truncated percent would silently lose sub-1% holders. 18// 19// u2605FAIL-CLOSED: a zero or negative denominator yields ENT_UNKNOWN, never zero percent. "0% owned" 20// and "we cannot compute this" are different answers. 21// STRUCTURE: pure decision core, zero I/O. license_tier: ORIGINAL LIB. 22 23import "nx_matter_lib.nx" 24 25const ENT_UNKNOWN: i64 = 0 - 1 26const ENT_VOID: i64 = 0 - 2 27 28func ent_is1(v: i64) -> i64 { 29 if v == 1 { return 1 } 30 return 0 31} 32 33// u2605the authority check. Issuing beyond the authorised count is VOID, not merely flagged. 34func ent_issue_ok_pure(authorized: i64, issued: i64) -> i64 { 35 if authorized < 0 { return 0 } 36 if issued < 0 { return 0 } 37 if issued > authorized { return 0 } 38 return 1 39} 40 41// shares available to issue under the current charter; negative capacity is impossible, so an 42// over-issued table reports VOID rather than a negative headroom figure. 43func ent_authorized_remaining_pure(authorized: i64, issued: i64) -> i64 { 44 if ent_issue_ok_pure(authorized, issued) == 0 { return ENT_VOID } 45 return authorized - issued 46} 47 48// outstanding = issued minus treasury. Treasury shares exist but do not vote or participate. 49func ent_outstanding_pure(issued: i64, treasury: i64) -> i64 { 50 if issued < 0 { return ENT_UNKNOWN } 51 if treasury < 0 { return ENT_UNKNOWN } 52 if treasury > issued { return ENT_UNKNOWN } 53 return issued - treasury 54} 55 56// fully diluted adds everything that CAN become a share: granted options, the unissued pool, warrants 57// and convertibles. Omitting the UNISSUED pool is the most common understatement. 58func ent_fully_diluted_pure(outstanding: i64, options_granted: i64, options_available: i64, warrants: i64, convertibles: i64) -> i64 { 59 if outstanding == ENT_UNKNOWN { return ENT_UNKNOWN } 60 if options_granted < 0 { return ENT_UNKNOWN } 61 if options_available < 0 { return ENT_UNKNOWN } 62 if warrants < 0 { return ENT_UNKNOWN } 63 if convertibles < 0 { return ENT_UNKNOWN } 64 return outstanding + options_granted + options_available + warrants + convertibles 65} 66 67// ownership in PER MILLE against an explicit denominator; a non-positive denominator is UNKNOWN, 68// never 0 permille. 69func ent_permille_pure(held: i64, denominator: i64) -> i64 { 70 if denominator <= 0 { return ENT_UNKNOWN } 71 if held < 0 { return ENT_UNKNOWN } 72 return (held * 1000) / denominator 73} 74 75func ent_ownership_outstanding_pure(held: i64, outstanding: i64) -> i64 { 76 return ent_permille_pure(held, outstanding) 77} 78 79func ent_ownership_diluted_pure(held: i64, fully_diluted: i64) -> i64 { 80 return ent_permille_pure(held, fully_diluted) 81} 82 83// u2605dilution can only ever REDUCE a holder's percentage (or leave it equal when nothing is outstanding 84// beyond the shares themselves). 1 when that invariant holds. 85func ent_dilution_consistent_pure(outstanding_permille: i64, diluted_permille: i64) -> i64 { 86 if outstanding_permille == ENT_UNKNOWN { return 0 } 87 if diluted_permille == ENT_UNKNOWN { return 0 } 88 if diluted_permille > outstanding_permille { return 0 } 89 return 1 90} 91 92// the pool as a share of the fully diluted base -- the number investors actually negotiate. 93func ent_pool_permille_pure(options_granted: i64, options_available: i64, fully_diluted: i64) -> i64 { 94 if options_granted < 0 { return ENT_UNKNOWN } 95 if options_available < 0 { return ENT_UNKNOWN } 96 return ent_permille_pure(options_granted + options_available, fully_diluted) 97} 98 99// u2605A CAP TABLE IS VALID only when issuance is within authority, outstanding resolves, and the fully 100// diluted base is at least the outstanding count. Any one failing invalidates the whole table. 101func ent_table_valid_pure(authorized: i64, issued: i64, treasury: i64, fully_diluted: i64) -> i64 { 102 if ent_issue_ok_pure(authorized, issued) == 0 { return 0 } 103 let outs: i64 = ent_outstanding_pure(issued, treasury) 104 if outs == ENT_UNKNOWN { return 0 } 105 if fully_diluted == ENT_UNKNOWN { return 0 } 106 if fully_diluted < outs { return 0 } 107 return 1 108}