Source Code

;; Digital Will Contract
;; Digital asset will and legacy planning
;; Halal - responsible estate planning
;; Clarity 4 compatible

(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-AUTHORIZED (err u401))
(define-constant ERR-NOT-FOUND (err u404))
(define-constant ERR-NOT-EXECUTOR (err u405))

(define-data-var will-count uint u0)

(define-map wills uint {
  testator: principal, executor: principal,
  instructions: (string-utf8 200), total-value: uint,
  beneficiary-count: uint, executed: bool, created: uint
})
(define-map will-beneficiaries { will-id: uint, index: uint } {
  beneficiary: principal, share-pct: uint, amount: uint, distributed: bool
})
(define-map testator-will principal uint)
(define-map witnesses { will-id: uint, witness: principal } { attested: uint })
(define-map witness-count uint uint)

(define-public (create-will (executor principal) (instructions (string-utf8 200)) (total-value uint))
  (let ((id (+ (var-get will-count) u1)))
    (try! (stx-transfer? total-value tx-sender CONTRACT-OWNER))
    (map-set wills id { testator: tx-sender, executor: executor, instructions: instructions, total-value: total-value, beneficiary-count: u0, executed: false, created: stacks-block-height })
    (map-set testator-will tx-sender id)
    (var-set will-count id) (ok id)))

(define-public (add-beneficiary (will-id uint) (beneficiary principal) (share-pct uint))
  (let (
    (will (unwrap! (map-get? wills will-id) ERR-NOT-FOUND))
    (idx (get beneficiary-count will))
    (amount (/ (* (get total-value will) share-pct) u100))
  )
    (asserts! (is-eq tx-sender (get testator will)) ERR-NOT-AUTHORIZED)
    (map-set will-beneficiaries { will-id: will-id, index: idx } { beneficiary: beneficiary, share-pct: share-pct, amount: amount, distributed: false })
    (map-set wills will-id (merge will { beneficiary-count: (+ idx u1) }))
    (ok idx)))

(define-public (witness-will (will-id uint))
  (let ((wc (default-to u0 (map-get? witness-count will-id))))
    (asserts! (is-some (map-get? wills will-id)) ERR-NOT-FOUND)
    (map-set witnesses { will-id: will-id, witness: tx-sender } { attested: stacks-block-height })
    (map-set witness-count will-id (+ wc u1))
    (ok true)))

(define-public (execute-will (will-id uint) (beneficiary-index uint))
  (let (
    (will (unwrap! (map-get? wills will-id) ERR-NOT-FOUND))
    (ben (unwrap! (map-get? will-beneficiaries { will-id: will-id, index: beneficiary-index }) ERR-NOT-FOUND))
  )
    (asserts! (is-eq tx-sender (get executor will)) ERR-NOT-EXECUTOR)
    (asserts! (not (get distributed ben)) ERR-NOT-FOUND)
    (asserts! (>= (default-to u0 (map-get? witness-count will-id)) u2) ERR-NOT-FOUND)
    (try! (stx-transfer? (get amount ben) CONTRACT-OWNER (get beneficiary ben)))
    (map-set will-beneficiaries { will-id: will-id, index: beneficiary-index } (merge ben { distributed: true }))
    (ok (get amount ben))))

(define-read-only (get-will (id uint)) (map-get? wills id))
(define-read-only (get-beneficiary (will-id uint) (index uint)) (map-get? will-beneficiaries { will-id: will-id, index: index }))
(define-read-only (get-will-by-testator (who principal)) (map-get? testator-will who))
(define-read-only (get-will-count) (ok (var-get will-count)))
(define-read-only (get-witness-count (will-id uint)) (ok (default-to u0 (map-get? witness-count will-id))))

Functions (9)

FunctionAccessArgs
create-willpublicexecutor: principal, instructions: (string-utf8 200
add-beneficiarypublicwill-id: uint, beneficiary: principal, share-pct: uint
witness-willpublicwill-id: uint
execute-willpublicwill-id: uint, beneficiary-index: uint
get-willread-onlyid: uint
get-beneficiaryread-onlywill-id: uint, index: uint
get-will-by-testatorread-onlywho: principal
get-will-countread-only
get-witness-countread-onlywill-id: uint