Source Code

;; Multisig Wallet Contract
;; Simple multisig wallet requiring 2 of 3 approvals

(define-constant owner-1 tx-sender)
(define-data-var owner-2 principal tx-sender)
(define-data-var owner-3 principal tx-sender)

(define-map pending-transactions uint {
  to: principal,
  amount: uint,
  approvals: uint,
  executed: bool
})
(define-map has-approved {tx-id: uint, owner: principal} bool)
(define-data-var tx-nonce uint u0)

(define-public (propose-transaction (to principal) (amount uint))
  (let ((tx-id (+ (var-get tx-nonce) u1)))
    (map-set pending-transactions tx-id {
      to: to,
      amount: amount,
      approvals: u1,
      executed: false
    })
    (map-set has-approved {tx-id: tx-id, owner: tx-sender} true)
    (var-set tx-nonce tx-id)
    (ok tx-id)
  )
)

(define-public (approve-transaction (tx-id uint))
  (match (map-get? pending-transactions tx-id)
    tx-data (begin
      (asserts! (is-none (map-get? has-approved {tx-id: tx-id, owner: tx-sender})) (err u100))
      (map-set has-approved {tx-id: tx-id, owner: tx-sender} true)
      (let ((new-approvals (+ (get approvals tx-data) u1)))
        (map-set pending-transactions tx-id (merge tx-data {approvals: new-approvals}))
        (if (>= new-approvals u2)
          (execute-transaction tx-id)
          (ok true)
        )
      )
    )
    (err u101)
  )
)

(define-private (execute-transaction (tx-id uint))
  (match (map-get? pending-transactions tx-id)
    tx-data (begin
      (try! (as-contract (stx-transfer? (get amount tx-data) tx-sender (get to tx-data))))
      (map-set pending-transactions tx-id (merge tx-data {executed: true}))
      (ok true)
    )
    (err u102)
  )
)

(define-read-only (get-transaction (tx-id uint))
  (ok (map-get? pending-transactions tx-id))
)

Functions (4)

FunctionAccessArgs
propose-transactionpublicto: principal, amount: uint
approve-transactionpublictx-id: uint
execute-transactionprivatetx-id: uint
get-transactionread-onlytx-id: uint