Skip to content

WIP: PoX-5 and Epoch 4#7197

Draft
hstove-stacks wants to merge 89 commits into
developfrom
pox-wf-integration
Draft

WIP: PoX-5 and Epoch 4#7197
hstove-stacks wants to merge 89 commits into
developfrom
pox-wf-integration

Conversation

@hstove-stacks
Copy link
Copy Markdown
Contributor

This is an in-progress PR for iterative development of pox-5 work

hstove-stacks and others added 30 commits April 22, 2026 21:10
* pipe through the outputs from burndb to sortdb
* add validation routine for the L1 locking scripts
* add validation for the PoX reward set, checking scripts for matching outputs
Also includes the linked list and other state for per-cycle
signer set state.
Also moved the computation logic to a separate helper function, to help with unit testing.
The expected p2wsh script will instead now be computed in Clarity and
then the new function to be added will verify that the output exists.
Also simplifies many matches to reduce the number of places that need to
be touched each time an epoch or clarity version is added.
;; this is a list of outputs corresponding to their timelocks.
;; If the response is `err`, this is the amount of sBTC (in sats)
;; that they want to lock.
(btc-lockup (response {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this being a response is bad for UX. I'd rather see two optionals, btc-lockup and sbtc-lockup, with a check to ensure they are not both set.

Comment on lines +244 to +245
is-bond: bool,
index: uint,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if the ordering of these keys is consistent across all of these maps, I think is-bond is first, then index is second makes the most sense.

Comment on lines +738 to +746
(ok {
unlock-burn-height: (reward-cycle-to-unlock-height unlock-cycle),
staker: tx-sender,
signer: signer,
prev-unlock-height: prev-unlock-cycle,
unlock-cycle: unlock-cycle,
num-cycles: num-cycles,
amount-ustx: new-lock-amount,
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, field ordering in tuples is nice to be consistent when possible.

         (ok {
-            unlock-burn-height: (reward-cycle-to-unlock-height unlock-cycle),
-            staker: tx-sender,
             signer: signer,
+            staker: tx-sender,
+            amount-ustx: new-lock-amount,
+            num-cycles: num-cycles,
             prev-unlock-height: prev-unlock-cycle,
+            unlock-burn-height: (reward-cycle-to-unlock-height unlock-cycle),
             unlock-cycle: unlock-cycle,
-            num-cycles: num-cycles,
-            amount-ustx: new-lock-amount,
         })
     )
 )

)
)

(define-public (calculate-rewards (bond-periods (list 6 uint)))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be nice to have a read-only version of this that could be called any time to estimate rewards, and then call that from the actual one that checks the proper height and sets the persistent storage.

* Push PoX-5 activation far ahead in the snap/consensus tests: those are not ready for PoX-5 activation, and will require integration once signer-set calculation is in place. This is the bulk of the changeset (all the snap files are touched because this impacts the pox-4 auto-unlock heights)
* Remove the force-activate test instruction for PoX-5 calculation
* Compute the first-waterfall reward set with `PoxConstants` PoX-5 activation rather than Epoch-4.0 height
* Fix the signer set fetch API so that it will return a pox-5 signer set
Comment on lines +59 to +67
;; Keep these constants in lock-step with the address version buffs above
;; Maximum value of an address version as a uint
(define-constant MAX_ADDRESS_VERSION u6)
;; Maximum value of an address version that has a 20-byte hashbytes
;; (0x00, 0x01, 0x02, 0x03, and 0x04 have 20-byte hashbytes)
(define-constant MAX_ADDRESS_VERSION_BUFF_20 u4)
;; Maximum value of an address version that has a 32-byte hashbytes
;; (0x05 and 0x06 have 32-byte hashbytes)
(define-constant MAX_ADDRESS_VERSION_BUFF_32 u6)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are unused and can be deleted.


;; Used to prevent fractional multiplication errors
;; during reward calculations
(define-constant PRECISION u1000000000000000000) ;; 1e18
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be better performance for this to be a power of 2 (multiplies and divides become shifts).

;; The signer must have been registered already
(asserts! (is-some (get-signer-info signer)) ERR_SIGNER_NOT_FOUND)

;; the start-burn-ht must result in the next reward cycle, do not allow stackers
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
;; the start-burn-ht must result in the next reward cycle, do not allow stackers
;; the start-burn-ht must result in the next reward cycle, do not allow stakers

;;;; tx-sender principal must not be in a bond membership
(asserts! (is-none (get-bond-membership tx-sender)) ERR_ALREADY_STAKED)

;;;; the Stacker must have sufficient unlocked funds
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
;;;; the Stacker must have sufficient unlocked funds
;;;; the staker must have sufficient unlocked funds

Also, what's with the ;;;; for some comments?

))
)

;; Revoke contract-caller authorization to call stacking methods
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
;; Revoke contract-caller authorization to call stacking methods
;; Revoke contract-caller authorization to call staking methods

PoX-5: Integrate sbtc address calculation
;; normally, stacking methods may only be invoked by _direct_ transactions
;; (i.e., the tx-sender issues a direct contract-call to the stacking methods)
;; by issuing an allowance, the tx-sender may call through the allowed contract
(define-public (allow-contract-caller
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we still going to consider the post-condition replacement for this? I think it would be nice. See discussion.

Comment on lines +2006 to +2008
;; Give a contract-caller authorization to call stacking methods
;; normally, stacking methods may only be invoked by _direct_ transactions
;; (i.e., the tx-sender issues a direct contract-call to the stacking methods)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"stacking" -> "staking" x 3

)

(match last-item
last-stacker (let ((last-node (unwrap-panic (map-get? staker-set-ll-for-cycle {
Copy link
Copy Markdown
Contributor

@brice-stacks brice-stacks May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"last-staker"

)

(define-private (remove-staker-from-set-for-cycle
(stacker principal)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"staker"

(next-item (get next node))
)
(match prev-item
prev-stacker
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prev-staker

Comment on lines +221 to +238
;; State for tracking used signer key authorizations. This prevents re-use
;; of the same signature or pre-set authorization for multiple transactions.
;; Refer to the `signer-key-authorizations` map for the documentation on these fields
(define-map used-signer-key-authorizations
{
signer-key: (buff 33),
reward-cycle: uint,
period: uint,
topic: (string-ascii 14),
pox-addr: (optional {
version: (buff 1),
hashbytes: (buff 32),
}),
auth-id: uint,
max-amount: uint,
}
bool ;; Whether the field has been used or not
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this any more.

index: uint,
is-bond: bool,
staker: principal,
signer: principal,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to include the signer in the key here? I think we're already guaranteed to only have one entry per index/is-bond/staker, and adding the signer is just complicating it.

Comment on lines +866 to +868
index: cycle,
signer: signer,
is-bond: false,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep the ordering consistent.

Comment on lines +272 to +273
;; This is strictly for reward calculations - ie the STX
;; from Bitcoin staking are not accounted for here.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment could be more clear. Maybe something like:

This is strictly for reward calculations - i.e. when is-bond is false, only the STX from STX-only staking is accounted for here, not the STX from bonds.

Comment on lines +318 to +322
;;;; The last accounted balance (of sBTC held by this contract)
;;;; at a time of reward computation.
;;;; N.B. it is critical that this value is set to the contract's
;;;; sBTC balance after any transfer of sBTC out of this contract.
;; (define-data-var last-accounted-balance uint u0)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is just going to be another place for an error to crop up. Let's not track this, and just use sBTC's functions to figure out how much the contract holds.

(available-rewards (get available-rewards accumulator))
;; How much sBTC the bond is supposed to earn per calculation,
;; which is (totalSats * apy) / 48
(target-yield (/ (/ (* total-sats (get target-rate bond)) u10000) u48))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the target rate is an APY, and we are calculating the target yield for 1 pay cycle, I think we should be dividing by 50, not 48.

X = year / pay cycles
1 pay cycle = 1050 blocks
1 year = 365.25 days * 24 hours/day * 60 min/day = 525,960 min
1 block = 10 min
1 year = 52,596 blocks
X = 52,596 blocks / 1050 blocks ~= 50

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or are we just assuming that two consecutive bonds is approximately 1 year, so there are ~48 pay periods in one year.

(define-constant ERR_CANNOT_SETUP_BOND_TOO_LATE (err u3))
(define-constant ERR_BOND_ALREADY_SETUP (err u4))
(define-constant ERR_STAKER_ALREADY_ADDED (err u5))
(define-constant ERR_L1_LOCKUP_NOT_FOUND (err u6))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several of these constants are never used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants