;; 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)
)
)
)
)