Source Code


;; title: StackTax
;; Handles complex tax calculations, multiple currencies, deductions, and detailed reporting

;; Error codes
(define-constant ERR-NOT-AUTHORIZED (err u100))
(define-constant ERR-INVALID-AMOUNT (err u101))
(define-constant ERR-TAX-RATE-NOT-FOUND (err u102))
(define-constant ERR-INSUFFICIENT-BALANCE (err u103))
(define-constant ERR-INVALID-TAX-RATE (err u104))
(define-constant ERR-INVALID-CURRENCY (err u105))
(define-constant ERR-INVALID-DEDUCTION (err u106))
(define-constant ERR-REFUND-NOT-ALLOWED (err u107))
(define-constant ERR-INVALID-PERIOD (err u108))
(define-constant ERR-TRANSFER-FAILED (err u109))

;; Data variables
(define-data-var administrator principal tx-sender)
(define-data-var minimum-taxable-amount uint u100) ;; Minimum tax amount in base currency

;; Currency exchange rates (scaled by 1e8)
(define-map currency-exchange-rates
    { currency-code: (string-ascii 10) }
    { exchange-rate: uint,
      rate-update-timestamp: uint,
      currency-status: bool }
)

;; Tax rates with progressive brackets
(define-map income-tax-brackets
    { income-category: (string-ascii 24) }
    {
        tax-brackets: (list 10 {
            income-threshold: uint,
            tax-percentage: uint,
            bracket-description: (string-ascii 64)
        }),
        base-currency: (string-ascii 10),
        bracket-update-timestamp: uint
    }
)

;; Deductions configuration
(define-map available-deductions
    { deduction-code: (string-ascii 10) }
    {
        deduction-name: (string-ascii 64),
        maximum-deduction-amount: uint,
        deduction-percentage: uint,
        approval-required: bool
    }
)

;; Taxpayer records with enhanced tracking
(define-map taxpayer-profiles
    principal
    {
        cumulative-tax-paid: uint,
        cumulative-tax-refunded: uint,
        most-recent-payment: uint,
        taxpayer-category: (string-ascii 24),
        claimed-deductions: (list 20 {
            deduction-code: (string-ascii 10),
            deduction-amount: uint,
            deduction-approved: bool
        }),
        transaction-history: (list 50 {
            transaction-amount: uint,
            transaction-timestamp: uint,
            transaction-currency: (string-ascii 10)
        })
    }
)


;; Private helper for progressive tax calculation
(define-private (calculate-bracket-tax-amount 
    (tax-bracket { income-threshold: uint, tax-percentage: uint, bracket-description: (string-ascii 64) })
    (calculation-state { remaining-income: uint, accumulated-tax: uint }))
    (let (
        (taxable-bracket-amount (if (> (get remaining-income calculation-state) (get income-threshold tax-bracket))
            (- (get remaining-income calculation-state) (get income-threshold tax-bracket))
            u0))
        (bracket-tax-amount (/ (* taxable-bracket-amount (get tax-percentage tax-bracket)) u100))
    )
        { 
            remaining-income: (get remaining-income calculation-state),
            accumulated-tax: (+ (get accumulated-tax calculation-state) bracket-tax-amount)
        }
    )
)

;; Define helper function to update deduction approval
(define-private (update-deduction-approval 
    (index uint) 
    (current-index uint) 
    (deduction { deduction-code: (string-ascii 10), deduction-amount: uint, deduction-approved: bool })
    (target-index uint))
    (if (is-eq current-index target-index)
        ;; If this is the target index, return updated deduction with approved status
        {
            deduction-code: (get deduction-code deduction),
            deduction-amount: (get deduction-amount deduction),
            deduction-approved: true
        }
        ;; Otherwise return the original deduction unchanged
        deduction)
)

;; Private helper for calculating total approved deductions
(define-private (sum-approved-deductions 
    (deduction { deduction-code: (string-ascii 10), deduction-amount: uint, deduction-approved: bool }) 
    (running-total uint))
    (if (get deduction-approved deduction)
        (+ running-total (get deduction-amount deduction))
        running-total)
)



;; Read-only functions for enhanced reporting
(define-read-only (get-taxpayer-profile (taxpayer principal))
    (map-get? taxpayer-profiles taxpayer)
)

(define-read-only (get-currency-rate (currency-code (string-ascii 10)))
    (map-get? currency-exchange-rates { currency-code: currency-code })
)

(define-read-only (get-deduction-info (deduction-code (string-ascii 10)))
    (map-get? available-deductions { deduction-code: deduction-code })
)

(define-read-only (get-tax-bracket-info (income-category (string-ascii 24)))
    (map-get? income-tax-brackets { income-category: income-category })
)



;; Currency conversion function
(define-read-only (convert-between-currencies (amount uint) (source-currency (string-ascii 10)) (target-currency (string-ascii 10)))
    (let (
        (source-currency-rate (unwrap! (get-currency-rate source-currency) ERR-INVALID-CURRENCY))
        (target-currency-rate (unwrap! (get-currency-rate target-currency) ERR-INVALID-CURRENCY))
    )
        (ok (/ (* amount (get exchange-rate target-currency-rate)) (get exchange-rate source-currency-rate)))
    )
)



(define-read-only (calculate-progressive-tax (income-amount uint) (income-category (string-ascii 24)))
    (match (map-get? income-tax-brackets { income-category: income-category })
        bracket-data
        (let ((total-tax-due u0))
            (ok (fold calculate-bracket-tax-amount 
                (get tax-brackets bracket-data)
                { remaining-income: income-amount, accumulated-tax: u0 })))
        ERR-TAX-RATE-NOT-FOUND
    )
)



;; Enhanced reporting functions
(define-read-only (generate-annual-tax-report (taxpayer principal) (tax-year uint))
    (let (
        (taxpayer-profile (unwrap! (get-taxpayer-profile taxpayer) ERR-TAX-RATE-NOT-FOUND))
    )
        (ok {
            total-tax-paid: (get cumulative-tax-paid taxpayer-profile),
            total-tax-refunded: (get cumulative-tax-refunded taxpayer-profile),
            net-tax-paid: (- (get cumulative-tax-paid taxpayer-profile) (get cumulative-tax-refunded taxpayer-profile)),
            applied-deductions: (get claimed-deductions taxpayer-profile),
            payment-transactions: (get transaction-history taxpayer-profile)
        })
    )
)

(define-read-only (calculate-net-tax-obligation (taxpayer principal))
    (let (
        (taxpayer-profile (unwrap! (get-taxpayer-profile taxpayer) ERR-TAX-RATE-NOT-FOUND))
        (total-approved-deductions (fold sum-approved-deductions
            (get claimed-deductions taxpayer-profile)
            u0))
    )
        (ok (- (get cumulative-tax-paid taxpayer-profile) total-approved-deductions))
    )
)

Functions (8)

FunctionAccessArgs
get-taxpayer-profileread-onlytaxpayer: principal
get-currency-rateread-onlycurrency-code: (string-ascii 10
get-deduction-inforead-onlydeduction-code: (string-ascii 10
get-tax-bracket-inforead-onlyincome-category: (string-ascii 24
convert-between-currenciesread-onlyamount: uint, source-currency: (string-ascii 10
calculate-progressive-taxread-onlyincome-amount: uint, income-category: (string-ascii 24
generate-annual-tax-reportread-onlytaxpayer: principal, tax-year: uint
calculate-net-tax-obligationread-onlytaxpayer: principal