Skip to content

Feat: L1 and L2 early unlocks, updating signer#7199

Open
hstove-stacks wants to merge 25 commits into
stacks-network:pox-wf-integrationfrom
hstove-stacks:feat/pox-5-waterfall
Open

Feat: L1 and L2 early unlocks, updating signer#7199
hstove-stacks wants to merge 25 commits into
stacks-network:pox-wf-integrationfrom
hstove-stacks:feat/pox-5-waterfall

Conversation

@hstove-stacks
Copy link
Copy Markdown
Contributor

This PR includes the ability for bond participants to unlock some of their sBTC. I've also added the hook for a bond admin to announce an L1 early unlock.

This new functionality highlighted the need for a change in how our internal state was being tracked. Previously, a signer's total shares for a cycle only changed in an upcoming cycle, so there was no way for a change of balance to effect already earned rewards. This is not the case with bond unlocks. Because of this, I've refactored rewards tracking to have a "snapshot" capability, where snapshotting a signer's rewards is separate from the actual act of claiming rewards. This is also how I've implemented things in the signer manager contract.

This also highlighted the need to add a checkpoint-signer call that is invoked when a staker changes their signer or unlocks some of their shares. This is a new trait function, and now the relevant functions must provide old-signer-manager to allow this trait function to be invoked.

Moved from tracking `rewards-paid` to `rewards-per-token-paid`. This is required to account for scenarios where a signer's staked amount changes without claiming rewards. This is the case, for example, with early L1 unlocks.
@coveralls
Copy link
Copy Markdown

coveralls commented May 14, 2026

Coverage Report for CI Build 25903914664

Warning

Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes.
Quick fix: rebase this PR. Learn more →

Coverage decreased (-38.8%) to 47.122%

Details

  • Coverage decreased (-38.8%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 89242 coverage regressions across 343 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

89242 previously-covered lines in 343 files lost coverage.

Top 10 Files by Coverage Loss Lines Losing Coverage Coverage
stackslib/src/chainstate/stacks/db/transactions.rs 8105 7.51%
stackslib/src/chainstate/stacks/db/blocks.rs 4481 35.53%
stackslib/src/chainstate/stacks/transaction.rs 4313 9.87%
stackslib/src/chainstate/burn/db/sortdb.rs 4193 42.89%
stackslib/src/chainstate/stacks/boot/mod.rs 3564 13.75%
stackslib/src/net/chat.rs 3156 27.42%
stackslib/src/chainstate/burn/operations/leader_block_commit.rs 2578 18.84%
stackslib/src/net/db.rs 1960 28.99%
stacks-signer/src/signerdb.rs 1576 35.28%
stackslib/src/chainstate/stacks/index/test/node.rs 1317 0.0%

Coverage Stats

Coverage Status
Relevant Lines: 219309
Covered Lines: 103343
Line Coverage: 47.12%
Coverage Strength: 12880462.62 hits per line

💛 - Coveralls


;; As a bond participant with locked sBTC, remove a portion (or all)
;; of your locked sBTC.
(define-public (unstake-sbtc
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 may be controversial, but could we avoid the term "unstake" here so it doesn't get confused with STX unstaking? I know we're saying "Bitcoin staking," but in the contract, it's register-for-bond, not stake-sbtc. Maybe this could be called early-exit-bond or something?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it's register-for-bond, not stake-sbtc.

Right, but register-for-bond supports either sBTC or BTC, whereas this "sbtc early unlock" flow is pretty different (different caller, one allows amounts, etc). But I'm happy to call it early-exit-bond!


;; As a bond participant with locked sBTC, remove a portion (or all)
;; of your locked sBTC.
(define-public (unstake-sbtc
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.

Should this be permissioned, like the L1 early exit is?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Totally valid question, but we've decided to not permission this

))
))

(ok {
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 should add a print event in here.

)

;; As a bond participant with locked sBTC, remove a portion (or all)
;; of your locked sBTC.
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.

Can you add a note that all of the STX stays locked for the duration of the bond, regardless of any early exit?

)
)

(define-public (announce-l1-early-exit
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.

Could you add a comment here? Be sure to note that the STX remains locked.

(define-map signer-rewards-paid-for-cycle
;; Represents a snapshot of `rewards-per-token` at the last
;; time of rewards calculation for this specific signer
(define-map signer-rewards-per-token-paid-for-cycle
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 paid (and pending below) is little confusing. What if we called it signer-rewards-per-token-settled-for-cycle instead and instead of crystallize-rewards it was settle-rewards. We could also make signer-pending-rewards-for-cycle be signer-accrued-rewards-for-cycle. What do you think? Does that make it any more clear?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yep I am on board, especially with crystallize-rewards -> settle-rewards, and signer-rewards-per-token-settled-for-cycle. Instead of "accrued" can I suggest "unclaimed", since that's more accurate? The "pending" value is "rewards that have been settled but not transfered to the signer yet".

Previously, the maps were called `staker-set-..`, but this reflected a previous design. Now, the linked list only contains signer principals. This commit updates those maps, functions, and argument names to reflect the fact that the linked list contains the _signer_ set.
;; Take a snapshot of the signer's current rewards
(crystallize-rewards signer bond-index true)

(map-set staker-shares-staked-for-cycle {
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.

Do we need to allow a bond holder to register for bond N, then early exit (through this method or on the L1 with announce-l1-early-exit), then register for another bond, before N+6? In other words, do we need a special case here for when new-amount-sats is 0, to do more cleanup?

Comment on lines +417 to +422
;; @param target-rate; target yield rate (apy) in basis points
;; @param stx-value-ratio; representation of STX:BTC price
;; @param min-ustx-ratio; minimum amount of STX that must be locked
;; relative to BTC for this term. Represented in basis points.
;; @param early-exit-signers: An allowlist of bond members that can
;; participate in the bond.
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.

Feels like you should have a line for all parameters, not just some.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants