diff --git a/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/cp-staking.clar b/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/cp-staking.clar new file mode 100644 index 0000000000..f1886897c8 --- /dev/null +++ b/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/cp-staking.clar @@ -0,0 +1,1065 @@ +;; Crash Punk NFT(s) -> $SNOW Staking Contract +;; This contract is in charge of handling all staking within the Crash Punks ecosystem. +;; Written by StrataLabs + + +;; $SNOW FT Unique Properties +;; 1. Minting is only allowed by the staking contract + +(use-trait nft-trait .nft-trait.nft-trait) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; Cons, Vars, & Maps ;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;;;;;;;;;;;;;; +;; Vars/Cons ;; +;;;;;;;;;;;;;;; + +;; @desc - Uint that represents the *max* possible stake reward per block +(define-constant max-payout-per-block u69444) + +;; (temporary) Helper Variable to stake and unstake custodial +(define-data-var function-caller-helper-to-unstake principal tx-sender) + +;; @desc - List of principals that represents all whitelisted, actively-staking collections +(define-data-var whitelist-collections (list 100 principal) + (list + 'SP3QSAJQ4EA8WXEDSRRKMZZ29NH91VZ6C5X88FGZQ.crashpunks-v2 + 'SPAGKDWK07GB9T2X5PZ12N004PDW94MJGRR2JSHS.crash-punks-animated-series + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-punks + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-series-ep-1 + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-boxes + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-vip-pass + 'SP3K22XKPT9WJFCE957J94J6XXVZHP7747YNPDTFD.crash-punks-termination-shock + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crashpunks-punkettes + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.brandx + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.the-smiley-collection + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.xlove + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.cx-tokens + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.narcotix + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.hback-whales-nft + 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.monster-satoshibles + 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.satoshibles + 'SP3RBMGTRD92F0S8DTDJ4FVP3D76SM4A27EV93106.giraffe-mafia + 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus---booze-brains + 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus-creature-feature + 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.the-guests-woymuls + 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.misfit-chimp-society + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.the-guests + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.stacks-parrots-3d + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.byzantion-stacks-parrots + 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.stacculents + 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.steady-lads-msa + 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1 + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft + 'SP2W12MNM4SPV37VZHN4GCDG35G9ACG3FDKK7WF04.MetaBoy + 'SPVVASJ83H223TCEP8Z8SHZDFDBFXSM4EGSWCVR2.sol-townsfolk-nft + 'SP27F9EJH20K3GT6GHZG0RD08REZKY2TDMD6D9M2Z.btc-badgers-v2 + 'SP2X0TZ59D5SZ8ACQ6YMCHHNR2ZN51Z32E2CJ173.the-explorer-guild + 'SP2ESPYE74G94D2HD9X470426W1R6C2P22B4Z1Q5.skullcoin-souls-nft + 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys + ) +) +(define-data-var custodial-whitelist-collections (list 100 principal) + (list + 'SP3QSAJQ4EA8WXEDSRRKMZZ29NH91VZ6C5X88FGZQ.crashpunks-v2 + 'SPAGKDWK07GB9T2X5PZ12N004PDW94MJGRR2JSHS.crash-punks-animated-series + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-punks + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-series-ep-1 + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-boxes + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-vip-pass + 'SP3K22XKPT9WJFCE957J94J6XXVZHP7747YNPDTFD.crash-punks-termination-shock + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crashpunks-punkettes + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.brandx + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.the-smiley-collection + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.xlove + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.cx-tokens + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.narcotix + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.hback-whales-nft + 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.monster-satoshibles + 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.satoshibles + 'SP3RBMGTRD92F0S8DTDJ4FVP3D76SM4A27EV93106.giraffe-mafia + 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus---booze-brains + 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus-creature-feature + 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.the-guests-woymuls + 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.misfit-chimp-society + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.the-guests + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.stacks-parrots-3d + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.byzantion-stacks-parrots + 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.stacculents + 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.steady-lads-msa + 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1 + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft + 'SP2W12MNM4SPV37VZHN4GCDG35G9ACG3FDKK7WF04.MetaBoy + 'SPVVASJ83H223TCEP8Z8SHZDFDBFXSM4EGSWCVR2.sol-townsfolk-nft + 'SP27F9EJH20K3GT6GHZG0RD08REZKY2TDMD6D9M2Z.btc-badgers-v2 + 'SP2X0TZ59D5SZ8ACQ6YMCHHNR2ZN51Z32E2CJ173.the-explorer-guild + 'SP2ESPYE74G94D2HD9X470426W1R6C2P22B4Z1Q5.skullcoin-souls-nft + 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys + ) +) +(define-data-var non-custodial-whitelist-collections (list 100 principal) (list)) + +;; @desc - (temporary) Uint that's used to aggregate when calling "get-unclaimed-balance" +(define-data-var helper-total-unclaimed-balance uint u0) + +;; @desc - (temporary) Principal that's used to temporarily hold a collection principal +(define-data-var helper-collection-principal principal tx-sender) + +;; @desc - (temporary) List of uints that's used to temporarily hold the output of a map resulting in a list of height differences (aka blocks staked) +(define-data-var helper-height-difference-list (list 10000 uint) (list)) + +;; @desc - (temporary) Uint that needs to be removed when unstaking +(define-data-var id-being-removed uint u0) + +;; @desc - (temporary) Uint and Collection that needs to be removed when unstaking +(define-data-var id-and-collection-being-removed {collection: principal, nft: uint} {collection: tx-sender, nft: u0}) + +;; @desc - variable to set staking true or false +(define-data-var active-staking bool true) + +;; @desc - Map that keeps track of whitelisted principal (key) & corresponding multiplier (value) +(define-map collection-multiplier principal uint) +;; CrashPunks Collections +(map-set collection-multiplier 'SP3QSAJQ4EA8WXEDSRRKMZZ29NH91VZ6C5X88FGZQ.crashpunks-v2 u10) +(map-set collection-multiplier 'SPAGKDWK07GB9T2X5PZ12N004PDW94MJGRR2JSHS.crash-punks-animated-series u8) +(map-set collection-multiplier 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-punks u6) +(map-set collection-multiplier 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-series-ep-1 u5) +(map-set collection-multiplier 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-boxes u5) +(map-set collection-multiplier 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-vip-pass u3) +(map-set collection-multiplier 'SP3K22XKPT9WJFCE957J94J6XXVZHP7747YNPDTFD.crash-punks-termination-shock u2) +(map-set collection-multiplier 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crashpunks-punkettes u2) +;; Collaborations +(map-set collection-multiplier 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.brandx u1) +(map-set collection-multiplier 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.the-smiley-collection u1) +(map-set collection-multiplier 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.xlove u1) +(map-set collection-multiplier 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.cx-tokens u1) +(map-set collection-multiplier 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.narcotix u1) +(map-set collection-multiplier 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.hback-whales-nft u1) +(map-set collection-multiplier 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.monster-satoshibles u1) +(map-set collection-multiplier 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.satoshibles u1) +(map-set collection-multiplier 'SP3RBMGTRD92F0S8DTDJ4FVP3D76SM4A27EV93106.giraffe-mafia u1) +(map-set collection-multiplier 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus---booze-brains u1) +(map-set collection-multiplier 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus-creature-feature u1) +(map-set collection-multiplier 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.the-guests-woymuls u1) +(map-set collection-multiplier 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.misfit-chimp-society u1) +(map-set collection-multiplier 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.the-guests u1) +(map-set collection-multiplier 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.stacks-parrots-3d u1) +(map-set collection-multiplier 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.byzantion-stacks-parrots u1) +(map-set collection-multiplier 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.stacculents u1) +(map-set collection-multiplier 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.steady-lads-msa u1) +(map-set collection-multiplier 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1 u1) +(map-set collection-multiplier 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft u1) +(map-set collection-multiplier 'SP2W12MNM4SPV37VZHN4GCDG35G9ACG3FDKK7WF04.MetaBoy u1) +(map-set collection-multiplier 'SPVVASJ83H223TCEP8Z8SHZDFDBFXSM4EGSWCVR2.sol-townsfolk-nft u1) +(map-set collection-multiplier 'SP27F9EJH20K3GT6GHZG0RD08REZKY2TDMD6D9M2Z.btc-badgers-v2 u1) +(map-set collection-multiplier 'SP2X0TZ59D5SZ8ACQ6YMCHHNR2ZN51Z32E2CJ173.the-explorer-guild u1) +(map-set collection-multiplier 'SP2ESPYE74G94D2HD9X470426W1R6C2P22B4Z1Q5.skullcoin-souls-nft u1) +(map-set collection-multiplier 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft u1) +(map-set collection-multiplier 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys u1) + +;; @desc - List of principals that are whitelisted/have admin privileges +(define-data-var whitelist-admins (list 100 principal) (list tx-sender)) + +;; @desc - Map that tracks a staked item details (value) by collection & ID (key) +(define-map staked-item {collection: principal, id: uint} + { + staker: principal, + status: bool, + last-staked-or-claimed: uint + } +) + +;; @desc - Map that tracks all staked IDs (value) by collection principal (key) +(define-map all-stakes-in-collection principal (list 10000 uint)) + +;; @desc - Map that tracks all staked IDs in a collection (value) by user & collection & ID (key) +(define-map user-stakes-by-collection {user: principal, collection: principal} + (list 100 uint) +) + +;; @desc - Map that tracks all staked IDs with its collection (value) by user (key) +(define-map all-user-stakes principal (list 100 { collection: principal, nft: (list 100 uint)})) + + + +;;;;;;;;;;;;;;;; +;; Error Cons ;; +;;;;;;;;;;;;;;;; + +(define-constant ERR-NOT-AUTH (err u101)) +(define-constant ERR-NOT-STAKED (err u102)) +(define-constant ERR-STAKED-OR-NONE (err u103)) +(define-constant ERR-NOT-WHITELISTED (err u104)) +(define-constant ERR-UNWRAP (err u105)) +(define-constant ERR-NOT-OWNER (err u106)) +(define-constant ERR-MIN-STAKE-HEIGHT (err u107)) +(define-constant ERR-ALREADY-WHITELISTED (err u108)) +(define-constant ERR-MULTIPLIER (err u109)) +(define-constant ERR-STAKING-NOT-ACTIVE (err u110)) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Read Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-read-only (get-all-user-stakes (user principal)) + (map-get? all-user-stakes user) +) + +(define-read-only (is-staking-active) + (var-get active-staking) +) + +(define-read-only (active-admins) + (var-get whitelist-admins) +) + +(define-read-only (active-collections) + (var-get whitelist-collections) +) + +(define-read-only (custodial-active-collections) + (var-get custodial-whitelist-collections) +) + +(define-read-only (non-custodial-active-collections) + (var-get non-custodial-whitelist-collections) +) + +;; @desc - Read only to get how many snow per day a collection is generating +(define-read-only (get-generation-rate-of-a-collection (collection principal)) + (map-get? collection-multiplier collection) +) + +;; @desc - Read function that returns the current generation rate for tx-sender across all actively staked collective assets +(define-read-only (get-total-generation-rate-through-all-collections) + (let + ( + (list-of-collections-with-active-user-stakes (filter filter-out-collections-with-no-stakes (var-get whitelist-collections))) + (list-of-generation-per-collection (map map-from-list-staked-to-generation-per-collection list-of-collections-with-active-user-stakes)) + ) + (print list-of-collections-with-active-user-stakes) + (ok (fold + list-of-generation-per-collection u0)) + ) +) + +;; @desc - Filter function used which takes in all (list principal) stakeable/whitelist principals & outputs a (list principal) of actively-staked (by tx-sender) principals +(define-private (filter-out-collections-with-no-stakes (collection principal)) + (let + ( + (collection-staked-by-user-list (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: collection}))) + (collection-staked-by-user-count (len collection-staked-by-user-list)) + ) + (if (> collection-staked-by-user-count u0) + true + false + ) + ) +) + +;; @desc - Map function which takes in a list of actively-staked principals & returns a list of current generation rate per collection +(define-private (map-from-list-staked-to-generation-per-collection (collection principal)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier collection))) + (collection-staked-by-user-list (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: collection}))) + (collection-staked-by-user-count (len collection-staked-by-user-list)) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + ) + (* this-collection-multiplier-normalized collection-staked-by-user-count) + ) +) + +;; @desc - function that gets the unclaimed balance by item and collection +(define-read-only (get-unclaimed-balance-by-collection-and-item (collection ) (item uint)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier (contract-of collection)))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + (item-info (get-item-stake-details (contract-of collection) item)) + (get-time-from-staking-or-claiming (unwrap! (get last-staked-or-claimed item-info) ERR-UNWRAP)) + (time-passed (- block-height get-time-from-staking-or-claiming)) + ) + ;; check collection is existing whitelist collection + (asserts! (> this-collection-multiplier u0) ERR-NOT-WHITELISTED) + ;; check if item is staked + (asserts! (is-eq true (unwrap! (get status item-info) ERR-UNWRAP)) ERR-NOT-STAKED) + (ok (* this-collection-multiplier-normalized time-passed)) + ) +) + +;; @desc - function that gets the unclaimed balance by a list of items and a specific collection +(define-read-only (get-unclaimed-balance-by-collection-and-items (collection ) (items (list 10 (optional uint)))) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier (contract-of collection)))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + (item-info-1 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u0) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-1 (unwrap! (get last-staked-or-claimed item-info-1) ERR-UNWRAP)) + (time-passed-1 (- block-height get-time-from-staking-or-claiming-1)) + (item-info-2 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u1) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-2 (unwrap! (get last-staked-or-claimed item-info-2) ERR-UNWRAP)) + (time-passed-2 (- block-height get-time-from-staking-or-claiming-2)) + (item-info-3 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u2) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-3 (unwrap! (get last-staked-or-claimed item-info-3) ERR-UNWRAP)) + (time-passed-3 (- block-height get-time-from-staking-or-claiming-3)) + (item-info-4 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u3) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-4 (unwrap! (get last-staked-or-claimed item-info-4) ERR-UNWRAP)) + (time-passed-4 (- block-height get-time-from-staking-or-claiming-4)) + (item-info-5 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u4) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-5 (unwrap! (get last-staked-or-claimed item-info-5) ERR-UNWRAP)) + (time-passed-5 (- block-height get-time-from-staking-or-claiming-5)) + (item-info-6 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u5) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-6 (unwrap! (get last-staked-or-claimed item-info-6) ERR-UNWRAP)) + (time-passed-6 (- block-height get-time-from-staking-or-claiming-6)) + (item-info-7 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u6) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-7 (unwrap! (get last-staked-or-claimed item-info-7) ERR-UNWRAP)) + (time-passed-7 (- block-height get-time-from-staking-or-claiming-7)) + (item-info-8 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u7) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-8 (unwrap! (get last-staked-or-claimed item-info-8) ERR-UNWRAP)) + (time-passed-8 (- block-height get-time-from-staking-or-claiming-8)) + (item-info-9 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u8) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-9 (unwrap! (get last-staked-or-claimed item-info-9) ERR-UNWRAP)) + (time-passed-9 (- block-height get-time-from-staking-or-claiming-9)) + (item-info-10 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u9) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-10 (unwrap! (get last-staked-or-claimed item-info-10) ERR-UNWRAP)) + (time-passed-10 (- block-height get-time-from-staking-or-claiming-10)) + ) + ;; check collection is existing whitelist collection + (asserts! (> this-collection-multiplier u0) ERR-NOT-WHITELISTED) + ;; check if item is staked + (asserts! (is-eq true (unwrap! (get status item-info-1) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-2) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-3) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-4) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-5) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-6) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-7) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-8) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-9) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-10) ERR-UNWRAP)) ERR-NOT-STAKED) + ;; Return a list of balance per each nft on the list + (ok + (list + (* this-collection-multiplier-normalized time-passed-1) + (* this-collection-multiplier-normalized time-passed-2) + (* this-collection-multiplier-normalized time-passed-3) + (* this-collection-multiplier-normalized time-passed-4) + (* this-collection-multiplier-normalized time-passed-5) + (* this-collection-multiplier-normalized time-passed-6) + (* this-collection-multiplier-normalized time-passed-7) + (* this-collection-multiplier-normalized time-passed-8) + (* this-collection-multiplier-normalized time-passed-9) + (* this-collection-multiplier-normalized time-passed-10) + ) + ) + ) +) + +;; @desc - Read function that returns a (list uint) of all actively-staked IDs in a collection by user +(define-read-only (get-items-staked-by-collection-and-user (collection principal) (user principal)) + (ok (default-to (list) (map-get? user-stakes-by-collection {user: user, collection: collection}))) +) + + +;; @desc - Read function that returns stake details (staker, status, last-staked-or-claimed) in a specific collection & id +(define-read-only (get-item-stake-details (collection principal) (item-id uint)) + (map-get? staked-item {collection: collection, id: item-id}) +) + +;; @desc - Read function that returns the tx-sender's total unclaimed balance across all whitelisted collections +(define-public (get-unclaimed-balance) + (let + ( + ;; Filter from (list principal) of all whitelist principals/NFTs to (list principal) of all whitelist principals/NFTs where user has > 0 stakes + (this-collection-stakes-by-user (filter filter-out-collections-with-no-stakes (var-get whitelist-collections))) + (list-of-height-differences (list)) + ) + ;; 1. Filter from whitelisted to active staked + ;; 2. Map from a list of principals to a list of uints + ;; clear temporary unclaimed balance uint + (var-set helper-total-unclaimed-balance u0) + ;; map through this-collection-stakes-by-user, don't care about output list, care about appending to list-of-height-differences + (map map-to-append-to-list-of-height-differences this-collection-stakes-by-user) + ;; return unclaimed balance from tx-sender + (ok (var-get helper-total-unclaimed-balance)) + ) +) + +;; @desc - looping through all the collections that a user *does* have active stakes, goal of this function is to append the unclaimed balance from each collection to a new list (helper-height-difference) +(define-private (map-to-append-to-list-of-height-differences (collection principal)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier collection))) + (this-collection-stakes-by-user (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: collection}))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + ) + ;; set helper list to empty + (var-set helper-height-difference-list (list)) + ;; Set collection helper var for folding through height differences + (var-set helper-collection-principal collection) + ;; Use map as a loop to append helper list with get-unclaimed-balance-by-collection + (map append-helper-list-from-id-staked-to-height-difference this-collection-stakes-by-user) + ;; Total unclaimed balance in collection + (var-set helper-total-unclaimed-balance + (+ + (var-get helper-total-unclaimed-balance) + (* this-collection-multiplier-normalized (fold + (var-get helper-height-difference-list) u0)) + ) + ) + tx-sender + ) +) + +;; @desc - function to append the height-difference +(define-private (append-helper-list-from-id-staked-to-height-difference (staked-id uint)) + (let + ( + (staked-or-claimed-height (get last-staked-or-claimed (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (var-get helper-collection-principal), id: staked-id})))) + (height-difference (- block-height staked-or-claimed-height)) + ) + (var-set helper-height-difference-list + (unwrap! (as-max-len? (append (var-get helper-height-difference-list) height-difference) u1000) u0) + ) + u1 + ) +) + +;; @desc - Read function that outputs a tx-sender total unclaimed balance from a specific collection +(define-public (get-unclaimed-balance-by-collection (collection )) + (let + ( + (this-collection-multiplier (unwrap! (map-get? collection-multiplier (contract-of collection)) ERR-UNWRAP)) + (this-collection-stakes-by-user (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)}))) + (list-of-staked-height-differences (map map-from-id-staked-to-height-difference this-collection-stakes-by-user)) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + ) + ;; Assert at least one stake exists + (asserts! (and (> (len this-collection-stakes-by-user) u0) (> (len list-of-staked-height-differences) u0)) ERR-NOT-STAKED) + ;; Var-set helper-collection-principal for use in map-from-id-staked-to-height-difference + (var-set helper-collection-principal (contract-of collection)) + ;; Unclaimed $SNOW balance by user in this collection + ;; Fold to aggregate total blocks staked across all IDs, then multiply collection multiplier + (ok (* this-collection-multiplier-normalized (fold + list-of-staked-height-differences u0))) + ) +) + +;; @desc - Helper function used to map from a list of uint of staked ids to a list of uint of height-differences +(define-private (map-from-id-staked-to-height-difference (staked-id uint)) + (let + ( + (staked-or-claimed-height (get last-staked-or-claimed (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (var-get helper-collection-principal), id: staked-id})))) + ) + (print (- block-height staked-or-claimed-height)) + (- block-height staked-or-claimed-height) + ) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Stake Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-data-var combo-to-remove {collection: principal, nft: (list 100 uint)} {collection: tx-sender, nft: (list)}) + +(define-public (stake (collection ) (id uint)) + (let + ( + (current-all-staked-in-collection-list (default-to (list) (map-get? all-stakes-in-collection (contract-of collection)))) + (is-unstaked-in-all-staked-ids-list (index-of current-all-staked-in-collection-list id)) + (is-unstaked-in-staked-by-user-list (index-of (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)})) id)) + (is-unstaked-in-stake-details-map (get status (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (var-get helper-collection-principal), id: id})))) + (current-nft-owner (unwrap! (contract-call? collection get-owner id) ERR-UNWRAP)) + (custodial-list (var-get custodial-whitelist-collections)) + (transaction-sender tx-sender) + (current-stakes-in-collection (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)}))) + (current-user-stakes (default-to (list) (map-get? all-user-stakes tx-sender))) + (current-stakes-collection-and-nft (var-set combo-to-remove {collection: (contract-of collection), nft: current-stakes-in-collection})) + (reset-map (remove-a-stake (contract-of collection) tx-sender)) + + ) + ;; Assert collection is whitelisted + (asserts! (is-some (index-of (var-get whitelist-collections) (contract-of collection))) ERR-NOT-WHITELISTED) + ;; Asserts item is unstaked across all necessary storage + (asserts! (and (is-none is-unstaked-in-all-staked-ids-list) (is-none is-unstaked-in-staked-by-user-list) (not is-unstaked-in-stake-details-map)) ERR-STAKED-OR-NONE) + ;; Assert caller is current owner of NFT + (asserts! (is-eq (some tx-sender) current-nft-owner) ERR-NOT-OWNER) + ;; Asserts that Staking is active + (asserts! (var-get active-staking) ERR-STAKING-NOT-ACTIVE) + ;; manual staking for custodial + (if + (is-some (index-of custodial-list (contract-of collection))) + (unwrap! (contract-call? collection transfer id tx-sender .cp-staking) (err u401)) + false + ) + ;; Map set all staked ids list + (map-set all-stakes-in-collection (contract-of collection) + (unwrap! (as-max-len? (append (default-to (list) (map-get? all-stakes-in-collection (contract-of collection))) id) u10000) ERR-UNWRAP) + ) + + (map-set all-user-stakes tx-sender (unwrap! (as-max-len? (append (default-to (list) (map-get? all-user-stakes tx-sender)) {collection: (contract-of collection), nft: (unwrap! (as-max-len? (append current-stakes-in-collection id) u100) ERR-UNWRAP)}) u100) ERR-UNWRAP)) + + ;; Map set user staked in collection list + (map-set user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)} + (unwrap! (as-max-len? (append (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)})) id) u100) ERR-UNWRAP) + ) + (ok + ;; Map set staked-item details + (map-set staked-item {collection: (contract-of collection), id: id} + { + staker: tx-sender, + status: true, + last-staked-or-claimed: block-height + } + ) + ) + ) +) + +(define-private (remove-a-stake (collection principal) (user principal)) + (let + ( + (current-stakes-in-collection (default-to (list) (map-get? user-stakes-by-collection {user: user, collection: collection}))) + (current-user-stakes (default-to (list) (map-get? all-user-stakes user))) + (current-stakes-collection-and-nft {collection: collection, nft: current-stakes-in-collection}) + ) + (var-set combo-to-remove current-stakes-collection-and-nft) + (ok + (map-set all-user-stakes tx-sender (filter is-not-removeable-collection-and-id-list current-user-stakes)) + ) + ) +) + +(define-private (remove-a-specific-stake (collection principal) (user principal) (nft uint)) + (let + ( + (current-user-staked-by-collection-list (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: collection}))) + (current-user-stakes (default-to (list) (map-get? all-user-stakes user))) + (set-var (var-set id-being-removed nft)) + (substract-nft-in-stakes (filter is-not-id current-user-staked-by-collection-list)) + (current-stakes-collection-and-nft {collection: collection, nft: current-user-staked-by-collection-list}) + ) + (var-set combo-to-remove current-stakes-collection-and-nft) + (ok + (begin + (map-set all-user-stakes user (filter is-not-removeable-collection-and-id-list current-user-stakes)) + (map-set all-user-stakes user (unwrap! (as-max-len? (append (default-to (list) (map-get? all-user-stakes user)) {collection: collection, nft: substract-nft-in-stakes}) u100) ERR-UNWRAP)) + ) + ) + ) +) + +(define-public (stake-many (collection ) (nfts (list 10 uint))) + (let + ( + (nft-1 (element-at nfts u0)) + (nft-2 (element-at nfts u1)) + (nft-3 (element-at nfts u2)) + (nft-4 (element-at nfts u3)) + (nft-5 (element-at nfts u4)) + (nft-6 (element-at nfts u5)) + (nft-7 (element-at nfts u6)) + (nft-8 (element-at nfts u7)) + (nft-9 (element-at nfts u8)) + (nft-10 (element-at nfts u9)) + (staking-list (list nft-1 nft-2 nft-3 nft-4 nft-5 nft-6 nft-7 nft-8 nft-9 nft-10)) + (stake-1 (if (is-some nft-1) (some (stake collection (unwrap! nft-1 ERR-UNWRAP))) none)) + (stake-2 (if (is-some nft-2) (some (stake collection (unwrap! nft-2 ERR-UNWRAP))) none)) + (stake-3 (if (is-some nft-3) (some (stake collection (unwrap! nft-3 ERR-UNWRAP))) none)) + (stake-4 (if (is-some nft-4) (some (stake collection (unwrap! nft-4 ERR-UNWRAP))) none)) + (stake-5 (if (is-some nft-5) (some (stake collection (unwrap! nft-5 ERR-UNWRAP))) none)) + (stake-6 (if (is-some nft-6) (some (stake collection (unwrap! nft-6 ERR-UNWRAP))) none)) + (stake-7 (if (is-some nft-7) (some (stake collection (unwrap! nft-7 ERR-UNWRAP))) none)) + (stake-8 (if (is-some nft-8) (some (stake collection (unwrap! nft-8 ERR-UNWRAP))) none)) + (stake-9 (if (is-some nft-9) (some (stake collection (unwrap! nft-9 ERR-UNWRAP))) none)) + (stake-10 (if (is-some nft-10) (some (stake collection (unwrap! nft-10 ERR-UNWRAP))) none)) + (final-list (list stake-1 stake-2 stake-3 stake-4 stake-5 stake-6 stake-7 stake-8 stake-9 stake-10)) + ) + (ok final-list) + ) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Claim Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; @desc - Function that a user calls to claim any generated stake rewards for a specific collection & specific id +(define-public (claim-item-stake (collection-collective ) (staked-id uint)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier (contract-of collection-collective)))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + (current-staker (get staker (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection-collective), id: staked-id})))) + (stake-status (get status (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection-collective), id: staked-id})))) + (last-claimed-or-staked-height (get last-staked-or-claimed (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection-collective), id: staked-id})))) + (current-nft-owner (unwrap! (contract-call? collection-collective get-owner staked-id) ERR-NOT-AUTH)) + (blocks-staked (- block-height last-claimed-or-staked-height)) + ) + ;; assert collection-collective is active/whitelisted + (asserts! (is-some (index-of (var-get whitelist-collections) (contract-of collection-collective))) ERR-NOT-WHITELISTED) + ;; asserts is staked + (asserts! stake-status ERR-NOT-STAKED) + ;; asserts tx-sender is owner && asserts tx-sender is staker + (asserts! (is-eq tx-sender current-staker) ERR-NOT-OWNER) + ;; asserts height-difference > 0 + (asserts! (> blocks-staked u0) ERR-MIN-STAKE-HEIGHT) + ;; contract call to mint for X amount + (unwrap! (contract-call? .snow-token mint (* this-collection-multiplier-normalized blocks-staked) tx-sender) ERR-UNWRAP) + ;; update last-staked-or-claimed height + (ok (map-set staked-item {collection: (contract-of collection-collective), id: staked-id} + { + status: true, + last-staked-or-claimed: block-height, + staker: tx-sender + } + )) + ) +) + +;; @desc -Function that a user calls to stake any current or future SGC asset for $SNOW +;; @param - Collection (principal or collection?), ID (uint) -> bool? +(define-public (claim-all-stake) + (let + ( + (list-of-collections-with-active-user-stakes (filter filter-out-collections-with-no-stakes (var-get whitelist-collections))) + (unclaimed-balance-total (unwrap! (get-unclaimed-balance) ERR-UNWRAP)) + ) + ;; contract call to mint for X amount + (unwrap! (contract-call? .snow-token mint unclaimed-balance-total tx-sender) ERR-UNWRAP) + ;; loop through collections, then through IDs, reset last-staked-or-claimed value for each staked ID in each collection by user + (map map-to-loop-through-active-collection list-of-collections-with-active-user-stakes) + + (ok unclaimed-balance-total) + ) +) + +(define-private (map-to-loop-through-active-collection (collection principal)) + (let + ( + (collection-staked-by-user-list (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: collection}))) + ) + (var-set helper-collection-principal collection) + (map map-to-set-reset-last-claimed-or-staked-height collection-staked-by-user-list) + tx-sender + ) +) + +(define-private (map-to-set-reset-last-claimed-or-staked-height (staked-id uint)) + (begin + (map-set staked-item {collection: (var-get helper-collection-principal), id: staked-id} + (merge + (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (var-get helper-collection-principal), id: staked-id})) + {last-staked-or-claimed: block-height} + ) + ) + u0 + ) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Unstake Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-public (unstake-item (collection ) (staked-id uint)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier (contract-of collection)))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + (current-staker (get staker (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (stake-status (get status (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (last-claimed-or-staked-height (get last-staked-or-claimed (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (current-nft-owner (unwrap! (contract-call? collection get-owner staked-id) ERR-NOT-AUTH)) + (blocks-staked (- block-height last-claimed-or-staked-height)) + (current-all-staked-in-collection-list (default-to (list) (map-get? all-stakes-in-collection (contract-of collection)))) + (current-user-staked-by-collection-list (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)}))) + (custodial-list (var-get custodial-whitelist-collections)) + (set-var (var-set id-being-removed staked-id)) + (remove-stake (remove-a-specific-stake (contract-of collection) tx-sender staked-id)) + ) + ;; asserts is staked + (asserts! stake-status ERR-NOT-STAKED) + ;; asserts tx-sender is owner staker + (asserts! (is-eq tx-sender current-staker) ERR-NOT-OWNER) + + + + ;; temporary var set to help remove param + (var-set id-and-collection-being-removed {collection: (contract-of collection), nft: staked-id}) + ;; check if blocks-staked > 0 to see if there's any unclaimed $SNOW to claim + (if (> blocks-staked u0) + ;; if there is, need to claim snow balance + (unwrap! (contract-call? .snow-token mint (* this-collection-multiplier-normalized blocks-staked) tx-sender) ERR-UNWRAP) + ;; if not, proceed + true + ) + ;; set function caller to tx-sender to send from contract + (var-set function-caller-helper-to-unstake tx-sender) + ;;manual unstake of custodial + (if + (is-some (index-of custodial-list (contract-of collection))) + (as-contract (unwrap! (contract-call? collection transfer staked-id .cp-staking (var-get function-caller-helper-to-unstake)) (err u401))) + true + ) + ;; Set helper id for removal in filters below + (var-set id-being-removed staked-id) + ;; filter/remove staked-id from all-stakes-in-collection + (map-set all-stakes-in-collection (contract-of collection) (filter is-not-id current-all-staked-in-collection-list)) + ;; filter/remove staked-id from user-stakes-by-collection + (map-set user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)} (filter is-not-id current-user-staked-by-collection-list)) + + (ok (map-set staked-item {collection: (contract-of collection), id: staked-id} + { + status: false, + last-staked-or-claimed: block-height, + staker: tx-sender + } + )) + ) +) + +(define-private (is-not-id (list-id uint)) + (not (is-eq list-id (var-get id-being-removed))) +) + +;; @desc - Helper function for removing a specific combo of collection and nft from a user +(define-private (is-not-removeable-collection-and-id (combo {collection: principal, nft: uint})) + (not (is-eq combo (var-get id-and-collection-being-removed))) +) + +(define-private (is-not-removeable-collection-and-id-list (combo {collection: principal, nft: (list 100 uint)})) + (not (is-eq combo (var-get combo-to-remove))) +) + +(define-public (unstake-many (collection ) (nfts (list 10 uint))) + (let + ( + (nft-1 (element-at nfts u0)) + (nft-2 (element-at nfts u1)) + (nft-3 (element-at nfts u2)) + (nft-4 (element-at nfts u3)) + (nft-5 (element-at nfts u4)) + (nft-6 (element-at nfts u5)) + (nft-7 (element-at nfts u6)) + (nft-8 (element-at nfts u7)) + (nft-9 (element-at nfts u8)) + (nft-10 (element-at nfts u9)) + (staking-list (list nft-1 nft-2 nft-3 nft-4 nft-5 nft-6 nft-7 nft-8 nft-9 nft-10)) + (stake-1 (if (is-some nft-1) (some (unstake-item collection (unwrap! nft-1 ERR-UNWRAP))) none)) + (stake-2 (if (is-some nft-2) (some (unstake-item collection (unwrap! nft-2 ERR-UNWRAP))) none)) + (stake-3 (if (is-some nft-3) (some (unstake-item collection (unwrap! nft-3 ERR-UNWRAP))) none)) + (stake-4 (if (is-some nft-4) (some (unstake-item collection (unwrap! nft-4 ERR-UNWRAP))) none)) + (stake-5 (if (is-some nft-5) (some (unstake-item collection (unwrap! nft-5 ERR-UNWRAP))) none)) + (stake-6 (if (is-some nft-6) (some (unstake-item collection (unwrap! nft-6 ERR-UNWRAP))) none)) + (stake-7 (if (is-some nft-7) (some (unstake-item collection (unwrap! nft-7 ERR-UNWRAP))) none)) + (stake-8 (if (is-some nft-8) (some (unstake-item collection (unwrap! nft-8 ERR-UNWRAP))) none)) + (stake-9 (if (is-some nft-9) (some (unstake-item collection (unwrap! nft-9 ERR-UNWRAP))) none)) + (stake-10 (if (is-some nft-10) (some (unstake-item collection (unwrap! nft-10 ERR-UNWRAP))) none)) + (final-list (list stake-1 stake-2 stake-3 stake-4 stake-5 stake-6 stake-7 stake-8 stake-9 stake-10)) + ) + (ok final-list) + ) +) +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Admin Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; @desc - Function that only an admin user can call to add a new SGC collection for staking +;; @param - Collection (principal or collection?), Collection-Multiple (uint) +(define-public (admin-add-new-custodial-collection (collection ) (collection-multiple uint)) + (let + ( + (active-whitelist (var-get custodial-whitelist-collections)) + (all-whitelist (var-get whitelist-collections)) + ) + ;; assert the tx-sender is admin + (asserts! (is-some (index-of (var-get whitelist-admins) tx-sender)) ERR-NOT-AUTH) + ;; assert collection not already added + (asserts! (is-none (index-of all-whitelist (contract-of collection))) ERR-ALREADY-WHITELISTED) + ;; assert multiple < 10 + (asserts! (and (< collection-multiple u11) (> collection-multiple u0)) ERR-MULTIPLIER) + ;; update collection-multiplier map + (map-set collection-multiplier (contract-of collection) collection-multiple) + ;; add new principle to whitelist + (ok + (begin + (var-set custodial-whitelist-collections (unwrap! (as-max-len? (append active-whitelist (contract-of collection)) u100) ERR-UNWRAP)) + (var-set whitelist-collections (unwrap! (as-max-len? (append all-whitelist (contract-of collection)) u100) ERR-UNWRAP)) + ) + ) + ) +) + +(define-public (admin-remove-custodial-collection (collection )) + (let + ( + (active-whitelist (var-get custodial-whitelist-collections)) + (all-whitelist (var-get whitelist-collections)) + (removeable-principal-position-in-custodial-whitelist (index-of active-whitelist (contract-of collection))) + (removeable-principal-position-in-all-whitelist (index-of all-whitelist (contract-of collection))) + ) + ;; assert the tx-sender is admin + (asserts! (is-some (index-of (var-get whitelist-admins) tx-sender)) ERR-NOT-AUTH) + ;; assert collection is already added in custodial + (asserts! (is-some (index-of active-whitelist (contract-of collection))) ERR-NOT-WHITELISTED) + ;; assert collection is already added + (asserts! (is-some (index-of all-whitelist (contract-of collection))) ERR-NOT-WHITELISTED) + ;; update collection-multiplier map + (map-set collection-multiplier (contract-of collection) u0) + ;; temporary var set to help remove param principal + (var-set helper-collection-principal (contract-of collection)) + ;; add new principal to whitelist + (ok + (begin + (var-set whitelist-collections (filter is-not-removeable-collection active-whitelist)) + (var-set custodial-whitelist-collections (filter is-not-removeable-collection all-whitelist)) + ) + ) + ) +) + +(define-public (admin-add-new-non-custodial-collection (collection ) (collection-multiple uint)) + (let + ( + (active-whitelist (var-get non-custodial-whitelist-collections)) + (all-whitelist (var-get whitelist-collections)) + ) + ;; assert the tx-sender is admin + (asserts! (is-some (index-of (var-get whitelist-admins) tx-sender)) ERR-NOT-AUTH) + ;; assert collection not already added + (asserts! (is-none (index-of all-whitelist (contract-of collection))) ERR-ALREADY-WHITELISTED) + ;; assert multiple < 10 + (asserts! (and (< collection-multiple u11) (> collection-multiple u0)) ERR-MULTIPLIER) + ;; update collection-multiplier map + (map-set collection-multiplier (contract-of collection) collection-multiple) + ;; add new principal to whitelist + (ok + (begin + (var-set non-custodial-whitelist-collections (unwrap! (as-max-len? (append active-whitelist (contract-of collection)) u100) ERR-UNWRAP)) + (var-set whitelist-collections (unwrap! (as-max-len? (append all-whitelist (contract-of collection)) u100) ERR-UNWRAP)) + ) + ) + ) +) + +(define-public (admin-remove-non-custodial-collection (collection )) + (let + ( + (active-whitelist (var-get non-custodial-whitelist-collections)) + (all-whitelist (var-get whitelist-collections)) + (removeable-principal-position-in-non-custodial-whitelist (index-of active-whitelist (contract-of collection))) + (removeable-principal-position-in-all-whitelist (index-of all-whitelist (contract-of collection))) + ) + ;; assert the tx-sender is admin + (asserts! (is-some (index-of (var-get whitelist-admins) tx-sender)) ERR-NOT-AUTH) + ;; assert collection is already added in non custodial + (asserts! (is-some (index-of active-whitelist (contract-of collection))) ERR-NOT-WHITELISTED) + ;; assert collection is already added + (asserts! (is-some (index-of all-whitelist (contract-of collection))) ERR-NOT-WHITELISTED) + ;; update collection-multiplier map + (map-set collection-multiplier (contract-of collection) u0) + ;; temporary var set to help remove param principal + (var-set helper-collection-principal (contract-of collection)) + ;; add new principal to whitelist + (ok + (begin + (var-set whitelist-collections (filter is-not-removeable-collection active-whitelist)) + (var-set non-custodial-whitelist-collections (filter is-not-removeable-collection all-whitelist)) + ) + ) + ) +) + +;; @desc - Helper function for removing a specific collection from the whitelist +(define-private (is-not-removeable-collection (whitelist-collection principal)) + (not (is-eq whitelist-collection (var-get helper-collection-principal))) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Add Admin Address For Whitelisting ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; @desc - Function for add principals that have explicit permission to add current or future stakeable collections +;; @param - Principal that we're adding as whitelist +(define-public (add-admin-address-for-whitelisting (new-whitelist principal)) + (let + ( + (current-admin-list (var-get whitelist-admins)) + (caller-principal-position-in-list (index-of current-admin-list tx-sender)) + (param-principal-position-in-list (index-of current-admin-list new-whitelist)) + ) + ;; asserts tx-sender is an existing whitelist address + (asserts! (is-some caller-principal-position-in-list) ERR-NOT-AUTH) + ;; asserts param principal (new whitelist) doesn't already exist + (asserts! (is-none param-principal-position-in-list) ERR-ALREADY-WHITELISTED) + ;; append new whitelist address + (ok (var-set whitelist-admins (unwrap! (as-max-len? (append (var-get whitelist-admins) new-whitelist) u100) ERR-UNWRAP))) + ) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Remove Admin Address For Whitelisting ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; @desc - Function for removing principals that have explicit permission to add current or future stakeable collections +;; @param - Principal that we're adding removing as white +(define-public (remove-admin-address-for-whitelisting (remove-whitelist principal)) + (let + ( + (current-admin-list (var-get whitelist-admins)) + (caller-principal-position-in-list (index-of current-admin-list tx-sender)) + (removeable-principal-position-in-list (index-of current-admin-list remove-whitelist)) + ) + ;; assert the tx-sender is admin + (asserts! (is-some (index-of (var-get whitelist-admins) tx-sender)) ERR-NOT-AUTH) + ;; asserts param principal (removeable whitelist) already exist + (asserts! (is-eq removeable-principal-position-in-list) ERR-NOT-WHITELISTED) + ;; temporary var set to help remove param principal + (var-set helper-collection-principal remove-whitelist) + ;; filter existing whitelist address + (ok + (var-set whitelist-admins (filter is-not-removeable current-admin-list)) + ) + ) +) + +;; @desc - Helper function for removing a specific admin from the admin whitelist +(define-private (is-not-removeable (admin-principal principal)) + (not (is-eq admin-principal (var-get helper-collection-principal))) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Admin Manual Unstake ;; +;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; @desc - Function for emergency un-staking all manually custodied assets (Stacculents or Spookies) +;; @param - Principal of collection we're removing, ID of item we're manually unstaking & returning to user + +(define-public (admin-emergency-unstake (collection ) (staked-id uint) (original-owner principal)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier (contract-of collection)))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + (current-staker (get staker (default-to {status: false, last-staked-or-claimed: block-height, staker: original-owner} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (stake-status (get status (default-to {status: false, last-staked-or-claimed: block-height, staker: original-owner} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (last-claimed-or-staked-height (get last-staked-or-claimed (default-to {status: false, last-staked-or-claimed: block-height, staker: original-owner} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (current-nft-owner (unwrap! (contract-call? collection get-owner staked-id) ERR-NOT-AUTH)) + (blocks-staked (- block-height last-claimed-or-staked-height)) + (current-all-staked-in-collection-list (default-to (list) (map-get? all-stakes-in-collection (contract-of collection)))) + (current-user-staked-by-collection-list (default-to (list) (map-get? user-stakes-by-collection {user: original-owner, collection: (contract-of collection)}))) + (custodial-list (var-get custodial-whitelist-collections)) + (set-var (var-set id-being-removed staked-id)) + (remove-stake (remove-a-specific-stake (contract-of collection) original-owner staked-id)) + (admins (var-get whitelist-admins)) + ) + ;; asserts is staked + (asserts! stake-status ERR-NOT-STAKED) + ;; asserts original-owner is staker + (asserts! (is-eq original-owner current-staker) ERR-NOT-OWNER) + ;; asserts that tx-sender is admin + (asserts! (is-some (index-of admins tx-sender)) ERR-NOT-AUTH) + + ;; temporary var set to help remove param + (var-set id-and-collection-being-removed {collection: (contract-of collection), nft: staked-id}) + ;; check if blocks-staked > 0 to see if there's any unclaimed $SNOW to claim + (if (> blocks-staked u0) + ;; if there is, need to claim unstaked + (unwrap! (contract-call? .snow-token mint (* this-collection-multiplier-normalized blocks-staked) original-owner) ERR-UNWRAP) + ;; if not, proceed + true + ) + ;; set function caller to tx-sender to send from contract + (var-set function-caller-helper-to-unstake original-owner) + ;;manual unstake of custodial + (if + (is-some (index-of custodial-list (contract-of collection))) + (as-contract (unwrap! (contract-call? collection transfer staked-id .cp-staking original-owner) (err u401))) + true + ) + ;; Set helper id for removal in filters below + (var-set id-being-removed staked-id) + ;; filter/remove staked-id from all-stakes-in-collection + (map-set all-stakes-in-collection (contract-of collection) (filter is-not-id current-all-staked-in-collection-list)) + ;; filter/remove staked-id from user-stakes-by-collection + (map-set user-stakes-by-collection {user: original-owner, collection: (contract-of collection)} (filter is-not-id current-user-staked-by-collection-list)) + ;; update last-staked-or-claimed height + (ok (map-set staked-item {collection: (contract-of collection), id: staked-id} + { + status: false, + last-staked-or-claimed: block-height, + staker: original-owner + } + )) + ) +) + +(define-public (admin-emergency-unstake-many (collection ) (nfts (list 10 uint)) (original-owner principal)) + (let + ( + (admins (var-get whitelist-admins)) + (nft-1 (element-at nfts u0)) + (nft-2 (element-at nfts u1)) + (nft-3 (element-at nfts u2)) + (nft-4 (element-at nfts u3)) + (nft-5 (element-at nfts u4)) + (nft-6 (element-at nfts u5)) + (nft-7 (element-at nfts u6)) + (nft-8 (element-at nfts u7)) + (nft-9 (element-at nfts u8)) + (nft-10 (element-at nfts u9)) + (staking-list (list nft-1 nft-2 nft-3 nft-4 nft-5 nft-6 nft-7 nft-8 nft-9 nft-10)) + (stake-1 (if (is-some nft-1) (some (admin-emergency-unstake collection (unwrap! nft-1 ERR-UNWRAP) original-owner)) none)) + (stake-2 (if (is-some nft-2) (some (admin-emergency-unstake collection (unwrap! nft-2 ERR-UNWRAP) original-owner)) none)) + (stake-3 (if (is-some nft-3) (some (admin-emergency-unstake collection (unwrap! nft-3 ERR-UNWRAP) original-owner)) none)) + (stake-4 (if (is-some nft-4) (some (admin-emergency-unstake collection (unwrap! nft-4 ERR-UNWRAP) original-owner)) none)) + (stake-5 (if (is-some nft-5) (some (admin-emergency-unstake collection (unwrap! nft-5 ERR-UNWRAP) original-owner)) none)) + (stake-6 (if (is-some nft-6) (some (admin-emergency-unstake collection (unwrap! nft-6 ERR-UNWRAP) original-owner)) none)) + (stake-7 (if (is-some nft-7) (some (admin-emergency-unstake collection (unwrap! nft-7 ERR-UNWRAP) original-owner)) none)) + (stake-8 (if (is-some nft-8) (some (admin-emergency-unstake collection (unwrap! nft-8 ERR-UNWRAP) original-owner)) none)) + (stake-9 (if (is-some nft-9) (some (admin-emergency-unstake collection (unwrap! nft-9 ERR-UNWRAP) original-owner)) none)) + (stake-10 (if (is-some nft-10) (some (admin-emergency-unstake collection (unwrap! nft-10 ERR-UNWRAP) original-owner)) none)) + (final-list (list stake-1 stake-2 stake-3 stake-4 stake-5 stake-6 stake-7 stake-8 stake-9 stake-10)) + ) + (asserts! (is-some (index-of admins tx-sender)) ERR-NOT-AUTH) + (ok final-list) + ) +) + +;; Function to change a collection multiplier (amount of SNOW generated per day) +(define-public (change-collection-multiplier (collection principal) (new-multiplier uint)) + (let + ( + (admins (var-get whitelist-admins)) + ) + (asserts! (is-some (index-of admins tx-sender)) ERR-NOT-AUTH) + (ok (map-set collection-multiplier collection new-multiplier)) + ) +) + +(define-public (switch-staking) + (let + ( + (admins (var-get whitelist-admins)) + ) + (asserts! (is-some (index-of admins tx-sender)) ERR-NOT-AUTH) + + (ok (if (var-get active-staking) + (var-set active-staking false) + (var-set active-staking true) + )) + ) +) diff --git a/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/ft-trait.clar b/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/ft-trait.clar new file mode 100644 index 0000000000..ae299b1be8 --- /dev/null +++ b/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/ft-trait.clar @@ -0,0 +1,24 @@ +(define-trait sip-010-trait + ( + ;; Transfer from the caller to a new principal + (transfer (uint principal principal (optional (buff 34))) (response bool uint)) + + ;; the human readable name of the token + (get-name () (response (string-ascii 32) uint)) + + ;; the ticker symbol, or empty if none + (get-symbol () (response (string-ascii 32) uint)) + + ;; the number of decimals used, e.g. 6 would mean 1_000_000 represents 1 token + (get-decimals () (response uint uint)) + + ;; the balance of the passed principal + (get-balance (principal) (response uint uint)) + + ;; the current total supply (which does not need to be a constant) + (get-total-supply () (response uint uint)) + + ;; an optional URI that represents metadata of this token + (get-token-uri () (response (optional (string-utf8 256)) uint)) + ) +) \ No newline at end of file diff --git a/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/nft-trait.clar b/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/nft-trait.clar new file mode 100644 index 0000000000..cc558fdb5a --- /dev/null +++ b/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/nft-trait.clar @@ -0,0 +1,15 @@ +(define-trait nft-trait + ( + ;; Last token ID, limited to uint range + (get-last-token-id () (response uint uint)) + + ;; URI for metadata associated with the token + (get-token-uri (uint) (response (optional (string-ascii 256)) uint)) + + ;; Owner of a given token identifier + (get-owner (uint) (response (optional principal) uint)) + + ;; Transfer from the sender to a new principal + (transfer (uint principal principal) (response bool uint)) + ) +) diff --git a/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/snow-token.clar b/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/snow-token.clar new file mode 100644 index 0000000000..d0be54d5e8 --- /dev/null +++ b/contracts/SP14VDDN583TB43F06NFV36YRAS0QWQC75QBDFBFR/snow-token.clar @@ -0,0 +1,172 @@ +;; $SNOW FT Contract +;; This contract represents the $SNOW FT - the fungible token for the CrashPunks metaverse. +;; Written by StrataLabs + +;; $SNOW FT Unique Properties +;; 1. Minting is only allowed by the staking contract + +(impl-trait .ft-trait.sip-010-trait) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; Cons, Vars, & Maps ;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-constant contract-owner tx-sender) +(define-constant TOKEN_NAME "SNOW") +(define-constant TOKEN_SYMBOL "SNW") +(define-constant TOKEN_DECIMALS u6) +(define-constant TOKEN_MAX_SUPPLY u100000000000000) + +;;;;;;;;;;;;;;;;;;; +;; FT Vars/Cons ;; +;;;;;;;;;;;;;;;;;;; + +(define-fungible-token SNOW TOKEN_MAX_SUPPLY) +(define-data-var activate-transfer bool false) +(define-data-var TOKEN_URI (optional (string-utf8 256)) (some u"https://gateway.pinata.cloud/ipfs/QmerTxsPTgfdR2iz5xV6oqy7jprPoga5NNiEJRtgQ2pF2H")) +(define-data-var mint-active bool true) + +;;;;;;;;;;;;;;;; +;; Error Cons ;; +;;;;;;;;;;;;;;;; + +(define-constant ERR_SENDER_NOT_VALID (err u1000)) +(define-constant ERR_SENDER_AND_RECIPENT_IS_EQUAL (err u1001)) +(define-constant ERR_INSUFFICIENT_AMOUNT (err u1002)) +(define-constant ERR_GETING_BALANCE_OF_SENDER (err u1003)) +(define-constant ERR_SENDER_BALANCE_NOT_VALID (err u1004)) +(define-constant ERR_NOT_ALLOWED (err u1005)) +(define-constant ERR_RECIPIENT_NOT_VALID (err u1006)) +(define-constant ERR_TRANSFER_NOT_ACTIVATED (err u1007)) +(define-constant ERR_NOT_AUTH (err u1008)) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; SIP10 Functions ;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Regular transfer function for SIP-010 but we need to activita the transfer function before being able to actually transfer +(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34)))) + (begin + + ;; assert sender is tx-sender + (asserts! (is-eq tx-sender sender) ERR_SENDER_NOT_VALID) + + ;; assert sender is not recipient + (asserts! (not (is-eq sender recipient)) ERR_SENDER_AND_RECIPENT_IS_EQUAL) + + ;; assert amount transferred > 0 + (asserts! (> amount u0) ERR_INSUFFICIENT_AMOUNT) + + ;; assert amount transferred =< balance of sender + (asserts! (<= amount (unwrap! (get-balance sender) ERR_GETING_BALANCE_OF_SENDER)) ERR_SENDER_BALANCE_NOT_VALID) + + ;; assert the transfer function is activated + (asserts! (var-get activate-transfer) ERR_TRANSFER_NOT_ACTIVATED) + + ;; transfer + (try! (ft-transfer? SNOW amount sender recipient)) + (match memo to-print (print to-print) 0x) + (ok true) + ) +) + +(define-public (change-transfer-state) + (ok (var-set activate-transfer true)) +) + +(define-public (update-token-uri (new-uri (optional (string-utf8 256)))) + (begin + (asserts! (is-eq tx-sender contract-owner) ERR_NOT_ALLOWED) + (ok (var-set TOKEN_URI new-uri)) + ) +) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Read Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-read-only (get-name) + (ok TOKEN_NAME) +) + +(define-read-only (get-symbol) + (ok TOKEN_SYMBOL) +) + +(define-read-only (get-decimals) + (ok TOKEN_DECIMALS) +) + +(define-read-only (get-balance (account principal)) + (ok (ft-get-balance SNOW account)) +) + +(define-read-only (get-total-supply) + (ok (ft-get-supply SNOW)) +) + +(define-read-only (get-token-uri) + (ok (var-get TOKEN_URI)) +) + +(define-read-only (get-max-supply) + (ok TOKEN_MAX_SUPPLY) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Mint Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Regular SIP-010 mint function, except this is only callable by the CrashPunks staking contract or admin +(define-public (mint (amount uint) (recipient principal)) + (let + ( + (current-total-supply (ft-get-supply SNOW)) + ) + + ;; If mint is active, check that the tx-sender is contract-owner or staking contract, if it is not active only check that the sender is staking contract + (if (var-get mint-active) + (asserts! (or (is-eq tx-sender contract-owner) (is-eq contract-caller .cp-staking)) ERR_NOT_AUTH) + (asserts! (is-eq contract-caller .cp-staking) ERR_NOT_AUTH) + ) + + ;; asserts that recipient is not staking contract + (asserts! (not (is-eq recipient .cp-staking)) ERR_RECIPIENT_NOT_VALID) + + ;; asserts that amount is greater than 0 + (asserts! (> amount u0) ERR_INSUFFICIENT_AMOUNT) + + ;; asserts that amount is less than + (asserts! (<= amount (- TOKEN_MAX_SUPPLY current-total-supply)) ERR_NOT_ALLOWED) + (ft-mint? SNOW amount recipient) + ) +) + +(define-public (burn (amount uint) (sender principal)) + (begin + (asserts! (is-eq tx-sender sender) ERR_SENDER_NOT_VALID) + (asserts! (> amount u0) ERR_INSUFFICIENT_AMOUNT) + (asserts! (<= amount (ft-get-balance SNOW sender)) ERR_SENDER_BALANCE_NOT_VALID) + (ft-burn? SNOW amount sender) + ) +) + +;; Change the mint-active so that only the staking contract can mint SNOW tokens +(define-public (turn-off-mint-by-owner) + (ok + (begin + (asserts! (is-eq tx-sender contract-owner) ERR_NOT_AUTH) + (var-set mint-active false) + ) + ) +) \ No newline at end of file diff --git a/contracts/SP19PNSTFW26TEQR4X252SDS5NNSJK4GMY50NTVG1/bns-1696359057084-v1.clar b/contracts/SP19PNSTFW26TEQR4X252SDS5NNSJK4GMY50NTVG1/bns-1696359057084-v1.clar new file mode 100644 index 0000000000..d066a2a3fd --- /dev/null +++ b/contracts/SP19PNSTFW26TEQR4X252SDS5NNSJK4GMY50NTVG1/bns-1696359057084-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: ayyy + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x61797979 u193236715 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP1B3MPBNJ7X1ZNKEETJEMM5SFRGG9XKG6QVZXKQ5/bns-1696355572459-v1.clar b/contracts/SP1B3MPBNJ7X1ZNKEETJEMM5SFRGG9XKG6QVZXKQ5/bns-1696355572459-v1.clar new file mode 100644 index 0000000000..19ab29d819 --- /dev/null +++ b/contracts/SP1B3MPBNJ7X1ZNKEETJEMM5SFRGG9XKG6QVZXKQ5/bns-1696355572459-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: benkingsley + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x62656e6b696e67736c6579 u24154589372 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP1FEYRZXT30THW3M58RG3V628A1T6R02SDD1PP5/bns-1696360321068-v1.clar b/contracts/SP1FEYRZXT30THW3M58RG3V628A1T6R02SDD1PP5/bns-1696360321068-v1.clar new file mode 100644 index 0000000000..8f5ae05a69 --- /dev/null +++ b/contracts/SP1FEYRZXT30THW3M58RG3V628A1T6R02SDD1PP5/bns-1696360321068-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: allyson + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x616c6c79736f6e u193236715 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP1XHZTY3P6XZJARQTEQA5MVDZXZTT2TRP80GKP32/bns-1696343627666-v1.clar b/contracts/SP1XHZTY3P6XZJARQTEQA5MVDZXZTT2TRP80GKP32/bns-1696343627666-v1.clar new file mode 100644 index 0000000000..324c273757 --- /dev/null +++ b/contracts/SP1XHZTY3P6XZJARQTEQA5MVDZXZTT2TRP80GKP32/bns-1696343627666-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: digitalvault + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x6469676974616c7661756c74 u96618356521740 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP29JSK6V6P47J7JNC5BVYZJ8DBHGMWCAPT349PHK/celestial-wonders.clar b/contracts/SP29JSK6V6P47J7JNC5BVYZJ8DBHGMWCAPT349PHK/celestial-wonders.clar new file mode 100644 index 0000000000..752b8edee7 --- /dev/null +++ b/contracts/SP29JSK6V6P47J7JNC5BVYZJ8DBHGMWCAPT349PHK/celestial-wonders.clar @@ -0,0 +1,208 @@ +;; celestial-wonders +;; contractType: continuous + +(impl-trait 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait) +;;(impl-trait .nft-trait.nft-trait) + +(define-non-fungible-token celestial-wonders uint) + +(define-constant DEPLOYER tx-sender) + +(define-constant ERR-NOT-AUTHORIZED u101) +(define-constant ERR-INVALID-USER u102) +(define-constant ERR-LISTING u103) +(define-constant ERR-WRONG-COMMISSION u104) +(define-constant ERR-NOT-FOUND u105) +(define-constant ERR-NFT-MINT u106) +(define-constant ERR-CONTRACT-LOCKED u107) +(define-constant ERR-METADATA-FROZEN u111) +(define-constant ERR-INVALID-PERCENTAGE u114) + +(define-data-var last-id uint u0) +(define-data-var artist-address principal 'SP29JSK6V6P47J7JNC5BVYZJ8DBHGMWCAPT349PHK) +(define-data-var locked bool false) +(define-data-var metadata-frozen bool false) + +(define-map cids uint (string-ascii 64)) + +(define-public (lock-contract) + (begin + (asserts! (or (is-eq tx-sender (var-get artist-address)) (is-eq tx-sender DEPLOYER)) (err ERR-NOT-AUTHORIZED)) + (var-set locked true) + (ok true))) + +(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 (burn (token-id uint)) + (begin + (asserts! (is-owner token-id tx-sender) (err ERR-NOT-AUTHORIZED)) + (asserts! (is-none (map-get? market token-id)) (err ERR-LISTING)) + (nft-burn? celestial-wonders token-id tx-sender))) + +(define-public (set-token-uri (hash (string-ascii 64)) (token-id uint)) + (begin + (asserts! (or (is-eq tx-sender (var-get artist-address)) (is-eq tx-sender DEPLOYER)) (err ERR-NOT-AUTHORIZED)) + (asserts! (not (var-get metadata-frozen)) (err ERR-METADATA-FROZEN)) + (print { notification: "token-metadata-update", payload: { token-class: "nft", token-ids: (list token-id), contract-id: (as-contract tx-sender) }}) + (map-set cids token-id hash) + (ok true))) + +(define-public (freeze-metadata) + (begin + (asserts! (or (is-eq tx-sender (var-get artist-address)) (is-eq tx-sender DEPLOYER)) (err ERR-NOT-AUTHORIZED)) + (var-set metadata-frozen true) + (ok true))) + +(define-private (is-owner (token-id uint) (user principal)) + (is-eq user (unwrap! (nft-get-owner? celestial-wonders token-id) false))) + +(define-public (transfer (id uint) (sender principal) (recipient principal)) + (begin + (asserts! (is-eq tx-sender sender) (err ERR-NOT-AUTHORIZED)) + (asserts! (is-none (map-get? market id)) (err ERR-LISTING)) + (trnsfr id sender recipient))) + +(define-read-only (get-owner (token-id uint)) + (ok (nft-get-owner? celestial-wonders token-id))) + +(define-read-only (get-last-token-id) + (ok (var-get last-id))) + +(define-read-only (get-token-uri (token-id uint)) + (ok (some (concat "ipfs://" (unwrap-panic (map-get? cids token-id)))))) + +(define-read-only (get-artist-address) + (ok (var-get artist-address))) + +(define-public (claim (uris (list 25 (string-ascii 64)))) + (mint-many uris)) + +(define-private (mint-many (uris (list 25 (string-ascii 64)))) + (let + ( + (token-id (+ (var-get last-id) u1)) + (art-addr (var-get artist-address)) + (id-reached (fold mint-many-iter uris token-id)) + (current-balance (get-balance tx-sender)) + ) + (asserts! (or (is-eq tx-sender DEPLOYER) (is-eq tx-sender art-addr)) (err ERR-NOT-AUTHORIZED)) + (asserts! (is-eq (var-get locked) false) (err ERR-CONTRACT-LOCKED)) + (var-set last-id (- id-reached u1)) + (map-set token-count tx-sender (+ current-balance (- id-reached token-id))) + (ok id-reached))) + +(define-private (mint-many-iter (hash (string-ascii 64)) (next-id uint)) + (begin + (unwrap! (nft-mint? celestial-wonders next-id tx-sender) next-id) + (map-set cids next-id hash) + (+ next-id u1))) + +;; NON-CUSTODIAL FUNCTIONS START +(use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + +(define-map token-count principal uint) +(define-map market uint {price: uint, commission: principal, royalty: uint}) + +(define-read-only (get-balance (account principal)) + (default-to u0 + (map-get? token-count account))) + +(define-private (trnsfr (id uint) (sender principal) (recipient principal)) + (match (nft-transfer? celestial-wonders id sender recipient) + success + (let + ((sender-balance (get-balance sender)) + (recipient-balance (get-balance recipient))) + (map-set token-count + sender + (- sender-balance u1)) + (map-set token-count + recipient + (+ recipient-balance u1)) + (ok success)) + error (err error))) + +(define-private (is-sender-owner (id uint)) + (let ((owner (unwrap! (nft-get-owner? celestial-wonders id) false))) + (or (is-eq tx-sender owner) (is-eq contract-caller owner)))) + +(define-read-only (get-listing-in-ustx (id uint)) + (map-get? market id)) + +(define-public (list-in-ustx (id uint) (price uint) (comm-trait )) + (let ((listing {price: price, commission: (contract-of comm-trait), royalty: (var-get royalty-percent)})) + (asserts! (is-sender-owner id) (err ERR-NOT-AUTHORIZED)) + (map-set market id listing) + (print (merge listing {a: "list-in-ustx", id: id})) + (ok true))) + +(define-public (unlist-in-ustx (id uint)) + (begin + (asserts! (is-sender-owner id) (err ERR-NOT-AUTHORIZED)) + (map-delete market id) + (print {a: "unlist-in-ustx", id: id}) + (ok true))) + +(define-public (buy-in-ustx (id uint) (comm-trait )) + (let ((owner (unwrap! (nft-get-owner? celestial-wonders id) (err ERR-NOT-FOUND))) + (listing (unwrap! (map-get? market id) (err ERR-LISTING))) + (price (get price listing)) + (royalty (get royalty listing))) + (asserts! (is-eq (contract-of comm-trait) (get commission listing)) (err ERR-WRONG-COMMISSION)) + (try! (stx-transfer? price tx-sender owner)) + (try! (pay-royalty price royalty)) + (try! (contract-call? comm-trait pay id price)) + (try! (trnsfr id owner tx-sender)) + (map-delete market id) + (print {a: "buy-in-ustx", id: id}) + (ok true))) + +(define-data-var royalty-percent uint u500) + +(define-read-only (get-royalty-percent) + (ok (var-get royalty-percent))) + +(define-public (set-royalty-percent (royalty uint)) + (begin + (asserts! (or (is-eq tx-sender (var-get artist-address)) (is-eq tx-sender DEPLOYER)) (err ERR-INVALID-USER)) + (asserts! (and (>= royalty u0) (<= royalty u1000)) (err ERR-INVALID-PERCENTAGE)) + (ok (var-set royalty-percent royalty)))) + +(define-private (pay-royalty (price uint) (royalty uint)) + (let ( + (royalty-amount (/ (* price royalty) u10000)) + ) + (if (and (> royalty-amount u0) (not (is-eq tx-sender (var-get artist-address)))) + (try! (stx-transfer? royalty-amount tx-sender (var-get artist-address))) + (print false) + ) + (ok true))) + +;; NON-CUSTODIAL FUNCTIONS END + +(try! (nft-mint? celestial-wonders u1 'SP29JSK6V6P47J7JNC5BVYZJ8DBHGMWCAPT349PHK)) +(map-set token-count 'SP29JSK6V6P47J7JNC5BVYZJ8DBHGMWCAPT349PHK (+ (get-balance 'SP29JSK6V6P47J7JNC5BVYZJ8DBHGMWCAPT349PHK) u1)) +(map-set cids u1 "Qma41mJeXRtARQAMz1vgDb1EjTGpNMdwcwo9iWyVhEVNKY/json/1.json") +(var-set last-id u1) + +(define-data-var license-uri (string-ascii 80) "https://arweave.net/zmc1WTspIhFyVY82bwfAIcIExLFH5lUcHHUN0wXg4W8/3") +(define-data-var license-name (string-ascii 40) "COMMERCIAL-NO-HATE") + +(define-read-only (get-license-uri) + (ok (var-get license-uri))) + +(define-read-only (get-license-name) + (ok (var-get license-name))) + +(define-public (set-license-uri (uri (string-ascii 80))) + (begin + (asserts! (or (is-eq tx-sender (var-get artist-address)) (is-eq tx-sender DEPLOYER)) (err ERR-NOT-AUTHORIZED)) + (ok (var-set license-uri uri)))) + +(define-public (set-license-name (name (string-ascii 40))) + (begin + (asserts! (or (is-eq tx-sender (var-get artist-address)) (is-eq tx-sender DEPLOYER)) (err ERR-NOT-AUTHORIZED)) + (ok (var-set license-name name)))) \ No newline at end of file diff --git a/contracts/SP2E839DB0HPSRA9DFQJWK1M897YDJP8KB47VP053/bns-1696360242604-v1.clar b/contracts/SP2E839DB0HPSRA9DFQJWK1M897YDJP8KB47VP053/bns-1696360242604-v1.clar new file mode 100644 index 0000000000..7a73716ad3 --- /dev/null +++ b/contracts/SP2E839DB0HPSRA9DFQJWK1M897YDJP8KB47VP053/bns-1696360242604-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: dks + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x646b73 u1932367150 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP2ESJP12VN9ZNR5TGZCWS08ZAR3DW2JSYSVA0Q48/bns-1696355711127-v1.clar b/contracts/SP2ESJP12VN9ZNR5TGZCWS08ZAR3DW2JSYSVA0Q48/bns-1696355711127-v1.clar new file mode 100644 index 0000000000..9bfbae295d --- /dev/null +++ b/contracts/SP2ESJP12VN9ZNR5TGZCWS08ZAR3DW2JSYSVA0Q48/bns-1696355711127-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: evanrachelwood + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x6576616e72616368656c776f6f64 u24154589372 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP2FF1HZCRC4B8YAAAW0RVWMYM20JWJG3RF5MKHV4/bns-1696355786431-v1.clar b/contracts/SP2FF1HZCRC4B8YAAAW0RVWMYM20JWJG3RF5MKHV4/bns-1696355786431-v1.clar new file mode 100644 index 0000000000..f1639b7615 --- /dev/null +++ b/contracts/SP2FF1HZCRC4B8YAAAW0RVWMYM20JWJG3RF5MKHV4/bns-1696355786431-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: elijahwood + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x656c696a6168776f6f64 u24154589372 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP2Q9NY1RZCKKK0H90BRZKT7MCTQFBTHVWNKDMVBB/bns-1696355246712-v1.clar b/contracts/SP2Q9NY1RZCKKK0H90BRZKT7MCTQFBTHVWNKDMVBB/bns-1696355246712-v1.clar new file mode 100644 index 0000000000..dbf3e47d51 --- /dev/null +++ b/contracts/SP2Q9NY1RZCKKK0H90BRZKT7MCTQFBTHVWNKDMVBB/bns-1696355246712-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: tokyostockexchange + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x746f6b796f73746f636b65786368616e6765 u24154589372 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP2Q9WM22JKRWG1KNBJVG1KADXAF1QWT0B5NFEXS5/bns-1696358279705-v1.clar b/contracts/SP2Q9WM22JKRWG1KNBJVG1KADXAF1QWT0B5NFEXS5/bns-1696358279705-v1.clar new file mode 100644 index 0000000000..cccb53358e --- /dev/null +++ b/contracts/SP2Q9WM22JKRWG1KNBJVG1KADXAF1QWT0B5NFEXS5/bns-1696358279705-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: meliza + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x6d656c697a61 u19323672 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP2YRF99Q0NYQ486EM3MARBPRW20ZP7HXEVXQQM5A/bns-1696358706730-v1.clar b/contracts/SP2YRF99Q0NYQ486EM3MARBPRW20ZP7HXEVXQQM5A/bns-1696358706730-v1.clar new file mode 100644 index 0000000000..b29bd9c71f --- /dev/null +++ b/contracts/SP2YRF99Q0NYQ486EM3MARBPRW20ZP7HXEVXQQM5A/bns-1696358706730-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: treez + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x747265657a u1932367150 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP305KMFDPXPCDF068N5GA70Z2VAGMESZS76D0F0A/bns-1696359015111-v1.clar b/contracts/SP305KMFDPXPCDF068N5GA70Z2VAGMESZS76D0F0A/bns-1696359015111-v1.clar new file mode 100644 index 0000000000..f4cb17fdae --- /dev/null +++ b/contracts/SP305KMFDPXPCDF068N5GA70Z2VAGMESZS76D0F0A/bns-1696359015111-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: manbun + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x6d616e62756e u19323672 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/cp-staking.clar b/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/cp-staking.clar new file mode 100644 index 0000000000..f1886897c8 --- /dev/null +++ b/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/cp-staking.clar @@ -0,0 +1,1065 @@ +;; Crash Punk NFT(s) -> $SNOW Staking Contract +;; This contract is in charge of handling all staking within the Crash Punks ecosystem. +;; Written by StrataLabs + + +;; $SNOW FT Unique Properties +;; 1. Minting is only allowed by the staking contract + +(use-trait nft-trait .nft-trait.nft-trait) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; Cons, Vars, & Maps ;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;;;;;;;;;;;;;; +;; Vars/Cons ;; +;;;;;;;;;;;;;;; + +;; @desc - Uint that represents the *max* possible stake reward per block +(define-constant max-payout-per-block u69444) + +;; (temporary) Helper Variable to stake and unstake custodial +(define-data-var function-caller-helper-to-unstake principal tx-sender) + +;; @desc - List of principals that represents all whitelisted, actively-staking collections +(define-data-var whitelist-collections (list 100 principal) + (list + 'SP3QSAJQ4EA8WXEDSRRKMZZ29NH91VZ6C5X88FGZQ.crashpunks-v2 + 'SPAGKDWK07GB9T2X5PZ12N004PDW94MJGRR2JSHS.crash-punks-animated-series + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-punks + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-series-ep-1 + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-boxes + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-vip-pass + 'SP3K22XKPT9WJFCE957J94J6XXVZHP7747YNPDTFD.crash-punks-termination-shock + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crashpunks-punkettes + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.brandx + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.the-smiley-collection + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.xlove + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.cx-tokens + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.narcotix + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.hback-whales-nft + 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.monster-satoshibles + 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.satoshibles + 'SP3RBMGTRD92F0S8DTDJ4FVP3D76SM4A27EV93106.giraffe-mafia + 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus---booze-brains + 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus-creature-feature + 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.the-guests-woymuls + 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.misfit-chimp-society + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.the-guests + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.stacks-parrots-3d + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.byzantion-stacks-parrots + 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.stacculents + 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.steady-lads-msa + 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1 + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft + 'SP2W12MNM4SPV37VZHN4GCDG35G9ACG3FDKK7WF04.MetaBoy + 'SPVVASJ83H223TCEP8Z8SHZDFDBFXSM4EGSWCVR2.sol-townsfolk-nft + 'SP27F9EJH20K3GT6GHZG0RD08REZKY2TDMD6D9M2Z.btc-badgers-v2 + 'SP2X0TZ59D5SZ8ACQ6YMCHHNR2ZN51Z32E2CJ173.the-explorer-guild + 'SP2ESPYE74G94D2HD9X470426W1R6C2P22B4Z1Q5.skullcoin-souls-nft + 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys + ) +) +(define-data-var custodial-whitelist-collections (list 100 principal) + (list + 'SP3QSAJQ4EA8WXEDSRRKMZZ29NH91VZ6C5X88FGZQ.crashpunks-v2 + 'SPAGKDWK07GB9T2X5PZ12N004PDW94MJGRR2JSHS.crash-punks-animated-series + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-punks + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-series-ep-1 + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-boxes + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-vip-pass + 'SP3K22XKPT9WJFCE957J94J6XXVZHP7747YNPDTFD.crash-punks-termination-shock + 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crashpunks-punkettes + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.brandx + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.the-smiley-collection + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.xlove + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.cx-tokens + 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.narcotix + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.hback-whales-nft + 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.monster-satoshibles + 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.satoshibles + 'SP3RBMGTRD92F0S8DTDJ4FVP3D76SM4A27EV93106.giraffe-mafia + 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus---booze-brains + 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus-creature-feature + 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.the-guests-woymuls + 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.misfit-chimp-society + 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.the-guests + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.stacks-parrots-3d + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.byzantion-stacks-parrots + 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.stacculents + 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.steady-lads-msa + 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1 + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft + 'SP2W12MNM4SPV37VZHN4GCDG35G9ACG3FDKK7WF04.MetaBoy + 'SPVVASJ83H223TCEP8Z8SHZDFDBFXSM4EGSWCVR2.sol-townsfolk-nft + 'SP27F9EJH20K3GT6GHZG0RD08REZKY2TDMD6D9M2Z.btc-badgers-v2 + 'SP2X0TZ59D5SZ8ACQ6YMCHHNR2ZN51Z32E2CJ173.the-explorer-guild + 'SP2ESPYE74G94D2HD9X470426W1R6C2P22B4Z1Q5.skullcoin-souls-nft + 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft + 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys + ) +) +(define-data-var non-custodial-whitelist-collections (list 100 principal) (list)) + +;; @desc - (temporary) Uint that's used to aggregate when calling "get-unclaimed-balance" +(define-data-var helper-total-unclaimed-balance uint u0) + +;; @desc - (temporary) Principal that's used to temporarily hold a collection principal +(define-data-var helper-collection-principal principal tx-sender) + +;; @desc - (temporary) List of uints that's used to temporarily hold the output of a map resulting in a list of height differences (aka blocks staked) +(define-data-var helper-height-difference-list (list 10000 uint) (list)) + +;; @desc - (temporary) Uint that needs to be removed when unstaking +(define-data-var id-being-removed uint u0) + +;; @desc - (temporary) Uint and Collection that needs to be removed when unstaking +(define-data-var id-and-collection-being-removed {collection: principal, nft: uint} {collection: tx-sender, nft: u0}) + +;; @desc - variable to set staking true or false +(define-data-var active-staking bool true) + +;; @desc - Map that keeps track of whitelisted principal (key) & corresponding multiplier (value) +(define-map collection-multiplier principal uint) +;; CrashPunks Collections +(map-set collection-multiplier 'SP3QSAJQ4EA8WXEDSRRKMZZ29NH91VZ6C5X88FGZQ.crashpunks-v2 u10) +(map-set collection-multiplier 'SPAGKDWK07GB9T2X5PZ12N004PDW94MJGRR2JSHS.crash-punks-animated-series u8) +(map-set collection-multiplier 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-punks u6) +(map-set collection-multiplier 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crash-punks-animated-series-ep-1 u5) +(map-set collection-multiplier 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-boxes u5) +(map-set collection-multiplier 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.crash-punks-vip-pass u3) +(map-set collection-multiplier 'SP3K22XKPT9WJFCE957J94J6XXVZHP7747YNPDTFD.crash-punks-termination-shock u2) +(map-set collection-multiplier 'SPQE8N8BHMT462W2XPK028GDM4RMQBSHAAY8D37G.crashpunks-punkettes u2) +;; Collaborations +(map-set collection-multiplier 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.brandx u1) +(map-set collection-multiplier 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.the-smiley-collection u1) +(map-set collection-multiplier 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.xlove u1) +(map-set collection-multiplier 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.cx-tokens u1) +(map-set collection-multiplier 'SP8HMQP4Q63V3E6SXXPXZ4WJXA263HBD95QY2AM3.narcotix u1) +(map-set collection-multiplier 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.hback-whales-nft u1) +(map-set collection-multiplier 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.monster-satoshibles u1) +(map-set collection-multiplier 'SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.satoshibles u1) +(map-set collection-multiplier 'SP3RBMGTRD92F0S8DTDJ4FVP3D76SM4A27EV93106.giraffe-mafia u1) +(map-set collection-multiplier 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus---booze-brains u1) +(map-set collection-multiplier 'SP3M05ETW09E98NNFMFHT1WND3ZRX9DV31TFC6DFW.hooch-haus-creature-feature u1) +(map-set collection-multiplier 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.the-guests-woymuls u1) +(map-set collection-multiplier 'SP3252T1HMQHZTA9S22WZ2HZMKC4CVH965SHSERTH.misfit-chimp-society u1) +(map-set collection-multiplier 'SP1CSHTKVHMMQJ7PRQRFYW6SB4QAW6SR3XY2F81PA.the-guests u1) +(map-set collection-multiplier 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.stacks-parrots-3d u1) +(map-set collection-multiplier 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.byzantion-stacks-parrots u1) +(map-set collection-multiplier 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.stacculents u1) +(map-set collection-multiplier 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.steady-lads-msa u1) +(map-set collection-multiplier 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1 u1) +(map-set collection-multiplier 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft u1) +(map-set collection-multiplier 'SP2W12MNM4SPV37VZHN4GCDG35G9ACG3FDKK7WF04.MetaBoy u1) +(map-set collection-multiplier 'SPVVASJ83H223TCEP8Z8SHZDFDBFXSM4EGSWCVR2.sol-townsfolk-nft u1) +(map-set collection-multiplier 'SP27F9EJH20K3GT6GHZG0RD08REZKY2TDMD6D9M2Z.btc-badgers-v2 u1) +(map-set collection-multiplier 'SP2X0TZ59D5SZ8ACQ6YMCHHNR2ZN51Z32E2CJ173.the-explorer-guild u1) +(map-set collection-multiplier 'SP2ESPYE74G94D2HD9X470426W1R6C2P22B4Z1Q5.skullcoin-souls-nft u1) +(map-set collection-multiplier 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft u1) +(map-set collection-multiplier 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys u1) + +;; @desc - List of principals that are whitelisted/have admin privileges +(define-data-var whitelist-admins (list 100 principal) (list tx-sender)) + +;; @desc - Map that tracks a staked item details (value) by collection & ID (key) +(define-map staked-item {collection: principal, id: uint} + { + staker: principal, + status: bool, + last-staked-or-claimed: uint + } +) + +;; @desc - Map that tracks all staked IDs (value) by collection principal (key) +(define-map all-stakes-in-collection principal (list 10000 uint)) + +;; @desc - Map that tracks all staked IDs in a collection (value) by user & collection & ID (key) +(define-map user-stakes-by-collection {user: principal, collection: principal} + (list 100 uint) +) + +;; @desc - Map that tracks all staked IDs with its collection (value) by user (key) +(define-map all-user-stakes principal (list 100 { collection: principal, nft: (list 100 uint)})) + + + +;;;;;;;;;;;;;;;; +;; Error Cons ;; +;;;;;;;;;;;;;;;; + +(define-constant ERR-NOT-AUTH (err u101)) +(define-constant ERR-NOT-STAKED (err u102)) +(define-constant ERR-STAKED-OR-NONE (err u103)) +(define-constant ERR-NOT-WHITELISTED (err u104)) +(define-constant ERR-UNWRAP (err u105)) +(define-constant ERR-NOT-OWNER (err u106)) +(define-constant ERR-MIN-STAKE-HEIGHT (err u107)) +(define-constant ERR-ALREADY-WHITELISTED (err u108)) +(define-constant ERR-MULTIPLIER (err u109)) +(define-constant ERR-STAKING-NOT-ACTIVE (err u110)) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Read Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-read-only (get-all-user-stakes (user principal)) + (map-get? all-user-stakes user) +) + +(define-read-only (is-staking-active) + (var-get active-staking) +) + +(define-read-only (active-admins) + (var-get whitelist-admins) +) + +(define-read-only (active-collections) + (var-get whitelist-collections) +) + +(define-read-only (custodial-active-collections) + (var-get custodial-whitelist-collections) +) + +(define-read-only (non-custodial-active-collections) + (var-get non-custodial-whitelist-collections) +) + +;; @desc - Read only to get how many snow per day a collection is generating +(define-read-only (get-generation-rate-of-a-collection (collection principal)) + (map-get? collection-multiplier collection) +) + +;; @desc - Read function that returns the current generation rate for tx-sender across all actively staked collective assets +(define-read-only (get-total-generation-rate-through-all-collections) + (let + ( + (list-of-collections-with-active-user-stakes (filter filter-out-collections-with-no-stakes (var-get whitelist-collections))) + (list-of-generation-per-collection (map map-from-list-staked-to-generation-per-collection list-of-collections-with-active-user-stakes)) + ) + (print list-of-collections-with-active-user-stakes) + (ok (fold + list-of-generation-per-collection u0)) + ) +) + +;; @desc - Filter function used which takes in all (list principal) stakeable/whitelist principals & outputs a (list principal) of actively-staked (by tx-sender) principals +(define-private (filter-out-collections-with-no-stakes (collection principal)) + (let + ( + (collection-staked-by-user-list (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: collection}))) + (collection-staked-by-user-count (len collection-staked-by-user-list)) + ) + (if (> collection-staked-by-user-count u0) + true + false + ) + ) +) + +;; @desc - Map function which takes in a list of actively-staked principals & returns a list of current generation rate per collection +(define-private (map-from-list-staked-to-generation-per-collection (collection principal)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier collection))) + (collection-staked-by-user-list (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: collection}))) + (collection-staked-by-user-count (len collection-staked-by-user-list)) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + ) + (* this-collection-multiplier-normalized collection-staked-by-user-count) + ) +) + +;; @desc - function that gets the unclaimed balance by item and collection +(define-read-only (get-unclaimed-balance-by-collection-and-item (collection ) (item uint)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier (contract-of collection)))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + (item-info (get-item-stake-details (contract-of collection) item)) + (get-time-from-staking-or-claiming (unwrap! (get last-staked-or-claimed item-info) ERR-UNWRAP)) + (time-passed (- block-height get-time-from-staking-or-claiming)) + ) + ;; check collection is existing whitelist collection + (asserts! (> this-collection-multiplier u0) ERR-NOT-WHITELISTED) + ;; check if item is staked + (asserts! (is-eq true (unwrap! (get status item-info) ERR-UNWRAP)) ERR-NOT-STAKED) + (ok (* this-collection-multiplier-normalized time-passed)) + ) +) + +;; @desc - function that gets the unclaimed balance by a list of items and a specific collection +(define-read-only (get-unclaimed-balance-by-collection-and-items (collection ) (items (list 10 (optional uint)))) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier (contract-of collection)))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + (item-info-1 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u0) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-1 (unwrap! (get last-staked-or-claimed item-info-1) ERR-UNWRAP)) + (time-passed-1 (- block-height get-time-from-staking-or-claiming-1)) + (item-info-2 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u1) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-2 (unwrap! (get last-staked-or-claimed item-info-2) ERR-UNWRAP)) + (time-passed-2 (- block-height get-time-from-staking-or-claiming-2)) + (item-info-3 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u2) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-3 (unwrap! (get last-staked-or-claimed item-info-3) ERR-UNWRAP)) + (time-passed-3 (- block-height get-time-from-staking-or-claiming-3)) + (item-info-4 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u3) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-4 (unwrap! (get last-staked-or-claimed item-info-4) ERR-UNWRAP)) + (time-passed-4 (- block-height get-time-from-staking-or-claiming-4)) + (item-info-5 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u4) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-5 (unwrap! (get last-staked-or-claimed item-info-5) ERR-UNWRAP)) + (time-passed-5 (- block-height get-time-from-staking-or-claiming-5)) + (item-info-6 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u5) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-6 (unwrap! (get last-staked-or-claimed item-info-6) ERR-UNWRAP)) + (time-passed-6 (- block-height get-time-from-staking-or-claiming-6)) + (item-info-7 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u6) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-7 (unwrap! (get last-staked-or-claimed item-info-7) ERR-UNWRAP)) + (time-passed-7 (- block-height get-time-from-staking-or-claiming-7)) + (item-info-8 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u7) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-8 (unwrap! (get last-staked-or-claimed item-info-8) ERR-UNWRAP)) + (time-passed-8 (- block-height get-time-from-staking-or-claiming-8)) + (item-info-9 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u8) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-9 (unwrap! (get last-staked-or-claimed item-info-9) ERR-UNWRAP)) + (time-passed-9 (- block-height get-time-from-staking-or-claiming-9)) + (item-info-10 (get-item-stake-details (contract-of collection) (unwrap! (unwrap! (element-at items u9) ERR-UNWRAP) ERR-UNWRAP))) + (get-time-from-staking-or-claiming-10 (unwrap! (get last-staked-or-claimed item-info-10) ERR-UNWRAP)) + (time-passed-10 (- block-height get-time-from-staking-or-claiming-10)) + ) + ;; check collection is existing whitelist collection + (asserts! (> this-collection-multiplier u0) ERR-NOT-WHITELISTED) + ;; check if item is staked + (asserts! (is-eq true (unwrap! (get status item-info-1) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-2) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-3) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-4) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-5) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-6) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-7) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-8) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-9) ERR-UNWRAP)) ERR-NOT-STAKED) + (asserts! (is-eq true (unwrap! (get status item-info-10) ERR-UNWRAP)) ERR-NOT-STAKED) + ;; Return a list of balance per each nft on the list + (ok + (list + (* this-collection-multiplier-normalized time-passed-1) + (* this-collection-multiplier-normalized time-passed-2) + (* this-collection-multiplier-normalized time-passed-3) + (* this-collection-multiplier-normalized time-passed-4) + (* this-collection-multiplier-normalized time-passed-5) + (* this-collection-multiplier-normalized time-passed-6) + (* this-collection-multiplier-normalized time-passed-7) + (* this-collection-multiplier-normalized time-passed-8) + (* this-collection-multiplier-normalized time-passed-9) + (* this-collection-multiplier-normalized time-passed-10) + ) + ) + ) +) + +;; @desc - Read function that returns a (list uint) of all actively-staked IDs in a collection by user +(define-read-only (get-items-staked-by-collection-and-user (collection principal) (user principal)) + (ok (default-to (list) (map-get? user-stakes-by-collection {user: user, collection: collection}))) +) + + +;; @desc - Read function that returns stake details (staker, status, last-staked-or-claimed) in a specific collection & id +(define-read-only (get-item-stake-details (collection principal) (item-id uint)) + (map-get? staked-item {collection: collection, id: item-id}) +) + +;; @desc - Read function that returns the tx-sender's total unclaimed balance across all whitelisted collections +(define-public (get-unclaimed-balance) + (let + ( + ;; Filter from (list principal) of all whitelist principals/NFTs to (list principal) of all whitelist principals/NFTs where user has > 0 stakes + (this-collection-stakes-by-user (filter filter-out-collections-with-no-stakes (var-get whitelist-collections))) + (list-of-height-differences (list)) + ) + ;; 1. Filter from whitelisted to active staked + ;; 2. Map from a list of principals to a list of uints + ;; clear temporary unclaimed balance uint + (var-set helper-total-unclaimed-balance u0) + ;; map through this-collection-stakes-by-user, don't care about output list, care about appending to list-of-height-differences + (map map-to-append-to-list-of-height-differences this-collection-stakes-by-user) + ;; return unclaimed balance from tx-sender + (ok (var-get helper-total-unclaimed-balance)) + ) +) + +;; @desc - looping through all the collections that a user *does* have active stakes, goal of this function is to append the unclaimed balance from each collection to a new list (helper-height-difference) +(define-private (map-to-append-to-list-of-height-differences (collection principal)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier collection))) + (this-collection-stakes-by-user (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: collection}))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + ) + ;; set helper list to empty + (var-set helper-height-difference-list (list)) + ;; Set collection helper var for folding through height differences + (var-set helper-collection-principal collection) + ;; Use map as a loop to append helper list with get-unclaimed-balance-by-collection + (map append-helper-list-from-id-staked-to-height-difference this-collection-stakes-by-user) + ;; Total unclaimed balance in collection + (var-set helper-total-unclaimed-balance + (+ + (var-get helper-total-unclaimed-balance) + (* this-collection-multiplier-normalized (fold + (var-get helper-height-difference-list) u0)) + ) + ) + tx-sender + ) +) + +;; @desc - function to append the height-difference +(define-private (append-helper-list-from-id-staked-to-height-difference (staked-id uint)) + (let + ( + (staked-or-claimed-height (get last-staked-or-claimed (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (var-get helper-collection-principal), id: staked-id})))) + (height-difference (- block-height staked-or-claimed-height)) + ) + (var-set helper-height-difference-list + (unwrap! (as-max-len? (append (var-get helper-height-difference-list) height-difference) u1000) u0) + ) + u1 + ) +) + +;; @desc - Read function that outputs a tx-sender total unclaimed balance from a specific collection +(define-public (get-unclaimed-balance-by-collection (collection )) + (let + ( + (this-collection-multiplier (unwrap! (map-get? collection-multiplier (contract-of collection)) ERR-UNWRAP)) + (this-collection-stakes-by-user (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)}))) + (list-of-staked-height-differences (map map-from-id-staked-to-height-difference this-collection-stakes-by-user)) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + ) + ;; Assert at least one stake exists + (asserts! (and (> (len this-collection-stakes-by-user) u0) (> (len list-of-staked-height-differences) u0)) ERR-NOT-STAKED) + ;; Var-set helper-collection-principal for use in map-from-id-staked-to-height-difference + (var-set helper-collection-principal (contract-of collection)) + ;; Unclaimed $SNOW balance by user in this collection + ;; Fold to aggregate total blocks staked across all IDs, then multiply collection multiplier + (ok (* this-collection-multiplier-normalized (fold + list-of-staked-height-differences u0))) + ) +) + +;; @desc - Helper function used to map from a list of uint of staked ids to a list of uint of height-differences +(define-private (map-from-id-staked-to-height-difference (staked-id uint)) + (let + ( + (staked-or-claimed-height (get last-staked-or-claimed (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (var-get helper-collection-principal), id: staked-id})))) + ) + (print (- block-height staked-or-claimed-height)) + (- block-height staked-or-claimed-height) + ) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Stake Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-data-var combo-to-remove {collection: principal, nft: (list 100 uint)} {collection: tx-sender, nft: (list)}) + +(define-public (stake (collection ) (id uint)) + (let + ( + (current-all-staked-in-collection-list (default-to (list) (map-get? all-stakes-in-collection (contract-of collection)))) + (is-unstaked-in-all-staked-ids-list (index-of current-all-staked-in-collection-list id)) + (is-unstaked-in-staked-by-user-list (index-of (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)})) id)) + (is-unstaked-in-stake-details-map (get status (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (var-get helper-collection-principal), id: id})))) + (current-nft-owner (unwrap! (contract-call? collection get-owner id) ERR-UNWRAP)) + (custodial-list (var-get custodial-whitelist-collections)) + (transaction-sender tx-sender) + (current-stakes-in-collection (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)}))) + (current-user-stakes (default-to (list) (map-get? all-user-stakes tx-sender))) + (current-stakes-collection-and-nft (var-set combo-to-remove {collection: (contract-of collection), nft: current-stakes-in-collection})) + (reset-map (remove-a-stake (contract-of collection) tx-sender)) + + ) + ;; Assert collection is whitelisted + (asserts! (is-some (index-of (var-get whitelist-collections) (contract-of collection))) ERR-NOT-WHITELISTED) + ;; Asserts item is unstaked across all necessary storage + (asserts! (and (is-none is-unstaked-in-all-staked-ids-list) (is-none is-unstaked-in-staked-by-user-list) (not is-unstaked-in-stake-details-map)) ERR-STAKED-OR-NONE) + ;; Assert caller is current owner of NFT + (asserts! (is-eq (some tx-sender) current-nft-owner) ERR-NOT-OWNER) + ;; Asserts that Staking is active + (asserts! (var-get active-staking) ERR-STAKING-NOT-ACTIVE) + ;; manual staking for custodial + (if + (is-some (index-of custodial-list (contract-of collection))) + (unwrap! (contract-call? collection transfer id tx-sender .cp-staking) (err u401)) + false + ) + ;; Map set all staked ids list + (map-set all-stakes-in-collection (contract-of collection) + (unwrap! (as-max-len? (append (default-to (list) (map-get? all-stakes-in-collection (contract-of collection))) id) u10000) ERR-UNWRAP) + ) + + (map-set all-user-stakes tx-sender (unwrap! (as-max-len? (append (default-to (list) (map-get? all-user-stakes tx-sender)) {collection: (contract-of collection), nft: (unwrap! (as-max-len? (append current-stakes-in-collection id) u100) ERR-UNWRAP)}) u100) ERR-UNWRAP)) + + ;; Map set user staked in collection list + (map-set user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)} + (unwrap! (as-max-len? (append (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)})) id) u100) ERR-UNWRAP) + ) + (ok + ;; Map set staked-item details + (map-set staked-item {collection: (contract-of collection), id: id} + { + staker: tx-sender, + status: true, + last-staked-or-claimed: block-height + } + ) + ) + ) +) + +(define-private (remove-a-stake (collection principal) (user principal)) + (let + ( + (current-stakes-in-collection (default-to (list) (map-get? user-stakes-by-collection {user: user, collection: collection}))) + (current-user-stakes (default-to (list) (map-get? all-user-stakes user))) + (current-stakes-collection-and-nft {collection: collection, nft: current-stakes-in-collection}) + ) + (var-set combo-to-remove current-stakes-collection-and-nft) + (ok + (map-set all-user-stakes tx-sender (filter is-not-removeable-collection-and-id-list current-user-stakes)) + ) + ) +) + +(define-private (remove-a-specific-stake (collection principal) (user principal) (nft uint)) + (let + ( + (current-user-staked-by-collection-list (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: collection}))) + (current-user-stakes (default-to (list) (map-get? all-user-stakes user))) + (set-var (var-set id-being-removed nft)) + (substract-nft-in-stakes (filter is-not-id current-user-staked-by-collection-list)) + (current-stakes-collection-and-nft {collection: collection, nft: current-user-staked-by-collection-list}) + ) + (var-set combo-to-remove current-stakes-collection-and-nft) + (ok + (begin + (map-set all-user-stakes user (filter is-not-removeable-collection-and-id-list current-user-stakes)) + (map-set all-user-stakes user (unwrap! (as-max-len? (append (default-to (list) (map-get? all-user-stakes user)) {collection: collection, nft: substract-nft-in-stakes}) u100) ERR-UNWRAP)) + ) + ) + ) +) + +(define-public (stake-many (collection ) (nfts (list 10 uint))) + (let + ( + (nft-1 (element-at nfts u0)) + (nft-2 (element-at nfts u1)) + (nft-3 (element-at nfts u2)) + (nft-4 (element-at nfts u3)) + (nft-5 (element-at nfts u4)) + (nft-6 (element-at nfts u5)) + (nft-7 (element-at nfts u6)) + (nft-8 (element-at nfts u7)) + (nft-9 (element-at nfts u8)) + (nft-10 (element-at nfts u9)) + (staking-list (list nft-1 nft-2 nft-3 nft-4 nft-5 nft-6 nft-7 nft-8 nft-9 nft-10)) + (stake-1 (if (is-some nft-1) (some (stake collection (unwrap! nft-1 ERR-UNWRAP))) none)) + (stake-2 (if (is-some nft-2) (some (stake collection (unwrap! nft-2 ERR-UNWRAP))) none)) + (stake-3 (if (is-some nft-3) (some (stake collection (unwrap! nft-3 ERR-UNWRAP))) none)) + (stake-4 (if (is-some nft-4) (some (stake collection (unwrap! nft-4 ERR-UNWRAP))) none)) + (stake-5 (if (is-some nft-5) (some (stake collection (unwrap! nft-5 ERR-UNWRAP))) none)) + (stake-6 (if (is-some nft-6) (some (stake collection (unwrap! nft-6 ERR-UNWRAP))) none)) + (stake-7 (if (is-some nft-7) (some (stake collection (unwrap! nft-7 ERR-UNWRAP))) none)) + (stake-8 (if (is-some nft-8) (some (stake collection (unwrap! nft-8 ERR-UNWRAP))) none)) + (stake-9 (if (is-some nft-9) (some (stake collection (unwrap! nft-9 ERR-UNWRAP))) none)) + (stake-10 (if (is-some nft-10) (some (stake collection (unwrap! nft-10 ERR-UNWRAP))) none)) + (final-list (list stake-1 stake-2 stake-3 stake-4 stake-5 stake-6 stake-7 stake-8 stake-9 stake-10)) + ) + (ok final-list) + ) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Claim Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; @desc - Function that a user calls to claim any generated stake rewards for a specific collection & specific id +(define-public (claim-item-stake (collection-collective ) (staked-id uint)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier (contract-of collection-collective)))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + (current-staker (get staker (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection-collective), id: staked-id})))) + (stake-status (get status (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection-collective), id: staked-id})))) + (last-claimed-or-staked-height (get last-staked-or-claimed (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection-collective), id: staked-id})))) + (current-nft-owner (unwrap! (contract-call? collection-collective get-owner staked-id) ERR-NOT-AUTH)) + (blocks-staked (- block-height last-claimed-or-staked-height)) + ) + ;; assert collection-collective is active/whitelisted + (asserts! (is-some (index-of (var-get whitelist-collections) (contract-of collection-collective))) ERR-NOT-WHITELISTED) + ;; asserts is staked + (asserts! stake-status ERR-NOT-STAKED) + ;; asserts tx-sender is owner && asserts tx-sender is staker + (asserts! (is-eq tx-sender current-staker) ERR-NOT-OWNER) + ;; asserts height-difference > 0 + (asserts! (> blocks-staked u0) ERR-MIN-STAKE-HEIGHT) + ;; contract call to mint for X amount + (unwrap! (contract-call? .snow-token mint (* this-collection-multiplier-normalized blocks-staked) tx-sender) ERR-UNWRAP) + ;; update last-staked-or-claimed height + (ok (map-set staked-item {collection: (contract-of collection-collective), id: staked-id} + { + status: true, + last-staked-or-claimed: block-height, + staker: tx-sender + } + )) + ) +) + +;; @desc -Function that a user calls to stake any current or future SGC asset for $SNOW +;; @param - Collection (principal or collection?), ID (uint) -> bool? +(define-public (claim-all-stake) + (let + ( + (list-of-collections-with-active-user-stakes (filter filter-out-collections-with-no-stakes (var-get whitelist-collections))) + (unclaimed-balance-total (unwrap! (get-unclaimed-balance) ERR-UNWRAP)) + ) + ;; contract call to mint for X amount + (unwrap! (contract-call? .snow-token mint unclaimed-balance-total tx-sender) ERR-UNWRAP) + ;; loop through collections, then through IDs, reset last-staked-or-claimed value for each staked ID in each collection by user + (map map-to-loop-through-active-collection list-of-collections-with-active-user-stakes) + + (ok unclaimed-balance-total) + ) +) + +(define-private (map-to-loop-through-active-collection (collection principal)) + (let + ( + (collection-staked-by-user-list (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: collection}))) + ) + (var-set helper-collection-principal collection) + (map map-to-set-reset-last-claimed-or-staked-height collection-staked-by-user-list) + tx-sender + ) +) + +(define-private (map-to-set-reset-last-claimed-or-staked-height (staked-id uint)) + (begin + (map-set staked-item {collection: (var-get helper-collection-principal), id: staked-id} + (merge + (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (var-get helper-collection-principal), id: staked-id})) + {last-staked-or-claimed: block-height} + ) + ) + u0 + ) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Unstake Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-public (unstake-item (collection ) (staked-id uint)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier (contract-of collection)))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + (current-staker (get staker (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (stake-status (get status (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (last-claimed-or-staked-height (get last-staked-or-claimed (default-to {status: false, last-staked-or-claimed: block-height, staker: tx-sender} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (current-nft-owner (unwrap! (contract-call? collection get-owner staked-id) ERR-NOT-AUTH)) + (blocks-staked (- block-height last-claimed-or-staked-height)) + (current-all-staked-in-collection-list (default-to (list) (map-get? all-stakes-in-collection (contract-of collection)))) + (current-user-staked-by-collection-list (default-to (list) (map-get? user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)}))) + (custodial-list (var-get custodial-whitelist-collections)) + (set-var (var-set id-being-removed staked-id)) + (remove-stake (remove-a-specific-stake (contract-of collection) tx-sender staked-id)) + ) + ;; asserts is staked + (asserts! stake-status ERR-NOT-STAKED) + ;; asserts tx-sender is owner staker + (asserts! (is-eq tx-sender current-staker) ERR-NOT-OWNER) + + + + ;; temporary var set to help remove param + (var-set id-and-collection-being-removed {collection: (contract-of collection), nft: staked-id}) + ;; check if blocks-staked > 0 to see if there's any unclaimed $SNOW to claim + (if (> blocks-staked u0) + ;; if there is, need to claim snow balance + (unwrap! (contract-call? .snow-token mint (* this-collection-multiplier-normalized blocks-staked) tx-sender) ERR-UNWRAP) + ;; if not, proceed + true + ) + ;; set function caller to tx-sender to send from contract + (var-set function-caller-helper-to-unstake tx-sender) + ;;manual unstake of custodial + (if + (is-some (index-of custodial-list (contract-of collection))) + (as-contract (unwrap! (contract-call? collection transfer staked-id .cp-staking (var-get function-caller-helper-to-unstake)) (err u401))) + true + ) + ;; Set helper id for removal in filters below + (var-set id-being-removed staked-id) + ;; filter/remove staked-id from all-stakes-in-collection + (map-set all-stakes-in-collection (contract-of collection) (filter is-not-id current-all-staked-in-collection-list)) + ;; filter/remove staked-id from user-stakes-by-collection + (map-set user-stakes-by-collection {user: tx-sender, collection: (contract-of collection)} (filter is-not-id current-user-staked-by-collection-list)) + + (ok (map-set staked-item {collection: (contract-of collection), id: staked-id} + { + status: false, + last-staked-or-claimed: block-height, + staker: tx-sender + } + )) + ) +) + +(define-private (is-not-id (list-id uint)) + (not (is-eq list-id (var-get id-being-removed))) +) + +;; @desc - Helper function for removing a specific combo of collection and nft from a user +(define-private (is-not-removeable-collection-and-id (combo {collection: principal, nft: uint})) + (not (is-eq combo (var-get id-and-collection-being-removed))) +) + +(define-private (is-not-removeable-collection-and-id-list (combo {collection: principal, nft: (list 100 uint)})) + (not (is-eq combo (var-get combo-to-remove))) +) + +(define-public (unstake-many (collection ) (nfts (list 10 uint))) + (let + ( + (nft-1 (element-at nfts u0)) + (nft-2 (element-at nfts u1)) + (nft-3 (element-at nfts u2)) + (nft-4 (element-at nfts u3)) + (nft-5 (element-at nfts u4)) + (nft-6 (element-at nfts u5)) + (nft-7 (element-at nfts u6)) + (nft-8 (element-at nfts u7)) + (nft-9 (element-at nfts u8)) + (nft-10 (element-at nfts u9)) + (staking-list (list nft-1 nft-2 nft-3 nft-4 nft-5 nft-6 nft-7 nft-8 nft-9 nft-10)) + (stake-1 (if (is-some nft-1) (some (unstake-item collection (unwrap! nft-1 ERR-UNWRAP))) none)) + (stake-2 (if (is-some nft-2) (some (unstake-item collection (unwrap! nft-2 ERR-UNWRAP))) none)) + (stake-3 (if (is-some nft-3) (some (unstake-item collection (unwrap! nft-3 ERR-UNWRAP))) none)) + (stake-4 (if (is-some nft-4) (some (unstake-item collection (unwrap! nft-4 ERR-UNWRAP))) none)) + (stake-5 (if (is-some nft-5) (some (unstake-item collection (unwrap! nft-5 ERR-UNWRAP))) none)) + (stake-6 (if (is-some nft-6) (some (unstake-item collection (unwrap! nft-6 ERR-UNWRAP))) none)) + (stake-7 (if (is-some nft-7) (some (unstake-item collection (unwrap! nft-7 ERR-UNWRAP))) none)) + (stake-8 (if (is-some nft-8) (some (unstake-item collection (unwrap! nft-8 ERR-UNWRAP))) none)) + (stake-9 (if (is-some nft-9) (some (unstake-item collection (unwrap! nft-9 ERR-UNWRAP))) none)) + (stake-10 (if (is-some nft-10) (some (unstake-item collection (unwrap! nft-10 ERR-UNWRAP))) none)) + (final-list (list stake-1 stake-2 stake-3 stake-4 stake-5 stake-6 stake-7 stake-8 stake-9 stake-10)) + ) + (ok final-list) + ) +) +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Admin Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; @desc - Function that only an admin user can call to add a new SGC collection for staking +;; @param - Collection (principal or collection?), Collection-Multiple (uint) +(define-public (admin-add-new-custodial-collection (collection ) (collection-multiple uint)) + (let + ( + (active-whitelist (var-get custodial-whitelist-collections)) + (all-whitelist (var-get whitelist-collections)) + ) + ;; assert the tx-sender is admin + (asserts! (is-some (index-of (var-get whitelist-admins) tx-sender)) ERR-NOT-AUTH) + ;; assert collection not already added + (asserts! (is-none (index-of all-whitelist (contract-of collection))) ERR-ALREADY-WHITELISTED) + ;; assert multiple < 10 + (asserts! (and (< collection-multiple u11) (> collection-multiple u0)) ERR-MULTIPLIER) + ;; update collection-multiplier map + (map-set collection-multiplier (contract-of collection) collection-multiple) + ;; add new principle to whitelist + (ok + (begin + (var-set custodial-whitelist-collections (unwrap! (as-max-len? (append active-whitelist (contract-of collection)) u100) ERR-UNWRAP)) + (var-set whitelist-collections (unwrap! (as-max-len? (append all-whitelist (contract-of collection)) u100) ERR-UNWRAP)) + ) + ) + ) +) + +(define-public (admin-remove-custodial-collection (collection )) + (let + ( + (active-whitelist (var-get custodial-whitelist-collections)) + (all-whitelist (var-get whitelist-collections)) + (removeable-principal-position-in-custodial-whitelist (index-of active-whitelist (contract-of collection))) + (removeable-principal-position-in-all-whitelist (index-of all-whitelist (contract-of collection))) + ) + ;; assert the tx-sender is admin + (asserts! (is-some (index-of (var-get whitelist-admins) tx-sender)) ERR-NOT-AUTH) + ;; assert collection is already added in custodial + (asserts! (is-some (index-of active-whitelist (contract-of collection))) ERR-NOT-WHITELISTED) + ;; assert collection is already added + (asserts! (is-some (index-of all-whitelist (contract-of collection))) ERR-NOT-WHITELISTED) + ;; update collection-multiplier map + (map-set collection-multiplier (contract-of collection) u0) + ;; temporary var set to help remove param principal + (var-set helper-collection-principal (contract-of collection)) + ;; add new principal to whitelist + (ok + (begin + (var-set whitelist-collections (filter is-not-removeable-collection active-whitelist)) + (var-set custodial-whitelist-collections (filter is-not-removeable-collection all-whitelist)) + ) + ) + ) +) + +(define-public (admin-add-new-non-custodial-collection (collection ) (collection-multiple uint)) + (let + ( + (active-whitelist (var-get non-custodial-whitelist-collections)) + (all-whitelist (var-get whitelist-collections)) + ) + ;; assert the tx-sender is admin + (asserts! (is-some (index-of (var-get whitelist-admins) tx-sender)) ERR-NOT-AUTH) + ;; assert collection not already added + (asserts! (is-none (index-of all-whitelist (contract-of collection))) ERR-ALREADY-WHITELISTED) + ;; assert multiple < 10 + (asserts! (and (< collection-multiple u11) (> collection-multiple u0)) ERR-MULTIPLIER) + ;; update collection-multiplier map + (map-set collection-multiplier (contract-of collection) collection-multiple) + ;; add new principal to whitelist + (ok + (begin + (var-set non-custodial-whitelist-collections (unwrap! (as-max-len? (append active-whitelist (contract-of collection)) u100) ERR-UNWRAP)) + (var-set whitelist-collections (unwrap! (as-max-len? (append all-whitelist (contract-of collection)) u100) ERR-UNWRAP)) + ) + ) + ) +) + +(define-public (admin-remove-non-custodial-collection (collection )) + (let + ( + (active-whitelist (var-get non-custodial-whitelist-collections)) + (all-whitelist (var-get whitelist-collections)) + (removeable-principal-position-in-non-custodial-whitelist (index-of active-whitelist (contract-of collection))) + (removeable-principal-position-in-all-whitelist (index-of all-whitelist (contract-of collection))) + ) + ;; assert the tx-sender is admin + (asserts! (is-some (index-of (var-get whitelist-admins) tx-sender)) ERR-NOT-AUTH) + ;; assert collection is already added in non custodial + (asserts! (is-some (index-of active-whitelist (contract-of collection))) ERR-NOT-WHITELISTED) + ;; assert collection is already added + (asserts! (is-some (index-of all-whitelist (contract-of collection))) ERR-NOT-WHITELISTED) + ;; update collection-multiplier map + (map-set collection-multiplier (contract-of collection) u0) + ;; temporary var set to help remove param principal + (var-set helper-collection-principal (contract-of collection)) + ;; add new principal to whitelist + (ok + (begin + (var-set whitelist-collections (filter is-not-removeable-collection active-whitelist)) + (var-set non-custodial-whitelist-collections (filter is-not-removeable-collection all-whitelist)) + ) + ) + ) +) + +;; @desc - Helper function for removing a specific collection from the whitelist +(define-private (is-not-removeable-collection (whitelist-collection principal)) + (not (is-eq whitelist-collection (var-get helper-collection-principal))) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Add Admin Address For Whitelisting ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; @desc - Function for add principals that have explicit permission to add current or future stakeable collections +;; @param - Principal that we're adding as whitelist +(define-public (add-admin-address-for-whitelisting (new-whitelist principal)) + (let + ( + (current-admin-list (var-get whitelist-admins)) + (caller-principal-position-in-list (index-of current-admin-list tx-sender)) + (param-principal-position-in-list (index-of current-admin-list new-whitelist)) + ) + ;; asserts tx-sender is an existing whitelist address + (asserts! (is-some caller-principal-position-in-list) ERR-NOT-AUTH) + ;; asserts param principal (new whitelist) doesn't already exist + (asserts! (is-none param-principal-position-in-list) ERR-ALREADY-WHITELISTED) + ;; append new whitelist address + (ok (var-set whitelist-admins (unwrap! (as-max-len? (append (var-get whitelist-admins) new-whitelist) u100) ERR-UNWRAP))) + ) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Remove Admin Address For Whitelisting ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; @desc - Function for removing principals that have explicit permission to add current or future stakeable collections +;; @param - Principal that we're adding removing as white +(define-public (remove-admin-address-for-whitelisting (remove-whitelist principal)) + (let + ( + (current-admin-list (var-get whitelist-admins)) + (caller-principal-position-in-list (index-of current-admin-list tx-sender)) + (removeable-principal-position-in-list (index-of current-admin-list remove-whitelist)) + ) + ;; assert the tx-sender is admin + (asserts! (is-some (index-of (var-get whitelist-admins) tx-sender)) ERR-NOT-AUTH) + ;; asserts param principal (removeable whitelist) already exist + (asserts! (is-eq removeable-principal-position-in-list) ERR-NOT-WHITELISTED) + ;; temporary var set to help remove param principal + (var-set helper-collection-principal remove-whitelist) + ;; filter existing whitelist address + (ok + (var-set whitelist-admins (filter is-not-removeable current-admin-list)) + ) + ) +) + +;; @desc - Helper function for removing a specific admin from the admin whitelist +(define-private (is-not-removeable (admin-principal principal)) + (not (is-eq admin-principal (var-get helper-collection-principal))) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Admin Manual Unstake ;; +;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; @desc - Function for emergency un-staking all manually custodied assets (Stacculents or Spookies) +;; @param - Principal of collection we're removing, ID of item we're manually unstaking & returning to user + +(define-public (admin-emergency-unstake (collection ) (staked-id uint) (original-owner principal)) + (let + ( + (this-collection-multiplier (default-to u0 (map-get? collection-multiplier (contract-of collection)))) + (this-collection-multiplier-normalized (/ (* this-collection-multiplier max-payout-per-block) u10)) + (current-staker (get staker (default-to {status: false, last-staked-or-claimed: block-height, staker: original-owner} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (stake-status (get status (default-to {status: false, last-staked-or-claimed: block-height, staker: original-owner} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (last-claimed-or-staked-height (get last-staked-or-claimed (default-to {status: false, last-staked-or-claimed: block-height, staker: original-owner} (map-get? staked-item {collection: (contract-of collection), id: staked-id})))) + (current-nft-owner (unwrap! (contract-call? collection get-owner staked-id) ERR-NOT-AUTH)) + (blocks-staked (- block-height last-claimed-or-staked-height)) + (current-all-staked-in-collection-list (default-to (list) (map-get? all-stakes-in-collection (contract-of collection)))) + (current-user-staked-by-collection-list (default-to (list) (map-get? user-stakes-by-collection {user: original-owner, collection: (contract-of collection)}))) + (custodial-list (var-get custodial-whitelist-collections)) + (set-var (var-set id-being-removed staked-id)) + (remove-stake (remove-a-specific-stake (contract-of collection) original-owner staked-id)) + (admins (var-get whitelist-admins)) + ) + ;; asserts is staked + (asserts! stake-status ERR-NOT-STAKED) + ;; asserts original-owner is staker + (asserts! (is-eq original-owner current-staker) ERR-NOT-OWNER) + ;; asserts that tx-sender is admin + (asserts! (is-some (index-of admins tx-sender)) ERR-NOT-AUTH) + + ;; temporary var set to help remove param + (var-set id-and-collection-being-removed {collection: (contract-of collection), nft: staked-id}) + ;; check if blocks-staked > 0 to see if there's any unclaimed $SNOW to claim + (if (> blocks-staked u0) + ;; if there is, need to claim unstaked + (unwrap! (contract-call? .snow-token mint (* this-collection-multiplier-normalized blocks-staked) original-owner) ERR-UNWRAP) + ;; if not, proceed + true + ) + ;; set function caller to tx-sender to send from contract + (var-set function-caller-helper-to-unstake original-owner) + ;;manual unstake of custodial + (if + (is-some (index-of custodial-list (contract-of collection))) + (as-contract (unwrap! (contract-call? collection transfer staked-id .cp-staking original-owner) (err u401))) + true + ) + ;; Set helper id for removal in filters below + (var-set id-being-removed staked-id) + ;; filter/remove staked-id from all-stakes-in-collection + (map-set all-stakes-in-collection (contract-of collection) (filter is-not-id current-all-staked-in-collection-list)) + ;; filter/remove staked-id from user-stakes-by-collection + (map-set user-stakes-by-collection {user: original-owner, collection: (contract-of collection)} (filter is-not-id current-user-staked-by-collection-list)) + ;; update last-staked-or-claimed height + (ok (map-set staked-item {collection: (contract-of collection), id: staked-id} + { + status: false, + last-staked-or-claimed: block-height, + staker: original-owner + } + )) + ) +) + +(define-public (admin-emergency-unstake-many (collection ) (nfts (list 10 uint)) (original-owner principal)) + (let + ( + (admins (var-get whitelist-admins)) + (nft-1 (element-at nfts u0)) + (nft-2 (element-at nfts u1)) + (nft-3 (element-at nfts u2)) + (nft-4 (element-at nfts u3)) + (nft-5 (element-at nfts u4)) + (nft-6 (element-at nfts u5)) + (nft-7 (element-at nfts u6)) + (nft-8 (element-at nfts u7)) + (nft-9 (element-at nfts u8)) + (nft-10 (element-at nfts u9)) + (staking-list (list nft-1 nft-2 nft-3 nft-4 nft-5 nft-6 nft-7 nft-8 nft-9 nft-10)) + (stake-1 (if (is-some nft-1) (some (admin-emergency-unstake collection (unwrap! nft-1 ERR-UNWRAP) original-owner)) none)) + (stake-2 (if (is-some nft-2) (some (admin-emergency-unstake collection (unwrap! nft-2 ERR-UNWRAP) original-owner)) none)) + (stake-3 (if (is-some nft-3) (some (admin-emergency-unstake collection (unwrap! nft-3 ERR-UNWRAP) original-owner)) none)) + (stake-4 (if (is-some nft-4) (some (admin-emergency-unstake collection (unwrap! nft-4 ERR-UNWRAP) original-owner)) none)) + (stake-5 (if (is-some nft-5) (some (admin-emergency-unstake collection (unwrap! nft-5 ERR-UNWRAP) original-owner)) none)) + (stake-6 (if (is-some nft-6) (some (admin-emergency-unstake collection (unwrap! nft-6 ERR-UNWRAP) original-owner)) none)) + (stake-7 (if (is-some nft-7) (some (admin-emergency-unstake collection (unwrap! nft-7 ERR-UNWRAP) original-owner)) none)) + (stake-8 (if (is-some nft-8) (some (admin-emergency-unstake collection (unwrap! nft-8 ERR-UNWRAP) original-owner)) none)) + (stake-9 (if (is-some nft-9) (some (admin-emergency-unstake collection (unwrap! nft-9 ERR-UNWRAP) original-owner)) none)) + (stake-10 (if (is-some nft-10) (some (admin-emergency-unstake collection (unwrap! nft-10 ERR-UNWRAP) original-owner)) none)) + (final-list (list stake-1 stake-2 stake-3 stake-4 stake-5 stake-6 stake-7 stake-8 stake-9 stake-10)) + ) + (asserts! (is-some (index-of admins tx-sender)) ERR-NOT-AUTH) + (ok final-list) + ) +) + +;; Function to change a collection multiplier (amount of SNOW generated per day) +(define-public (change-collection-multiplier (collection principal) (new-multiplier uint)) + (let + ( + (admins (var-get whitelist-admins)) + ) + (asserts! (is-some (index-of admins tx-sender)) ERR-NOT-AUTH) + (ok (map-set collection-multiplier collection new-multiplier)) + ) +) + +(define-public (switch-staking) + (let + ( + (admins (var-get whitelist-admins)) + ) + (asserts! (is-some (index-of admins tx-sender)) ERR-NOT-AUTH) + + (ok (if (var-get active-staking) + (var-set active-staking false) + (var-set active-staking true) + )) + ) +) diff --git a/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/ft-trait.clar b/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/ft-trait.clar new file mode 100644 index 0000000000..ae299b1be8 --- /dev/null +++ b/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/ft-trait.clar @@ -0,0 +1,24 @@ +(define-trait sip-010-trait + ( + ;; Transfer from the caller to a new principal + (transfer (uint principal principal (optional (buff 34))) (response bool uint)) + + ;; the human readable name of the token + (get-name () (response (string-ascii 32) uint)) + + ;; the ticker symbol, or empty if none + (get-symbol () (response (string-ascii 32) uint)) + + ;; the number of decimals used, e.g. 6 would mean 1_000_000 represents 1 token + (get-decimals () (response uint uint)) + + ;; the balance of the passed principal + (get-balance (principal) (response uint uint)) + + ;; the current total supply (which does not need to be a constant) + (get-total-supply () (response uint uint)) + + ;; an optional URI that represents metadata of this token + (get-token-uri () (response (optional (string-utf8 256)) uint)) + ) +) \ No newline at end of file diff --git a/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/nft-trait.clar b/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/nft-trait.clar new file mode 100644 index 0000000000..cc558fdb5a --- /dev/null +++ b/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/nft-trait.clar @@ -0,0 +1,15 @@ +(define-trait nft-trait + ( + ;; Last token ID, limited to uint range + (get-last-token-id () (response uint uint)) + + ;; URI for metadata associated with the token + (get-token-uri (uint) (response (optional (string-ascii 256)) uint)) + + ;; Owner of a given token identifier + (get-owner (uint) (response (optional principal) uint)) + + ;; Transfer from the sender to a new principal + (transfer (uint principal principal) (response bool uint)) + ) +) diff --git a/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/snow-token.clar b/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/snow-token.clar new file mode 100644 index 0000000000..5fbfbb3200 --- /dev/null +++ b/contracts/SP321TKKGKABFB949WR18QT2MWJZQ88QHSDK7VKS7/snow-token.clar @@ -0,0 +1,172 @@ +;; $SNOW FT Contract +;; This contract represents the $SNOW FT - the fungible token for the CrashPunks metaverse. +;; Written by StrataLabs + +;; $SNOW FT Unique Properties +;; 1. Minting is only allowed by the staking contract + +(impl-trait .ft-trait.sip-010-trait) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; Cons, Vars, & Maps ;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-constant contract-owner tx-sender) +(define-constant TOKEN_NAME "SNOW") +(define-constant TOKEN_SYMBOL "SNW") +(define-constant TOKEN_DECIMALS u6) +(define-constant TOKEN_MAX_SUPPLY u100000000000000) + +;;;;;;;;;;;;;;;;;;; +;; FT Vars/Cons ;; +;;;;;;;;;;;;;;;;;;; + +(define-fungible-token SNOW TOKEN_MAX_SUPPLY) +(define-data-var activate-transfer bool false) +(define-data-var TOKEN_URI (optional (string-utf8 256)) (some u"https://gateway.pinata.cloud/ipfs/QmerTxsPTgfdR2iz5xV6oqy7jprPoga5NNiEJRtgQ2pF2H")) +(define-data-var mint-active bool true) + +;;;;;;;;;;;;;;;; +;; Error Cons ;; +;;;;;;;;;;;;;;;; + +(define-constant ERR_SENDER_NOT_VALID (err u1000)) +(define-constant ERR_SENDER_AND_RECIPENT_IS_EQUAL (err u1001)) +(define-constant ERR_INSUFFICIENT_AMOUNT (err u1002)) +(define-constant ERR_GETING_BALANCE_OF_SENDER (err u1003)) +(define-constant ERR_SENDER_BALANCE_NOT_VALID (err u1004)) +(define-constant ERR_NOT_ALLOWED (err u1005)) +(define-constant ERR_RECIPIENT_NOT_VALID (err u1006)) +(define-constant ERR_TRANSFER_NOT_ACTIVATED (err u1007)) +(define-constant ERR_NOT_AUTH (err u1008)) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; SIP10 Functions ;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Regular transfer function for SIP-010 but we need to activita the transfer function before being able to actually transfer +(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34)))) + (begin + + ;; assert sender is tx-sender + (asserts! (is-eq tx-sender sender) ERR_SENDER_NOT_VALID) + + ;; assert sender is not recipient + (asserts! (not (is-eq sender recipient)) ERR_SENDER_AND_RECIPENT_IS_EQUAL) + + ;; assert amount transferred > 0 + (asserts! (> amount u0) ERR_INSUFFICIENT_AMOUNT) + + ;; assert amount transferred =< balance of sender + (asserts! (<= amount (unwrap! (get-balance sender) ERR_GETING_BALANCE_OF_SENDER)) ERR_SENDER_BALANCE_NOT_VALID) + + ;; assert the transfer function is activated + (asserts! (var-get activate-transfer) ERR_TRANSFER_NOT_ACTIVATED) + + ;; transfer + (try! (ft-transfer? SNOW amount sender recipient)) + (match memo to-print (print to-print) 0x) + (ok true) + ) +) + +(define-public (change-transfer-state) + (ok (var-set activate-transfer true)) +) + +(define-public (update-token-uri (new-uri (optional (string-utf8 256)))) + (begin + (asserts! (is-eq tx-sender contract-owner) ERR_NOT_ALLOWED) + (ok (var-set TOKEN_URI new-uri)) + ) +) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Read Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-read-only (get-name) + (ok TOKEN_NAME) +) + +(define-read-only (get-symbol) + (ok TOKEN_SYMBOL) +) + +(define-read-only (get-decimals) + (ok TOKEN_DECIMALS) +) + +(define-read-only (get-balance (account principal)) + (ok (ft-get-balance SNOW account)) +) + +(define-read-only (get-total-supply) + (ok (ft-get-supply SNOW)) +) + +(define-read-only (get-token-uri) + (ok (var-get TOKEN_URI)) +) + +(define-read-only (get-max-supply) + (ok TOKEN_MAX_SUPPLY) +) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;; Mint Functions ;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Regular SIP-010 mint function, except this is only callable by the CrashPunks staking contract or admin +(define-public (mint (amount uint) (recipient principal)) + (let + ( + (current-total-supply (ft-get-supply SNOW)) + ) + + ;; If mint is active, check that the tx-sender is contract-owner or staking contract, if it is not active only check that the sender is staking contract + (if (var-get mint-active) + (asserts! (or (is-eq tx-sender contract-owner) (is-eq contract-caller .cp-staking)) ERR_NOT_AUTH) + (asserts! (is-eq contract-caller .cp-staking) ERR_NOT_AUTH) + ) + + ;; asserts that recipient is not staking contract + (asserts! (not (is-eq recipient .cp-staking)) ERR_RECIPIENT_NOT_VALID) + + ;; asserts that amount is greater than 0 + (asserts! (> amount u0) ERR_INSUFFICIENT_AMOUNT) + + ;; asserts that amount is less than + (asserts! (<= amount (- TOKEN_MAX_SUPPLY current-total-supply)) ERR_NOT_ALLOWED) + (ft-mint? SNOW amount recipient) + ) +) + +(define-public (burn (amount uint) (sender principal)) + (begin + (asserts! (is-eq tx-sender sender) ERR_SENDER_NOT_VALID) + (asserts! (> amount u0) ERR_INSUFFICIENT_AMOUNT) + (asserts! (<= amount (ft-get-balance SNOW sender)) ERR_SENDER_BALANCE_NOT_VALID) + (ft-burn? SNOW amount sender) + ) +) + +;; Change the mint-active so that only the staking contract can mint SNOW tokens +(define-public (turn-off-mint-by-owner) + (ok + (begin + (asserts! (is-eq tx-sender contract-owner) ERR_NOT_AUTH) + (var-set mint-active false) + ) + ) +) diff --git a/contracts/SP376YY7EA9DQ41BFXW2E1N1BZWJ2W1100ZECZEHP/bns-1696360695071-v1.clar b/contracts/SP376YY7EA9DQ41BFXW2E1N1BZWJ2W1100ZECZEHP/bns-1696360695071-v1.clar new file mode 100644 index 0000000000..de195791c2 --- /dev/null +++ b/contracts/SP376YY7EA9DQ41BFXW2E1N1BZWJ2W1100ZECZEHP/bns-1696360695071-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: salv + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x73616c76 u96618358 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP38JYJSRV2Y63KCAHSCMA245K15A5W3FKPNBVR07/bns-1696359424665-v1.clar b/contracts/SP38JYJSRV2Y63KCAHSCMA245K15A5W3FKPNBVR07/bns-1696359424665-v1.clar new file mode 100644 index 0000000000..9de7e3215c --- /dev/null +++ b/contracts/SP38JYJSRV2Y63KCAHSCMA245K15A5W3FKPNBVR07/bns-1696359424665-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: jnw + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x6a6e77 u193236715 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP3PB4839X26X0DFHNH7KHTJ1VAMNHZSPGVYEZWKT/bns-1696359235477-v1.clar b/contracts/SP3PB4839X26X0DFHNH7KHTJ1VAMNHZSPGVYEZWKT/bns-1696359235477-v1.clar new file mode 100644 index 0000000000..8db9e57cc4 --- /dev/null +++ b/contracts/SP3PB4839X26X0DFHNH7KHTJ1VAMNHZSPGVYEZWKT/bns-1696359235477-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: idiots + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x6964696f7473 u1932367150 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP3RDV45F9XSC4ZEY5T2J530DPB1MGKAPBV8HWZT6/bns-1696360010842-v1.clar b/contracts/SP3RDV45F9XSC4ZEY5T2J530DPB1MGKAPBV8HWZT6/bns-1696360010842-v1.clar new file mode 100644 index 0000000000..aaf8cd2cbe --- /dev/null +++ b/contracts/SP3RDV45F9XSC4ZEY5T2J530DPB1MGKAPBV8HWZT6/bns-1696360010842-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: hnw + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x686e77 u1932367150 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP3TJA00RJVPZMKA4NHFKZMWR07P8E98H24Y01913/bns-1696358536806-v1.clar b/contracts/SP3TJA00RJVPZMKA4NHFKZMWR07P8E98H24Y01913/bns-1696358536806-v1.clar new file mode 100644 index 0000000000..087c6453ae --- /dev/null +++ b/contracts/SP3TJA00RJVPZMKA4NHFKZMWR07P8E98H24Y01913/bns-1696358536806-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: nyit + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x6e796974 u19323672 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP3V9BARGK0PSJMRDCZQKA7TQ62J62PKVR66C1B9P/bns-1696349565900-v1.clar b/contracts/SP3V9BARGK0PSJMRDCZQKA7TQ62J62PKVR66C1B9P/bns-1696349565900-v1.clar new file mode 100644 index 0000000000..0d064f1e09 --- /dev/null +++ b/contracts/SP3V9BARGK0PSJMRDCZQKA7TQ62J62PKVR66C1B9P/bns-1696349565900-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: orionprotocol + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x6f72696f6e70726f746f636f6c u96618358 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SP4Y6C79NH6A0Z9F7GC5RKGWFSA5TQ9EAD24YKB5/bns-1696355333412-v1.clar b/contracts/SP4Y6C79NH6A0Z9F7GC5RKGWFSA5TQ9EAD24YKB5/bns-1696355333412-v1.clar new file mode 100644 index 0000000000..78d7fd23e0 --- /dev/null +++ b/contracts/SP4Y6C79NH6A0Z9F7GC5RKGWFSA5TQ9EAD24YKB5/bns-1696355333412-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: shanghaistockexchange + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x7368616e6768616973746f636b65786368616e6765 u24154589372 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SPACRBHZ1G1P6DXDEYHSHRKPBEJJTT8F1JF2TEMC/bns-1696346323909-v1.clar b/contracts/SPACRBHZ1G1P6DXDEYHSHRKPBEJJTT8F1JF2TEMC/bns-1696346323909-v1.clar new file mode 100644 index 0000000000..eea3038e9f --- /dev/null +++ b/contracts/SPACRBHZ1G1P6DXDEYHSHRKPBEJJTT8F1JF2TEMC/bns-1696346323909-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: e2e4 + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x65326534 u670075939250405 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SPMG577CE9A32QQZQR9B2KJ66VEHRGEWW23HWF63/bns-1696355443723-v1.clar b/contracts/SPMG577CE9A32QQZQR9B2KJ66VEHRGEWW23HWF63/bns-1696355443723-v1.clar new file mode 100644 index 0000000000..9208ccd183 --- /dev/null +++ b/contracts/SPMG577CE9A32QQZQR9B2KJ66VEHRGEWW23HWF63/bns-1696355443723-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: stockexchangeofhongkong + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x73746f636b65786368616e67656f66686f6e676b6f6e67 u24154589372 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SPQAXJ9P941C30BDYKY78K6P24Z6RHG3QDHY1H8D/bns-1696355189240-v1.clar b/contracts/SPQAXJ9P941C30BDYKY78K6P24Z6RHG3QDHY1H8D/bns-1696355189240-v1.clar new file mode 100644 index 0000000000..677d8566e3 --- /dev/null +++ b/contracts/SPQAXJ9P941C30BDYKY78K6P24Z6RHG3QDHY1H8D/bns-1696355189240-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: embracergroup + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x656d62726163657267726f7570 u24154589372 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/contracts/SPRT4F40SVC51Q7N5RGYMG3P1YEJRN93SVAQXTSH/bns-1696355627947-v1.clar b/contracts/SPRT4F40SVC51Q7N5RGYMG3P1YEJRN93SVAQXTSH/bns-1696355627947-v1.clar new file mode 100644 index 0000000000..94e890286d --- /dev/null +++ b/contracts/SPRT4F40SVC51Q7N5RGYMG3P1YEJRN93SVAQXTSH/bns-1696355627947-v1.clar @@ -0,0 +1,126 @@ + + ;; version: 1 + ;; name: ralphfiennes + ;; namespace: btc + + (use-trait commission-trait 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.commission-trait.commission) + + (define-constant DEPLOYER_CONTRACT_PRINCIPAL (as-contract tx-sender)) + (define-constant COMM-ADDR 'SP7NDX6YRAH6C99WCZJWKF2SYR1GQRF7X6894QSJ) + + (define-constant ERR-ALREADY-LISTED (err u401)) + (define-constant ERR-WRONG-COMMISSION (err u402)) + (define-constant ERR-NOT-AUTHORIZED (err u403)) + (define-constant ERR-NOT-FOUND (err u404)) + (define-constant ERR-WRONG-PRICE (err u405)) + (define-constant ERR-TRANSFER-FAILED (err u500)) + + (define-data-var current-namespace (buff 20) 0x00) + (define-data-var current-name (buff 48) 0x00) + + (define-map listings { namespace: (buff 20), name: (buff 48) } { price: uint, lister: principal, commission: principal }) + + (define-read-only (is-admin) + (is-eq tx-sender COMM-ADDR) + ) + + (define-read-only (get-listing) + (map-get? listings { namespace: (var-get current-namespace), name: (var-get current-name) }) + ) + + (define-read-only (get-current-name) + { namespace: (var-get current-namespace), name: (var-get current-name) } + ) + + (define-private (list-name (namespace (buff 20)) (name (buff 48)) (price uint) (commission )) + (begin + (asserts! (is-none (get-listing)) ERR-ALREADY-LISTED) + (try! (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + DEPLOYER_CONTRACT_PRINCIPAL + none + ))) + (var-set current-namespace namespace) + (var-set current-name name) + (ok (map-set listings {name: name, namespace: namespace} + {price: price, lister: tx-sender, commission: (contract-of commission)})) + ) + ) + + (define-public (change-price (namespace (buff 20)) (name (buff 48)) (new-price uint) (commission )) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (is-eq tx-sender lister) ERR-NOT-AUTHORIZED) + (ok (map-set listings { namespace: namespace, name: name } { price: new-price, lister: lister, commission: (contract-of commission) })) + ) + ) + + (define-public (unlist-name (namespace (buff 20)) (name (buff 48))) + (let ( + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing))) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (map-delete listings {namespace: namespace, name: name}) + (as-contract + (to-bool-response (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + lister + none + )) + ) + ) + ) + + (define-public (purchase-name (namespace (buff 20)) (name (buff 48)) (expected-price uint) (commission ) (recipient (optional principal))) + (let ( + (new-owner (if (is-some recipient) (unwrap-panic recipient) tx-sender)) + (listing (unwrap! (map-get? listings {namespace: namespace, name: name}) ERR-NOT-FOUND)) + (price (get price listing)) + (lister (get lister listing)) + (list-commission (get commission listing)) + ) + (asserts! (is-eq (contract-of commission) list-commission) ERR-WRONG-COMMISSION) + (asserts! (is-eq price expected-price) ERR-WRONG-PRICE) + (try! (contract-call? commission pay u0 price)) + (try! (stx-transfer? price tx-sender lister)) + (map-delete listings {namespace: namespace, name: name}) + (to-bool-response (as-contract + (contract-call? + 'SP000000000000000000002Q6VF78.bns + name-transfer + namespace + name + new-owner + none + ) + )) + ) + ) + + (define-public (withdraw-stx (amount uint)) + (let ( + (listing (unwrap! (get-listing) ERR-NOT-FOUND)) + (lister (get lister listing)) + ) + (asserts! (or (is-eq tx-sender lister) (is-admin)) ERR-NOT-AUTHORIZED) + (try! (as-contract (stx-transfer? amount tx-sender lister))) + (ok amount) + ) + ) + + (define-private (to-bool-response (value (response bool int))) + (match value + success (ok success) + error (err (to-uint error)))) + + (list-name 0x627463 0x72616c70686669656e6e6573 u24154589372 'SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.gamma-commission-3-5) + \ No newline at end of file diff --git a/last-block.txt b/last-block.txt index fa47c5ecf3..b356c79a65 100644 --- a/last-block.txt +++ b/last-block.txt @@ -1 +1 @@ -123238 \ No newline at end of file +123376 \ No newline at end of file