;; title: insurance-pool
;; version:
;; summary:
;; description:
;; token definitions
(define-fungible-token sbtc-token)
;; constants
(define-constant err-not-member (err u101))
(define-constant err-proposal-not-found (err u102))
(define-constant err-voting-ended (err u103))
(define-constant err-insufficient-funds (err u104))
(define-constant err-already-voted (err u105))
(define-constant err-voting-not-ended (err u106))
(define-constant err-already-executed (err u107))
(define-constant err-proposal-rejected (err u108))
(define-constant err-asset-restriction-failed (err u109))
(define-constant err-invalid-signature (err u110))
(define-constant err-passkey-not-found (err u111))
(define-constant err-invalid-contract-hash (err u112))
;; Voting period: 24 hours (144 blocks * 10 minutes per block)
(define-constant voting-period-blocks u144)
;; data vars
(define-data-var proposal-nonce uint u0)
(define-data-var treasury-principal principal tx-sender)
;; data maps
(define-map dao-members principal bool)
(define-map proposals
uint
{
creator: principal,
amount: uint,
recipient: principal,
yes-votes: uint,
no-votes: uint,
end-block: uint,
end-timestamp: uint,
executed: bool,
created-at: uint
}
)
(define-map member-votes { proposal-id: uint, voter: principal } bool)
;; passkey storage for biometric authentication (Clarity 4)
(define-map member-passkeys principal (buff 33))
;; trusted contracts registry (Clarity 4)
(define-map trusted-contracts principal bool)
;; read-only functions (defined before use)
(define-read-only (is-member (user principal))
(default-to false (map-get? dao-members user))
)
;; public functions
(define-public (join-dao)
(begin
(map-set dao-members tx-sender true)
(ok true)
)
)
;; Join DAO with passkey (secp256r1-verify - Clarity 4)
(define-public (join-dao-with-passkey (public-key (buff 33)) (message-hash (buff 32)) (signature (buff 64)))
(begin
(asserts! (secp256r1-verify message-hash signature public-key) err-invalid-signature)
(map-set dao-members tx-sender true)
(map-set member-passkeys tx-sender public-key)
(ok true)
)
)
;; Vote with passkey authentication (secp256r1-verify - Clarity 4)
(define-public (vote-with-passkey (proposal-id uint) (vote-yes bool) (message-hash (buff 32)) (signature (buff 64)))
(let (
(proposal (unwrap! (map-get? proposals proposal-id) err-proposal-not-found))
(passkey (unwrap! (map-get? member-passkeys tx-sender) err-passkey-not-found))
)
(asserts! (secp256r1-verify message-hash signature passkey) err-invalid-signature)
(asserts! (is-member tx-sender) err-not-member)
(asserts! (< stacks-block-time (get end-timestamp proposal)) err-voting-ended)
(asserts! (is-none (map-get? member-votes { proposal-id: proposal-id, voter: tx-sender })) err-already-voted)
(map-set member-votes { proposal-id: proposal-id, voter: tx-sender } true)
(if vote-yes
(map-set proposals proposal-id (merge proposal { yes-votes: (+ (get yes-votes proposal) u1) }))
(map-set proposals proposal-id (merge proposal { no-votes: (+ (get no-votes proposal) u1) }))
)
(ok true)
)
)
;; Register trusted contract - simplified (Clarity 4)
(define-public (register-trusted-contract (contract principal))
(begin
(asserts! (is-member tx-sender) err-not-member)
(map-set trusted-contracts contract true)
(ok true)
)
)
(define-public (deposit (amount uint))
(begin
(asserts! (is-member tx-sender) err-not-member)
(ft-mint? sbtc-token amount tx-sender)
)
)
(define-public (create-proposal (amount uint) (recipient principal))
(let (
(proposal-id (+ (var-get proposal-nonce) u1))
(current-time stacks-block-time)
(voting-deadline (+ stacks-block-time u86400)) ;; 24 hours in seconds
)
(asserts! (is-member tx-sender) err-not-member)
(map-set proposals proposal-id {
creator: tx-sender,
amount: amount,
recipient: recipient,
yes-votes: u0,
no-votes: u0,
end-block: (+ stacks-block-height voting-period-blocks),
end-timestamp: voting-deadline,
executed: false,
created-at: current-time
})
(var-set proposal-nonce proposal-id)
(ok proposal-id)
)
)
(define-public (vote (proposal-id uint) (vote-yes bool))
(let ((proposal (unwrap! (map-get? proposals proposal-id) err-proposal-not-found)))
(asserts! (is-member tx-sender) err-not-member)
(asserts! (< stacks-block-time (get end-timestamp proposal)) err-voting-ended)
(asserts! (is-none (map-get? member-votes { proposal-id: proposal-id, voter: tx-sender })) err-already-voted)
(map-set member-votes { proposal-id: proposal-id, voter: tx-sender } true)
(if vote-yes
(map-set proposals proposal-id (merge proposal { yes-votes: (+ (get yes-votes proposal) u1) }))
(map-set proposals proposal-id (merge proposal { no-votes: (+ (get no-votes proposal) u1) }))
)
(ok true)
)
)
(define-public (execute-proposal (proposal-id uint))
(let (
(proposal (unwrap! (map-get? proposals proposal-id) err-proposal-not-found))
(transfer-amount (get amount proposal))
(transfer-recipient (get recipient proposal))
)
(asserts! (>= stacks-block-time (get end-timestamp proposal)) err-voting-not-ended)
(asserts! (not (get executed proposal)) err-already-executed)
(asserts! (> (get yes-votes proposal) (get no-votes proposal)) err-proposal-rejected)
(asserts! (>= (ft-get-balance sbtc-token tx-sender) transfer-amount) err-insufficient-funds)
;; Execute transfer
(try! (ft-transfer? sbtc-token transfer-amount tx-sender transfer-recipient))
(map-set proposals proposal-id (merge proposal { executed: true }))
(ok true)
)
)
;; Batch vote on multiple proposals (Clarity 4 - uses stacks-block-time)
(define-public (batch-vote (proposal-ids (list 10 uint)) (votes (list 10 bool)))
(begin
(asserts! (is-member tx-sender) err-not-member)
(asserts! (is-eq (len proposal-ids) (len votes)) (err u300))
(ok (map batch-vote-helper proposal-ids votes))
)
)
;; Helper for batch voting
(define-private (batch-vote-helper (proposal-id uint) (vote-yes bool))
(match (map-get? proposals proposal-id)
proposal
(if (and
(< stacks-block-time (get end-timestamp proposal))
(is-none (map-get? member-votes { proposal-id: proposal-id, voter: tx-sender })))
(begin
(map-set member-votes { proposal-id: proposal-id, voter: tx-sender } true)
(if vote-yes
(map-set proposals proposal-id (merge proposal { yes-votes: (+ (get yes-votes proposal) u1) }))
(map-set proposals proposal-id (merge proposal { no-votes: (+ (get no-votes proposal) u1) }))
)
true
)
false
)
false
)
)
;; Update member passkey (secp256r1-verify - Clarity 4)
(define-public (update-passkey (new-public-key (buff 33)) (message-hash (buff 32)) (signature (buff 64)))
(let ((old-passkey (unwrap! (map-get? member-passkeys tx-sender) err-passkey-not-found)))
(asserts! (secp256r1-verify message-hash signature old-passkey) err-invalid-signature)
(asserts! (is-member tx-sender) err-not-member)
(map-set member-passkeys tx-sender new-public-key)
(ok true)
)
)
;; Cancel proposal before voting ends (Clarity 4 - uses stacks-block-time)
(define-public (cancel-proposal (proposal-id uint))
(let ((proposal (unwrap! (map-get? proposals proposal-id) err-proposal-not-found)))
(asserts! (is-eq tx-sender (get creator proposal)) (err u301))
(asserts! (< stacks-block-time (get end-timestamp proposal)) err-voting-ended)
(asserts! (not (get executed proposal)) err-already-executed)
(map-set proposals proposal-id (merge proposal {
executed: true,
end-timestamp: stacks-block-time
}))
(ok true)
)
)
;; Delegate voting power with passkey (secp256r1-verify - Clarity 4)
(define-map delegations { delegator: principal, proposal-id: uint } principal)
(define-public (delegate-vote (proposal-id uint) (delegate principal) (message-hash (buff 32)) (signature (buff 64)))
(let (
(proposal (unwrap! (map-get? proposals proposal-id) err-proposal-not-found))
(passkey (unwrap! (map-get? member-passkeys tx-sender) err-passkey-not-found))
)
(asserts! (secp256r1-verify message-hash signature passkey) err-invalid-signature)
(asserts! (is-member tx-sender) err-not-member)
(asserts! (is-member delegate) err-not-member)
(asserts! (< stacks-block-time (get end-timestamp proposal)) err-voting-ended)
(asserts! (is-none (map-get? member-votes { proposal-id: proposal-id, voter: tx-sender })) err-already-voted)
(map-set delegations { delegator: tx-sender, proposal-id: proposal-id } delegate)
(ok true)
)
)
;; Execute delegated vote
(define-public (execute-delegated-vote (proposal-id uint) (delegator principal) (vote-yes bool))
(let (
(proposal (unwrap! (map-get? proposals proposal-id) err-proposal-not-found))
(delegate (unwrap! (map-get? delegations { delegator: delegator, proposal-id: proposal-id }) (err u302)))
)
(asserts! (is-eq tx-sender delegate) (err u303))
(asserts! (< stacks-block-time (get end-timestamp proposal)) err-voting-ended)
(asserts! (is-none (map-get? member-votes { proposal-id: proposal-id, voter: delegator })) err-already-voted)
(map-set member-votes { proposal-id: proposal-id, voter: delegator } true)
(if vote-yes
(map-set proposals proposal-id (merge proposal { yes-votes: (+ (get yes-votes proposal) u1) }))
(map-set proposals proposal-id (merge proposal { no-votes: (+ (get no-votes proposal) u1) }))
)
(ok true)
)
)
;; Emergency withdraw for proposal creator if rejected (Clarity 4 - uses stacks-block-time)
(define-public (withdraw-rejected-proposal (proposal-id uint))
(let ((proposal (unwrap! (map-get? proposals proposal-id) err-proposal-not-found)))
(asserts! (is-eq tx-sender (get creator proposal)) (err u304))
(asserts! (>= stacks-block-time (get end-timestamp proposal)) err-voting-not-ended)
(asserts! (not (get executed proposal)) err-already-executed)
(asserts! (<= (get yes-votes proposal) (get no-votes proposal)) (err u305))
(map-set proposals proposal-id (merge proposal { executed: true }))
(ok true)
)
)
;; Extend voting period (Clarity 4 - uses stacks-block-time)
(define-public (extend-voting-period (proposal-id uint) (additional-seconds uint))
(let ((proposal (unwrap! (map-get? proposals proposal-id) err-proposal-not-found)))
(asserts! (is-eq tx-sender (get creator proposal)) (err u306))
(asserts! (< stacks-block-time (get end-timestamp proposal)) err-voting-ended)
(asserts! (not (get executed proposal)) err-already-executed)
(asserts! (<= additional-seconds u172800) (err u307)) ;; max 48 hours extension
(map-set proposals proposal-id (merge proposal {
end-timestamp: (+ (get end-timestamp proposal) additional-seconds)
}))
(ok true)
)
)
;; Revoke vote delegation (Clarity 4 - uses stacks-block-time)
(define-public (revoke-delegation (proposal-id uint))
(let ((proposal (unwrap! (map-get? proposals proposal-id) err-proposal-not-found)))
(asserts! (is-member tx-sender) err-not-member)
(asserts! (< stacks-block-time (get end-timestamp proposal)) err-voting-ended)
(asserts! (is-some (map-get? delegations { delegator: tx-sender, proposal-id: proposal-id })) (err u308))
(map-delete delegations { delegator: tx-sender, proposal-id: proposal-id })
(ok true)
)
)
;; Bulk deposit for multiple members (Clarity 4)
(define-public (bulk-deposit (recipients (list 20 principal)) (amounts (list 20 uint)))
(begin
(asserts! (is-member tx-sender) err-not-member)
(asserts! (is-eq (len recipients) (len amounts)) (err u309))
(ok (map bulk-deposit-helper recipients amounts))
)
)
;; Helper for bulk deposit
(define-private (bulk-deposit-helper (recipient principal) (amount uint))
(match (ft-mint? sbtc-token amount recipient)
success true
error false
)
)