Source Code

(use-trait ft-trait 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.trait-sip-010.sip-010-trait)

;; ERRS

(define-constant ERR-INSUFFICIENT-AMOUNT (err u5001))
(define-constant ERR-NOT-AUTHORIZED (err u5009))
(define-constant ERR-BELOW-MIN-PERIOD (err u6000))
(define-constant ERR-PRESALE-STARTED (err u7000))
(define-constant ERR-PRESALE-NOT-STARTED (err u7001))
(define-constant ERR-PRESALE-ENDED (err u7002))
(define-constant ERR-PRESALE-NOT-ENDED (err u7003))
(define-constant ERR-NOT-PARTICIPANT (err u7004))
(define-constant ERR-ALREADY-CLAIMED (err u7005))
(define-constant ERR-POOL-NOT-FUNDED (err u8000))
(define-constant ERR-MAX-DEPOSIT-EXCEEDED (err u8001))
(define-constant ERR-HARDCAP-EXCEEDED (err u8002))
(define-constant ERR-MIN-TARGET-NOT-REACHED (err u8003))

(define-constant ONE_8 u100000000)
(define-constant ONE_6 u1000000)

;; DATA MAPS AND VARS

;; set caller as contract owner
(define-data-var contract-owner principal tx-sender)

;; amount allocated for presale
(define-constant MEMEGOAT-POOL u1350000000000000) ;; 1.35 Biliion Memegoat

;; hardcap
(define-constant PRESALE-HARDCAP u50000000000) ;; 50K STX 

;; softcap
(define-constant PRESALE-SOFTCAP u25000000000) ;; 25K STX

;; stx pool
(define-data-var stx-pool uint u0)

;; check for testnet
(define-data-var min-stx-deposit uint u20000000) ;; 20 STX
(define-data-var max-stx-deposit uint u200000000) ;; 200 STX

(define-data-var presale-started bool false)
(define-data-var no-of-participants uint u0)
(define-data-var duration uint u0)
(define-data-var release-block uint u0)
(define-data-var vault-funded bool false)

(define-map users-deposits
    { user-addr: principal }
    uint
)

(define-map user-claimed 
  { user-addr : principal }
  bool
)

;; MANAGEMENT CALLS

(define-public (set-contract-owner (owner principal))
  (begin
    (try! (check-is-owner)) 
    (ok (var-set contract-owner owner))
  )
)

(define-public (set-duration (no-of-blocks uint))
  (begin
    (try! (check-is-owner))
    (asserts! (not (var-get presale-started)) ERR-PRESALE-STARTED)
    (asserts! (>= no-of-blocks u144) ERR-BELOW-MIN-PERIOD) ;; rough estimate of one day
    (ok (var-set duration no-of-blocks))
  )
)

(define-public (fund-launchpad)
  (begin
    (try! (check-is-owner))
    (asserts! (not (var-get presale-started)) ERR-PRESALE-STARTED)
    (try! (contract-call? .memegoatstx transfer-fixed (decimals-to-fixed MEMEGOAT-POOL) tx-sender .memegoat-vault-v1 none))
    (var-set vault-funded true)
    (ok true)
  )
)

(define-public (start-presale)
  (begin
    (try! (check-is-owner))
    (asserts! (>= (var-get duration) u144) ERR-BELOW-MIN-PERIOD)
    ;; (asserts! (is-eq MEMEGOAT-POOL (try! (contract-call? .memegoat-vault-v1 get-balance .memegoatstx))) ERR-POOL-NOT-FUNDED)
    (asserts! (var-get vault-funded) ERR-POOL-NOT-FUNDED)
    (var-set presale-started true)
    (ok (var-set release-block (+ (var-get duration) block-height)))
  )
)

;; READ ONLY CALLS

(define-read-only (get-user-deposits (user-addr principal)) 
  (default-to u0 (map-get? users-deposits {user-addr: user-addr}))
)

(define-read-only (calculate-allocation (user-addr principal))
  (let
    ((user-deposit (get-user-deposits user-addr)))
    (* (get-stx-quote) user-deposit) 
  )
)

(define-read-only (check-if-claimed (user-addr principal)) 
  (default-to false (map-get? user-claimed { user-addr: user-addr }))
)

(define-read-only (get-contract-owner)
  (ok (var-get contract-owner))
)

(define-read-only (get-stx-quote)
  (/ MEMEGOAT-POOL (var-get stx-pool))
)

(define-read-only (get-hardcap)
  (ok PRESALE-HARDCAP)
)

(define-read-only (get-softcap)
  (ok PRESALE-SOFTCAP)
)

(define-read-only (get-memegoatpool)
  (ok MEMEGOAT-POOL)
)

(define-read-only (get-stx-pool)
  (ok (var-get stx-pool))
)

(define-read-only (get-no-of-participants)
  (ok (var-get no-of-participants))
)

(define-read-only (get-release-block)
  (ok (var-get release-block))
)

(define-read-only (get-duration)
  (ok (var-get duration))
)

;; PRIVATE CALLS

(define-private (check-is-owner)
  (ok (asserts! (is-eq tx-sender (var-get contract-owner)) ERR-NOT-AUTHORIZED))
)

(define-private (decimals-to-fixed (amount uint)) 
  (/ (* amount ONE_8) ONE_6)
)

;; depositStx
(define-public (deposit-stx (amount uint))
  (begin
    (asserts! (>= amount (var-get min-stx-deposit)) ERR-INSUFFICIENT-AMOUNT)
    (asserts! (var-get presale-started) ERR-PRESALE-NOT-STARTED)
    (asserts! (> (var-get release-block) block-height) ERR-PRESALE-ENDED)
    (let
      (
        (stx-pool-balance (var-get stx-pool))
        (exists (is-some (map-get? users-deposits { user-addr: tx-sender })))
        (user-deposit (get-user-deposits tx-sender))
        (participants (var-get no-of-participants))
      )

      ;; check that hardcap has not been reached
      (asserts! (<= (+ amount stx-pool-balance) PRESALE-HARDCAP) ERR-HARDCAP-EXCEEDED)

      ;; check that user has not exceeded max deposit
      (asserts! (<= (+ user-deposit amount) (var-get max-stx-deposit)) ERR-MAX-DEPOSIT-EXCEEDED)
    
      ;; transfer stx to vault
      (try! (stx-transfer? amount tx-sender .memegoat-vault-v1))

      ;; increment pool balance
      (var-set stx-pool (+ stx-pool-balance amount))

      ;; update user deposits
      (map-set users-deposits {user-addr:tx-sender} (+ user-deposit amount))

      ;; update no of participants
      (if exists
        (var-set no-of-participants participants)
        (var-set no-of-participants (+ participants u1))
      )
    )
    (ok (get-user-deposits tx-sender))
  )
)

;; claim memegoat
(define-public (claim-token)
  (begin
    (asserts! (var-get presale-started) ERR-PRESALE-NOT-STARTED)
    (asserts! (< (var-get release-block) block-height) ERR-PRESALE-NOT-ENDED)
    (let
      (
        (stx-pool-balance (var-get stx-pool))
        (sender tx-sender)
        (exists (is-some (map-get? users-deposits {user-addr: sender})))
        (user-allocation (calculate-allocation sender))
        (claimed (check-if-claimed sender))
      )

      (asserts! (>= stx-pool-balance PRESALE-SOFTCAP) ERR-MIN-TARGET-NOT-REACHED)

      (asserts! exists ERR-NOT-PARTICIPANT)
      (asserts! (not claimed) ERR-ALREADY-CLAIMED)
          
      ;; transfer token from vault
      (as-contract (try! (contract-call? .memegoat-vault-v1 transfer-ft .memegoatstx (decimals-to-fixed user-allocation) sender)))      
      
      ;; set user status to claimed 
      (map-set user-claimed { user-addr: sender } true)
    )
    (ok true)
  )
)

Functions (20)

FunctionAccessArgs
set-contract-ownerpublicowner: principal
set-durationpublicno-of-blocks: uint
fund-launchpadpublic
start-presalepublic
get-user-depositsread-onlyuser-addr: principal
calculate-allocationread-onlyuser-addr: principal
check-if-claimedread-onlyuser-addr: principal
get-contract-ownerread-only
get-stx-quoteread-only
get-hardcapread-only
get-softcapread-only
get-memegoatpoolread-only
get-stx-poolread-only
get-no-of-participantsread-only
get-release-blockread-only
get-durationread-only
check-is-ownerprivate
decimals-to-fixedprivateamount: uint
deposit-stxpublicamount: uint
claim-tokenpublic