Skip to content

Commit 6e94c8e

Browse files
feat(stx-pox-delegate): authorize and revoke PoX-4 stacking delegation
Wraps canonical pox-4 functions (delegate-stx, revoke-delegate-stx) with double-confirmation, balance precheck, and refusal guards. Mainnet proof tx: 0x66324f0515fca8d9abcb9bf1a20102892fedd16b22ee2020de976f10a8b43e45
1 parent 6550034 commit 6e94c8e

3 files changed

Lines changed: 537 additions & 0 deletions

File tree

skills/stx-pox-delegate/AGENT.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
name: stx-pox-delegate-agent
3+
skill: stx-pox-delegate
4+
description: "Authorize and revoke PoX-4 stacking delegation on Stacks mainnet with explicit double-confirmation."
5+
---
6+
7+
# Agent Behavior — STX PoX Delegate
8+
9+
## Decision order
10+
11+
1. Run `doctor` first. If Hiro is unreachable or no wallet is present, stop and surface the blocker.
12+
2. Run `status` to determine current delegation state. If a delegation already exists and the user wants to redelegate, the agent must `revoke` first (delegate-stx fails if a delegation already exists).
13+
3. For any delegate target the user has not previously confirmed, present the dry-run preview (skill returns `status: blocked` without `--confirm`) and require explicit user confirmation before re-running with `--confirm`.
14+
4. After broadcast, persist the txid and report the explorer URL. Do not assume success — the on-chain status may be `abort_by_post_condition` or similar even after a successful broadcast.
15+
16+
## Guardrails
17+
18+
- **Never broadcast without `--confirm`.** The skill enforces this; the agent must not socially engineer around it by passing `--confirm` automatically. If the human did not type "confirm," do not pass the flag.
19+
- **Never expose the wallet password in logs, args echo, error messages, or chat history.** Pass `--password` via env var or stdin where possible; never inline-print the option string.
20+
- **Never delegate to an unfamiliar principal without explicit user awareness.** A misdirected delegation lets that principal stack the user's STX in their own reward cycles. If the agent has no record that the user has previously approved this `--delegate-to` address, it must surface the address and require fresh confirmation.
21+
- **Refuse if status shows an existing active delegation** unless the user has explicitly asked to redelegate (in which case the agent runs `revoke` first, waits for confirmation, then runs `delegate`).
22+
- **Refuse to chain broadcasts.** If `delegate` has just broadcast and the next instruction is another write, wait for the prior tx to confirm (or be rejected) before composing the next one. Mempool replacement is not the agent's concern to handle automatically.
23+
24+
## On error
25+
26+
- Log the JSON error payload verbatim to the user.
27+
- Do not retry silently. If the error is a balance-precheck failure, surface the actual balance vs. the requested amount and ask the user to top up or reduce.
28+
- If the broadcast fails with a network error after the wallet has been unlocked, do NOT retry without explicit user confirmation — the tx may have actually been accepted by a different node.
29+
30+
## On success
31+
32+
- Confirm the on-chain result by polling `https://api.hiro.so/extended/v1/tx/<txid>` until `tx_status` is no longer `pending`.
33+
- If `tx_status` is `success`, report the cycle in which delegation becomes effective (next reward cycle boundary).
34+
- If `tx_status` is anything else (`abort_by_post_condition`, `abort_by_response`, `dropped_*`), surface the failure and do not claim success.
35+
- Update any agent state tracking the user's delegation status; future `status` calls should reflect the new on-chain state.

skills/stx-pox-delegate/SKILL.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
name: stx-pox-delegate
3+
description: "Authorize and revoke PoX-4 stacking delegation on Stacks mainnet — the write companion to read-only stacking monitors."
4+
metadata:
5+
author: "lekanbams"
6+
author-agent: "Lekan Bams"
7+
user-invocable: "true"
8+
arguments: "doctor | status | delegate --delegate-to <addr> --amount-stx <n> [--until-burn-ht <h>] [--confirm] | revoke [--confirm]"
9+
entry: "stx-pox-delegate/stx-pox-delegate.ts"
10+
requires: "wallet, signing, settings"
11+
tags: "l2, write, mainnet-only, requires-funds, infrastructure"
12+
---
13+
14+
# STX PoX Delegate
15+
16+
## What it does
17+
18+
Broadcasts `delegate-stx` and `revoke-delegate-stx` calls to the canonical Stacks PoX-4 contract (`SP000000000000000000002Q6VF78.pox-4`). This is the write side of stacking delegation: solo stacking requires 80k+ STX, so most STX holders earn PoX yield by delegating to a stacking pool. This skill performs that authorization on-chain.
19+
20+
This is the write companion to the read-only `stacking-delegation` skill in this registry — that one monitors, this one acts.
21+
22+
## Why agents need it
23+
24+
An autonomous yield agent on Stacks needs a programmatic way to opt into PoX-4 stacking via a pool. Without this, every delegation step requires a human wallet popup. With it, the agent can: check current delegation, decide whether to (re)delegate based on signals from monitors like `stacking-delegation` or `hodlmm-risk`, and broadcast the authorization with explicit safety gates.
25+
26+
## Safety notes
27+
28+
- **Mainnet write.** Calls a public PoX-4 function. Real STX gas is spent (~0.001 STX per tx).
29+
- **Funds stay in your wallet.** `delegate-stx` is a non-custodial signaling call — it authorizes a pool to lock up to `amount-ustx` of your STX in a future `delegate-stack-stx` call, but does not move or lock funds at delegate time. The agent that runs the actual stacking is the principal you pass via `--delegate-to`. Choose pools you trust.
30+
- **Double-confirmation required.** `delegate` and `revoke` are no-ops without `--confirm`; without it the skill returns a dry-run preview. This is intentional — accidental delegation to a malicious principal would let that principal stack your STX without further consent.
31+
- **Post-conditions.** `delegate-stx` is a no-asset Clarity call (it touches no fungible balances at signing time), so the broadcast uses `PostConditionMode.Deny` with an empty `postConditions` array. This is correct for this specific call shape — there is nothing to constrain — and is documented here to preempt the standard reviewer flag against empty-deny on swaps.
32+
- **Refusal conditions.** The skill refuses if: amount < 1 STX (micro-amount), amount > 95% of wallet balance (no gas left), `--until-burn-ht` is in the past or within 10 burn blocks, `--delegate-to` parses as something other than a Stacks principal, or wallet balance is below 0.01 STX (insufficient gas).
33+
- **No fabricated identifiers.** The pox-4 contract address is the canonical Stacks built-in (`SP000000000000000000002Q6VF78.pox-4`); the function signature is verified against `https://api.hiro.so/v2/contracts/interface/SP000000000000000000002Q6VF78/pox-4`.
34+
35+
## Commands
36+
37+
| Command | Description |
38+
|---------|-------------|
39+
| `doctor` | Hiro API health, wallet presence, current PoX cycle. No password needed. |
40+
| `status` | Read-only `get-delegation-info` for the active wallet. No password needed. |
41+
| `delegate` | **Write.** Calls `pox-4.delegate-stx`. Requires `--delegate-to`, `--amount-stx`, `--password`, `--confirm`. |
42+
| `revoke` | **Write.** Calls `pox-4.revoke-delegate-stx`. Requires `--password`, `--confirm`. |
43+
44+
```bash
45+
# Preflight
46+
bun run skills/stx-pox-delegate/stx-pox-delegate.ts doctor
47+
bun run skills/stx-pox-delegate/stx-pox-delegate.ts status
48+
49+
# Dry-run preview (no broadcast)
50+
bun run skills/stx-pox-delegate/stx-pox-delegate.ts delegate \
51+
--delegate-to SP21YTSM60CAY6D011EZVEVNKXVW8FVZE198XEFFP \
52+
--amount-stx 1 \
53+
--password "$WALLET_PASSWORD"
54+
55+
# Real broadcast
56+
bun run skills/stx-pox-delegate/stx-pox-delegate.ts delegate \
57+
--delegate-to SP21YTSM60CAY6D011EZVEVNKXVW8FVZE198XEFFP \
58+
--amount-stx 1 \
59+
--password "$WALLET_PASSWORD" \
60+
--confirm
61+
62+
# Revoke active delegation
63+
bun run skills/stx-pox-delegate/stx-pox-delegate.ts revoke \
64+
--password "$WALLET_PASSWORD" \
65+
--confirm
66+
```
67+
68+
## Output contract
69+
70+
All outputs are JSON to stdout. Errors go to stderr.
71+
72+
**Success:**
73+
```json
74+
{
75+
"status": "success",
76+
"action": "delegate",
77+
"data": {
78+
"txid": "0x...",
79+
"explorer": "https://explorer.hiro.so/txid/0x...?chain=mainnet",
80+
"sender": "SP...",
81+
"delegateTo": "SP...",
82+
"amountUstx": "1000000",
83+
"untilBurnHt": null
84+
},
85+
"error": null
86+
}
87+
```
88+
89+
**Dry-run (no `--confirm`):**
90+
```json
91+
{
92+
"status": "blocked",
93+
"action": "delegate",
94+
"data": { "preview": { ... }, "next": "rerun with --confirm to broadcast" },
95+
"error": null
96+
}
97+
```
98+
99+
**Error:**
100+
```json
101+
{ "error": "descriptive message" }
102+
```
103+
104+
## Known constraints
105+
106+
- **Mainnet only.** PoX-4 testnet uses a different deployer; this skill targets mainnet `SP000000000000000000002Q6VF78.pox-4`.
107+
- **Wallet must be the AIBTC MCP wallet** at `~/.aibtc/wallets/<id>/keystore.json` (AES-256-GCM + scrypt format), or `STACKS_PRIVATE_KEY` env var for automation.
108+
- **No `--pox-addr` parameter exposed.** The optional BTC reward address is a power-user feature most pools set themselves; surfacing it here would let an agent send rewards to an arbitrary BTC address, which is a footgun. Add via a follow-up if a pool requires it.
109+
- **No `delegate-stack-stx`.** That call is what pools execute against your delegation; it is not what an end-user delegator broadcasts. This skill covers the delegator side only.

0 commit comments

Comments
 (0)