Source Code

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This is the contract for the Gold/Silver and Lotto phase of the Stacks Invaders Project
;; This is not a NFT or a fungible token, but a minting contract for special traits that will be integrated in the original asset
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data declarations  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Constants and other data
(define-constant DEPLOYER tx-sender )
(define-data-var artist-address principal 'SM1SGQPHTZCK5PAY57ZAVP0FW4PQKKWY0JTAJJ9A0)

;; error codes
(define-constant ERR-NOT-AUTHORIZED u104)
(define-constant ERR-INVALID-USER u105)
(define-constant ERR-PAUSED u109)
(define-constant ERR-BLOCK-NOT-FOUND-FOR-TOKEN u404)
(define-constant ERR-PATTERN-ALREADY-MINTED u115)


;; Internal variables
(define-data-var total-price-lotto uint u3000000)   ;; 3 STX
(define-data-var mint-paused bool true)

(define-data-var lotto-counter  uint u1)
;; map to save the base model per number preferences.
(define-map base-model-special
    {model-id: uint}
    {model-hexa: (string-ascii 8024)}
)
;; maps to save generated token vs block. (access via token or block)

(define-map generated-dmt-lotto
    {lotto-id: uint}
    {token-id: uint, miner: principal, block-id: uint}
)
(define-map generated-dmt-lotto-by-token
    {token-id: uint}
    {lotto-id: uint, miner: principal, block-id: uint }
)
(define-map success-dmt-lotto-by-block
    {block-id: uint }
    {lotto-id: uint, model-id: uint}
)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Core functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;LOTTO
(define-public (upgrade-lotto-trait (token-id uint))
  (let 
    (
      (price (var-get total-price-lotto))
      (lotto-counter-in (var-get lotto-counter))
      (lotto-counter-new (+ lotto-counter-in u1))
      (token-uri (default-to "NOT_FOUND" (unwrap! (contract-call? 'SPV8C2N59MA417HYQNG6372GCV0SEQE01EV4Z1RQ.stacks-invaders-v0 get-token-uri token-id) (err ERR-BLOCK-NOT-FOUND-FOR-TOKEN))))
      ;;(token-uri  "ipfs://ipfs/QmeLBGNTKeUYU6bxxVWh5A2BPxjvweVZddSCVEfR7jWBXr/153184.json")
      (uri_found (asserts! ( is-eq false (is-eq token-uri "NOT_FOUND")) (err ERR-BLOCK-NOT-FOUND-FOR-TOKEN)))
      (block-full    (default-to "000000" (slice? token-uri u59 u65)))  
      (block-full-int (default-to u99 (string-to-uint? block-full)))
    )
    (asserts! (or (is-eq false (var-get mint-paused)) (is-eq tx-sender DEPLOYER) (is-eq tx-sender (var-get artist-address))) (err ERR-PAUSED)) ;; check if mint is on/off
    (asserts! (is-owner token-id tx-sender) (err ERR-NOT-AUTHORIZED))                               ;; check NFT ownership
    (asserts! (is-eq none (get lotto-id (map-get? generated-dmt-lotto-by-token  (tuple (token-id token-id ))))) (err ERR-PATTERN-ALREADY-MINTED)) ;; check if NFT is already in the pool
  ;; Change data from here on:
    (begin 
    (if (or (is-eq tx-sender (var-get artist-address)) (is-eq tx-sender DEPLOYER))
      (begin
        (map-set generated-dmt-lotto-by-token  { token-id: token-id } { lotto-id: lotto-counter-in , miner: tx-sender , block-id: block-full-int }) ;; save the minted token and the block to the array (lotto-map) - 
        (map-set generated-dmt-lotto { lotto-id: lotto-counter-in } { token-id: token-id, miner: tx-sender, block-id: block-full-int}) ;; save the minted token and the block to the array (lotto-map) - 
        (var-set lotto-counter lotto-counter-new) ;; increase the counter in 1 -
      )
      (begin       
        (try! (stx-transfer? price tx-sender (var-get artist-address))) ;; pay the minting fee
        (map-set generated-dmt-lotto-by-token  { token-id: token-id } { lotto-id: lotto-counter-in , miner: tx-sender , block-id: block-full-int }) ;; save the minted token and the block to the array (lotto-map) - 
        (map-set generated-dmt-lotto { lotto-id: lotto-counter-in } { token-id: token-id, miner: tx-sender , block-id: block-full-int }) ;; save the minted token and the block to the array (lotto-map) - 
        (var-set lotto-counter lotto-counter-new) ;; increase the counter in 1 -
      )    
    )    
    (ok token-id)
    )    
)
)
;; set winners
(define-public (set-lotto-winners (winner-ticket uint) (winner-model uint))
  (let 
    (
      (winner-block (default-to u99 (get block-id (map-get? generated-dmt-lotto  (tuple ( lotto-id winner-ticket )))))) 

    )
    (asserts! (or (is-eq tx-sender DEPLOYER) (is-eq tx-sender (var-get artist-address))) (err ERR-NOT-AUTHORIZED)) ;; check if mint is on/off
  ;; Change data from here on:
    (begin 
        (map-set success-dmt-lotto-by-block  { block-id: winner-block } { lotto-id: winner-ticket , model-id: winner-model })       
    (ok winner-block)
    )    
)
)

;;;
(define-read-only (get-80-special-design-by-block (block-id uint)) 
  (let 
    (
      ;; split block numbers
      (winner-ticket (default-to u99 (get model-id (map-get? success-dmt-lotto-by-block  (tuple ( block-id block-id )))))) 
      ;; unpack into colours and patterns
      (base-mod-special (default-to "none" (get model-hexa (map-get? base-model-special  (tuple ( model-id winner-ticket )))))) 
    )

  (ok base-mod-special) 
  )
)

(define-read-only (get-80-special-design (model-id uint)) 
  (let 
    (
      ;; unpack into colours and patterns
      (base-mod-special (default-to "none" (get model-hexa (map-get? base-model-special  (tuple ( model-id model-id )))))) 
    )
  (ok base-mod-special) 
  )
)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Support functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-read-only (is-wallet-cool) 
  (let (
  (artist-address-boolean (is-eq tx-sender (var-get artist-address)))
  (deployer-address-boolean (is-eq tx-sender DEPLOYER))
  (boolean-return (or artist-address-boolean deployer-address-boolean))  
  )
(ok boolean-return)
) 
)
(define-public (model-special-set (model-id-input uint) (model-hexa-input (string-ascii 8024)) )
  (let
  (
      (model-ascii (int-to-ascii model-id-input))
  )
  (begin
    (asserts! (or (is-eq tx-sender (var-get artist-address)) (is-eq tx-sender DEPLOYER)) (err ERR-INVALID-USER))
    (map-set base-model-special { model-id: model-id-input } { model-hexa: model-hexa-input })
    (ok "Post successful")
  )
  )
)

(define-read-only (get-lotto-details-token (token-id uint)) 
  (let (
    (lotto-id  (default-to u0 (get lotto-id (map-get? generated-dmt-lotto-by-token  (tuple (token-id token-id ))))) 
    ;;(original-svg  (unwrap! (contract-call? 'SPV8C2N59MA417HYQNG6372GCV0SEQE01EV4Z1RQ.stacks-invaders-v0 get-token-svg token-id-int) (err ERR-BLOCK-NOT-FOUND-FOR-TOKEN)))
    )
  )
  (ok lotto-id) 
)
)

(define-read-only (get-lotto-details-ticket (lotto-id uint)) 
  (let (
    (token-id  (default-to u0 (get token-id (map-get? generated-dmt-lotto  (tuple (lotto-id lotto-id ))))) 
    ;;(original-svg  (unwrap! (contract-call? 'SPV8C2N59MA417HYQNG6372GCV0SEQE01EV4Z1RQ.stacks-invaders-v0 get-token-svg token-id-int) (err ERR-BLOCK-NOT-FOUND-FOR-TOKEN)))
    )
  )
  (ok token-id) 
)
)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Setting, getting and toggling functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-read-only (get-current-lotto-counter) 
  (let (
      (lotto-counter-in (var-get lotto-counter))
  )
  (ok lotto-counter-in) 
)
)

(define-public (set-artist-address (address principal))
  (begin
    (asserts! (or (is-eq tx-sender (var-get artist-address)) (is-eq tx-sender DEPLOYER)) (err ERR-INVALID-USER))
    (ok (var-set artist-address address))))

(define-public (toggle-pause)
  (begin
    (asserts! (or (is-eq tx-sender (var-get artist-address)) (is-eq tx-sender DEPLOYER)) (err ERR-INVALID-USER))
    (ok (var-set mint-paused (not (var-get mint-paused))))))

(define-private (is-owner (token-id uint) (user principal))

    (is-eq user (default-to DEPLOYER (unwrap! (contract-call? 'SPV8C2N59MA417HYQNG6372GCV0SEQE01EV4Z1RQ.stacks-invaders-v0 get-owner token-id) false))))

(define-read-only (get-paused)
  (ok (var-get mint-paused)))

(define-read-only (get-artist-address)
  (ok (var-get artist-address)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; End of Contract. Thanks for reading!
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Functions (14)

FunctionAccessArgs
upgrade-lotto-traitpublictoken-id: uint
set-lotto-winnerspublicwinner-ticket: uint, winner-model: uint
get-80-special-design-by-blockread-onlyblock-id: uint
get-80-special-designread-onlymodel-id: uint
is-wallet-coolread-only
model-special-setpublicmodel-id-input: uint, model-hexa-input: (string-ascii 8024
get-lotto-details-tokenread-onlytoken-id: uint
get-lotto-details-ticketread-onlylotto-id: uint
get-current-lotto-counterread-only
set-artist-addresspublicaddress: principal
toggle-pausepublic
is-ownerprivatetoken-id: uint, user: principal
get-pausedread-only
get-artist-addressread-only