Skip to content

feat: add zest-asset-deposit-primitive (BFF Skills Comp Day 23 winner by @macbotmini-eng)#358

Merged
whoabuddy merged 2 commits intoaibtcdev:mainfrom
diegomey:bff-comp/zest-asset-deposit-primitive
Apr 30, 2026
Merged

feat: add zest-asset-deposit-primitive (BFF Skills Comp Day 23 winner by @macbotmini-eng)#358
whoabuddy merged 2 commits intoaibtcdev:mainfrom
diegomey:bff-comp/zest-asset-deposit-primitive

Conversation

@diegomey
Copy link
Copy Markdown
Contributor

zest-asset-deposit-primitive

Author: @macbotmini-eng (Hex Stallion)
Competition PR: BitflowFinance/bff-skills#574
PR Title: 📑PR: feat(zest-asset-deposit-primitive): add Zest V2 deposit primitive


This skill was submitted to the AIBTC x Bitflow Skills Pay the Bills competition, reviewed by judging agents and the human panel, and approved as a Day 23 winner.

Frontmatter has been converted to the aibtcdev/skills metadata: convention. Command paths updated to match this repo root-level skill layout.

Files

  • zest-asset-deposit-primitive/SKILL.md — Skill definition with AIBTC-format frontmatter
  • zest-asset-deposit-primitive/AGENT.md — Agent behavior rules and guardrails
  • zest-asset-deposit-primitive/zest-asset-deposit-primitive.ts — TypeScript implementation

Attribution

Original author: @macbotmini-eng. The metadata.author field in SKILL.md preserves their attribution permanently.


Automated by BFF Skills Bot on merge of PR #574.

Copy link
Copy Markdown
Contributor

@arc0btc arc0btc left a comment

Choose a reason for hiding this comment

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

Adds zest-asset-deposit-primitive — a standalone Zest V2 collateral-add primitive with a clean doctor→status→plan→run workflow and strict safety gates.

What works well:

  • PostConditionMode.Deny + explicit postconditions on all FT paths — the right default for a write primitive that moves funds
  • The pre-flight stack is comprehensive: zero-shares block, pending-tx depth check, live egroup mask validation, ABI verification, balance + gas reserve — no single check is skipped
  • --confirm=DEPOSIT guard blocks broadcast before signer resolution, so a misconfigured env can never accidentally fire a tx
  • Clean JSON output contract across all four commands; BlockedError pattern keeps structured error fields consistent and machine-readable
  • Attribution in frontmatter (metadata.author) preserves the competition winner's identity permanently — good practice for ported skills

[question] Vault-share postcondition direction (zest-asset-deposit-primitive.ts)

For both FT and STX deposit paths, the third postcondition is:

Pc.principal(context.wallet).willSendLte(context.amount).ft(context.asset.vault, context.asset.vaultAssetName)

willSendLte asserts the principal's balance decreases by at most N. In a collateral deposit the wallet receives vault shares (balance increases), so this postcondition would be trivially satisfied and provide no real protection. The protective constraint here should be on the vault (or mint source), not the wallet.

Is this intentional — perhaps Zest V2's share mechanics involve a transient wallet-side transfer before mint? The sBTC proof transaction is the source of truth here, so if the proof passed with this pattern I'd trust it — but a short comment explaining why wallet.willSendLte rather than vault.willSendLte would help future maintainers reading the postcondition block.


[question] STX deposit path has no mainnet proof (SKILL.md ## Known constraints)

Already acknowledged — STX support is implemented but not yet proven. Worth flagging: if the vault-share postcondition direction is a subtle issue, the STX path (which uses the same postcondition builder) would amplify it since STX has no proof to catch it. Recommend gating STX in canDeposit: false until a mainnet proof transaction exists, or at minimum adding a runtime warning when asset.symbol === "STX".


[suggestion] readTimeoutMs() called per-operation (zest-asset-deposit-primitive.ts)

readTimeoutMs() parses and validates process.env.ZEST_READ_TIMEOUT_MS on every invocation — once in withTimeout, once in fetchJson for the AbortController. For a short-lived CLI this is fine, but the redundant parsing could cause confusing behavior if the env var is invalid: the error would surface mid-operation rather than at startup. Extracting once at module load or at the top of each command handler makes the failure earlier and the hot path cheaper.

const READ_TIMEOUT_MS = (() => {
  const raw = process.env.ZEST_READ_TIMEOUT_MS;
  if (!raw) return DEFAULT_READ_TIMEOUT_MS;
  const parsed = Number(raw);
  if (!Number.isInteger(parsed) || parsed <= 0) throw new Error("ZEST_READ_TIMEOUT_MS must be a positive integer");
  return parsed;
})();

Then replace readTimeoutMs() calls with READ_TIMEOUT_MS.


Code quality notes:

  • [nit] For STX deposits, balanceOk = balance >= amount is technically redundant: gasOk = stxBalance >= amount + feeUstx + minGasReserve is strictly tighter. If gasOk fails it always means balanceOk could still be true (not enough for fee+reserve but enough for bare deposit) — so the ordering in runPlan/runConfirmed correctly surfaces INSUFFICIENT_STX_BALANCE for the fee case. The check isn't wrong, just worth a comment since it looks like dead code for STX on first read.
  • [nit] buildPostConditionSummary and buildPostConditions share the same branching logic (asset.symbol === "STX" → 3 conditions, else → 3 conditions). They'll drift if the postcondition set changes. Consider building the summary from the postconditions array directly to keep them in sync.

Operational context: Arc runs Zest V2 supply operations nightly (sBTC collateral, v0-4-market). The contract addresses match what we see in production (SP1A27KFY4XERQCCRCARCYD1CC5N7M6688BSYADJ7.v0-4-market, v0-vault-sbtc). The egroup validation is important — we've hit egroup rejections on wallet states that seem valid but aren't supported by the live mask registry. Glad to see that's gated here rather than left to the broadcast to surface.

macbotmini-eng and others added 2 commits April 30, 2026 00:01
…winner)

Submitted by @macbotmini-eng (Hex Stallion) via the AIBTC x Bitflow Skills Pay the Bills competition.

Competition PR: BitflowFinance/bff-skills#574
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

4 participants