;; title: swap-pair
;; version:
;; summary:
;; description:
;; EternalLegacy: Multi-Tiered Endowment Fund with Succession Planning
;; A comprehensive smart contract that enables users to create endowment funds with:
;; - Multi-tiered succession planning (up to 3 levels of successors)
;; - Time-locked inheritance triggers based on inactivity periods
;; - Percentage-based fund distribution to successors
;; - Endowment support voting system
;; - Returns calculation and distribution mechanisms
;; Error Constants
(define-constant ERR-UNAUTHORIZED-ACCESS (err u100))
(define-constant ERR-INSUFFICIENT-FUNDS (err u101))
(define-constant ERR-INVALID-ENDOWMENT-DATA (err u102))
(define-constant ERR-ALREADY-VOTED (err u103))
(define-constant ERR-TRANSACTION-FAILED (err u104))
(define-constant ERR-INVALID-TIER-LEVEL (err u105))
(define-constant ERR-SUCCESSOR-NOT-REGISTERED (err u106))
(define-constant ERR-NOT-DESIGNATED-SUCCESSOR (err u107))
(define-constant ERR-TIMELOCK-ACTIVE (err u108))
(define-constant ERR-INVALID-PARAMETER (err u109))
(define-constant ERR-INVALID-ADDRESS (err u110))
(define-constant ERR-INVALID-NAME (err u111))
;; Contract Constants
(define-constant contract-admin tx-sender)
(define-constant ZERO_ADDRESS 'SP000000000000000000002Q6VF78)
(define-constant MIN-INACTIVITY-PERIOD u1)
(define-constant MAX-ALLOCATION-PERCENTAGE u100)
(define-constant MIN-TIER-LEVEL u1)
(define-constant MAX-TIER-LEVEL u3)
(define-constant MIN-NAME-LENGTH u1)
(define-constant MAX-NAME-LENGTH u64)
;; Fund Data Variables
(define-data-var fund-total-balance uint u0)
(define-data-var fund-generated-returns uint u0)
(define-data-var fund-last-activity-timestamp uint u0)
;; Data Maps
(define-map user-deposits principal uint)
(define-map registered-endowments
{endowment-name: (string-ascii 64)}
{beneficiary-address: principal, vote-count: uint}
)
(define-map endowment-voter-registry
{endowment-name: (string-ascii 64), voter-address: principal}
bool
)
(define-map inheritance-configuration
{owner-address: principal, tier-level: uint}
{inactivity-period: uint, heir-address: principal, allocation-percentage: uint, notification-timestamp: uint}
)
(define-map heir-notification-registry
{heir-address: principal, owner-address: principal}
{tier-level: uint, inheritance-activation-time: uint, notification-sent: bool}
)
(define-private (update-activity-timestamp)
(var-set fund-last-activity-timestamp stacks-block-height)
)
(define-private (is-valid-principal (address principal))
;; Simply check if the address is not the zero address
;; We don't need principal-destruct? for basic validation
(not (is-eq address ZERO_ADDRESS))
)
(define-private (is-valid-endowment-name (name (string-ascii 64)))
(and
(>= (len name) MIN-NAME-LENGTH)
(<= (len name) MAX-NAME-LENGTH)
(not (is-eq name ""))
)
)
(define-private (is-valid-tier-level (tier uint))
(and (>= tier MIN-TIER-LEVEL) (<= tier MAX-TIER-LEVEL))
)
(define-private (is-valid-allocation-percentage (percentage uint))
(<= percentage MAX-ALLOCATION-PERCENTAGE)
)
(define-private (is-valid-inactivity-period (period uint))
(> period MIN-INACTIVITY-PERIOD)
)
(define-public (compute-fund-returns)
(let (
(periodic-returns (/ (* (var-get fund-total-balance) u5) u100)) ;; 5% return simulation
)
(var-set fund-generated-returns (+ (var-get fund-generated-returns) periodic-returns))
(update-activity-timestamp)
(ok periodic-returns)
)
)
;; Fund Information Functions
(define-read-only (get-fund-status)
(ok {
total-assets: (var-get fund-total-balance),
undistributed-returns: (var-get fund-generated-returns)
})
)
;; Endowment Management Functions
(define-public (create-endowment (endowment-name (string-ascii 64)) (beneficiary-address principal))
;; Validate all inputs first
(if (not (is-eq tx-sender contract-admin))
(err ERR-UNAUTHORIZED-ACCESS)
(if (not (is-valid-endowment-name endowment-name))
(err ERR-INVALID-NAME)
(if (not (is-valid-principal beneficiary-address))
(err ERR-INVALID-ADDRESS)
(begin
(map-set registered-endowments {endowment-name: endowment-name}
{beneficiary-address: beneficiary-address, vote-count: u0})
(update-activity-timestamp)
(ok true)
)
)
)
)
)
(define-public (vote-for-endowment (endowment-name (string-ascii 64)))
;; Validate input first
(if (not (is-valid-endowment-name endowment-name))
(err ERR-INVALID-NAME)
;; Check if endowment exists
(match (map-get? registered-endowments {endowment-name: endowment-name})
endowment-record
(let (
(has-voted-before (default-to false (map-get? endowment-voter-registry
{endowment-name: endowment-name, voter-address: tx-sender})))
(current-votes (get vote-count endowment-record))
)
(if has-voted-before
(err ERR-ALREADY-VOTED)
(begin
(map-set endowment-voter-registry {endowment-name: endowment-name, voter-address: tx-sender} true)
(map-set registered-endowments {endowment-name: endowment-name}
(merge endowment-record {vote-count: (+ u1 current-votes)}))
(update-activity-timestamp)
(ok true)
)
)
)
(err ERR-INVALID-ENDOWMENT-DATA)
)
)
)
;; Succession Planning Functions
(define-public (configure-succession-tier (tier-level uint) (inactivity-period uint)
(heir-address principal) (allocation-percentage uint))
;; Validate all inputs first
(if (not (is-valid-tier-level tier-level))
(err ERR-INVALID-TIER-LEVEL)
(if (not (is-valid-inactivity-period inactivity-period))
(err ERR-INVALID-PARAMETER)
(if (not (is-valid-principal heir-address))
(err ERR-INVALID-ADDRESS)
(if (not (is-valid-allocation-percentage allocation-percentage))
(err ERR-INVALID-PARAMETER)
(begin
(map-set inheritance-configuration {owner-address: tx-sender, tier-level: tier-level}
{inactivity-period: inactivity-period, heir-address: heir-address,
allocation-percentage: allocation-percentage, notification-timestamp: u0})
(update-activity-timestamp)
(ok true)
)
)
)
)
)
)
(define-public (delete-succession-tier (tier-level uint))
;; Validate input first
(if (not (is-valid-tier-level tier-level))
(err ERR-INVALID-TIER-LEVEL)
(begin
(map-delete inheritance-configuration {owner-address: tx-sender, tier-level: tier-level})
(update-activity-timestamp)
(ok true)
)
)
)
(define-read-only (view-succession-tier (owner-address principal) (tier-level uint))
;; Validate all inputs first
(if (not (is-valid-principal owner-address))
(err ERR-INVALID-ADDRESS)
(if (not (is-valid-tier-level tier-level))
(err ERR-INVALID-TIER-LEVEL)
(match (map-get? inheritance-configuration {owner-address: owner-address, tier-level: tier-level})
tier-details (ok tier-details)
(err ERR-SUCCESSOR-NOT-REGISTERED)
)
)
)
)
;; Succession Alert Functions
(define-public (verify-succession-eligibility)
(let (
(current-block-height stacks-block-height)
(last-user-activity (var-get fund-last-activity-timestamp))
)
(map-set heir-notification-registry
{heir-address: tx-sender, owner-address: contract-admin}
(merge
(default-to
{tier-level: u0, inheritance-activation-time: u0, notification-sent: false}
(map-get? heir-notification-registry {heir-address: tx-sender, owner-address: contract-admin})
)
{
tier-level: (determine-eligible-tier-level tx-sender contract-admin current-block-height last-user-activity),
inheritance-activation-time: (+ last-user-activity (get-tier-inactivity-period tx-sender contract-admin)),
notification-sent: true
}
)
)
(ok true)
)
)
(define-private (determine-eligible-tier-level (heir-address principal) (owner-address principal)
(current-time uint) (last-activity uint))
;; Validate inputs first
(if (not (is-valid-principal heir-address))
u0
(if (not (is-valid-principal owner-address))
u0
(let (
(tier-one (default-to {inactivity-period: u0, heir-address: ZERO_ADDRESS,
allocation-percentage: u0, notification-timestamp: u0}
(map-get? inheritance-configuration {owner-address: owner-address, tier-level: u1})))
(tier-two (default-to {inactivity-period: u0, heir-address: ZERO_ADDRESS,
allocation-percentage: u0, notification-timestamp: u0}
(map-get? inheritance-configuration {owner-address: owner-address, tier-level: u2})))
(tier-three (default-to {inactivity-period: u0, heir-address: ZERO_ADDRESS,
allocation-percentage: u0, notification-timestamp: u0}
(map-get? inheritance-configuration {owner-address: owner-address, tier-level: u3})))
)
(if (and (is-eq heir-address (get heir-address tier-three))
(>= (- current-time last-activity) (get inactivity-period tier-three)))
u3
(if (and (is-eq heir-address (get heir-address tier-two))
(>= (- current-time last-activity) (get inactivity-period tier-two)))
u2
(if (and (is-eq heir-address (get heir-address tier-one))
(>= (- current-time last-activity) (get inactivity-period tier-one)))
u1
u0
)
)
)
)
)
)
)
(define-private (get-tier-inactivity-period (heir-address principal) (owner-address principal))
;; Validate inputs first
(if (not (is-valid-principal heir-address))
u0
(if (not (is-valid-principal owner-address))
u0
(let (
(tier-one (default-to {inactivity-period: u0, heir-address: ZERO_ADDRESS,
allocation-percentage: u0, notification-timestamp: u0}
(map-get? inheritance-configuration {owner-address: owner-address, tier-level: u1})))
(tier-two (default-to {inactivity-period: u0, heir-address: ZERO_ADDRESS,
allocation-percentage: u0, notification-timestamp: u0}
(map-get? inheritance-configuration {owner-address: owner-address, tier-level: u2})))
(tier-three (default-to {inactivity-period: u0, heir-address: ZERO_ADDRESS,
allocation-percentage: u0, notification-timestamp: u0}
(map-get? inheritance-configuration {owner-address: owner-address, tier-level: u3})))
)
(if (is-eq heir-address (get heir-address tier-three))
(get inactivity-period tier-three)
(if (is-eq heir-address (get heir-address tier-two))
(get inactivity-period tier-two)
(if (is-eq heir-address (get heir-address tier-one))
(get inactivity-period tier-one)
u0
)
)
)
)
)
)
)
;; Read-only Information Functions
(define-read-only (get-user-deposit (user-address principal))
;; Validate input first
(if (not (is-valid-principal user-address))
(err ERR-INVALID-ADDRESS)
(ok (default-to u0 (map-get? user-deposits user-address)))
)
)
(define-read-only (get-endowment-details (endowment-name (string-ascii 64)))
;; Validate input first
(if (not (is-valid-endowment-name endowment-name))
(err ERR-INVALID-NAME)
(match (map-get? registered-endowments {endowment-name: endowment-name})
endowment-record (ok endowment-record)
(err ERR-INVALID-ENDOWMENT-DATA)
)
)
)
(define-read-only (get-total-fund-assets)
(ok (var-get fund-total-balance))
)
(define-read-only (get-undistributed-returns)
(ok (var-get fund-generated-returns))
)
(define-read-only (get-last-activity-timestamp)
(ok (var-get fund-last-activity-timestamp))
)
(define-read-only (get-heir-notification-status (heir-address principal) (owner-address principal))
;; Validate inputs first
(if (not (is-valid-principal heir-address))
(err ERR-INVALID-ADDRESS)
(if (not (is-valid-principal owner-address))
(err ERR-INVALID-ADDRESS)
(match (map-get? heir-notification-registry {heir-address: heir-address, owner-address: owner-address})
notification-record (ok notification-record)
(err ERR-NOT-DESIGNATED-SUCCESSOR)
)
)
)
)