Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
dd68934
feat: bond participant can update their signer
hstove-stacks May 7, 2026
b3b0062
feat: start of early-l1-unlocks (test is failing)
hstove-stacks May 8, 2026
5484612
feat: update rewards-tracking state
hstove-stacks May 11, 2026
459bdae
feat: refactor signer manager checkpointing to allow proper bookkeeping
hstove-stacks May 11, 2026
c8f123f
feat: unstake sBTC
hstove-stacks May 11, 2026
48b0489
feat: add and use stubs for merkle proof validation
hstove-stacks May 12, 2026
d2ec176
feat: serialize the correct lockup script in clarity
hstove-stacks May 12, 2026
95400fb
feat: validate that the correct timelock script is used in l1 lockups
hstove-stacks May 12, 2026
0f7ac98
feat: import pox-5 changes from pox-locking
hstove-stacks May 13, 2026
14cbeec
fix: set bond admin to deploy, update clarigen
hstove-stacks May 13, 2026
beac945
Merge remote-tracking branch 'upstream/pox-wf-integration' into feat/…
hstove-stacks May 13, 2026
b600fdb
feat: pox-5 fixed after merge
hstove-stacks May 13, 2026
c0bcc58
fix: re-add default sender as bond-admin
hstove-stacks May 13, 2026
2fadb79
fix: location of set-bond-admin
hstove-stacks May 13, 2026
1b047e6
fix: allowed caller authorization expiration was backwards
hstove-stacks May 13, 2026
8e1a770
fix: gaps between `calculate-rewards` led to incorrect available rewards
hstove-stacks May 13, 2026
41d4553
fix: prevent update-bond-registration with same signer
hstove-stacks May 13, 2026
66dab62
fix: prevent registering for bond after it started
hstove-stacks May 13, 2026
bcdfc68
fix: cannot register for bond if stx-only staking
hstove-stacks May 13, 2026
71dc557
fix: concurrent bonds with the same stx-value-index have correct order
hstove-stacks May 13, 2026
85973f0
fix: correct is-in-prepare-phase check
hstove-stacks May 13, 2026
4eb94af
fix: allow unstaking sbtc after bond is over
hstove-stacks May 13, 2026
9a1249f
fix: update clarigen types
hstove-stacks May 13, 2026
6135a56
fix: add `get-total-ustx-stacked` for /v2/pox compatibility
hstove-stacks May 15, 2026
109f282
fix: var naming around signer set linked list
hstove-stacks May 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 137 additions & 33 deletions contrib/core-contract-tests/contracts/test-pox-5-signer.clar
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,17 @@
uint
)

(define-map staker-rewards-paid-for-cycle
(define-map staker-rewards-paid-per-token-for-cycle
{
is-bond: bool,
index: uint,
staker: principal,
}
uint
)

;; Represents pending, but unclaimed rewards for a staker
(define-map staker-pending-rewards-for-cycle
{
is-bond: bool,
index: uint,
Expand All @@ -32,12 +42,14 @@
;; #[allow(unused_binding)]
(staker principal)
;; #[allow(unused_binding)]
(first-index uint)
;; #[allow(unused_binding)]
(num-indexes uint)
;; #[allow(unused_binding)]
(amount-ustx uint)
;; #[allow(unused_binding)]
(amount-sats uint)
;; #[allow(unused_binding)]
(num-cycles uint)
;; #[allow(unused_binding)]
(is-bond bool)
;; #[allow(unused_binding)]
(signer-calldata (optional (buff 500)))
Expand All @@ -63,6 +75,87 @@
)
)

;; Handling rewards checkpointing for a staker
(define-public (checkpoint-staker
(staker principal)
(first-index uint)
(num-indexes uint)
(is-bond bool)
)
(begin
(try! (fold checkpoint-staker-for-index
(unwrap-panic (slice?
(list
u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15
u16 u17 u18 u19 u20 u21 u22 u23 u24 u25 u26 u27 u28 u29
u30 u31 u32 u33 u34 u35 u36 u37 u38 u39 u40 u41 u42 u43
u44 u45 u46 u47 u48 u49 u50 u51 u52 u53 u54 u55 u56 u57
u58 u59 u60 u61 u62 u63 u64 u65 u66 u67 u68 u69 u70 u71
u72 u73 u74 u75 u76 u77 u78 u79 u80 u81 u82 u83 u84 u85
u86 u87 u88 u89 u90 u91 u92 u93 u94 u95
)
u0 num-indexes
))
(ok {
staker: staker,
first-index: first-index,
is-bond: is-bond,
})
))
(ok true)
)
)

(define-private (checkpoint-staker-for-index
(index-offset uint)
(acc-res (response {
staker: principal,
first-index: uint,
is-bond: bool,
}
uint
))
)
(let (
(acc (try! acc-res))
(staker (get staker acc))
(index (+ (get first-index acc) index-offset))
)
(crystallize-staker-rewards staker index (get is-bond acc))
(ok acc)
)
)

(define-private (crystallize-staker-rewards
(staker principal)
(index uint)
(is-bond bool)
)
(let (
(earned (get-earned-staker-rewards staker index is-bond))
(rewards-per-token (get-rewards-per-token-for-cycle index is-bond))
)
(map-set staker-pending-rewards-for-cycle {
staker: staker,
index: index,
is-bond: is-bond,
}
earned
)
(map-set staker-rewards-paid-per-token-for-cycle {
staker: staker,
index: index,
is-bond: is-bond,
}
rewards-per-token
)
{
earned: earned,
rewards-per-token: rewards-per-token,
}
)
)

(define-public (claim-rewards
(bond-periods (list 6 uint))
(reward-cycle uint)
Expand All @@ -71,33 +164,33 @@
(try! (contract-call? .pox-5 claim-rewards bond-periods reward-cycle))
))))
(update-rewards-info
(get rewards-per-share (get stx-rewards new-rewards-info)) false
(get rewards-per-token (get stx-rewards new-rewards-info)) false
reward-cycle
)
(fold update-bond-rewards-info (get bond-rewards new-rewards-info) true)
(ok new-rewards-info)
)
)

(define-read-only (get-claimable-rewards
;; Get the total amount of rewards earned since the last
;; rewards snapshot for this staker.
;;
;; `earned = (shares * (rpt - rptPaid)) / PRECISION + pending`
(define-read-only (get-earned-staker-rewards
(staker principal)
(index uint)
(is-bond bool)
)
(let (
(rewards-paid (get-staker-rewards-paid-for-cycle staker index is-bond))
(rewards-per-share (get-rewards-per-token-for-cycle index is-bond))
(shares-staked (contract-call? .pox-5 get-staker-shares-staked-for-cycle staker
(shares (contract-call? .pox-5 get-staker-shares-staked-for-cycle staker
index is-bond current-contract
))
(rewards-pending (- (/ (* shares-staked rewards-per-share) PRECISION) rewards-paid))
(rpt-current (get-rewards-per-token-for-cycle index is-bond))
(rpt-paid (get-staker-rewards-per-token-paid-for-cycle staker index is-bond))
(pending (get-staker-pending-rewards-for-cycle staker index is-bond))
(newly-earned (/ (* shares (- rpt-current rpt-paid)) PRECISION))
)
{
rewards-paid: rewards-paid,
rewards-pending: rewards-pending,
shares-staked: shares-staked,
rewards-per-share: rewards-per-share,
}
(+ pending newly-earned)
)
)

Expand All @@ -107,27 +200,26 @@
)
(let (
(staker tx-sender)
(rewards (get-claimable-rewards staker index is-bond))
(rewards-pending (get rewards-pending rewards))
(rewards-paid (get rewards-paid rewards))
(rewards-info (crystallize-staker-rewards staker index is-bond))
(earned (get earned rewards-info))
)
(asserts! (> rewards-pending u0) ERR_NO_CLAIMABLE_REWARDS)
(map-set staker-rewards-paid-for-cycle {
index: index,
is-bond: is-bond,
(asserts! (> earned u0) ERR_NO_CLAIMABLE_REWARDS)
(map-set staker-pending-rewards-for-cycle {
staker: staker,
is-bond: is-bond,
index: index,
}
(+ rewards-pending rewards-paid)
u0
)
(try! (as-contract?
((with-ft 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
"sbtc-token" rewards-pending
"sbtc-token" earned
))
(try! (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
transfer rewards-pending tx-sender staker none
transfer earned tx-sender staker none
))
))
(ok rewards)
(ok earned)
)
)

Expand All @@ -149,10 +241,8 @@
(define-private (update-bond-rewards-info
(bond-info {
bond-index: uint,
rewards-paid: uint,
rewards-pending: uint,
shares-staked: uint,
rewards-per-share: uint,
earned: uint,
rewards-per-token: uint,
})
;; #[allow(unused_binding)]
(acc bool)
Expand All @@ -161,7 +251,7 @@
is-bond: true,
index: (get bond-index bond-info),
}
(get rewards-per-share bond-info)
(get rewards-per-token bond-info)
)
)

Expand All @@ -177,13 +267,27 @@
)
)

(define-read-only (get-staker-rewards-paid-for-cycle
(define-read-only (get-staker-rewards-per-token-paid-for-cycle
(staker principal)
(index uint)
(is-bond bool)
)
(default-to u0
(map-get? staker-rewards-paid-per-token-for-cycle {
staker: staker,
index: index,
is-bond: is-bond,
})
)
)

(define-read-only (get-staker-pending-rewards-for-cycle
(staker principal)
(index uint)
(is-bond bool)
)
(default-to u0
(map-get? staker-rewards-paid-for-cycle {
(map-get? staker-pending-rewards-for-cycle {
staker: staker,
index: index,
is-bond: is-bond,
Expand Down
Loading
Loading