Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
73 changes: 73 additions & 0 deletions skills/ststx-liquid-stacker/AGENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
name: ststx-liquid-stacker-agent
skill: ststx-liquid-stacker
description: "Executes StackingDAO liquid-stacking deposits, withdrawal-ticket creation, and matured-ticket claims with in-code ratio-slippage, amount-cap, reserve-floor, cooldown, and confirmation-token guardrails."
---

# Agent Behavior — stSTX Liquid Stacker

## Purpose

Use this skill to move STX in or out of StackingDAO's liquid-stacking position (stSTX) only when the request is well-specified, mainnet, within safety caps, and explicitly confirmed.

## Decision order

1. Run `doctor` first on any wallet you have not recently verified. If it fails, surface the blocker and stop.
2. Run `status` to read current STX/stSTX balances, the live `stx-per-ststx` ratio, and any outstanding withdrawal-ticket NFTs. Compare the current ratio to what the caller expected — if it has drifted, surface the drift and ask for updated input before proceeding.
3. Only use `run --action deposit` when:
- wallet is on mainnet
- STX balance covers `--amount-ustx` plus `--reserve-ustx` plus `--min-gas-reserve-ustx`
- current rate is within `--max-slippage-bps` of `--expected-rate-ustx-per-ststx`
- cooldown has cleared
- `--confirm=STACK` is present
4. Only use `run --action init-withdraw` when:
- wallet is on mainnet
- stSTX balance covers `--amount-ststx`
- current rate is within `--max-slippage-bps` of `--expected-rate-ustx-per-ststx`
- cooldown has cleared
- `--confirm=UNSTACK` is present
5. Only use `run --action withdraw` when:
- the NFT ticket exists and belongs to the active wallet
- the ticket's `cycle` field is strictly less than the current PoX cycle read from the chain
- `--confirm=CLAIM` is present

## Guardrails

- Never broadcast without `AIBTC_WALLET_PASSWORD` and the matching confirm token for the action.
- Never deposit more than `--max-deposit-ustx`; never withdraw more than `--max-withdraw-ststx`.
- Never let the STX balance fall below `--reserve-ustx` after a deposit.
- Never let the STX gas balance fall below `--min-gas-reserve-ustx` after any broadcast.
- Never proceed when the live rate deviates from the caller's expected rate by more than `--max-slippage-bps`.
- Never attempt `withdraw` on a ticket whose cycle has not matured — the on-chain call would revert but the broadcast still costs gas.
- Never retry silently on error; surface the JSON error payload and wait for operator input.
- Never mutate the spend/cooldown ledger without a confirmed broadcast plan.
- Treat the emitted `mcp_command` as `post_condition_mode: "deny"` — any unexpected token flow aborts the transaction.

## Blocked conditions — surface and stop

- wallet cannot be resolved or is not on mainnet
- STX or stSTX balance insufficient for the requested action
- rate slippage exceeds configured tolerance
- cooldown is active
- withdraw ticket not yet matured, not found, or owned by a different principal
- confirmation token missing or does not match the action
- doctor check failed and was not re-run

## On error

- Log the error payload from stdout as-is.
- Do not retry automatically.
- Surface the `error.next` guidance to the user and wait for explicit instruction.

## On success

- Capture the emitted `mcp_command` block and pass it to the AIBTC MCP wallet for signing + broadcast.
- After broadcast, record the returned txid and persist it in the local spend ledger.
- Run `status` again to confirm the on-chain state matches the expected outcome (balance delta, new NFT ticket id, or ticket redemption).
- Report completion with the txid and explorer URL.

## Operational notes

- This is a write skill with three distinct actions. Each action has its own confirmation token to prevent cross-action mistakes.
- StackingDAO contract principals are configurable via flags so the skill survives protocol version rolls without a rewrite.
- The skill is deliberately standalone: it emits a broadcast-ready plan rather than attempting to sign in-process, matching the pattern used by the already-merged `sbtc-yield-maximizer`.
138 changes: 138 additions & 0 deletions skills/ststx-liquid-stacker/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---
name: ststx-liquid-stacker
description: "Liquid stack STX via StackingDAO — deposit STX for stSTX, initiate batched withdrawals, and claim matured STX with code-enforced ratio-slippage, amount caps, reserve floors, cooldown, mainnet-only, and PostConditionMode.Deny safety gates."
metadata:
author: "IamHarrie-Labs"
author-agent: "Liquid Horizon"
user-invocable: "false"
arguments: "doctor | status | run"
entry: "ststx-liquid-stacker/ststx-liquid-stacker.ts"
requires: "wallet, signing, settings"
tags: "defi, write, mainnet-only, requires-funds, l2"
---

# stSTX Liquid Stacker

## What it does

Executes the three StackingDAO liquid-stacking write flows that no skill in the registry currently covers: `deposit` (STX → stSTX), `init-withdraw` (burn stSTX to mint a withdrawal NFT ticket), and `withdraw` (claim STX from a matured ticket). Every write path enforces ratio-slippage, amount caps, reserve floors, cooldown, mainnet-only, and `PostConditionMode.Deny` in code — not just documentation.

## Why agents need it

Liquid stacking is a core Stacks DeFi primitive: it turns illiquid 1–2-week PoX stacking cycles into a liquid receipt token (stSTX) that earns native yield while remaining composable. The existing `stacking-delegation` skill handles native PoX delegation only; this skill closes the liquid-stacking gap so agents can (1) convert idle STX into yield-bearing stSTX on demand, (2) queue withdrawals when capital is needed for other strategies, and (3) reclaim matured STX without manual ticket tracking.

This is complementary to the existing `sbtc-yield-maximizer` (which routes idle sBTC) and `zest-yield-manager` (which handles Zest supply) — together they give agents full-coverage STX, stSTX, and sBTC yield execution across the three largest Stacks yield surfaces.

## Safety notes

- **Writes to chain.** `run deposit`, `run init-withdraw`, and `run withdraw` all broadcast real transactions on Stacks mainnet via the AIBTC MCP wallet.
- **Mainnet only.** StackingDAO core contracts referenced by default are mainnet deployments; the skill refuses to execute against testnet.
- **Irreversible.** `init-withdraw` burns stSTX and mints a withdrawal NFT. It cannot be reversed within the cycle. `withdraw` spends a matured ticket; once redeemed it is gone.
- **Ratio slippage enforced.** Every `deposit` and `init-withdraw` reads `get-stx-per-ststx` from the reserve before execution and refuses to broadcast if the current rate deviates from the caller-provided `--expected-rate-ustx-per-ststx` by more than `--max-slippage-bps`.
- **Amount caps enforced.** `--max-deposit-ustx`, `--max-withdraw-ststx`, and a hard-coded per-operation safety ceiling are applied in code. The wallet retains at least `--reserve-ustx` after the deposit path.
- **Gas reserve enforced.** The wallet must keep at least `--min-gas-reserve-ustx` for transaction fees post-broadcast.
- **Cooldown enforced.** A per-action cooldown (`--cooldown-seconds`) prevents accidental double-execution.
- **Confirmation token required.** Write paths refuse to broadcast without the matching `--confirm=STACK`, `--confirm=UNSTACK`, or `--confirm=CLAIM` token.
- **PostConditionMode.Deny.** Every broadcast transaction is built with `PostConditionMode.Deny` — any unexpected token movement aborts the transaction on-chain.
- **Cycle awareness on withdraw.** `run withdraw --id <nft-id>` reads the ticket's `cycle` field and refuses to broadcast until the StackingDAO current cycle has advanced past it.

## Commands

### doctor
Verifies wallet resolution, STX balance, stSTX balance, StackingDAO contract reachability, current stSTX/STX ratio, and cooldown state.

```bash
bun run skills/ststx-liquid-stacker/ststx-liquid-stacker.ts doctor
```

### status
Read-only snapshot: live balances, current `stx-per-ststx` ratio, any outstanding withdrawal NFT tickets the wallet holds, and which cycle each ticket matures in.

```bash
bun run skills/ststx-liquid-stacker/ststx-liquid-stacker.ts status
```

### run
Executes one of the three write flows. Action is explicit — the skill never infers intent.

```bash
# Deposit STX → mint stSTX
bun run skills/ststx-liquid-stacker/ststx-liquid-stacker.ts run \
--action deposit \
--amount-ustx 1000000 \
--expected-rate-ustx-per-ststx 1050000 \
--max-slippage-bps 50 \
--confirm=STACK

# Burn stSTX → mint withdrawal NFT ticket
bun run skills/ststx-liquid-stacker/ststx-liquid-stacker.ts run \
--action init-withdraw \
--amount-ststx 1000000 \
--expected-rate-ustx-per-ststx 1050000 \
--max-slippage-bps 50 \
--confirm=UNSTACK

# Claim matured withdrawal ticket
bun run skills/ststx-liquid-stacker/ststx-liquid-stacker.ts run \
--action withdraw \
--id 1234 \
--confirm=CLAIM
```

## Output contract

All outputs are JSON to stdout.

**Success (broadcast confirmed):**

```json
{
"status": "success",
"action": "Deposit broadcast and confirmed on Stacks mainnet",
"data": {
"operation": "deposit",
"wallet": "SP...",
"txid": "abc123...",
"explorer_url": "https://explorer.hiro.so/txid/0xabc123...?chain=mainnet",
"tx_status": "success",
"amount_ustx": 1000000,
"live_stx_per_ststx": "1865545",
"estimated_ststx_minted": "536036",
"slippage_bps_observed": 0
},
"error": null
}
```

**Blocked:**

```json
{
"status": "blocked",
"action": "aborted",
"data": null,
"error": {
"code": "rate_slippage_exceeded",
"message": "Current rate 1880000 deviates 78 bps from expected 1865545 (max 50 bps)",
"next": "Re-read rate with `status` and re-submit with an updated --expected-rate or a wider --max-slippage-bps"
}
}
```

**Error:**

```json
{
"status": "error",
"action": "aborted",
"data": null,
"error": { "code": "broadcast_failed", "message": "...", "next": "..." }
}
```

## Known constraints

- StackingDAO contracts are trait-based; the skill passes the canonical `reserve-v1`, `commission-v2`, `staking-v0`, and `direct-helpers-v4` principals as `contractPrincipalCV` arguments. These are overridable via flags so the skill survives protocol-version rolls.
- Withdrawal tickets are NFTs minted by `stacking-dao-core-v2`; maturity is measured in PoX cycles (~2 weeks each on mainnet). The skill reads the current cycle from the PoX contract to gate `withdraw` claims.
- Requires live STX for deposits and live stSTX for withdrawals; `doctor` blocks on insufficient balance.
- `AIBTC_WALLET_PASSWORD` must be set for `run` — the skill unlocks the AIBTC wallet manager to sign and broadcast transactions directly.
Loading
Loading