Source Code


        ;; 
        ;; fak.fun PRE @version 1.0
        ;; Pre-launch contract for token distribution
        ;; Dynamic allocation: 1-7 seats per user in Period 1
        ;; Each seat = 0.00006900 BTC, targeting 200 seats total with minimum 100 users
        
        ;; Pre-launch participants are activating the DEX contract 
        ;; and therefore can claim fees generated by DEX
        ;; Fee airdrops are separate from token purchase and vesting.
    
        (use-trait faktory-token 'SP3XXMS38VTAWTVPE5682XSBFXPTH7XCPEBTX8AN2.faktory-trait-v1.sip-010-trait) 
        
        (define-constant SEATS u200)
        (define-constant MIN-USERS u100)
        (define-constant MAX-SEATS-PER-USER u7)
        (define-constant PRICE-PER-SEAT u6900) ;; 6.9K sats per seat
        (define-constant TOKENS-PER-SEAT u100000000000000) ;; 1M 
        (define-constant DEX-AMOUNT u1000000)
        (define-constant MULTI-SIG-AMOUNT u30000)
        (define-constant FEE-AMOUNT u350000)
    
        (define-constant FT-INITIALIZED-BALANCE u20000000000000000) ;; 200M tokens for pre-launch if supply 1B
        
        ;; Vesting schedule (percentages add up to 100)
        (define-constant VESTING-SCHEDULE
          (list 
          ;; Initial release - 10% at once
          {height: u100, percent: u10, id: u0}    ;; 10% at initial unlock
          
          ;; Second phase - 20% total across 6 drips
          {height: u250, percent: u3, id: u1}     ;; 3%
          {height: u400, percent: u3, id: u2}     ;; 3%
          {height: u550, percent: u3, id: u3}     ;; 3%
          {height: u700, percent: u3, id: u4}     ;; 3%
          {height: u850, percent: u4, id: u5}     ;; 4%
          {height: u1000, percent: u4, id: u6}    ;; 4% - hitting 30% total at original second milestone
          
          ;; Third phase - 30% total across 7 drips
          {height: u1200, percent: u4, id: u7}    ;; 4%
          {height: u1400, percent: u4, id: u8}    ;; 4%
          {height: u1600, percent: u4, id: u9}    ;; 4%
          {height: u1750, percent: u4, id: u10}   ;; 4%
          {height: u1900, percent: u4, id: u11}   ;; 4%
          {height: u2000, percent: u5, id: u12}   ;; 5%
          {height: u2100, percent: u5, id: u13}   ;; 5% - hitting 60% total at original third milestone
          
          ;; Final phase - 40% total across 7 drips
          {height: u2500, percent: u5, id: u14}   ;; 5%
          {height: u2900, percent: u5, id: u15}   ;; 5%
          {height: u3300, percent: u6, id: u16}   ;; 6%
          {height: u3600, percent: u6, id: u17}   ;; 6%
          {height: u3900, percent: u6, id: u18}   ;; 6%
          {height: u4100, percent: u6, id: u19}   ;; 6%
          {height: u4200, percent: u6, id: u20})) ;; 6% - hitting 100% total at original final milestone
    
        (define-constant FAKTORY1 'SMH8FRN30ERW1SX26NJTJCKTDR3H27NRJ6W75WQE)
        (define-constant FAKTORY2 'SM362G0X1YNB2M3FWWFAASV9WB3XHQ8RWP512SSX3)
        
        ;; Data vars
        (define-data-var ft-balance uint u0)
        (define-data-var stx-balance uint u0)
        (define-data-var total-seats-taken uint u0)
        (define-data-var total-users uint u0)
        (define-data-var distribution-height uint u0)
        (define-data-var deployment-height uint burn-block-height)
        (define-data-var accelerated-vesting bool false)
        (define-data-var market-open bool false)
        (define-data-var governance-active bool false)
        (define-data-var acc-distributed uint u0)
    
        ;; Token, Dex and sBTC
        (define-constant TOKEN-DAO 'SPV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RCJDC22.bouncr-faktory) ;; param
        (define-constant DEX-DAO 'SPV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RCJDC22.bouncr-faktory-dex) ;; param
      
        ;; Define a data variable to track seat holders
        (define-data-var seat-holders (list 200 {owner: principal, seats: uint}) (list))
        
        ;; Track seat ownership and claims
        (define-map seats-owned principal uint)
        (define-map claimed-amounts principal uint)
        
        ;; Error constants
        (define-constant ERR-NO-SEATS-LEFT (err u301))
        (define-constant ERR-NOT-SEAT-OWNER (err u302))
        (define-constant ERR-NOTHING-TO-CLAIM (err u304))
        (define-constant ERR-NOT-AUTHORIZED (err u305))
        (define-constant ERR-WRONG-TOKEN (err u307))
        (define-constant ERR-CONTRACT-INSUFFICIENT-FUNDS (err u311))
        (define-constant ERR-INVALID-SEAT-COUNT (err u313))
        (define-constant ERR-REMOVING-HOLDER (err u316))
        (define-constant ERR-DISTRIBUTION-ALREADY-SET (err u320))
        (define-constant ERR-DISTRIBUTION-NOT-INITIALIZED (err u321))
        
        ;; Helper function to update seat holders list
        (define-private (update-seat-holder (owner principal) (seat-count uint))
        (let ((current-holders (var-get seat-holders))
                (updated-list (update-or-add-holder current-holders owner seat-count)))
            (var-set seat-holders updated-list)))
    
        ;; Helper to update or add a holder to the list
        (define-private (update-or-add-holder 
            (holders (list 200 {owner: principal, seats: uint}))
            (owner principal) (seat-count uint))
        (let ((position (find-holder-position holders)))
            (if (is-some position)
                ;; Update existing holder - unwrap the optional result
                (unwrap-panic (replace-at? holders (unwrap-panic position) {owner: owner, seats: seat-count}))
                ;; Add new holder
                (unwrap-panic (as-max-len? (append holders {owner: owner, seats: seat-count}) u200)))))
    
        ;; Helper to find a holder's position in the list
        (define-private (find-holder-position 
            (holders (list 200 {owner: principal, seats: uint})))
        (let ((result (fold check-if-owner 
                            holders 
                            {found: false, index: u0})))
            (if (get found result)
                (some (get index result))
                none)))
    
        (define-private (check-if-owner 
            (entry {owner: principal, seats: uint}) 
            (state {found: bool, index: uint}))
        (if (get found state)
            ;; Already found, just pass through
            state
            ;; Check if this is the owner we're looking for
            (if (is-eq (get owner entry) tx-sender)
                ;; Found it, update state
                {found: true, index: (get index state)}
                ;; Not found, increment counter
                {found: false, index: (+ (get index state) u1)})))
    
        (define-private (remove-seat-holder)
        (let ((filtered-list (filter not-matching-owner (var-get seat-holders))))
            (var-set seat-holders filtered-list)
            (ok true)))
    
        (define-private (not-matching-owner (entry {owner: principal, seats: uint}))
        (not (is-eq (get owner entry) tx-sender)))
    
        ;; Main functions
        ;; Buy seats in Period 1
        (define-public (buy-up-to (seat-count uint))
            (let (
                (current-seats (var-get total-seats-taken))
                (user-seats (default-to u0 (map-get? seats-owned tx-sender)))
                (max-total-allowed (get-max-seats-allowed))
                (max-additional-allowed (if (>= (var-get total-users) MIN-USERS)
                                            max-total-allowed ;; if quota of users is attained, anyone can buy
                                            (if (>= user-seats max-total-allowed)
                                                u0
                                                (- max-total-allowed user-seats))))
                (actual-seats (if (> seat-count max-additional-allowed) 
                                max-additional-allowed
                                seat-count)))
                
                (asserts! (is-eq (var-get distribution-height) u0) ERR-DISTRIBUTION-ALREADY-SET)
                (asserts! (> actual-seats u0) ERR-INVALID-SEAT-COUNT)
                (asserts! (<= (+ user-seats actual-seats) MAX-SEATS-PER-USER) ERR-INVALID-SEAT-COUNT)
                (asserts! (< current-seats SEATS) ERR-NO-SEATS-LEFT)
    
                ;; Process payment
                (match (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token 
                                transfer (* PRICE-PER-SEAT actual-seats) tx-sender (as-contract tx-sender) none)
                    success 
                        (begin
                            (if (is-eq user-seats u0) 
                                (var-set total-users (+ (var-get total-users) u1))
                                true)
                            (map-set seats-owned tx-sender (+ user-seats actual-seats))
                            (var-set total-seats-taken (+ current-seats actual-seats))
                            (var-set stx-balance (+ (var-get stx-balance) (* PRICE-PER-SEAT actual-seats)))
                            (update-seat-holder tx-sender (+ user-seats actual-seats))
                            
                            (if (and (>= (var-get total-users) MIN-USERS)  ;; Check if we should set distribution height
                                    (>= (var-get total-seats-taken) SEATS))
                                (try! (initialize-token-distribution))
                                true)
                            (print {
                                type: "buy-seats",
                                buyer: tx-sender,
                                seats-owned: (+ user-seats actual-seats),
                                total-users: (var-get total-users),
                                total-seats-taken: (+ current-seats actual-seats),
                                stx-balance: (var-get stx-balance),
                                seat-holders: (var-get seat-holders),
                                distribution-height: (var-get distribution-height) 
                                })
                            (ok true))
                    error (err error))))
    
        ;; Refund logic only for Period 1 expired and Period 2 not started
        (define-public (refund)
            (let (
                (user-seats (default-to u0 (map-get? seats-owned tx-sender)))
                (seat-owner tx-sender))
                (asserts! (is-eq (var-get distribution-height) u0) ERR-DISTRIBUTION-ALREADY-SET)
                (asserts! (> user-seats u0) ERR-NOT-SEAT-OWNER)
                
                ;; Process refund
                (match (as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token 
                                            transfer (* PRICE-PER-SEAT user-seats) tx-sender seat-owner none))
                    success 
                        (let ((is-removed (unwrap! (remove-seat-holder) ERR-REMOVING-HOLDER)))
                            (map-delete seats-owned tx-sender)
                            (var-set total-seats-taken (- (var-get total-seats-taken) user-seats))
                            (var-set total-users (- (var-get total-users) u1))
                            (var-set stx-balance (- (var-get stx-balance) (* PRICE-PER-SEAT user-seats)))
                            (print {
                                type: "refund",
                                user: tx-sender,
                                seats-refunded: user-seats,
                                seat-holders: (var-get seat-holders),
                                total-seats-taken: (var-get total-seats-taken),
                                total-users: (var-get total-users),
                                stx-balance: (var-get stx-balance)
                                })
                            (ok true))
                    error (err error))))
      
      (define-private (get-claimable-amount (owner principal))
          (begin
              (if (> (var-get distribution-height) u0)
                  (let ((claimed (default-to u0 (map-get? claimed-amounts owner)))
                        (seats-owner (default-to u0 (map-get? seats-owned owner)))
                        (vested (fold check-claimable VESTING-SCHEDULE u0)))
                      (- (* vested seats-owner) claimed)) ;; double claiming is impossible    
                  u0))) ;; If distribution not initialized (equals u0), nothing is claimable
      
      (define-private (check-claimable (entry {height: uint, percent: uint, id: uint}) (current-total uint))
          (let ((distribution-start (var-get distribution-height)))
              (if (<= (+ distribution-start (get height entry)) burn-block-height)
                  (+ current-total (/ (* TOKENS-PER-SEAT (get percent entry)) u100))
                  (if (and 
                      (var-get accelerated-vesting)   ;; token graduated, accelerated vesting
                      (<= (get id entry) u13))          ;; we're in first 13 entries (0,1,2)
                      (+ current-total (/ (* TOKENS-PER-SEAT (get percent entry)) u100))
                      current-total))))
      
      ;; Claim vested tokens
      (define-public (claim (ft <faktory-token>))
          (let ((claimable (get-claimable-amount tx-sender))
                (seat-owner tx-sender))
              (asserts! (> (var-get distribution-height) u0) ERR-DISTRIBUTION-NOT-INITIALIZED) 
              (asserts! (is-eq (contract-of ft) TOKEN-DAO) ERR-WRONG-TOKEN)
              (asserts! (> (default-to u0 (map-get? seats-owned tx-sender)) u0) ERR-NOT-SEAT-OWNER)
              (asserts! (> claimable u0) ERR-NOTHING-TO-CLAIM)
              (asserts! (>= (var-get ft-balance) claimable) ERR-CONTRACT-INSUFFICIENT-FUNDS)
              (match (as-contract (contract-call? ft transfer claimable tx-sender seat-owner none))
                  success
                      (begin
                          (map-set claimed-amounts tx-sender 
                              (+ (default-to u0 (map-get? claimed-amounts tx-sender)) claimable))
                          (var-set ft-balance (- (var-get ft-balance) claimable)) ;; reduce ft-balance by claimable
                          (print {
                              type: "claim",
                              user: tx-sender,
                              amount-claimed: claimable,
                              total-claimed: (map-get? claimed-amounts tx-sender),
                              ft-balance: (var-get ft-balance)
                              })
                          (ok claimable))
                  error (err error))))
    
        ;; Claim vested tokens on behalf of a specific holder
        (define-public (claim-on-behalf (ft <faktory-token>) (holder principal))
            (let ((claimable (get-claimable-amount holder)))
                (asserts! (> (var-get distribution-height) u0) ERR-DISTRIBUTION-NOT-INITIALIZED) 
                (asserts! (is-eq (contract-of ft) TOKEN-DAO) ERR-WRONG-TOKEN)
                (asserts! (> (default-to u0 (map-get? seats-owned holder)) u0) ERR-NOT-SEAT-OWNER)
                (asserts! (> claimable u0) ERR-NOTHING-TO-CLAIM)
                (asserts! (>= (var-get ft-balance) claimable) ERR-CONTRACT-INSUFFICIENT-FUNDS) 
                (match (as-contract (contract-call? ft transfer claimable tx-sender holder none))
                    success
                        (begin
                            (map-set claimed-amounts holder 
                                (+ (default-to u0 (map-get? claimed-amounts holder)) claimable))
                            (var-set ft-balance (- (var-get ft-balance) claimable))
                            (print {
                                type: "claim",
                                user: holder,
                                amount-claimed: claimable,
                                total-claimed: (map-get? claimed-amounts holder),
                                ft-balance: (var-get ft-balance)
                            })
                            (ok claimable))
                    error (err error))))
    
      ;; Read only functions
     (define-read-only (get-max-seats-allowed)
        (let (
            (total-users-now (var-get total-users))
            (seats-remaining (- SEATS (var-get total-seats-taken)))
            ;; Check if we've already met the minimum users requirement
            (users-remaining (if (>= total-users-now MIN-USERS)
                               u0  ;; No more users needed
                               (- MIN-USERS total-users-now)))
            (max-possible (if (>= total-users-now MIN-USERS)
                               seats-remaining  ;; No more users needed
                               (+ (- seats-remaining users-remaining) u1))))
            (if (>= max-possible MAX-SEATS-PER-USER)
                MAX-SEATS-PER-USER
                max-possible)))
      
        (define-read-only (get-contract-status)
            (ok 
            {
                is-distribution-period: (> (var-get distribution-height) u0),
                total-users: (var-get total-users),
                total-seats-taken: (var-get total-seats-taken),
                deployment-height: (var-get deployment-height),
                distribution-height: (var-get distribution-height),
                accelerated-vesting: (var-get accelerated-vesting),
                market-open: (var-get market-open),
                governance-active: (var-get governance-active),
                seat-holders: (var-get seat-holders)
            }))
      
      (define-read-only (get-user-info (user principal))
          (ok
          {
              seats-owned: (default-to u0 (map-get? seats-owned user)),
              amount-claimed: (default-to u0 (map-get? claimed-amounts user)),
              claimable-amount: (get-claimable-amount user)
          }))
      
      (define-read-only (get-user-claimable (user principal))
        (ok
        {
            claimable-amount: (get-claimable-amount user)
        }))
      
      (define-read-only (get-remaining-seats)
          (ok {remainin-seats: (- SEATS (var-get total-seats-taken))}))
      
      (define-read-only (get-seats-owned (address principal))
          (ok {seats-owned: (default-to u0 (map-get? seats-owned address))}))
      
      (define-read-only (get-claimed-amount (address principal))
          (ok {claimed-amount:
          (default-to u0 (map-get? claimed-amounts address))}))
      
      (define-read-only (get-vesting-schedule)
          (ok {vesting-schedule: VESTING-SCHEDULE}))
      
      (define-read-only (get-seat-holders)
          (ok {seat-holders: (var-get seat-holders)}))
    
      (define-read-only (is-market-open) 
          (ok (var-get market-open))
      )
      
      (define-read-only (is-governance-active)
          (ok (var-get governance-active))
      )
      
      ;; on pre-launch successful completion
      (define-private (initialize-token-distribution)
          (begin
              (var-set market-open true)
              (var-set governance-active true) ;; jason:  in core/action proposal, checks from create proposal, deadlocks anything happening
              (try! (as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token 
                                        transfer DEX-AMOUNT tx-sender DEX-DAO none))) ;; BTC to DEX  
              (try! (as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token 
                                        transfer MULTI-SIG-AMOUNT tx-sender FAKTORY1 none))) 
              (try! (as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token 
                                        transfer FEE-AMOUNT tx-sender FAKTORY2 none)))  
              (var-set distribution-height burn-block-height)
              (var-set last-airdrop-height (some burn-block-height))
              (var-set ft-balance FT-INITIALIZED-BALANCE)
              (var-set stx-balance u0)
              (print {
                  type: "distribution-initialized",
                  token-contract: TOKEN-DAO,
                  distribution-height: burn-block-height,
                  ft-balance: FT-INITIALIZED-BALANCE
              })
              (ok true)))
      
    ;; on Bonding
    (define-public (toggle-bonded)
        (begin
            (asserts! (is-eq contract-caller DEX-DAO) ERR-NOT-AUTHORIZED)
            (var-set accelerated-vesting true) 
            (var-set final-airdrop-mode true) 
            (print {
                type: "bonded",
                token-contract: TOKEN-DAO,
                bonded-height: burn-block-height,
            }) 
            (ok true)))
    
    ;; Simplified Fee Distribution System
    ;; Constants
    (define-constant COOLDOWN-PERIOD u1050) ;; Longer cooldown between airdrops
    
    ;; Error constants
    (define-constant ERR-NO-FEES-TO-DISTRIBUTE (err u323))
    (define-constant ERR-COOLDOWN-ACTIVE (err u324))
    (define-constant ERR-TOTAL-SEATS-ZERO (err u325))
    
    ;; Data vars for fee tracking
    (define-data-var accumulated-fees uint u0)        ;; Total fees accumulated since last airdrop
    (define-data-var last-airdrop-height (optional uint) (some u0)) ;; Block height of the last airdrop
    (define-data-var final-airdrop-mode bool false)   ;; Toggle for final airdrop mode
    
    ;; Add this function to allow the DEX to send fees to the contract
    (define-public (create-fees-receipt (amount uint))
        (let ((current-fees (var-get accumulated-fees)))
            ;; Only the DEX contract can call this function
            (asserts! (is-eq contract-caller DEX-DAO) ERR-NOT-AUTHORIZED)
            
            ;; Update accumulated fees
            (var-set accumulated-fees (+ current-fees amount))
            
            (print {
                type: "fees-received",
                amount: amount,
                total-accumulated: (+ current-fees amount)
            })
            (ok true)))
    
    ;; Check if airdrop can be triggered
    (define-read-only (can-trigger-airdrop)
        (let ((cooldown-expired (>= burn-block-height (+ (unwrap-panic (var-get last-airdrop-height)) COOLDOWN-PERIOD)))
              (has-fees (> (var-get accumulated-fees) u0))
              (final-mode (var-get final-airdrop-mode)))
            
            (or (and cooldown-expired has-fees)    
                (and final-mode has-fees))))      
    
    ;; Main airdrop function - anyone can call
    (define-public (trigger-fee-airdrop)
        (let ((total-fees (var-get accumulated-fees))
              (total-seats (var-get total-seats-taken))
              (can-airdrop (can-trigger-airdrop))
              (acc-fees (var-get accumulated-fees)))
            
            ;; Check if airdrop can be triggered
            (asserts! can-airdrop (if (> total-fees u0) 
                                     ERR-COOLDOWN-ACTIVE 
                                     ERR-NO-FEES-TO-DISTRIBUTE))
            
            ;; Must have fees to distribute and seats must exist
            (asserts! (> total-fees u0) ERR-NO-FEES-TO-DISTRIBUTE)
            (asserts! (> total-seats u0) ERR-TOTAL-SEATS-ZERO)
            
            ;; Distribute fees to all seat holders
            (var-set acc-distributed u0)
            (let ((distributions (map distribute-to-holder (var-get seat-holders))))
                 
                 (if (> (- acc-fees (var-get acc-distributed)) u0)
                     (match (as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token 
                                         transfer (- acc-fees (var-get acc-distributed)) tx-sender FAKTORY1 none))
                         success
                             (begin
                                 (print {
                                     type: "fee-residual",
                                     recipient: FAKTORY1,
                                     amount: (- acc-fees (var-get acc-distributed))
                                 })
                                 true)
                         error false)
                     true)
     
                 ;; Reset accumulated fees and update last airdrop height
                 (var-set accumulated-fees u0)
                 (var-set last-airdrop-height (some burn-block-height))
                 
                 (print {
                     type: "fee-airdrop",
                     total-distributed: total-fees,
                     timestamp: burn-block-height,
                     distributions: distributions
                 })
                 (ok total-fees))))
    
    ;; Helper function to distribute fees to a single holder
    (define-private (distribute-to-holder (entry {owner: principal, seats: uint}))
        (let ((holder (get owner entry))
              (user-seats (get seats entry))
              (total-seats (var-get total-seats-taken))
              (total-fees (var-get accumulated-fees))
              (user-share (if (and (> user-seats u0) (> total-seats u0))
                             (/ (* total-fees user-seats) total-seats)
                             u0)))
            
            ;; Only distribute if the user's share is greater than zero
            (if (> user-share u0)
                (match (as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token 
                                        transfer user-share tx-sender holder none))
                     success
                         (begin 
                             (var-set acc-distributed (+ (var-get acc-distributed) user-share))
                             {recipient: holder, amount: user-share})
                     error {recipient: holder, amount: u0})  
                 {recipient: holder, amount: u0})))
    
    ;; Helper to extract principal from seat-holder entry
    (define-private (get-holder-principal (entry {owner: principal, seats: uint}))
        (get owner entry))
    
    ;; Get all unique seat holders
    (define-read-only (get-all-seat-holders)
        (ok (var-get seat-holders)))
    
    ;; Get fee distribution info for UI
    (define-read-only (get-fee-distribution-info)
        (ok {
            accumulated-fees: (var-get accumulated-fees),
            last-airdrop-height: (var-get last-airdrop-height),
            current-height: burn-block-height,
            cooldown-period: COOLDOWN-PERIOD,
            final-airdrop-mode: (var-get final-airdrop-mode),
            can-trigger-now: (can-trigger-airdrop)
        }))
    
    ;; Get user's expected share in the next airdrop
    (define-read-only (get-user-expected-share (user principal))
        (let ((user-seats (default-to u0 (map-get? seats-owned user)))
              (total-seats (var-get total-seats-taken))
              (total-fees (var-get accumulated-fees)))
            
            (ok {
                user: user,
                user-seats: user-seats,
                total-seats: total-seats,
                total-accumulated-fees: total-fees,
                expected-share: (if (and (> user-seats u0) (> total-seats u0) (> total-fees u0))
                                  (/ (* total-fees user-seats) total-seats)
                                  u0)
            })))

Functions (33)

FunctionAccessArgs
update-seat-holderprivateowner: principal, seat-count: uint
update-or-add-holderprivateholders: (list 200 {owner: principal, seats: uint}
find-holder-positionprivateholders: (list 200 {owner: principal, seats: uint}
check-if-ownerprivateentry: {owner: principal, seats: uint}, state: {found: bool, index: uint}
remove-seat-holderprivate
not-matching-ownerprivateentry: {owner: principal, seats: uint}
buy-up-topublicseat-count: uint
refundpublic
get-claimable-amountprivateowner: principal
check-claimableprivateentry: {height: uint, percent: uint, id: uint}, current-total: uint
claimpublicft: <faktory-token>
claim-on-behalfpublicft: <faktory-token>, holder: principal
get-max-seats-allowedread-only
get-contract-statusread-only
get-user-inforead-onlyuser: principal
get-user-claimableread-onlyuser: principal
get-remaining-seatsread-only
get-seats-ownedread-onlyaddress: principal
get-claimed-amountread-onlyaddress: principal
get-vesting-scheduleread-only
get-seat-holdersread-only
is-market-openread-only
is-governance-activeread-only
initialize-token-distributionprivate
toggle-bondedpublic
create-fees-receiptpublicamount: uint
can-trigger-airdropread-only
trigger-fee-airdroppublic
distribute-to-holderprivateentry: {owner: principal, seats: uint}
get-holder-principalprivateentry: {owner: principal, seats: uint}
get-all-seat-holdersread-only
get-fee-distribution-inforead-only
get-user-expected-shareread-onlyuser: principal