Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
fad6731
feat(oracle): add bSTX/STX exchange rate oracle base contract
thewealthyplace Feb 24, 2026
62c2ef8
feat(oracle): add block-time-weighted TWAP accumulator contract
thewealthyplace Feb 24, 2026
0ca470f
feat(oracle): add standalone circuit breaker contract
thewealthyplace Feb 24, 2026
2ec6c2b
feat(defi): add ALEX governance proposal contract for bSTX collateral…
thewealthyplace Feb 24, 2026
fe84281
feat(defi): add bSTX/STX concentrated liquidity pool contract for Bit…
thewealthyplace Feb 24, 2026
1e17db6
chore: register oracle, ALEX governance, and Bitflow pool contracts i…
thewealthyplace Feb 24, 2026
e3b6991
test(oracle): add comprehensive tests for bSTX oracle spot rate and TWAP
thewealthyplace Feb 24, 2026
d288d2e
test(oracle): add circuit breaker tests covering trip, reset, and thr…
thewealthyplace Feb 24, 2026
7abd465
test(governance): add ALEX governance proposal tests
thewealthyplace Feb 24, 2026
c32af14
test(defi): add Bitflow bSTX/STX pool tests covering liquidity and swaps
thewealthyplace Feb 24, 2026
650e1db
feat(registry): add get-total-stacked and get-aggregate-stacked read-…
thewealthyplace Feb 24, 2026
63bb026
test(oracle): add TWAP accumulator tests for block-time-weighted pric…
thewealthyplace Feb 24, 2026
98933af
test(registry): add tests for get-total-stacked and get-aggregate-sta…
thewealthyplace Feb 24, 2026
45a11b9
docs: add comprehensive bSTX DeFi collateral integration guide
thewealthyplace Feb 24, 2026
ebfbc2f
docs: add ALEX governance forum proposal for bSTX collateral listing
thewealthyplace Feb 24, 2026
bbd9be3
docs(readme): add DeFi collateral integration section and update roadmap
thewealthyplace Feb 24, 2026
a8d1df2
ci: update workflow to run oracle, governance, and Bitflow pool tests
thewealthyplace Feb 24, 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
36 changes: 33 additions & 3 deletions .github/workflows/pool-tests.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Pool Contract Tests
name: Contract Tests

on:
push:
Expand All @@ -8,7 +8,7 @@ on:

jobs:
clarinet-test:
name: Clarinet Unit Tests
name: Clarinet Unit Tests (pool + oracle + defi)
runs-on: ubuntu-latest

steps:
Expand All @@ -19,7 +19,7 @@ jobs:
curl -L https://github.com/hirosystems/clarinet/releases/latest/download/clarinet-linux-x64-glibc.tar.gz \
| tar -xz -C /usr/local/bin

- name: Run Clarinet checks
- name: Run Clarinet checks (all contracts)
run: clarinet check

- name: Run contract tests
Expand All @@ -31,6 +31,36 @@ jobs:
file: coverage.lcov
fail_ci_if_error: false

oracle-tests:
name: Oracle & DeFi Contract Tests
runs-on: ubuntu-latest
needs: clarinet-test

steps:
- uses: actions/checkout@v4

- name: Install Clarinet
run: |
curl -L https://github.com/hirosystems/clarinet/releases/latest/download/clarinet-linux-x64-glibc.tar.gz \
| tar -xz -C /usr/local/bin

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Install test dependencies
run: npm install @hirosystems/clarinet-sdk @stacks/transactions vitest --save-dev

- name: Run oracle tests
run: npx vitest run tests/bitstake-bstx-oracle.test.ts tests/bitstake-bstx-oracle-twap.test.ts tests/bitstake-oracle-circuit-breaker.test.ts --reporter=verbose

- name: Run governance tests
run: npx vitest run tests/bitstake-alex-governance.test.ts --reporter=verbose

- name: Run Bitflow pool tests
run: npx vitest run tests/bitstake-bitflow-pool.test.ts --reporter=verbose

typescript-test:
name: TypeScript Tests
runs-on: ubuntu-latest
Expand Down
25 changes: 25 additions & 0 deletions Clarinet.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,29 @@ path = "contracts/bitstake-rewards.clar"
clarity_version = 2
epoch = "2.5"

[contracts.bitstake-bstx-oracle]
path = "contracts/bitstake-bstx-oracle.clar"
clarity_version = 2
epoch = "2.5"

[contracts.bitstake-bstx-oracle-twap]
path = "contracts/bitstake-bstx-oracle-twap.clar"
clarity_version = 2
epoch = "2.5"

[contracts.bitstake-oracle-circuit-breaker]
path = "contracts/bitstake-oracle-circuit-breaker.clar"
clarity_version = 2
epoch = "2.5"

[contracts.bitstake-alex-governance]
path = "contracts/bitstake-alex-governance.clar"
clarity_version = 2
epoch = "2.5"

[contracts.bitstake-bitflow-pool]
path = "contracts/bitstake-bitflow-pool.clar"
clarity_version = 2
epoch = "2.5"

[[deployment_plan.genesis]]
45 changes: 44 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,57 @@ When you deposit STX, you receive `bSTX` — a SIP-010 compliant liquid staking

---

## DeFi Collateral Integration

bSTX tokens are designed to be used as collateral in Stacks DeFi protocols while continuing to earn BTC stacking yield.

### Phase 1 Integrations

| Protocol | Integration | Status |
|-----------|---------------------|----------|
| ALEX | Lending collateral | Proposed |
| Bitflow | bSTX/STX LP pair | Deployed |
| Velar | Synthetic collateral| Planned |

### bSTX/STX Oracle

The `bitstake-bstx-oracle` contract provides an on-chain exchange rate:

```clarity
;; Returns bSTX/STX rate at 6 decimal precision
;; e.g. 1_050_000 = 1.05 STX per bSTX
(contract-call? .bitstake-bstx-oracle get-spot-rate)
```

Rate manipulation is mitigated by:
- **TWAP accumulator** — block-time-weighted 20-checkpoint window
- **Circuit breaker** — trips on >5% single-observation or >10% rolling deviation

### Bitflow bSTX/STX Pool

```clarity
;; Add liquidity to bSTX/STX concentrated pool (0.95–1.05 range, 0.05% fee)
(contract-call? .bitstake-bitflow-pool add-liquidity bstx-amount stx-amount min-bstx min-stx)

;; Swap STX for bSTX
(contract-call? .bitstake-bitflow-pool swap-stx-for-bstx stx-in min-bstx-out)
```

See [docs/bstx-defi-collateral.md](docs/bstx-defi-collateral.md) for the full integration guide.

---

## Roadmap

- [x] Core pool stacking contracts
- [x] bSTX liquid token
- [x] BTC reward distribution
- [x] bSTX/STX oracle with TWAP and circuit breaker
- [x] ALEX governance proposal for bSTX collateral listing
- [x] Bitflow bSTX/STX concentrated liquidity pool
- [ ] Frontend dashboard with live APY
- [ ] Multi-pool strategy (conservative / aggressive)
- [ ] DeFi integrations (bSTX as collateral)
- [ ] ALEX lending collateral (pending governance vote)
- [ ] Mobile app
- [ ] Governance token for protocol decisions

Expand Down
182 changes: 182 additions & 0 deletions contracts/bitstake-alex-governance.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
;; bitstake-alex-governance.clar
;; Governance proposal for bSTX collateral listing on ALEX lending protocol
;;
;; Records the on-chain intent to submit bSTX as a lending collateral asset.
;; Proposal parameters: 75% LTV, 80% liquidation threshold, 5% liquidation bonus.
;; Status lifecycle: DRAFT → SUBMITTED → ACTIVE → PASSED | REJECTED

(define-constant CONTRACT-OWNER tx-sender)

;; Status codes
(define-constant STATUS-DRAFT u0)
(define-constant STATUS-SUBMITTED u1)
(define-constant STATUS-ACTIVE u2)
(define-constant STATUS-PASSED u3)
(define-constant STATUS-REJECTED u4)

;; Error codes
(define-constant ERR-NOT-OWNER (err u500))
(define-constant ERR-INVALID-TRANSITION (err u501))
(define-constant ERR-PROPOSAL-NOT-FOUND (err u502))
(define-constant ERR-DUPLICATE (err u503))
(define-constant ERR-INVALID-PARAMS (err u504))

;; LTV / liquidation constants (basis points, 10000 = 100%)
(define-constant PROPOSED-LTV-BPS u7500) ;; 75%
(define-constant LIQUIDATION-THRESHOLD-BPS u8000) ;; 80%
(define-constant LIQUIDATION-BONUS-BPS u500) ;; 5%
(define-constant PRECISION u10000)

;; ── Storage ───────────────────────────────────────────────────────────

(define-data-var proposal-count uint u0)

(define-map proposals
uint
{
title: (string-ascii 128),
description: (string-ascii 512),
collateral-asset: principal,
oracle-contract: principal,
ltv-bps: uint,
liquidation-threshold: uint,
liquidation-bonus: uint,
status: uint,
submitted-at: uint,
votes-for: uint,
votes-against: uint
}
)

;; Track which addresses have voted on each proposal
(define-map votes { proposal-id: uint, voter: principal } bool)

;; ── Internal ──────────────────────────────────────────────────────────

(define-private (get-proposal-or-fail (id uint))
(match (map-get? proposals id)
p (ok p)
(err ERR-PROPOSAL-NOT-FOUND)
)
)

(define-private (status-allows-transition (current uint) (next uint))
(or
(and (is-eq current STATUS-DRAFT) (is-eq next STATUS-SUBMITTED))
(and (is-eq current STATUS-SUBMITTED) (is-eq next STATUS-ACTIVE))
(and (is-eq current STATUS-ACTIVE) (is-eq next STATUS-PASSED))
(and (is-eq current STATUS-ACTIVE) (is-eq next STATUS-REJECTED))
)
)

;; ── Create Proposal ───────────────────────────────────────────────────

(define-public (create-proposal
(title (string-ascii 128))
(description (string-ascii 512))
(collateral principal)
(oracle principal)
(ltv-bps uint)
(liq-threshold uint)
(liq-bonus uint)
)
(begin
(asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-OWNER)
(asserts! (and (> ltv-bps u0) (< ltv-bps PRECISION)) ERR-INVALID-PARAMS)
(asserts! (> liq-threshold ltv-bps) ERR-INVALID-PARAMS)
(asserts! (< liq-threshold PRECISION) ERR-INVALID-PARAMS)
(asserts! (and (> liq-bonus u0) (< liq-bonus u2000)) ERR-INVALID-PARAMS)

(let ((id (+ (var-get proposal-count) u1)))
(map-set proposals id {
title: title,
description: description,
collateral-asset: collateral,
oracle-contract: oracle,
ltv-bps: ltv-bps,
liquidation-threshold: liq-threshold,
liquidation-bonus: liq-bonus,
status: STATUS-DRAFT,
submitted-at: block-height,
votes-for: u0,
votes-against: u0
})
(var-set proposal-count id)
(print { event: "proposal-created", id: id, title: title, ltv: ltv-bps })
(ok id)
)
)
)

;; ── Status Transitions ────────────────────────────────────────────────

(define-public (transition-status (proposal-id uint) (new-status uint))
(let ((proposal (try! (get-proposal-or-fail proposal-id))))
(asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-OWNER)
(asserts! (status-allows-transition (get status proposal) new-status) ERR-INVALID-TRANSITION)
(map-set proposals proposal-id (merge proposal {
status: new-status,
submitted-at: (if (is-eq new-status STATUS-SUBMITTED) block-height (get submitted-at proposal))
}))
(print { event: "status-transition", id: proposal-id, from: (get status proposal), to: new-status })
(ok true)
)
)

;; ── Voting ────────────────────────────────────────────────────────────

;; Signalling vote (not binding — records community sentiment on-chain)
(define-public (cast-vote (proposal-id uint) (support bool))
(let (
(proposal (try! (get-proposal-or-fail proposal-id)))
(key { proposal-id: proposal-id, voter: tx-sender })
)
(asserts! (is-eq (get status proposal) STATUS-ACTIVE) ERR-INVALID-TRANSITION)
(asserts! (is-none (map-get? votes key)) ERR-DUPLICATE)
(map-set votes key support)
(map-set proposals proposal-id
(merge proposal {
votes-for: (if support (+ (get votes-for proposal) u1) (get votes-for proposal)),
votes-against: (if support (get votes-against proposal) (+ (get votes-against proposal) u1))
})
)
(print { event: "vote-cast", id: proposal-id, voter: tx-sender, support: support })
(ok true)
)
)

;; ── Read-Only ─────────────────────────────────────────────────────────

(define-read-only (get-proposal (id uint))
(ok (map-get? proposals id))
)

(define-read-only (get-proposal-count)
(ok (var-get proposal-count))
)

(define-read-only (get-vote (proposal-id uint) (voter principal))
(ok (map-get? votes { proposal-id: proposal-id, voter: voter }))
)

(define-read-only (get-default-params)
(ok {
ltv-bps: PROPOSED-LTV-BPS,
liquidation-threshold: LIQUIDATION-THRESHOLD-BPS,
liquidation-bonus: LIQUIDATION-BONUS-BPS
})
)

;; ── Initialise Default Proposal ───────────────────────────────────────

(begin
(try! (create-proposal
"List bSTX as Collateral on ALEX Lending"
"Enable bSTX (Liquid bitstake STX) as accepted collateral on ALEX lending with 75% LTV, 80% liquidation threshold, and bSTX/STX oracle feed from bitstake-bstx-oracle. Users can borrow against stacked positions without unlocking."
CONTRACT-OWNER ;; placeholder — replace with lbSTX contract principal at deploy
CONTRACT-OWNER ;; placeholder — replace with oracle principal at deploy
PROPOSED-LTV-BPS
LIQUIDATION-THRESHOLD-BPS
LIQUIDATION-BONUS-BPS
))
)
Loading
Loading