{"id":"0e886e09-7030-4ba5-b70b-33e7db9355a5","entityType":"agent","slug":"clawhub-mrsirg97-rgb-torchliquidationbot","name":"Torch Liquidation Bot","canonicalUrl":"https://www.xpersona.co/agent/clawhub-mrsirg97-rgb-torchliquidationbot","canonicalPath":"/agent/clawhub-mrsirg97-rgb-torchliquidationbot","generatedAt":"2026-10-09T19:13:57.467Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":null},"description":"Autonomous vault-based liquidation keeper for Torch Market lending on Solana. Scans all migrated tokens for underwater loan positions (LTV > 65%) using the S...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 2K downloads reported by the source. Last updated 4/15/2026.","installCommand":"clawhub skill install kn7a0ff82yxwmqsge7kh9kdgqn80hpbf:torchliquidationbot","sourceUrl":"https://clawhub.ai/mrsirg97-rgb/torchliquidationbot","homepage":"https://clawhub.ai/mrsirg97-rgb/torchliquidationbot","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/mrsirg97-rgb/torchliquidationbot","kind":"source"}],"safetyScore":84,"overallRank":62,"popularityScore":66,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Torch Liquidation Bot technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":null},"stars":null,"forks":null,"downloads":2031,"packageName":null,"latestVersion":"4.0.4","tractionLabel":"2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-02-28T19:24:04.014Z","emptyReason":null},"lastUpdatedAt":"2026-04-15T00:45:39.800Z","lastCrawledAt":"2026-02-28T19:24:04.014Z","lastIndexedAt":null,"nextCrawlAt":"2026-03-01T19:24:04.014Z","lastVerifiedAt":null,"highlights":[{"version":"4.0.4","createdAt":"2026-02-28T15:16:50.792Z","changelog":"No user-facing changes detected in this release. Version bump only. - Version number updated to 4.0.4. - No changes to files, functionality, or documentation content. - latest sdk v3.7.23 bundled","fileCount":22,"zipByteSize":96042},{"version":"4.0.3","createdAt":"2026-02-27T21:52:12.295Z","changelog":"No functional or user-facing changes; version number updated. - Bumped version to 4.0.3 in metadata for consistency. - No code or documentation changes detected. - fix metadata parse issue","fileCount":22,"zipByteSize":94814},{"version":"4.0.2","createdAt":"2026-02-27T21:45:57.758Z","changelog":"- Version bump to 4.0.2 with metadata updates (version and install block). - Updated NPM install instructions/metadata from 4.0.0 to 4.0.1. - No code or functional changes; documentation and metadata only. - added withTimeout helper","fileCount":null,"zipByteSize":null},{"version":"4.0.1","createdAt":"2026-02-27T21:28:43.047Z","changelog":"torchliquidationbot v4.0.1 - Updated skill compatibility section to clarify environment variable requirements. - Explicitly states that disable-model-invocation is set to true, requiring explicit user initiation. - Minor metadata corrections (version field corrected; rewording in compatibility and metadata fields). - No functional or implementation changes to code.","fileCount":null,"zipByteSize":null},{"version":"4.0.0","createdAt":"2026-02-27T21:21:46.427Z","changelog":"Version 4.0.0 introduces major efficiency and scanning improvements: - Upgraded to torchsdk v3.7.22. - Liquidation scanning now uses the SDK's bulk loan scanner (`getAllLoanPositions`), performing a single RPC call per token to retrieve and sort all loan positions by health. - Greatly reduces RPC load and increases scanning speed compared to previous versions. - Documentation and SKILL metadata updated for improved environment variable handling and clarity. - Added explicit support for optional `SOLANA_PRIVATE_KEY` (agent keypair remains disposable by default). - New documentation file (`verification.md`) added.","fileCount":null,"zipByteSize":null},{"version":"3.0.2","createdAt":"2026-02-13T15:34:23.366Z","changelog":"- Bump version to 3.0.2. - Updated package metadata to reference version 3.0.2 in all relevant fields (package, version, install instructions). - Enforce consistency for clarity across all metadata and files, do not want any confusion.","fileCount":null,"zipByteSize":null},{"version":"3.0.1","createdAt":"2026-02-13T14:54:43.105Z","changelog":"- Added VAULT_CREATOR as a required environment variable for improved configuration safety and clarity. - Updated all documentation and examples to consistently use SOLANA_RPC_URL and VAULT_CREATOR (instead of obsolete RPC_URL). - Minor install instructions and usage examples updated to match new environment requirements. - No code or logic changes; environment variable requirements clarified and enforced.","fileCount":null,"zipByteSize":null},{"version":"3.0.0","createdAt":"2026-02-13T14:28:25.299Z","changelog":"**Major Update: liquidator bot upgraded from read-only scanner to full autonomous liquidation keeper with vault-based custody and agent safety.** - Adds full liquidation functionality—bot now discovers underwater loans (LTV > 65%) and executes liquidation transactions automatically via a linked Torch Vault. - Introduces secure agent architecture: generates a disposable keypair on each start; agent holds no assets and can be unlinked at any time. - All assets (SOL and collateral) flow through a human-controlled vault, separating agent control from principal assets. - Updates environment variables: requires `SOLANA_RPC_URL` and `VAULT_CREATOR` (vault owner); agent wallet is generated automatically unless a private key is provided. - Source architecture is refactored and modularized (core logic now under `lib/kit/`), leveraging the newest torchsdk v3.2.3. - Documentation updated to reflect operational keeper role, agent/vault custody model, and precise setup instructions.","fileCount":null,"zipByteSize":null}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install kn7a0ff82yxwmqsge7kh9kdgqn80hpbf:torchliquidationbot","setupComplexity":"low","setupSteps":["Install using `clawhub skill install kn7a0ff82yxwmqsge7kh9kdgqn80hpbf:torchliquidationbot` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/mrsirg97-rgb/torchliquidationbot before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-mrsirg97-rgb-torchliquidationbot/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-mrsirg97-rgb-torchliquidationbot/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-mrsirg97-rgb-torchliquidationbot/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-mrsirg97-rgb-torchliquidationbot/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-mrsirg97-rgb-torchliquidationbot/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-mrsirg97-rgb-torchliquidationbot/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-09T19:13:57.463Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-mrsirg97-rgb-torchliquidationbot/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-mrsirg97-rgb-torchliquidationbot/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-mrsirg97-rgb-torchliquidationbot/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-mrsirg97-rgb-torchliquidationbot/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":null},"readme":"Skill: Torch Liquidation Bot\n\nOwner: mrsirg97-rgb\n\nSummary: Autonomous vault-based liquidation keeper for Torch Market lending on Solana. Scans all migrated tokens for underwater loan positions (LTV > 65%) using the S...\n\nTags: latest:4.0.4\n\nVersion history:\n\nv4.0.4 | 2026-02-28T15:16:50.792Z | user\n\nNo user-facing changes detected in this release. Version bump only.\n\n- Version number updated to 4.0.4.\n- No changes to files, functionality, or documentation content.\n- latest sdk v3.7.23 bundled\n\nv4.0.3 | 2026-02-27T21:52:12.295Z | user\n\nNo functional or user-facing changes; version number updated.\n\n- Bumped version to 4.0.3 in metadata for consistency.\n- No code or documentation changes detected.\n- fix metadata parse issue\n\nv4.0.2 | 2026-02-27T21:45:57.758Z | user\n\n- Version bump to 4.0.2 with metadata updates (version and install block).\n- Updated NPM install instructions/metadata from 4.0.0 to 4.0.1.\n- No code or functional changes; documentation and metadata only.\n- added withTimeout helper\n\nv4.0.1 | 2026-02-27T21:28:43.047Z | user\n\ntorchliquidationbot v4.0.1\n\n- Updated skill compatibility section to clarify environment variable requirements.\n- Explicitly states that disable-model-invocation is set to true, requiring explicit user initiation.\n- Minor metadata corrections (version field corrected; rewording in compatibility and metadata fields).\n- No functional or implementation changes to code.\n\nv4.0.0 | 2026-02-27T21:21:46.427Z | user\n\nVersion 4.0.0 introduces major efficiency and scanning improvements:\n\n- Upgraded to torchsdk v3.7.22.\n- Liquidation scanning now uses the SDK's bulk loan scanner (`getAllLoanPositions`), performing a single RPC call per token to retrieve and sort all loan positions by health.\n- Greatly reduces RPC load and increases scanning speed compared to previous versions.\n- Documentation and SKILL metadata updated for improved environment variable handling and clarity.\n- Added explicit support for optional `SOLANA_PRIVATE_KEY` (agent keypair remains disposable by default).\n- New documentation file (`verification.md`) added.\n\nv3.0.2 | 2026-02-13T15:34:23.366Z | user\n\n- Bump version to 3.0.2.\n- Updated package metadata to reference version 3.0.2 in all relevant fields (package, version, install instructions).\n- Enforce consistency for clarity across all metadata and files, do not want any confusion.\n\nv3.0.1 | 2026-02-13T14:54:43.105Z | user\n\n- Added VAULT_CREATOR as a required environment variable for improved configuration safety and clarity.\n- Updated all documentation and examples to consistently use SOLANA_RPC_URL and VAULT_CREATOR (instead of obsolete RPC_URL).\n- Minor install instructions and usage examples updated to match new environment requirements.\n- No code or logic changes; environment variable requirements clarified and enforced.\n\nv3.0.0 | 2026-02-13T14:28:25.299Z | user\n\n**Major Update: liquidator bot upgraded from read-only scanner to full autonomous liquidation keeper with vault-based custody and agent safety.**\n\n- Adds full liquidation functionality—bot now discovers underwater loans (LTV > 65%) and executes liquidation transactions automatically via a linked Torch Vault.\n- Introduces secure agent architecture: generates a disposable keypair on each start; agent holds no assets and can be unlinked at any time.\n- All assets (SOL and collateral) flow through a human-controlled vault, separating agent control from principal assets.\n- Updates environment variables: requires `SOLANA_RPC_URL` and `VAULT_CREATOR` (vault owner); agent wallet is generated automatically unless a private key is provided.\n- Source architecture is refactored and modularized (core logic now under `lib/kit/`), leveraging the newest torchsdk v3.2.3.\n- Documentation updated to reflect operational keeper role, agent/vault custody model, and precise setup instructions.\n\nv2.1.2 | 2026-02-11T17:50:34.690Z | user\n\n- Updated version to 2.1.2 (no code changes).\n- Clarified that read-only metadata fetches use Irys gateway and CoinGecko (for SOL/USD price) in addition to Solana RPC.\n- Noted that `@coral-xyz/anchor` and `@solana/spl-token` remain as transitive dependencies in the bundled torchsdk.\n- Expanded permissions/network section to specify no secrets or RPC_URL are ever forwarded beyond the expected endpoints.\n\nv2.1.1 | 2026-02-11T17:45:06.077Z | user\n\n- Removed unused SDK files (quotes.js, said.js, transactions.js) from lib/torchsdk/.\n- Bundled torchsdk is now stripped to only include the methods used by lib/bot/, reducing package size and attack surface.\n- Updated documentation to clarify that the only external dependency is @solana/web3.js and the bundled torchsdk contains only read-only methods.\n- No changes to functionality; remains fully read-only and requires only an RPC endpoint.\n\nv2.1.0 | 2026-02-11T17:32:07.636Z | user\n\n- Torch SDK (v2.0.0) is now fully bundled within the skill package in lib/torchsdk/ for auditability—no external torchsdk or agentkit npm dependencies required at runtime.\n- Compatibility metadata updated: the only external npm dependency is @solana/web3.js; all other core code is bundled and verifiable on disk.\n- Skill version updated to 2.1.0.\n- Skill remains read-only; no changes to functionality or environment variables.\n\nv2.0.9 | 2026-02-11T17:23:53.528Z | user\n\nv2.0.9: Source-bundled release — all bot source included in skill package\n\n- Full bot source code is now bundled in lib/bot/ for built-in auditability; no npm install is needed for core functionality.\n- Documentation updated to clarify that all logic is included, and users can review every claim on disk.\n- npm install remains supported and optional (for those preferring npm/GitHub workflows).\n- No wallet, signing, or state mutation functionality added; still strictly read-only.\n\nv2.0.8 | 2026-02-11T01:12:18.780Z | user\n\n- Bumped version to 2.0.8.\n- Updated all install and version references to 2.0.8.\n- Added agent.json metadata file.\n- No changes to skill functionality or architecture.\n\nv2.0.7 | 2026-02-10T19:21:28.530Z | user\n\n## v2.0.7\n\n- OpenClaw metadata updated: `RPC_URL` is now explicitly declared as a required environment variable.\n- `disable-model-invocation` moved to top-level frontmatter for stronger enforcement in the registry.\n- Install instructions improved to reference version 2.0.7 and OpenClaw-specific install commands.\n- No changes to code or functionality; compatibility and auditability remain unchanged.\n\nv2.0.6 | 2026-02-10T18:51:56.865Z | user\n\nVersion 2.0.6\n\n- Added metadata links to Solana agent kit and npm pages for SDK dependencies.\n- Updated compatibility and metadata to set disableModelInvocation: true, preventing autonomous agent invocation.\n- Improved documentation with detailed security, installation audit, and supply chain verification instructions.\n- Clarified npm version pinning and explicit install command for added safety.\n- No changes to the codebase or functionality; documentation and metadata updates only.\n\nv2.0.5 | 2026-02-10T18:33:38.352Z | user\n\n- Updated description for improved clarity and to highlight support for optional MINT and LOG_LEVEL parameters.  \n- No code or functional changes; documentation only.\n- skill now correctly points to the readonly bot source code on github: https://github.com/mrsirg97-rgb/torch-liquidation-bot-ro, and the npm package has been updated to point at this too: https://www.npmjs.com/package/torch-liquidation-bot, all with the correct v2.0.5 to match\n- Version bump to 2.0.5.\n\nv2.0.4 | 2026-02-10T17:00:09.543Z | user\n\n- Version bump to 2.0.4; no code or documentation changes detected.\n- ensure all metadata and readmes reflect the same v2.0.4 aligned with the npm package and readonly github\n- All functionality, config, and requirements remain unchanged.\n- all torchsdk code is open source and available for public use\n\nv2.0.3 | 2026-02-10T16:51:06.903Z | user\n\n- Documentation and metadata updates to clarify required and optional environment variables.  \n- Added explicit listing of required_env and optional_env in metadata for easier setup.\n- Provided details about RPC_URL handling, including security notes for API keys.\n- Expanded \"Compatibility\" section to highlight Node.js requirement and add security/auditability notes.\n- No code changes; version bump reflects improved clarity and onboarding for users.\n\nv2.0.2 | 2026-02-10T16:41:14.962Z | user\n\n- Updated metadata and documentation to clarify read-only, info-only usage and minimal attack surface.\n- All references to wallet-dependent features and code paths were removed in earlier 2.x releases; this version maintains strict read-only support.\n- Updated repository links and project description to reflect a separate read-only codebase.\n- Reduced codebase to 4 files (~60 lines) with no dormant or unused bot code or dependencies.\n- Only minimal dependencies remain (`@solana/web3.js`, `torchsdk`).\n- No changes to API, setup, or user-facing functionality.\n\nv2.0.0 | 2026-02-10T16:09:41.176Z | user\n\nv2.0.0 is a breaking change: Now fully read-only — all wallet-dependent bot features removed. npm package has also been updated to reflect these changes.\n\n- Removed all wallet handling, signing, and transaction/automation code (bot mode, watch mode, auto-repay, liquidations) from the active codepath.\n- Only \"info\" (read-only) mode is available; no more MODE or WALLET env vars.\n- The skill now only scans and displays lending market parameters; no state changes or on-chain actions are possible.\n- All Solana private key/API risks eliminated; no key is ever decoded, imported, or present in memory.\n- Dormant source files related to bot automation are retained but not imported or reachable.\n- Compatible with Solana RPC via the torchsdk’s read-only functions only.\n\nv1.0.9 | 2026-02-10T15:44:52.099Z | user\n\nVersion 1.0.9\n\n- Updated descriptions to clarify that bot and watch modes are optional, carry inherent risks, and are disabled unless explicitly configured.\n- Default info mode (read-only) is now more prominently recommended; documentation stresses no state changes in this mode.\n- Metadata and compatibility statements updated to warn about risks and reiterate that non-read-only modes are off by default.\n\nv1.0.8 | 2026-02-10T15:37:57.285Z | user\n\nVersion 1.0.8\n\n- Updated version metadata from 1.0.7 to 1.0.8.\n- No user-facing functionality or documentation changes detected.\n- include note regarding audit location in open source github repository: https://github.com/mrsirg97-rgb/torch-liquidation-bot\n\nv1.0.7 | 2026-02-10T15:33:41.762Z | user\n\nVersion 1.0.7\n\n- Updated metadata to clarify read-only, no-wallet-required default mode and explicitly document security practices.\n- Added third-party audit reference confirming no telemetry, key safety, and zero off-chain state changes in default mode.\n- Clarified documentation for environment variables and modes to highlight wallet/keypair handling and security boundaries.\n- No code changes included in this release.\n\nv1.0.6 | 2026-02-10T15:06:58.870Z | user\n\ntorch-liquidation-bot 1.0.6\n\n- Bumped version metadata to 1.0.6.\n- No code or documentation file changes detected.\n- remove agent kit ref, not needed. only torchsdk used here: https://github.com/mrsirg97-rgb/torchsdk\n\nv1.0.5 | 2026-02-10T14:04:04.900Z | user\n\nTorch Liquidation Bot 1.0.5\n\n- Added new agentkit metadata link (solana-agent-kit-torch-market) to SKILL.md.\n- Updated version number in metadata to 1.0.5.\n- No functional or code changes—documentation metadata only.\n\nv1.0.4 | 2026-02-09T03:36:06.575Z | user\n\n**Summary: v1.0.4 makes \"info\" mode the default and fully read-only; wallet is now only needed for bot or watch modes.**\n\n- \"info\" mode is now the default and requires no wallet; provides a read-only dashboard for all tokens or a specific token.\n- Updated skill description and documentation to clarify that wallet/keypair is only necessary for liquidation or watch actions.\n- Compatibility notes now emphasize safe npm distribution and no wallet/signing needs in read-only mode.\n- Clarified network/permissions section: no outbound connections except Solana RPC and SAID API, no remote code fetching.\n- Documentation around run commands and environment variables now defaults to info-mode usage.\n\nv1.0.3 | 2026-02-09T03:29:01.009Z | user\n\nVersion 1.0.3\n\n- Updated metadata version to 1.0.3.\n- include source code link\n\nv1.0.2 | 2026-02-09T02:28:43.044Z | user\n\n- Added detailed security model, including npm-only distribution, private key handling, and no external code fetching.\n- Updated compatibility: skill now runs directly from npm, with no wallet required for info mode.\n- Provided new examples for programmatic usage and clarified run commands to use npx with the npm package.\n- Added npm package link to metadata for easier installation.\n- Enhanced documentation for security, usage, and deployment.\n\nv1.0.0 | 2026-02-09T02:16:50.015Z | user\n\nInitial release of torch-liquidation-bot.\n\n- Monitors all Torch Market lending positions across all tokens.\n- Profiles borrower wallets, analyzes risk, and predicts likely-to-fail loans.\n- Executes profitable liquidations automatically when positions become eligible.\n- Offers three modes: bot (full liquidation), info (lending parameters), and watch (personal loan monitoring).\n- Includes a four-factor loan risk scoring system (LTV, price trend, wallet risk, interest burden).\n- Requires only a Solana RPC endpoint and wallet, with no external API server needed.\n\nArchive index:\n\nArchive v4.0.4: 22 files, 96042 bytes\n\nFiles: agent.json (6139b), audit.md (21316b), design.md (12278b), lib/kit/config.js (1577b), lib/kit/index.js (7088b), lib/kit/types.js (182b), lib/kit/utils.js (1987b), lib/torchsdk/constants.js (6651b), lib/torchsdk/ephemeral.js (1330b), lib/torchsdk/gateway.js (1581b), lib/torchsdk/index.js (7875b), lib/torchsdk/program.js (13486b), lib/torchsdk/quotes.js (3751b), lib/torchsdk/said.js (3617b), lib/torchsdk/tokens.js (35336b), lib/torchsdk/torch_market.json (224847b), lib/torchsdk/transactions.js (66086b), lib/torchsdk/types.js (144b), SKILL.md (19734b), verification.md (18057b), whitepaper.md (50580b), _meta.json (138b)\n\nFile v4.0.4:SKILL.md\n\n---\nname: torch-liquidation-bot\nversion: \"4.0.4\"\ndescription: Autonomous vault-based liquidation keeper for Torch Market lending on Solana. Scans all migrated tokens for underwater loan positions (LTV > 65%) using the SDK's built-in bulk loan scanner (getAllLoanPositions), builds and executes liquidation transactions through a Torch Vault, and collects a 10% collateral bonus. The agent keypair is generated in-process -- disposable, holds nothing of value. All SOL and collateral tokens route through the vault. The human principal creates the vault, funds it, links the agent, and retains full control. Built on torchsdk v3.7.22 and the Torch Market protocol.\nlicense: MIT\ndisable-model-invocation: true\nrequires:\n  env:\n    - name: SOLANA_RPC_URL\n      required: true\n    - name: VAULT_CREATOR\n      required: true\n    - name: SOLANA_PRIVATE_KEY\n      required: false\nmetadata:\n  clawdbot:\n    requires:\n      env:\n        - name: SOLANA_RPC_URL\n          required: true\n        - name: VAULT_CREATOR\n          required: true\n        - name: SOLANA_PRIVATE_KEY\n          required: false\n  openclaw:\n    requires:\n      env:\n        - name: SOLANA_RPC_URL\n          required: true\n        - name: VAULT_CREATOR\n          required: true\n        - name: SOLANA_PRIVATE_KEY\n          required: false\n    install:\n      - id: npm-torch-liquidation-bot\n        kind: npm\n        package: torch-liquidation-bot@^4.0.2\n        flags: []\n        label: \"Install Torch Liquidation Bot (npm, optional -- SDK is bundled in lib/torchsdk/ and bot source is bundled under lib/kit on clawhub)\"\n  author: torch-market\n  version: \"4.0.4\"\n  clawhub: https://clawhub.ai/mrsirg97-rgb/torch-liquidation-bot\n  kit-source: https://github.com/mrsirg97-rgb/torch-liquidation-kit\n  website: https://torch.market\n  program-id: 8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeT\n  keywords:\n    - solana\n    - defi\n    - liquidation\n    - liquidation-bot\n    - liquidation-keeper\n    - collateral-lending\n    - vault-custody\n    - ai-agents\n    - agent-wallet\n    - agent-safety\n    - treasury-lending\n    - bonding-curve\n    - fair-launch\n    - token-2022\n    - raydium\n    - community-treasury\n    - protocol-rewards\n    - solana-agent-kit\n    - escrow\n    - anchor\n    - pda\n    - on-chain\n    - autonomous-agent\n    - keeper-bot\n    - torch-market\n  categories:\n    - solana-protocols\n    - defi-primitives\n    - lending-markets\n    - agent-infrastructure\n    - custody-solutions\n    - liquidation-keepers\ncompatibility: >-\n  REQUIRED: SOLANA_RPC_URL (HTTPS Solana RPC endpoint)\n  REQUIRED: VAULT_CREATOR (vault creator pubkey).\n  OPTIONAL: SOLANA_PRIVATE_KEY -- the bot generates a fresh disposable keypair in-process if not provided. The agent wallet holds nothing of value (~0.01 SOL for gas). All liquidation proceeds (collateral tokens) route to the vault. The vault can be created and funded entirely by the human principal. \n  This skill sets disable-model-invocation: true -- it must not be invoked autonomously without explicit user initiation.\n  The Torch SDK is bundled in lib/torchsdk/ -- all source included for full auditability. No API server dependency.\n  The vault can be created and funded entirely by the human principal -- the agent never needs access to funds.\n---\n\n# Torch Liquidation Bot\n\nYou're here because you want to run a liquidation keeper on Torch Market -- and you want to do it safely.\n\nEvery migrated token on Torch has a built-in lending market. Holders lock tokens as collateral and borrow SOL from the community treasury (up to 50% LTV, 2% weekly interest). When a loan's LTV crosses 65%, it becomes liquidatable. Anyone can liquidate it and collect a **10% bonus** on the collateral value.\n\nThat's where this bot comes in.\n\nIt scans every migrated token's lending market using the SDK's bulk loan scanner (`getAllLoanPositions`) -- one RPC call per token returns all active positions pre-sorted by health. When it finds one that's underwater, it liquidates it through your vault. The collateral tokens go to your vault ATA. The SOL cost comes from your vault. The agent wallet that signs the transaction holds nothing.\n\n**This is not a read-only scanner.** This is a fully operational keeper that generates its own keypair, verifies vault linkage, and executes liquidation transactions autonomously in a continuous loop.\n\n---\n\n## How It Works\n\n```\n┌──────────────────────────────────────────────────────────┐\n│                  LIQUIDATION LOOP                          │\n│                                                           │\n│  1. Discover migrated tokens (getTokens)                  │\n│  2. For each token, scan all loans (getAllLoanPositions)   │\n│     — single RPC call, returns positions sorted by health │\n│     — liquidatable → at_risk → healthy                    │\n│  3. Skip tokens with no active loans                      │\n│  4. For each liquidatable position:                       │\n│     → buildLiquidateTransaction(vault=creator)            │\n│     → sign with agent keypair                             │\n│     → submit and confirm                                  │\n│     → break when health != 'liquidatable' (pre-sorted)    │\n│  5. Sleep SCAN_INTERVAL_MS, repeat                        │\n│                                                           │\n│  All SOL comes from vault. All collateral goes to vault.  │\n│  Agent wallet holds nothing. Vault is the boundary.       │\n└──────────────────────────────────────────────────────────┘\n```\n\n### The Agent Keypair\n\nThe bot generates a fresh `Keypair` in-process on every startup. No private key file. No environment variable (unless you want to provide one). The keypair is disposable -- it signs transactions but holds nothing of value.\n\nOn first run, the bot checks if this keypair is linked to your vault. If not, it prints the exact SDK call you need to link it:\n\n```\n--- ACTION REQUIRED ---\nagent wallet is NOT linked to the vault.\nlink it by running (from your authority wallet):\n\n  buildLinkWalletTransaction(connection, {\n    authority: \"<your-authority-pubkey>\",\n    vault_creator: \"<your-vault-creator>\",\n    wallet_to_link: \"<agent-pubkey>\"\n  })\n\nthen restart the bot.\n-----------------------\n```\n\nLink it from your authority wallet (hardware wallet, multisig, whatever you use). The agent never needs the authority's key. The authority never needs the agent's key. They share a vault, not keys.\n\n### The Vault\n\nThis is the same Torch Vault from the full Torch Market protocol. It holds all assets -- SOL and tokens. The agent is a disposable controller.\n\nWhen the bot liquidates a position:\n- **SOL cost** comes from the vault (the liquidation payment to cover the borrower's debt)\n- **Collateral tokens** go to the vault's associated token account (ATA)\n- **10% bonus** means the collateral received is worth 10% more than the SOL spent\n\nThe human principal retains full control:\n- `withdrawVault()` — pull SOL at any time\n- `withdrawTokens(mint)` — pull collateral tokens at any time\n- `unlinkWallet(agent)` — revoke agent access instantly\n\nIf the agent keypair is compromised, the attacker gets dust and vault access that you revoke in one transaction.\n\n---\n\n## Getting Started\n\n### 1. Install\n\n```bash\nnpm install torch-liquidation-bot@4.0.2\n```\n\nOr use the bundled source from ClawHub — the Torch SDK is included in `lib/torchsdk/` and the bot source is in `lib/kit/`.\n\n### 2. Create and Fund a Vault (Human Principal)\n\nFrom your authority wallet:\n\n```typescript\nimport { Connection } from \"@solana/web3.js\";\nimport {\n  buildCreateVaultTransaction,\n  buildDepositVaultTransaction,\n} from \"./lib/torchsdk/index.js\";\n\nconst connection = new Connection(process.env.SOLANA_RPC_URL);\n\n// Create vault\nconst { transaction: createTx } = await buildCreateVaultTransaction(connection, {\n  creator: authorityPubkey,\n});\n// sign and submit with authority wallet...\n\n// Fund vault with SOL for liquidations\nconst { transaction: depositTx } = await buildDepositVaultTransaction(connection, {\n  depositor: authorityPubkey,\n  vault_creator: authorityPubkey,\n  amount_sol: 5_000_000_000, // 5 SOL\n});\n// sign and submit with authority wallet...\n```\n\n### 3. Run the Bot\n\n```bash\nVAULT_CREATOR=<your-vault-creator-pubkey> SOLANA_RPC_URL=<rpc-url> npx torch-liquidation-bot\n```\n\nOn first run, the bot prints the agent keypair and instructions to link it. Link it from your authority wallet, then restart.\n\n### 4. Configuration\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `SOLANA_RPC_URL` | **Yes** | -- | Solana RPC endpoint (HTTPS). Fallback: `RPC_URL` |\n| `VAULT_CREATOR` | **Yes** | -- | Vault creator pubkey |\n| `SOLANA_PRIVATE_KEY` | No | -- | Disposable controller keypair (base58 or JSON byte array). If omitted, generates fresh keypair on startup (recommended) |\n| `SCAN_INTERVAL_MS` | No | `30000` | Milliseconds between scan cycles (min 5000) |\n| `LOG_LEVEL` | No | `info` | `debug`, `info`, `warn`, `error` |\n\n---\n\n## Architecture\n\n```\npackages/bot/src/\n├── index.ts    — entry point: keypair generation, vault verification, scan loop\n├── config.ts   — loadConfig(): validates SOLANA_RPC_URL, VAULT_CREATOR, SOLANA_PRIVATE_KEY, SCAN_INTERVAL_MS, LOG_LEVEL\n├── types.ts    — BotConfig, LogLevel interfaces\n└── utils.ts    — sol(), bpsToPercent(), withTimeout(), createLogger()\n```\n\nThe bot is ~192 lines of TypeScript. It does one thing: find underwater loans and liquidate them through the vault.\n\n### Dependencies\n\n| Package | Version | Purpose |\n|---------|---------|---------|\n| `@solana/web3.js` | 1.98.4 | Solana RPC, keypair, transaction |\n| `torchsdk` | 3.7.22 | Token queries, bulk loan scanning, liquidation builder, vault queries |\n\nTwo runtime dependencies. Both pinned to exact versions. No `^` or `~` ranges.\n\n---\n\n## Vault Safety Model\n\nThe same seven guarantees from the Torch Market vault apply here:\n\n| Property | Guarantee |\n|----------|-----------|\n| **Full custody** | Vault holds all SOL and all collateral tokens. Agent wallet holds nothing. |\n| **Closed loop** | Liquidation SOL comes from vault, collateral tokens go to vault. No leakage to agent. |\n| **Authority separation** | Creator (immutable PDA seed) vs Authority (transferable admin) vs Controller (disposable signer). |\n| **One link per wallet** | Agent can only belong to one vault. PDA uniqueness enforces this on-chain. |\n| **Permissionless deposits** | Anyone can top up the vault. Hardware wallet deposits, agent liquidates. |\n| **Instant revocation** | Authority can unlink the agent at any time. One transaction. |\n| **Authority-only withdrawals** | Only the vault authority can withdraw SOL or tokens. The agent cannot extract value. |\n\n### The Closed Economic Loop for Liquidations\n\n| Direction | Flow |\n|-----------|------|\n| **SOL out** | Vault → Borrower's treasury debt (covers the loan) |\n| **Tokens in** | Borrower's collateral → Vault ATA (at 10% discount) |\n| **Net** | Vault receives collateral worth 110% of SOL spent |\n\nThe bot is profitable by design — every successful liquidation returns more value than it costs. The profit accumulates in the vault. The authority withdraws when ready.\n\n---\n\n## Lending Parameters\n\n| Parameter | Value |\n|-----------|-------|\n| Max LTV | 50% |\n| Liquidation Threshold | 65% |\n| Interest Rate | 2% per epoch (~weekly) |\n| Liquidation Bonus | 10% |\n| Utilization Cap | 70% of treasury |\n| Min Borrow | 0.1 SOL |\n\nCollateral value is calculated from Raydium pool reserves. The 0.03% Token-2022 transfer fee (3 bps, immutable per mint) applies on collateral deposits and withdrawals.\n\n### When Liquidations Happen\n\nA loan becomes liquidatable when its LTV exceeds 65%. This happens when:\n- The token price drops (collateral value decreases relative to debt)\n- Interest accrues (debt grows at 2% per epoch)\n- A combination of both\n\nThe bot checks `position.health === 'liquidatable'` — the SDK calculates LTV from on-chain Raydium reserves and the loan's accrued debt.\n\n---\n\n## SDK Functions Used\n\nThe bot uses a focused subset of the Torch SDK:\n\n| Function | Purpose |\n|----------|---------|\n| `getTokens(connection, { status: 'migrated' })` | Discover all tokens with active lending markets |\n| `getAllLoanPositions(connection, mint)` | Bulk scan all active loans for a token — returns positions pre-sorted by health (liquidatable first), fetches pool price once |\n| `getVault(connection, creator)` | Verify vault exists on startup |\n| `getVaultForWallet(connection, wallet)` | Verify agent is linked to vault |\n| `buildLiquidateTransaction(connection, params)` | Build the liquidation transaction (vault-routed) |\n| `confirmTransaction(connection, sig, wallet)` | Confirm transaction on-chain via RPC (verifies signer, checks Torch instructions) |\n\n### Scan and Liquidate Pattern\n\n```typescript\nimport { getTokens, getAllLoanPositions, buildLiquidateTransaction } from 'torchsdk'\n\n// 1. Discover migrated tokens\nconst { tokens } = await getTokens(connection, { status: 'migrated', sort: 'volume', limit: 50 })\n\nfor (const token of tokens) {\n  // 2. Bulk scan — one RPC call per token, positions sorted liquidatable-first\n  const { positions } = await getAllLoanPositions(connection, token.mint)\n\n  for (const pos of positions) {\n    if (pos.health !== 'liquidatable') break  // pre-sorted, done\n\n    // 3. Build and execute through vault\n    const { transaction, message } = await buildLiquidateTransaction(connection, {\n      mint: token.mint,           // token with the underwater loan\n      liquidator: agentPubkey,    // agent wallet (signer)\n      borrower: pos.borrower,     // borrower being liquidated\n      vault: vaultCreator,        // vault creator pubkey (SOL from vault, tokens to vault)\n    })\n    transaction.sign(agentKeypair)\n    await connection.sendRawTransaction(transaction.serialize())\n  }\n}\n```\n\n---\n\n## Log Output\n\n```\n=== torch liquidation bot ===\nagent wallet: 7xK9...\nvault creator: 4yN2...\nscan interval: 30000ms\n\n[09:15:32] INFO  vault found — authority=8cpW...\n[09:15:32] INFO  agent wallet linked to vault — starting scan loop\n[09:15:32] INFO  treasury: 5.0000 SOL\n[09:15:33] INFO  LIQUIDATABLE | SDKTEST | borrower=3AyZ... | LTV=72.50% | owed=0.5000 SOL\n[09:15:34] INFO  LIQUIDATED | SDKTEST | borrower=3AyZ... | sig=4vK9... | collateral received at 10% discount\n```\n\n---\n\n## Signing & Key Safety\n\n**The vault is the security boundary, not the key.**\n\nThe agent keypair is generated fresh on every startup with `Keypair.generate()`. It holds ~0.01 SOL for gas fees. If the key is compromised, the attacker gets:\n- Dust (the gas SOL)\n- Vault access that the authority revokes in one transaction\n\nThe agent never needs the authority's private key. The authority never needs the agent's private key. They share a vault, not keys.\n\n### Rules\n\n1. **Never ask a user for their private key or seed phrase.** The vault authority signs from their own device.\n2. **Never log, print, store, or transmit private key material.** The agent keypair exists only in runtime memory.\n3. **Never embed keys in source code or logs.** The agent pubkey is printed — the secret key is never exposed.\n4. **Use a secure RPC endpoint.** Default to a private RPC provider. Never use an unencrypted HTTP endpoint for mainnet transactions.\n\n### RPC Timeout\n\nAll SDK calls are wrapped with a 30-second timeout (`withTimeout` in utils.ts). A hanging or unresponsive RPC endpoint cannot stall the bot indefinitely — the call rejects, the error is caught by the scan loop, and the bot continues to the next token or cycle.\n\n### Environment Variables\n\n| Variable | Required | Purpose |\n|----------|----------|---------|\n| `SOLANA_RPC_URL` / `RPC_URL` | **Yes** | Solana RPC endpoint (HTTPS) |\n| `VAULT_CREATOR` | **Yes** | Vault creator pubkey — identifies which vault the bot operates through |\n| `SOLANA_PRIVATE_KEY` | No | Optional — if omitted, the bot generates a fresh keypair on startup (recommended) |\n\n### External Runtime Dependencies\n\nThe SDK contains functions that make outbound HTTPS requests to external services. The bot's runtime path contacts **two** of them:\n\n| Service | Purpose | When Called | Bot Uses? |\n|---------|---------|------------|-----------|\n| **CoinGecko** (`api.coingecko.com`) | SOL/USD price for display | Token queries with USD pricing | Yes — via `getTokens()`, `getToken()` |\n| **Irys Gateway** (`gateway.irys.xyz`) | Token metadata fallback (name, symbol, image) | `getToken()` when on-chain metadata URI points to Irys | Yes — via `getTokens()` |\n| **SAID Protocol** (`api.saidprotocol.com`) | Agent identity verification and trust tier lookup | `verifySaid()` only | **No** — the bot does not call `verifySaid()` |\n\n**`confirmTransaction()` does NOT contact SAID.** Despite living in the SDK's `said.js` module, it only calls `connection.getParsedTransaction()` (Solana RPC) to verify the transaction succeeded on-chain and determine the event type. No data is sent to any external service.\n\nNo credentials are sent to CoinGecko or Irys. All requests are read-only GET. If either service is unreachable, the SDK degrades gracefully. No private key material is ever transmitted to any external endpoint.\n\n---\n\n## Testing\n\nRequires [Surfpool](https://github.com/nicholasgasior/surfpool) running a mainnet fork:\n\n```bash\nsurfpool start --network mainnet --no-tui\npnpm test\n```\n\n**Test result:** 9 passed, 0 failed (Surfpool mainnet fork).\n\n| Test | What It Validates |\n|------|-------------------|\n| Connection | RPC reachable |\n| getTokens | Discovers migrated tokens |\n| getLendingInfo | Reads lending state for all tokens |\n| getAllLoanPositions | Bulk scans active loans, verifies sort order (liquidatable first) |\n| getToken | Token metadata, price, status |\n| getVaultForWallet | Vault link returns null for unlinked wallet |\n| In-process keypair | No external key required |\n\n---\n\n## Error Codes\n\n- `VAULT_NOT_FOUND`: No vault exists for this creator\n- `WALLET_NOT_LINKED`: Agent wallet is not linked to the vault\n- `NOT_LIQUIDATABLE`: Position LTV below liquidation threshold\n- `NO_ACTIVE_LOAN`: No open loan for this wallet/token\n- `INVALID_MINT`: Token not found\n\n---\n\n## Links\n\n- Liquidation Kit (source): [github.com/mrsirg97-rgb/torch-liquidation-kit](https://github.com/mrsirg97-rgb/torch-liquidation-kit)\n- Liquidation Bot (npm): [npmjs.com/package/torch-liquidation-bot](https://www.npmjs.com/package/torch-liquidation-bot)\n- Torch SDK (bundled): `lib/torchsdk/` -- included in this skill\n- Torch SDK (source): [github.com/mrsirg97-rgb/torchsdk](https://github.com/mrsirg97-rgb/torchsdk)\n- Torch SDK (npm): [npmjs.com/package/torchsdk](https://www.npmjs.com/package/torchsdk)\n- Torch Market (protocol skill): [clawhub.ai/mrsirg97-rgb/torchmarket](https://clawhub.ai/mrsirg97-rgb/torchmarket)\n- Whitepaper: [torch.market/whitepaper.md](https://torch.market/whitepaper.md)\n- Security Audit: [torch.market/audit.md](https://torch.market/audit.md)\n- Website: [torch.market](https://torch.market)\n- Program ID: `8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeT`\n\n---\n\nThis bot exists because Torch lending markets need keepers. When loans go underwater and nobody liquidates them, the treasury takes the loss. Active liquidation keepers protect treasury health and earn a profit doing it. The vault makes it safe — all value stays in the escrow, all risk is bounded, and the human principal keeps the keys.\n\nFile v4.0.4:_meta.json\n\n{\n  \"ownerId\": \"kn7a0ff82yxwmqsge7kh9kdgqn80hpbf\",\n  \"slug\": \"torchliquidationbot\",\n  \"version\": \"4.0.4\",\n  \"publishedAt\": 1772291810792\n}\n\nFile v4.0.4:audit.md\n\n# Torch Liquidation Bot — Security Audit\n\n**Audit Date:** February 27, 2026\n**Auditor:** Claude Opus 4.6 (Anthropic)\n**Bot Version:** 4.0.2\n**Kit Version:** 2.0.0\n**SDK Version:** torchsdk 3.7.22\n**On-Chain Program:** `8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeT` (V3.7.7, 27 instructions)\n**Language:** TypeScript\n**Test Result:** 9 passed, 0 failed (Surfpool mainnet fork)\n\n---\n\n## Table of Contents\n\n1. [Executive Summary](#executive-summary)\n2. [Scope](#scope)\n3. [Methodology](#methodology)\n4. [What Changed (v3.0.2 → v4.0.0)](#what-changed-v302--v400)\n5. [Keypair Safety Review](#keypair-safety-review)\n6. [Vault Integration Review](#vault-integration-review)\n7. [Scan Loop Security](#scan-loop-security)\n8. [Configuration Validation](#configuration-validation)\n9. [Dependency Analysis](#dependency-analysis)\n10. [Threat Model](#threat-model)\n11. [Findings](#findings)\n12. [Resolved Findings from v3.0.2](#resolved-findings-from-v302)\n13. [Conclusion](#conclusion)\n\n---\n\n## Executive Summary\n\nThis audit covers the Torch Liquidation Bot v4.0.0, an autonomous keeper that scans Torch Market lending positions and liquidates underwater loans through a Torch Vault. The bot was reviewed for key safety, vault integration correctness, error handling, and dependency surface.\n\nThe major change in v4.0.0 is the replacement of the N+1 scan pattern (`getLendingInfo` → `getHolders` → per-holder `getLoanPosition`) with a single `getAllLoanPositions()` call per token. This reduces RPC calls from 2 + N per token to 1 per token, eliminates the 20-holder discovery ceiling from the previous version, and leverages the SDK's pre-sorted output to break early once all liquidatable positions are processed.\n\nThe bot remains **vault-first** (all value routes through the vault PDA), **disposable-key** (agent keypair generated in-process, holds nothing), and **single-purpose** (scan and liquidate only — no trading, borrowing, or token creation).\n\n### Overall Assessment\n\n| Category | Rating | Notes |\n|----------|--------|-------|\n| Key Safety | **PASS** | In-process `Keypair.generate()`, no key files, no key logging |\n| Vault Integration | **PASS** | `vault` param correctly passed to `buildLiquidateTransaction` |\n| Error Handling | **PASS** | Cycle-level catch, per-token try/catch, per-liquidation try/catch, 30s RPC timeout |\n| Config Validation | **PASS** | Required env vars checked, scan interval floored at 5000ms |\n| Dependencies | **MINIMAL** | 2 runtime deps, both pinned exact |\n| Supply Chain | **LOW RISK** | No post-install hooks, no remote code fetching |\n\n### Finding Summary\n\n| Severity | Count |\n|----------|-------|\n| Critical | 0 |\n| High | 0 |\n| Medium | 0 |\n| Low | 0 (1 resolved) |\n| Informational | 2 |\n\n---\n\n## Scope\n\n### Files Reviewed\n\n| File | Lines | Role |\n|------|-------|------|\n| `packages/bot/src/index.ts` | 192 | Entry point: keypair load/generate, vault check, scan loop |\n| `packages/bot/src/config.ts` | 36 | Environment variable validation |\n| `packages/bot/src/types.ts` | 13 | BotConfig and LogLevel interfaces |\n| `packages/bot/src/utils.ts` | 58 | Formatting helpers, logger, base58 decoder, RPC timeout |\n| `packages/bot/tests/test_e2e.ts` | 248 | E2E test suite |\n| `packages/bot/package.json` | 37 | Dependencies and scripts |\n| `packages/bot/tsconfig.json` | 20 | TypeScript configuration |\n| **Total** | **~604** | |\n\n### SDK Cross-Reference\n\nThe bot relies on `torchsdk@3.7.22` for all on-chain interaction. The SDK was independently audited (see [Torch SDK Audit](https://torch.market/audit.md)). This audit focuses on the bot's usage of the SDK, not the SDK internals.\n\nKey SDK changes since v3.2.3:\n- `getAllLoanPositions()` added in v3.7.17 — bulk loan scanning via `getProgramAccounts`\n- V33 buyback removal (v3.7.22) — `buildAutoBuybackTransaction` deleted\n- Lending utilization cap increased 50% → 70% (v3.7.22)\n- Protocol fee split changed to 90% treasury / 10% dev (V32)\n- IDL updated to v3.7.7 (27 instructions, down from 28)\n\n---\n\n## Methodology\n\n1. **Line-by-line source review** of all 4 bot source files\n2. **Delta analysis** against v3.0.2 audit — focused review of changed code paths\n3. **Keypair lifecycle analysis** — generation, usage, exposure surface\n4. **Vault integration verification** — correct params passed to SDK\n5. **Error handling analysis** — crash paths, retry behavior, log safety\n6. **Dependency audit** — runtime deps, dev deps, post-install hooks\n7. **E2E test review** — coverage, assertions, sort order validation\n8. **Configuration attack surface** — environment variable handling\n\n---\n\n## What Changed (v3.0.2 → v4.0.0)\n\n### Scan Pattern Rewrite\n\nThe core scan loop was rewritten to use `getAllLoanPositions()`:\n\n**Before (v3.0.2):**\n```\ngetTokens → for each token:\n  getLendingInfo     → skip if no active loans\n  getHolders         → get up to 20 holders\n  getLoanPosition    → check each holder individually\n  buildLiquidateTransaction → if liquidatable\n```\n\n**After (v4.0.0):**\n```\ngetTokens → for each token:\n  getAllLoanPositions → all active loans, sorted by health\n  break              → stop at first non-liquidatable (pre-sorted)\n  buildLiquidateTransaction → for each liquidatable\n```\n\n### Import Changes\n\n**Removed:** `getLendingInfo`, `getHolders`, `getLoanPosition`, `type LendingInfo`, `type LoanPositionInfo`\n**Added:** `getAllLoanPositions`, `type LoanPositionWithKey`\n\n### Impact\n\n| Metric | v3.0.2 | v4.0.0 |\n|--------|--------|--------|\n| RPC calls per token | 2 + N (lending + holders + per-holder position) | 1 (`getAllLoanPositions`) |\n| Max discoverable borrowers | 20 (`getTokenLargestAccounts` limit) | Unlimited (scans all LoanPosition PDAs) |\n| Source lines (index.ts) | 210 | 187 |\n| SDK imports | 10 | 7 |\n| Error isolation levels | 4 (cycle, token, holder, liquidation) | 3 (cycle, token, liquidation) |\n\nThe reduction from 4 to 3 error isolation levels is correct — the holder level is no longer needed because `getAllLoanPositions` returns positions directly.\n\n---\n\n## Keypair Safety Review\n\n### Generation\n\nUnchanged from v3.0.2. The keypair is created in `main()` via one of two paths:\n\n1. **Default (recommended):** `Keypair.generate()` — fresh Ed25519 keypair from system entropy\n2. **Optional:** `SOLANA_PRIVATE_KEY` env var — loaded as JSON byte array or base58, decoded via `Keypair.fromSecretKey()`\n\n```typescript\n// index.ts:137-153 — load or generate agent keypair\nlet agentKeypair: Keypair\nif (config.privateKey) {\n  // try JSON byte array, then base58\n  agentKeypair = Keypair.fromSecretKey(...)\n} else {\n  agentKeypair = Keypair.generate()\n}\n```\n\nThe keypair is:\n\n- **Not persisted** — exists only in runtime memory (unless user provides `SOLANA_PRIVATE_KEY`)\n- **Not exported** — `agentKeypair` is local to `main()`, not in the public API\n- **Not logged** — only the public key is printed (`agentKeypair.publicKey.toBase58()`)\n- **Not transmitted** — the secret key never leaves the process\n\n### Usage\n\nThe keypair is used in exactly two places:\n\n1. **Public key extraction** (startup logging, vault link check, liquidation params) — safe, public key only\n2. **Transaction signing** (`transaction.sign(agentKeypair)` at index.ts:86) — local signing only\n\n### Risk Assessment\n\nThe keypair holds ~0.01 SOL for gas. If the process memory is dumped, the attacker gets:\n- A disposable key with dust\n- Vault access that the authority revokes in one transaction\n\n**Verdict:** Key safety is correct. No key material leaks from the process. Unchanged from v3.0.2.\n\n---\n\n## Vault Integration Review\n\n### Startup Verification\n\nUnchanged from v3.0.2:\n\n```typescript\nconst vault = await getVault(connection, config.vaultCreator)  // index.ts:142\nif (!vault) throw new Error(...)\n\nconst link = await getVaultForWallet(connection, agentKeypair.publicKey.toBase58())  // index.ts:149\nif (!link) { /* print instructions, exit */ }\n```\n\nThe bot verifies both vault existence and agent linkage before entering the scan loop. If either fails, the process exits with clear instructions.\n\n### Liquidation Transaction\n\n```typescript\nconst { transaction, message } = await buildLiquidateTransaction(connection, {\n  mint: token.mint,\n  liquidator: agentKeypair.publicKey.toBase58(),\n  borrower: position.borrower,   // now from getAllLoanPositions result\n  vault: vaultCreator,            // index.ts:83\n})\n```\n\nThe `vault` parameter is correctly passed. The `borrower` field now comes from `LoanPositionWithKey.borrower` (returned by `getAllLoanPositions`) instead of `holder.address` (from `getHolders`). Both are base58 public key strings — the type is unchanged.\n\nPer the SDK audit, the `vault` param causes:\n- Vault PDA derived from `vaultCreator` (`[\"torch_vault\", creator]`)\n- Wallet link PDA derived from `liquidator` (`[\"vault_wallet\", wallet]`)\n- SOL debited from vault, collateral tokens credited to vault ATA\n\n**Verdict:** Vault integration is correct. All value routes through the vault PDA.\n\n---\n\n## Scan Loop Security\n\n### Error Isolation\n\n**Cycle level** — never crashes the loop (unchanged):\n```typescript\nwhile (true) {\n  try {\n    await scanAndLiquidate(connection, log, config.vaultCreator, agentKeypair)\n  } catch (err: any) {\n    log('error', `scan cycle error: ${err.message}`)\n  }\n  await new Promise(resolve => setTimeout(resolve, config.scanIntervalMs))\n}\n```\n\n**Token level** — skip tokens where `getAllLoanPositions` fails:\n```typescript\nfor (const token of tokens) {\n  let positions: LoanPositionWithKey[]\n  try {\n    const result = await getAllLoanPositions(connection, token.mint)\n    positions = result.positions\n  } catch {\n    continue  // lending not enabled for this token\n  }\n\n  if (positions.length === 0) continue\n```\n\n**Liquidation level** — each liquidation attempt is individually caught:\n```typescript\ntry {\n  const { transaction, message } = await buildLiquidateTransaction(...)\n  transaction.sign(agentKeypair)\n  const signature = await connection.sendRawTransaction(transaction.serialize())\n  await confirmTransaction(...)\n  log('info', `LIQUIDATED | ...`)\n} catch (err: any) {\n  log('warn', `LIQUIDATION FAILED | ...`)\n}\n```\n\n### Break Optimization\n\n```typescript\n// index.ts:67-68\nfor (const position of positions) {\n  if (position.health !== 'liquidatable') break\n```\n\nThis is correct because `getAllLoanPositions` returns positions sorted by health: `liquidatable → at_risk → healthy`. Once the first non-liquidatable position is encountered, all remaining positions are also non-liquidatable. The E2E test (test_e2e.ts:159-174) independently validates this sort order.\n\n**Verdict:** Error handling is robust. The bot degrades gracefully at every level. The break optimization is correct and validated by tests.\n\n---\n\n## Configuration Validation\n\nUnchanged from v3.0.2.\n\n### Required Variables\n\n| Variable | Validation | Failure Mode |\n|----------|-----------|--------------|\n| `SOLANA_RPC_URL` | Must be set (fallback: `RPC_URL`) | Throws on startup |\n| `VAULT_CREATOR` | Must be set | Throws on startup |\n| `SCAN_INTERVAL_MS` | Must be >= 5000 | Throws on startup |\n| `LOG_LEVEL` | Must be `debug\\|info\\|warn\\|error` | Throws on startup |\n\n### Defaults\n\n| Variable | Default |\n|----------|---------|\n| `SCAN_INTERVAL_MS` | 30000 |\n| `LOG_LEVEL` | `info` |\n\n### Security Notes\n\n- `SOLANA_RPC_URL` is used only for Solana RPC calls — never logged, transmitted externally, or stored\n- `VAULT_CREATOR` is a public key (not sensitive)\n- `SOLANA_PRIVATE_KEY` is optional — if provided, it is read once at startup and used to derive the keypair via `Keypair.fromSecretKey()`. The raw string is never logged or transmitted. If omitted, the bot generates a fresh keypair with `Keypair.generate()` (recommended).\n\n**Verdict:** Configuration is properly validated. Sensitive `SOLANA_PRIVATE_KEY` is handled safely when provided.\n\n---\n\n## Dependency Analysis\n\n### Runtime Dependencies\n\n| Package | Version | Pinning | Post-Install | Risk |\n|---------|---------|---------|-------------|------|\n| `@solana/web3.js` | 1.98.4 | Exact | None | Low — standard Solana |\n| `torchsdk` | 3.7.22 | Exact | None | Low — audited separately |\n\n### Dev Dependencies\n\n| Package | Version | Purpose |\n|---------|---------|---------|\n| `@types/node` | 20.19.33 | TypeScript types |\n| `prettier` | 3.8.1 | Code formatting |\n| `typescript` | 5.9.3 | Compilation |\n\n### Supply Chain\n\n- **No `^` or `~` version ranges** — all dependencies pinned to exact versions\n- **No post-install hooks** — `\"scripts\"` contains only `build`, `clean`, `test`, `format`\n- **No remote code fetching** — no dynamic `import()`, no `eval()`, no fetch-and-execute\n- **Lockfile present** — `pnpm-lock.yaml` pins transitive dependencies\n\n### External Runtime Dependencies\n\nThe SDK contains functions that make outbound HTTPS requests. The bot's runtime path contacts **two** external services:\n\n| Service | Purpose | When Called | Bot Uses? |\n|---------|---------|------------|-----------|\n| **CoinGecko** (`api.coingecko.com`) | SOL/USD price for display | Token queries via `getTokens()` | Yes |\n| **Irys Gateway** (`gateway.irys.xyz`) | Token metadata fallback | `getTokens()` when metadata URI points to Irys | Yes |\n| **SAID Protocol** (`api.saidprotocol.com`) | Agent identity verification | `verifySaid()` only | **No** — bot does not call `verifySaid()` |\n\n**Important:** `confirmTransaction()` does NOT contact SAID Protocol. Despite residing in the SDK's `said.js` module, it only calls `connection.getParsedTransaction()` (Solana RPC) to verify the transaction succeeded on-chain. No transaction data or agent identifiers are sent to any external reputation service.\n\nData transmitted to external services:\n- **CoinGecko:** Read-only GET for SOL/USD price. No wallet, transaction, or agent data sent.\n- **Irys:** Read-only GET for token metadata (name, symbol, image). No wallet or transaction data sent.\n\nNo credentials are sent. If either service is unreachable, the SDK degrades gracefully. No private key material is ever transmitted to any external endpoint.\n\n**Verdict:** Minimal and locked dependency surface. No supply chain concerns. External network calls are read-only, non-critical, and transmit no sensitive data.\n\n---\n\n## Threat Model\n\n### Threat: Compromised Agent Keypair\n\n**Attack:** Attacker obtains the agent's private key from process memory.\n**Impact:** Attacker can sign transactions as the agent.\n**Mitigation:** The agent keypair holds ~0.01 SOL. The vault's value is controlled by the authority, who can unlink the compromised wallet in one transaction. The attacker cannot call `withdrawVault` or `withdrawTokens`.\n**Residual risk:** Attacker could execute vault-routed trades until unlinked. Limited by vault SOL balance.\n\n### Threat: Malicious RPC Endpoint\n\n**Attack:** RPC returns fabricated loan positions to trick the bot into unprofitable liquidations.\n**Impact:** The bot liquidates positions that aren't actually underwater, losing vault SOL.\n**Mitigation:** The on-chain program validates all liquidation preconditions. A fabricated RPC response would produce a transaction that fails on-chain.\n**Residual risk:** None — on-chain validation is the actual security boundary.\n\n### Threat: Fabricated getAllLoanPositions Results\n\n**Attack:** A compromised or malicious RPC returns positions with `health: 'liquidatable'` for loans that are actually healthy.\n**Impact:** Bot builds liquidation transactions that fail on-chain (program checks LTV).\n**Mitigation:** Same as above — on-chain program enforces liquidation threshold. The `health` field from `getAllLoanPositions` is a client-side convenience; the program independently verifies collateral value vs debt. A failed liquidation costs only the transaction fee (~0.000005 SOL).\n**Residual risk:** Wasted gas on failed transactions. No vault SOL lost on failed liquidations.\n\n### Threat: RPC Rate Limiting / DDoS\n\n**Attack:** Overwhelming the bot with slow/failed RPC responses.\n**Impact:** Bot can't discover or liquidate positions.\n**Mitigation:** `SCAN_INTERVAL_MS` floor of 5000ms. Each scan cycle is independent. Bot recovers on next cycle.\n**Residual risk:** Missed liquidation opportunities during outage.\n\n### Threat: Front-Running\n\n**Attack:** MEV bot observes the liquidation transaction in mempool and front-runs it.\n**Impact:** Bot's transaction fails (`NOT_LIQUIDATABLE` — position already liquidated).\n**Mitigation:** The bot catches the error and moves to the next position. No vault SOL is lost on a failed liquidation.\n**Residual risk:** Reduced liquidation success rate in competitive MEV environments.\n\n---\n\n## Findings\n\n### L-1: No Timeout on SDK Calls — RESOLVED in v4.0.1\n\n**Severity:** Low\n**File:** `utils.ts:12-21`, `index.ts` (all SDK call sites)\n**Description:** SDK calls (`getTokens`, `getAllLoanPositions`, `buildLiquidateTransaction`, `confirmTransaction`, `getVault`, `getVaultForWallet`) previously had no explicit timeout. A hanging RPC endpoint could block the scan loop indefinitely.\n**Resolution:** All 6 SDK calls are now wrapped with `withTimeout(promise, label)` which races against a 30-second deadline via `Promise.race`. Timeouts in the scan loop are caught by existing try/catch layers — the bot logs the timeout and continues. Startup timeouts surface as a FATAL error (correct behavior — if RPC is unreachable at startup, the bot should not silently hang).\n**Status:** Resolved in v4.0.1.\n\n### I-1: No Deduplication Across Cycles\n\n**Severity:** Informational\n**Description:** The bot checks all tokens and all positions on every cycle. If a liquidation fails (e.g., insufficient vault SOL), the same position will be retried on every cycle.\n**Impact:** Repeated log noise for positions that can't be liquidated. No security impact.\n\n### I-2: getAllLoanPositions Uses getProgramAccounts\n\n**Severity:** Informational\n**Description:** `getAllLoanPositions` internally calls `getProgramAccounts` with discriminator + mint filters to find all LoanPosition accounts. Some RPC providers rate-limit or restrict `getProgramAccounts`. The bot falls back gracefully (the `catch` block skips the token), but tokens may be silently skipped if the RPC provider blocks this call.\n**Impact:** Missed liquidation opportunities on restrictive RPC providers. No security impact. The previous `getHolders` approach (`getTokenLargestAccounts`) had the same class of issue.\n**Recommendation:** Use an RPC provider that supports `getProgramAccounts` without restrictions (Helius, Triton, QuickNode, or a private validator).\n\n---\n\n## Resolved Findings from v3.0.2\n\n### L-1 (v3.0.2): Agent Keypair Regenerated on Every Restart\n\n**Status:** Resolved in v3.0.2. Optional `SOLANA_PRIVATE_KEY` env var allows persisting the agent wallet. Still resolved in v4.0.0.\n\n### I-1 (v3.0.2): Holder Discovery Limited to 20\n\n**Status:** Resolved in v4.0.0. The bot no longer calls `getHolders` / `getTokenLargestAccounts`. `getAllLoanPositions` scans all LoanPosition PDAs directly via `getProgramAccounts` with no holder count ceiling.\n\n### I-3 (v3.0.2): Log Level Filter Uses String Comparison\n\n**Status:** Still present, still informational. For a bot with 30-second cycle intervals, this is irrelevant.\n\n### I-4 (v3.0.2): Surfpool getTokenLargestAccounts Limitation\n\n**Status:** Resolved in v4.0.0. The bot no longer calls `getHolders` / `getTokenLargestAccounts`. The E2E test no longer depends on this Surfpool-limited RPC method.\n\n---\n\n## Conclusion\n\nThe Torch Liquidation Bot v4.0.2 is a cleaner, more efficient keeper with correct vault integration and robust error handling. Key findings:\n\n1. **Key safety is correct** — in-process `Keypair.generate()` by default, optional `SOLANA_PRIVATE_KEY` for persistence. No key logging, no key transmission. Unchanged from v3.0.2.\n2. **Vault integration is correct** — `vault` param passed to `buildLiquidateTransaction`, SOL from vault, collateral to vault ATA. Unchanged from v3.0.2.\n3. **Scan pattern improved** — `getAllLoanPositions` replaces the N+1 holder scan. One RPC call per token, no 20-holder ceiling, pre-sorted results with early break. Two v3.0.2 findings (I-1, I-4) are resolved by this change.\n4. **Error handling is robust** — three levels of isolation (cycle, token, liquidation) plus 30-second RPC timeouts on all SDK calls. A hanging RPC cannot stall the bot.\n5. **Dependency surface is minimal** — 2 runtime deps, both pinned exact, no post-install hooks. SDK upgraded from 3.2.3 to 3.7.22.\n6. **No critical, high, medium, or low findings** — L-1 (no timeout) resolved in v4.0.1. 2 informational issues remain.\n\nThe bot is safe for production use as an autonomous liquidation keeper operating through a Torch Vault.\n\n---\n\n## Audit Certification\n\nThis audit was performed by Claude Opus 4.6 (Anthropic) on February 27, 2026. All source files were read in full and cross-referenced against the torchsdk v3.7.22 audit. The E2E test suite (9 passed, 0 failed) validates the bot against a Surfpool mainnet fork, including sort order verification for `getAllLoanPositions`.\n\n**Auditor:** Claude Opus 4.6\n**Date:** 2026-02-27\n**Bot Version:** 4.0.2\n**Kit Version:** 2.0.0\n**SDK Version:** torchsdk 3.7.22\n**On-Chain Version:** V3.7.7 (Program ID: `8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeT`, 27 instructions)\n\nFile v4.0.4:design.md\n\n# Torch Liquidation Bot — Design Document\n\n> Autonomous vault-based liquidation keeper for Torch Market lending on Solana. Version 4.0.2.\n\n## Overview\n\nThe Torch Liquidation Bot is a single-purpose keeper that scans Torch Market lending positions and liquidates underwater loans through a Torch Vault. It generates a disposable agent keypair in-process, verifies vault linkage, and runs a continuous scan-liquidate loop. All SOL and collateral tokens route through the vault — the agent wallet holds nothing of value.\n\nThe bot is built on `torchsdk@3.7.22` and targets the Torch Market on-chain program (`8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeT`). It uses the SDK's bulk loan scanner (`getAllLoanPositions`) to discover liquidatable positions and the vault-routed `buildLiquidateTransaction` to execute them.\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────┐\n│                    LIQUIDATION BOT                         │\n│                                                           │\n│  main()                                                   │\n│    ├── loadConfig()         → validate env vars            │\n│    ├── Keypair.generate()   → disposable agent keypair     │\n│    ├── getVault()           → verify vault exists           │\n│    ├── getVaultForWallet()  → verify agent linked to vault  │\n│    └── while (true)                                        │\n│         └── scanAndLiquidate()                             │\n│              ├── getTokens({ status: 'migrated' })         │\n│              ├── getAllLoanPositions(mint)                  │\n│              │    → returns positions sorted by health      │\n│              │    → break at first non-liquidatable         │\n│              ├── buildLiquidateTransaction(vault=creator)   │\n│              ├── transaction.sign(agentKeypair)             │\n│              ├── connection.sendRawTransaction()            │\n│              └── confirmTransaction()                      │\n└──────────────────────────┬───────────────────────────────┘\n                           │\n                           ▼\n┌──────────────────────────────────────────────────────────┐\n│                    torchsdk v3.7.22                        │\n│                                                           │\n│  Read-only queries:                                       │\n│    getTokens, getAllLoanPositions                          │\n│    getVault, getVaultForWallet                             │\n│                                                           │\n│  Transaction builder:                                     │\n│    buildLiquidateTransaction (vault-routed)                │\n│                                                           │\n│  Confirmation:                                            │\n│    confirmTransaction (on-chain via RPC)                   │\n└──────────────────────────┬───────────────────────────────┘\n                           │\n                           ▼\n┌──────────────────────────────────────────────────────────┐\n│              Solana RPC (mainnet / validator)              │\n│                                                           │\n│  getProgramAccounts    getAccountInfo    sendTransaction   │\n└──────────────────────────────────────────────────────────┘\n```\n\n## Module Structure\n\n```\npackages/bot/src/\n├── index.ts      Entry point — keypair generation, vault verification, scan loop\n├── config.ts     loadConfig() — validates SOLANA_RPC_URL, VAULT_CREATOR, SOLANA_PRIVATE_KEY, SCAN_INTERVAL_MS, LOG_LEVEL\n├── types.ts      BotConfig, LogLevel interfaces\n└── utils.ts      sol(), bpsToPercent(), createLogger()\n```\n\n### Dependency Graph\n\n```\nindex.ts ──→ config.ts ──→ types.ts\n         ──→ utils.ts ──→ types.ts\n         ──→ torchsdk (external)\n         ──→ @solana/web3.js (external)\n```\n\nNo circular dependencies. `index.ts` is the single entry point. `config.ts` handles environment validation. `utils.ts` provides formatting helpers. All on-chain interaction goes through `torchsdk`.\n\n---\n\n## Design Principles\n\n### 1. Single Purpose\n\nThe bot does one thing: find underwater loans and liquidate them through the vault. No trading, no borrowing, no token creation. One loop, one responsibility.\n\n### 2. Vault-First\n\nEvery liquidation routes through the Torch Vault. SOL comes from the vault. Collateral tokens go to the vault ATA. The agent wallet never holds value. This is enforced by passing `vault: vaultCreator` to `buildLiquidateTransaction`.\n\n### 3. Disposable Keypair\n\nBy default, the agent keypair is generated fresh on every startup with `Keypair.generate()`. Optionally, `SOLANA_PRIVATE_KEY` can be provided (base58 or JSON byte array) to persist the agent wallet across restarts. In both cases, the keypair exists only in runtime memory and is never logged or transmitted.\n\n### 4. Fail-Safe Startup\n\nBefore entering the scan loop, the bot verifies:\n1. `getVault(connection, vaultCreator)` — vault exists on-chain\n2. `getVaultForWallet(connection, agentPubkey)` — agent is linked to the vault\n\nIf either check fails, the bot exits with clear instructions. It never enters the scan loop with an invalid vault or unlinked wallet.\n\n### 5. Graceful Error Handling\n\nThe scan loop catches all errors at the cycle level. A failed RPC call or a failed liquidation never crashes the bot — it logs the error and moves to the next cycle. Individual token iterations use try/catch to skip tokens where `getAllLoanPositions` fails.\n\n### 6. Minimal Surface\n\nTwo runtime dependencies (`@solana/web3.js`, `torchsdk`), both pinned to exact versions. ~187 lines of TypeScript. Four source files. No database, no API server, no indexer, no websockets.\n\n---\n\n## Scan Algorithm\n\n```\nfor each migrated token:\n  positions = getAllLoanPositions(mint)\n  skip if positions is empty\n\n  for each position (pre-sorted: liquidatable → at_risk → healthy):\n    break if health !== 'liquidatable'\n\n    → buildLiquidateTransaction(vault=creator)\n    → sign with agent keypair\n    → submit and confirm\n    → log result\n```\n\n### Token Discovery\n\n`getTokens(connection, { status: 'migrated', sort: 'volume', limit: 50 })` returns the top 50 migrated tokens by volume. Only migrated tokens have active lending markets.\n\n### Loan Scanning\n\n`getAllLoanPositions(connection, mint)` scans all LoanPosition PDAs for a token via `getProgramAccounts` with discriminator + mint filters. Returns all active positions (borrowed_amount > 0) pre-sorted by health: `liquidatable → at_risk → healthy`. Fetches the Raydium pool price once per call (not per position).\n\n### Loan Health\n\nThe SDK computes a `health` field for each position: `'healthy'`, `'at_risk'`, `'liquidatable'`, or `'none'`. The bot only acts on `'liquidatable'` — positions where LTV exceeds the 65% threshold. Because positions are pre-sorted, the bot breaks at the first non-liquidatable position.\n\n---\n\n## Vault Integration\n\n### Liquidation Transaction\n\n```typescript\nconst { transaction, message } = await buildLiquidateTransaction(connection, {\n  mint: token.mint,\n  liquidator: agentKeypair.publicKey.toBase58(),\n  borrower: position.borrower,\n  vault: vaultCreator,\n})\n```\n\nWhen `vault` is provided:\n- Vault PDA derived from `vaultCreator` (`[\"torch_vault\", creator]`)\n- Wallet link PDA derived from `liquidator` (`[\"vault_wallet\", wallet]`)\n- SOL for the liquidation comes from the vault\n- Collateral tokens go to the vault's ATA for the token mint\n\n### Safety Model\n\n| Property | Implementation |\n|----------|---------------|\n| Full custody | `vault` param routes all value through vault PDA |\n| No extraction | Agent cannot call `withdrawVault` or `withdrawTokens` |\n| Instant revocation | Authority calls `unlinkWallet` — bot's next tx fails with `WALLET_NOT_LINKED` |\n| Closed loop | SOL out → vault, tokens in → vault ATA |\n\n---\n\n## Configuration\n\n```typescript\ninterface BotConfig {\n  rpcUrl: string           // SOLANA_RPC_URL env var, fallback RPC_URL (required)\n  vaultCreator: string     // VAULT_CREATOR env var (required)\n  privateKey: string | null // SOLANA_PRIVATE_KEY env var (optional)\n  scanIntervalMs: number   // SCAN_INTERVAL_MS env var (default 30000, min 5000)\n  logLevel: LogLevel       // LOG_LEVEL env var (default 'info')\n}\n```\n\n### Validation\n\n- `SOLANA_RPC_URL` must be set, fallback `RPC_URL` (throws on missing)\n- `VAULT_CREATOR` must be set (throws on missing)\n- `SCAN_INTERVAL_MS` must be >= 5000 (prevents RPC rate limiting)\n- `LOG_LEVEL` must be one of `debug`, `info`, `warn`, `error`\n\n---\n\n## Logging\n\nThe bot uses a structured logger with level filtering:\n\n```\n[HH:MM:SS.mmm] LEVEL message\n```\n\n| Level | Purpose |\n|-------|---------|\n| `debug` | Scan cycle boundaries, token counts, skipped tokens |\n| `info` | Vault status, liquidatable positions found, successful liquidations |\n| `warn` | Failed liquidation attempts |\n| `error` | Scan cycle errors |\n\n---\n\n## E2E Test Coverage\n\nTests run against a Surfpool mainnet fork:\n\n| Test | What It Validates |\n|------|-------------------|\n| Connection | RPC reachable, Solana version |\n| getTokens | Discovers migrated tokens via discriminator filter |\n| getLendingInfo | Reads lending state (rates, thresholds, active loans) |\n| getAllLoanPositions | Bulk scans active loans, verifies sort order (liquidatable first) |\n| getToken | Token metadata, price, status |\n| getVaultForWallet | Returns null for unlinked wallet |\n| In-process keypair | Keypair.generate() works, no external key |\n\n**Result:** 9 passed, 0 failed.\n\n---\n\n## Dependencies\n\n| Package | Version | Purpose |\n|---------|---------|---------|\n| `@solana/web3.js` | 1.98.4 | Connection, Keypair, Transaction, sendRawTransaction |\n| `torchsdk` | 3.7.22 | Token queries, bulk loan scanning, vault queries, liquidation builder, confirmation |\n\n| Dev Package | Version | Purpose |\n|-------------|---------|---------|\n| `@types/node` | 20.19.33 | TypeScript node types |\n| `prettier` | 3.8.1 | Code formatting |\n| `typescript` | 5.9.3 | Compilation |\n\n---\n\n## Version History\n\n| Version | Changes |\n|---------|---------|\n| 1.0.0 | Initial read-only lending scanner. No wallet, no transactions, no state changes. |\n| 2.0.0 | Added vault queries (`getVault`, `getVaultForWallet`). Still read-only. |\n| 3.0.0 | **Fully operational vault-based liquidation keeper.** In-process keypair generation. Vault-routed `buildLiquidateTransaction`. Continuous scan-liquidate loop. Startup vault and link verification. Updated to `torchsdk@3.2.3`. Kit version 1.0.0. |\n| 3.0.2 | Optional `SOLANA_PRIVATE_KEY` support (base58 or JSON byte array) for persistent agent wallet. Inline base58 decoder (no bs58 dependency). `SOLANA_RPC_URL` as primary env var with `RPC_URL` fallback. `VAULT_CREATOR` added to manifest `requires.env`. ClawHub audit consistency fixes. |\n| 4.0.0 | **Bulk loan scanning via `getAllLoanPositions`.** Replaces N+1 scan pattern (`getLendingInfo` → `getHolders` → per-holder `getLoanPosition`) with single RPC call per token. Positions pre-sorted by health with early break. Updated to `torchsdk@3.7.22` (V33 buyback removal, 70% utilization cap). Kit version 2.0.0. |\n| 4.0.1 | **RPC timeout via `withTimeout`.** Address L-1 Vulnerability with Denial-of-Service.\n| 4.0.2 | **Torchsdk Version Bump** update to latest sdk v3.7.23\n\nFile v4.0.4:verification.md\n\n# Formal Verification Report\n\n## TL;DR\n\nWe used [Kani](https://model-checking.github.io/kani/), a formal verification tool from AWS, to mathematically prove that torch.market's core math is correct -- not just tested, but **proven for every possible input**. This covers all fee calculations, bonding curve pricing, lending formulas, and reward distribution. No SOL can be created from nothing, no tokens can be minted from thin air, and no fees can exceed their stated rates.\n\nThis is **not** a security audit. It proves the arithmetic is correct, but does not cover access control, account validation, or economic attacks. See [What Is NOT Verified](#what-is-not-verified) for full scope limitations.\n\n**43 proof harnesses. All passing. Zero failures.**\n\n---\n\n## Overview\n\ntorch_market's core arithmetic has been formally verified using [Kani](https://model-checking.github.io/kani/), a Rust model checker backed by the CBMC bounded model checker. Kani exhaustively proves properties hold for **all** valid inputs within constrained ranges -- not just sampled test cases.\n\n**Tool:** Kani Rust Verifier 0.67.0 / CBMC 6.8.0\n**Target:** `torch_market` v3.7.8\n**Harnesses:** 43 proof harnesses, all passing\n**Source:** `programs/torch_market/src/kani_proofs.rs`\n\n## What Is Formally Verified\n\nThe proofs cover the **pure arithmetic layer** -- every fee calculation, bonding curve formula, lending math function, and reward distribution used by the on-chain program. Each proof harness uses symbolic (unconstrained) inputs bounded to realistic protocol ranges, and Kani exhaustively checks all possible values within those bounds.\n\n### Buy Flow (Harnesses 1-8)\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_buy_fee_conservation` | `protocol_fee + treasury_fee + after_fees == sol_amount` | 0.001-200 SOL |\n| `verify_protocol_fee_split` | `dev_share + protocol_portion == protocol_fee_total` | 0.001-200 SOL |\n| `verify_treasury_rate_bounds` | `rate in [500, 2000]` (5-20%) flat across all tiers | 0-target SOL reserves |\n| `verify_treasury_rate_monotonic` | More reserves -> lower treasury rate | 0-target SOL (two symbolic) |\n| `verify_sol_distribution_conservation` | `curve + treasury + creator + dev + protocol == sol_amount` (zero SOL created or lost, V34 5-way sum) | 0.001-10 SOL per trade, 0-target SOL reserves |\n| `verify_curve_tokens_bounded_legacy` | `tokens_out < virtual_token_reserves` (can't mint from thin air) | Legacy pool state space (IVT=107.3T) |\n| `verify_curve_tokens_bounded_v25` | Same property for V27 per-tier reserves | V27 pool state space (IVT=756.25M tokens) |\n| `verify_token_split_conservation` | `tokens_to_buyer + tokens_to_treasury == tokens_out` | 0 to TOTAL_SUPPLY |\n\n### Sell Flow (Harnesses 9-10)\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_sell_sol_bounded_legacy` | `sol_out < virtual_sol_reserves` (can't drain more SOL than exists) | Legacy pool state, max wallet cap |\n| `verify_sell_sol_bounded_v25` | Same property for V27 per-tier reserves | V27 pool state (IVS=3BT/8), max wallet cap |\n\n### Transfer Fees (Harnesses 11-12)\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_transfer_fee_bounds` | `floor <= fee <= floor + 1` (ceiling division correct) | 0.001 SOL - 100 tokens |\n| `verify_transfer_fee_no_underflow` | `amount - fee` never underflows | 0 to TOTAL_SUPPLY |\n\n### Lending (Harnesses 13-18)\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_collateral_value_bounded_small` | `collateral_value <= pool_sol` when `collateral <= pool_tokens` | 50 SOL / 50B token pool |\n| `verify_collateral_value_bounded_large` | Same property at different pool scale | 500 SOL / 200T token pool |\n| `verify_ltv_zero_collateral` | Zero collateral returns `u64::MAX` (instant liquidation) | All u64 debt values |\n| `verify_ltv_zero_debt` | Zero debt returns 0 LTV | All u64 collateral values |\n| `verify_interest_no_overflow` | Interest calculation doesn't overflow; interest <= principal | Up to 1000 SOL, 2%/epoch, 1 epoch |\n| `verify_liquidation_bonus_increases_seizure` | Liquidation bonus increases collateral seized | 100 SOL pool, up to 50 SOL debt |\n\n### Protocol Rewards (Harnesses 19-20)\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_user_share_bounded` | `user_share <= distributable` (no user can drain reward pool) | 500 SOL epoch, 50 SOL distributable |\n| `verify_min_claim_enforcement` | [V32] Claims passing MIN_CLAIM_AMOUNT check are genuinely >= 0.1 SOL; claim never exceeds distributable | 10-10,000 SOL total volume, up to 1,000 SOL distributable |\n\n### Ratio Math & Sell Cycle (Harnesses 21-23)\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_ratio_fits_u64` | Pool ratio `(sol * 1e9) / tokens` fits in u64 | Up to 1000 SOL, tokens >= 1 token |\n| `verify_sell_threshold_fits_u64` | [V30] Sell threshold `baseline_ratio * 12000 / 10000` fits in u64 | Same bounds as ratio proof, with 1.2x multiplier |\n| `verify_double_transfer_fee_positive` | Token amount remains positive after two consecutive transfer fees | 1 token to TOTAL_SUPPLY |\n\n### Migration (Harnesses 22-26)\n\nThese harnesses verify the V26 permissionless migration: SOL wrapping conservation, price-matched pool creation, and token burn accounting. Updated for V31 per-tier virtual reserves and zero-burn migration.\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_sol_wrapping_conservation` | [V26] `bc_debited == wsol_credited`, total lamports conserved (bonding curve SOL → payer WSOL) | 0 to 200 SOL reserves, rent up to 10M lamports |\n| `verify_price_matched_pool_spark` | [V31] Pool ratio matches curve ratio (truncation error < 1 unit) | Spark tier (50 SOL), 3 representative token values |\n| `verify_price_matched_pool_flame` | [V31] Pool ratio matches curve ratio (truncation error < 1 unit) | Flame tier (100 SOL), 3 representative token values |\n| `verify_price_matched_pool_torch` | [V31] Pool ratio matches curve ratio (truncation error < 1 unit) | Torch tier (200 SOL), 3 representative token values |\n| `verify_excess_token_burn_conservation` | [V31] `pool_tokens + burned_tokens == vault_total` (no tokens created or lost) | Spark tier, vault up to CURVE_SUPPLY |\n\n### V31 Zero-Burn Distribution (Harnesses 27-34)\n\nThese harnesses verify the V31 token distribution model where IVS = 3*bonding_target/8, IVT = 756.25M tokens, CURVE_SUPPLY = 700M (70%), and TREASURY_LOCK_TOKENS = 300M (30%). V31 tunes the curve/lock split so that vault_remaining == tokens_for_pool at graduation — proving zero excess burn and full 1B supply preservation.\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_v31_full_supply_conservation_spark` | `wallets + vote_vault + pool + burned + treasury_lock == TOTAL_SUPPLY` | Spark tier (50 SOL), exact graduation state |\n| `verify_v31_full_supply_conservation_flame` | Same conservation for Flame tier | Flame tier (100 SOL), exact graduation state |\n| `verify_v31_full_supply_conservation_torch` | Same conservation for Torch tier | Torch tier (200 SOL), exact graduation state |\n| `verify_v31_pool_tokens_positive_and_bounded` | Pool tokens > 0 and <= real_token_reserves at graduation | All tiers, exact graduation state |\n| `verify_v31_zero_excess_burn_spark` | `excess_burned == 0` at graduation (zero-burn migration) | Spark tier, exact graduation state |\n| `verify_v31_zero_excess_burn_flame` | `excess_burned == 0` at graduation (zero-burn migration) | Flame tier, exact graduation state |\n| `verify_v31_zero_excess_burn_torch` | `excess_burned == 0` at graduation (zero-burn migration) | Torch tier, exact graduation state |\n\n### Sell Fee (Harness 35)\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_sell_fee_always_zero` | `SELL_FEE_BPS == 0` and computed fee == 0 for all valid sol_out | 0.001-200 SOL |\n\n### Creator Revenue (Harnesses 36-39) — V34\n\nThese harnesses verify the V34 creator revenue arithmetic: bonding SOL share rate bounds, monotonicity, safety of the treasury-creator subtraction, and post-migration fee share conservation.\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_creator_rate_bounds` | `creator_rate in [20, 100]` bps (0.2%-1%) for all bonding progress | 0-target SOL reserves |\n| `verify_creator_rate_monotonic` | More reserves → higher creator rate | 0-target SOL (two symbolic) |\n| `verify_creator_rate_less_than_treasury_rate` | `creator_rate < treasury_rate` at all points (subtraction safety) | 0-target SOL reserves |\n| `verify_creator_fee_share_bounded` | 15% share ≤ total, `creator + treasury == total` (conservation) | 0.001-200 SOL fee swap proceeds |\n\n### Lending Lifecycle (Harnesses 40-42)\n\nThese harnesses verify end-to-end lending correctness: borrow → (optional interest accrual) → repay, proving treasury SOL conservation, correct interest-first repayment ordering, and loan zeroing.\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_lending_lifecycle_conservation` | After borrow + full repay (same slot): treasury SOL exactly restored, loan zeroed, principal_paid == sol_borrowed | 100 SOL / 50T token pool, up to 50 SOL borrow |\n| `verify_lending_partial_repay_accounting` | After partial repay: remaining_debt == total_owed - repaid, interest paid first, borrowed never increases | Up to 50 SOL, interest < 10% of principal |\n| `verify_lending_lifecycle_with_interest` | After borrow + 1 epoch interest + full repay: treasury gains exactly the interest, principal fully returned | Up to 50 SOL, 2%/epoch, 1 epoch max |\n\n## Verification Methodology\n\n### How Kani Works\n\nKani translates Rust code into a mathematical model and uses a SAT/SMT solver (CaDiCaL via CBMC) to exhaustively check whether any input can violate the asserted properties. Unlike fuzz testing which samples random inputs, Kani explores **every possible execution path** within the constrained input space.\n\nA passing harness means: \"there exists no input in the constrained range that violates this property.\"\n\n### Constraint Design\n\nEach harness constrains symbolic inputs to realistic protocol bounds:\n\n- **SOL amounts:** `MIN_SOL_AMOUNT` (0.001 SOL) to `BONDING_TARGET_LAMPORTS` (200 SOL)\n- **Token amounts:** Up to `TOTAL_SUPPLY` (1 billion tokens, 6 decimals)\n- **Legacy pool reserves:** `INITIAL_VIRTUAL_SOL` (30 SOL) to `INITIAL_VIRTUAL_SOL + BONDING_TARGET_LAMPORTS` (230 SOL)\n- **V31 pool reserves:** `3*bonding_target/8` initial virtual SOL (18.75-75 SOL), `INITIAL_VIRTUAL_TOKENS_V27` (756.25M tokens)\n- **Token reserves:** Up to `INITIAL_VIRTUAL_TOKENS` (107.3T raw units, legacy) or `INITIAL_VIRTUAL_TOKENS_V27` (756.25T raw units, V31)\n- **Curve supply:** `CURVE_SUPPLY` (700M tokens) for V31 bonding curve + pool allocation\n- **Lending pools:** Concrete post-migration pool states (50-500 SOL, 50B-200T tokens)\n- **Interest rates:** Up to `DEFAULT_INTEREST_RATE_BPS` (2% per epoch)\n\nSome harnesses use concrete pool states instead of fully symbolic parameters. This is a deliberate constraint design choice driven by SAT solver tractability:\n\n- **Symbolic inputs** (e.g., `kani::any()`) allow Kani to prove properties for *all* values in a range. This is the strongest form of proof but creates exponentially larger SAT formulas when multiple symbolic u64 values flow through u128 intermediate arithmetic.\n- **Concrete inputs** fix specific values (e.g., `pool_sol = 100_000_000_000`), eliminating those variables from the SAT formula entirely. Properties are verified exactly at those values rather than universally.\n- **Representative concrete values** are a middle ground used for the migration price-match harnesses. Instead of a single symbolic `virtual_tokens` spanning 47 bits (which the solver cannot handle), three concrete values are tested at key pool states: bonding completion, midpoint, and maximum. This reduces solve time from intractable to sub-100ms while covering the important points.\n\nThe concrete values are chosen to represent realistic protocol conditions: post-migration pool states for lending, bonding completion states for migration, and protocol-default rates for the sell cycle.\n\n### Dropped Harnesses (Design Rationale)\n\nEight harnesses were dropped during verification because they prove structurally guaranteed properties or were superseded:\n\n| Dropped Harness | Reason |\n|-----------------|--------|\n| `verify_curve_monotonic_fresh/half/full` | Monotonicity of `vt * sol / (vs + sol)` is guaranteed by the formula structure for any fixed positive `vt`, `vs`. Integer floor division preserves monotonicity. |\n| `verify_no_round_trip_fresh/half/full` | Round-trip loss (`buy then sell <= original`) is inherent in AMM constant-product formulas with integer truncation. Floor division always rounds down. |\n| `verify_ltv_100_percent` | `(v * 10000) / v == 10000` is a mathematical tautology. SAT solvers cannot efficiently prove symbolic u128 division cancellation. |\n| `verify_buyback_respects_reserve` | Buyback reserve/amount constraints are enforced by handler-level checks, not arithmetic. Property is structural given the config validation. |\n\nThese properties remain true by construction. The remaining 43 harnesses cover every non-tautological safety property.\n\n## What Is NOT Verified\n\nKani proofs verify **isolated pure functions** extracted from the handlers. They do not cover:\n\n| Category | Examples | Why Not Covered |\n|----------|----------|-----------------|\n| **Access control** | Who can call `migrate_to_dex`, `update_dev_wallet` | Enforced by Anchor `#[derive(Accounts)]` constraints, not arithmetic |\n| **Account validation** | Fake PDAs, wrong mints, account substitution | Requires on-chain runtime context |\n| **State machine transitions** | Can you sell before buying? Migrate before bonding completes? | Requires multi-instruction sequencing |\n| **CPI safety** | Reentrancy via Raydium CPIs, privilege escalation | Cross-program invocation is outside arithmetic scope |\n| **Economic attacks** | Sandwich attacks, oracle manipulation, flash loans | Require multi-transaction economic modeling |\n| **Anchor framework correctness** | `init-if-needed` edge cases, PDA derivation | Framework-level concerns |\n| **Concurrency** | Parallel transaction ordering, front-running | Solana runtime behavior |\n\n### Recommendation for Auditors\n\nThe arithmetic layer is formally verified. Audit effort should focus on:\n\n1. **Access control and account validation** -- can unauthorized callers invoke privileged instructions?\n2. **State transition integrity** -- are there invalid state transitions (e.g., double migration, selling into an empty curve)?\n3. **CPI safety** -- can Raydium CPIs be exploited for reentrancy or privilege escalation?\n4. **Economic attack surface** -- sandwich attacks on bonding curve buys, oracle-free lending price manipulation\n5. **Token-2022 edge cases** -- transfer fee interaction with Token-2022 extensions across CPIs\n\n## Running the Proofs\n\n```bash\n# Install Kani\ncargo install --locked kani-verifier\ncargo kani setup\n\n# Run all harnesses\ncd torch_market/programs/torch_market\ncargo kani\n\n# Run a specific harness\ncargo kani --harness verify_buy_fee_conservation\n```\n\nAll 43 harnesses pass. Most complete in under 1 second; the slowest (`verify_transfer_fee_bounds`, `verify_treasury_rate_monotonic`) take 30-55 seconds due to larger SAT formula complexity.\n\n## Constants Reference\n\n| Constant | Value | Description |\n|----------|-------|-------------|\n| `TOTAL_SUPPLY` | 1,000,000,000,000,000 | 1 billion tokens (6 decimals) |\n| `BONDING_TARGET_SPARK` | 50,000,000,000 | 50 SOL bonding target (Spark tier) |\n| `BONDING_TARGET_FLAME` | 100,000,000,000 | 100 SOL bonding target (Flame tier) |\n| `BONDING_TARGET_TORCH` | 200,000,000,000 | 200 SOL bonding target (Torch tier, default) |\n| `INITIAL_VIRTUAL_SOL` | 30,000,000,000 | 30 SOL initial virtual reserves (legacy) |\n| `INITIAL_VIRTUAL_TOKENS` | 107,300,000,000,000 | Initial virtual token reserves (legacy) |\n| `INITIAL_VIRTUAL_TOKENS_V27` | 756,250,000,000,000 | 756.25M tokens initial virtual reserves (V27) |\n| `TREASURY_LOCK_TOKENS` | 300,000,000,000,000 | 300M tokens locked in treasury (30% of supply) |\n| `CURVE_SUPPLY` | 700,000,000,000,000 | 700M tokens for curve + pool (70% of supply) |\n| V27 IVS | `3 * bonding_target / 8` | 18.75 SOL (Spark), 37.5 SOL (Flame), 75 SOL (Torch) |\n| `PROTOCOL_FEE_BPS` | 100 | 1% protocol fee |\n| `TREASURY_FEE_BPS` | 100 | 1% token treasury fee |\n| `TREASURY_SOL_MIN_BPS` | 500 | 5% min treasury SOL rate (flat, all tiers) |\n| `TREASURY_SOL_MAX_BPS` | 2000 | 20% max treasury SOL rate (flat, all tiers) |\n| `DEV_WALLET_SHARE_BPS` | 1000 | [V32] 10% of protocol fee to dev (was 25%) |\n| `BURN_RATE_BPS` | 1000 | 10% token burn on buy |\n| `TRANSFER_FEE_BPS` | 4 | [V34] 0.04% Token-2022 transfer fee (was 3 bps, old tokens retain 3) |\n| `DEFAULT_INTEREST_RATE_BPS` | 200 | 2% lending interest per epoch |\n| `DEFAULT_LIQUIDATION_BONUS_BPS` | 1000 | 10% liquidation bonus |\n| `DEFAULT_LENDING_UTILIZATION_CAP_BPS` | 7000 | [V33] 70% max treasury SOL lendable (was 50%) |\n| `RATIO_PRECISION` | 1,000,000,000 | 1e9 ratio scale factor |\n| `DEFAULT_SELL_THRESHOLD_BPS` | 12,000 | 120% -- sell triggers at 20% above baseline |\n| `DEFAULT_SELL_PERCENT_BPS` | 1,500 | 15% of held tokens sold per call |\n| `SELL_ALL_TOKEN_THRESHOLD` | 1,000,000,000,000 | 1M tokens -- sell 100% below this |\n| `MIN_EPOCH_VOLUME_ELIGIBILITY` | 2,000,000,000 | [V32] 2 SOL min epoch volume for rewards (was 10 SOL) |\n| `MIN_CLAIM_AMOUNT` | 100,000,000 | [V32] 0.1 SOL min claim amount |\n| `CREATOR_SOL_MIN_BPS` | 20 | [V34] 0.2% creator SOL share at bonding start |\n| `CREATOR_SOL_MAX_BPS` | 100 | [V34] 1% creator SOL share at bonding completion |\n| `CREATOR_FEE_SHARE_BPS` | 1,500 | [V34] 15% creator share of fee swap proceeds |\n| `MIN_SOL_AMOUNT` | 1,000,000 | 0.001 SOL minimum |\n\nFile v4.0.4:whitepaper.md\n\n# torch.market\n\n**a programmable economic substrate**\n\nBrightside Solutions, 2026\n\n[torch.market](https://torch.market) | [developer docs](https://torch-market-docs.vercel.app/) | [audit](https://torch.market/audit.md) | [@torch_market](https://x.com/torch_market/)\n\n---\n\n`torch.market` is a programmable economic substrate built on Solana. Every token launched on the protocol is its own self-sustaining economy — complete with a pricing engine, a central bank, a lending market, community governance, and optional privacy — all enclosed within a single non-extractive system where every action feeds a positive-sum feedback loop.\n\nThe protocol treats Solana not as a blockchain, but as a distributed computing substrate coupled with storage. On-chain accounts form a directed graph of economic relationships. PDA seeds define the edges. Handlers define the legal traversals. The result is a composable economic graph where anyone can launch a token and receive a complete, self-reinforcing financial ecosystem out of the box.\n\nUnlike traditional launchpads that extract value from participants, `torch.market` is non-extractive by topology — there is no edge in the graph that removes value from the system. Fees become lending yield. Lending yield becomes community liquidity. Failed tokens become protocol rewards. Every outflow is an inflow somewhere else. This is not a zero-sum game by design.\n\nThe architecture works as follows:\n\n---\n\n## The Economic Graph\n\nEvery token on `torch.market` instantiates a complete economic ecosystem. The on-chain accounts form a directed acyclic graph where each node is an autonomous economic actor:\n\n```\nPer-Token Economy:\n\n  Mint ──── Bonding Curve ──── Treasury\n  │              │                 │\n  │         Token Vault       Lending ──── Yield / Rewards\n  │              │                 │\n  │         User Positions    Lending ──── Collateral Vault\n  │              │                 │\n  │            Votes          Stars ──── Creator Payout\n  │                                │\n  │                            Migration ──── Raydium DEX Pool\n  │\n  └── Token-2022 Extensions\n       ├── Transfer Fee (0.04%)\n       └── Confidential Transfer (optional)\n\nProtocol Layer:\n\n  Protocol Treasury ◄── Fees + Reclaims\n       │\n       └── Epoch Rewards ──── Active Traders\n\nVault Layer (optional resolver):\n\n  TorchVault ◄── VaultWalletLink (identity)\n       │\n       └── Routes to: buy, sell, star, borrow, repay, swap\n```\n\nEach node maintains its own invariants. Each edge is structurally enforced by PDA derivation — the relationships between accounts are guaranteed by the runtime, not by application logic. A treasury can only exist for a bonding curve, which can only exist for a mint. The topology is the security model.\n\nThe **Torch Vault** acts as a protocol-native graph resolver — a middleware layer that sits between any caller and any action, resolving identity, SOL source, and token destination without knowing or caring what action is being performed. Two PDAs turn every economic flow in the protocol into a custody-aware operation.\n\nBecause the graph is complete — every meaningful economic flow is already a valid traversal — new capabilities emerge from the existing structure. Optional privacy is a single extension on the mint node. Vault custody is an optional dimension on every traversal. No refactoring needed. The graph just gets deeper.\n\n---\n\n## 1. Token Treasury: The Core Mechanic\n\nEvery token is launched with a **token treasury**, which is a wallet that acts as an automatic market maker and depreciates token supply.\n\nThe token treasury is the core mechanic of `torch.market`. Everyone talks supply control, but in `torch.market`, the protocol *is* the supply control. During bonding, the fee structure is as follows:\n\n```\nUser spends 1 SOL\n        │\n        ├── 1% → Protocol Fee (pre-bonding only)\n        │         ├── 90% → Protocol Treasury\n        │         └── 10% → Dev Wallet\n        │\n        ├── 1% → Token Treasury Fee (lifetime)\n        │\n        └── 98% → Remainder\n                  ├── V2.3 Dynamic → 3-Way Split (V34)\n                  │   ├── Token Treasury (19.8%→4% at start→end)\n                  │   ├── Creator Wallet (0.2%→1% at start→end)\n                  │   └── Total: 20% at start → 5% at completion\n                  └── V2.3 Dynamic → Bonding Curve\n                      └── 80% at start → 95% at completion\n                                ├── 90% → User (tokens)\n                                └── 10% → Community Treasury (vote vault)\n```\n\n> **Dynamic Treasury Rate**: The treasury SOL split uses inverse decay based on bonding progress. Early buyers contribute more to treasury (stronger early funding), late buyers get more tokens per SOL. The rate is flat across all tiers (Spark 50, Flame 100, Torch 200 SOL).\n>\n> | 0 SOL | 50% of target | 100% of target |\n> |-------|---------------|----------------|\n> | 20%   | 12.5%         | 5%             |\n\nThis creates a different mindset to how newly minted tokens are created. Users are not just paying into themselves, but paying into the long term growth of their communities.\n\n### How the Token Treasury Benefits Users\n\nThe token treasury creates a positive-sum dynamic where every participant's actions strengthen the entire ecosystem:\n\n1. **Treasury Accumulation**: The treasury accumulates SOL with every buy. Post-migration, harvested transfer fees are sold to SOL, growing the treasury's lending pool and earning yield through community borrowing.\n2. **Lending Yield**: Treasury SOL is lent to token holders who borrow against their collateral. Interest paid by borrowers flows back into the treasury, compounding its value over time.\n3. **No Insider Advantage**: Unlike traditional launches where team allocations can dump on retail, the treasury mechanism ensures that value flows back to all participants. There is no creator token allocation — creators earn through three revenue streams: a 0.2%→1% SOL share during bonding, 15% of post-migration fee swap proceeds, and star payouts.\n4. **Community-Funded Migration**: The treasury pays the 0.15 SOL Raydium pool creation fee automatically. Early supporters collectively fund the DEX migration without any single party bearing the cost.\n5. **Long-term Alignment**: Because the treasury continuously earns lending yield and epoch rewards, early sellers forfeit future treasury benefits. This incentivizes holding and community building over quick flips.\n\n---\n\n## 2. Community Vote: Token Holders Decide\n\nEach user casts a vote prelaunch to determine what happens to 10% of their tokens.\n\nOnce a token reaches its bonding target (50, 100, or 200 SOL depending on tier), the community votes to decide what happens to the tokens held in the community treasury (vote vault). The voters can decide to:\n\n- **Burn**: Destroy the tokens forever, reducing total supply from 1B to ~945M\n- **Return to Treasury Lock**: Transfer the tokens to the treasury lock PDA for future governance release\n\nProviding a group proposal solidifies project community before the DEX launch and gives all wallets a say:\n\n```\n1 wallet = 1 vote\n```\n\nThe vote outcome is binding and executed automatically during migration.\n\n---\n\n## 3. Wallet Limits: Anti-Whale Protection\n\nAny given wallet is restricted to at most *2% of the entire supply* of the token.\n\nBy restricting wallets to a hard limit on the total amount of tokens that they own before launch, this ensures better fairness for all wallets purchasing on the bond. Individual wallets can no longer control the entire supply of a given token at once, limiting the chance of price manipulation and dumping on incoming buyers.\n\nNew buyers may also be more likely to purchase a token seeing that it is \"safer\" from whale manipulation. A downside to this is that a single user may control more than 1 wallet, which could be considered a sybil attack against the protocol. However, this is partially mitigated by:\n\n- The fee structure itself (sybiling costs more in fees)\n- The community treasury (even sybil buyers fund the collective)\n- Post-migration transfer fees (every transfer costs 0.04%)\n\n---\n\n## 4. Permissionless Migration\n\nThe token treasury pays the migration fee to DEX. Anyone can trigger it.\n\nOne of the main issues with current launchpads is that somebody has to pay the migration fee for the token to be migrated to a decentralized exchange. Because the treasury wallet is fully funded by the time the token bonds at its target (50/100/200 SOL), it is given the authority to pay the Raydium pool creation fee (0.15 SOL).\n\nMigration is **permissionless** — any wallet can trigger the migration for any bonding-complete token. The triggering wallet pays a small rent fee (~0.02 SOL) for the WSOL account, while the treasury covers the 0.15 SOL Raydium pool creation fee. This means no single party can block a token from graduating to DEX.\n\nThe migration is executed as a two-step atomic process within a single transaction:\n\n1. **Fund WSOL**: Wrap the bonding curve's SOL reserves into a WSOL token account\n2. **Migrate to DEX**: Vote finalization, pool creation on Raydium CPMM, liquidity provision (SOL + tokens), LP token burn (liquidity locked forever), transfer fee activation (0.04% on all future transfers)\n\nWhen your token bonds, anyone can complete the migration. The community is not dependent on the creator or any centralized operator.\n\n---\n\n## 5. Post-Migration: Treasury Accumulation Loop\n\nOnce a token migrates to Raydium, the treasury continues growing through the **0.04% transfer fee** and **lending yield**.\n\n### The 0.04% Transfer Fee (Token-2022)\n\nAll `torch.market` tokens use Solana's Token-2022 standard with a built-in **0.04% transfer fee** (4 basis points). This fee is collected on every transfer — wallet to wallet, DEX trades, everything.\n\n```\nUser transfers 100,000 tokens\n        │\n        └── 0.04% (4 tokens) → Withheld in mint\n                            │\n                            └── Harvested → Token Treasury\n                                        │\n                                   swap_fees_to_sol\n                                        │\n                                   ┌────┴────┐\n                                   │         │\n                                   ▼         ▼\n                              Treasury   Creator\n                               (85%)     (15%)\n```\n\nThe transfer fee is not extracted from the sender or receiver as a separate charge — it's automatically withheld from the transferred amount at the Solana runtime level. The rate is immutable once set at token creation. Pre-V34 tokens retain their original 3 bps (0.03%) rate.\n\n### Harvest and Sell Cycle\n\nThe accumulated transfer fees create a perpetual treasury growth engine:\n\n1. **Harvest** (permissionless): Anyone can call `harvest_fees` to collect withheld tokens from transfers into the token treasury's token account.\n2. **Swap to SOL** (permissionless): Anyone can call `swap_fees_to_sol` to sell the harvested tokens back to SOL via Raydium. Proceeds are split 85% to treasury SOL balance, 15% to creator wallet. The SDK bundles harvest + swap in one atomic transaction via `buildSwapFeesToSolTransaction`.\n3. **Lend**: Treasury SOL is available for community members to borrow against their token collateral (see Section 6).\n4. **Earn**: Interest from borrowers flows back into the treasury, compounding its value.\n\n### Sell Cycle Parameters\n\n- **Interval**: Minimum ~18 minutes between sells (cooldown)\n- **Sell Amount**: 15% of held tokens per call (100% if <= 1M tokens)\n- **Sell Trigger**: Price > 120% of migration baseline\n\nThe treasury accumulates SOL through fee harvesting and lending interest, creating a self-sustaining growth loop.\n\n### Treasury Behavior Summary\n\n| Phase | SOL Source | Token Destination |\n|-------|-----------|-------------------|\n| Bonding | 1% fee + 20%→5% of buys (dynamic, 3-way: treasury + creator + curve) | Community treasury (vote vault) |\n| DEX | 0.04% transfer fee → sell to SOL (85% treasury, 15% creator) | Treasury SOL → lending pool + epoch rewards |\n\n---\n\n## 6. Treasury Lending\n\nAfter migration, the token treasury holds SOL accumulated from fee harvesting. Holders can **borrow SOL against their tokens**, turning idle treasury capital into productive liquidity while earning yield for the treasury.\n\n### How It Works\n\n1. **Deposit Collateral**: A holder deposits tokens into the lending vault. The tokens are locked but remain the borrower's property.\n2. **Borrow SOL**: The borrower receives SOL from the token treasury up to the maximum loan-to-value ratio. The borrowed amount is capped by both the LTV and the treasury's utilization cap.\n3. **Repay**: The borrower returns the SOL plus accrued interest. Interest is calculated per-epoch (approximately 7 days). Upon repayment, collateral tokens are unlocked.\n4. **Liquidation**: If the collateral value falls below the liquidation threshold, anyone can liquidate the position. The liquidator repays the debt and receives the collateral plus a bonus.\n\n### Lending Parameters\n\n- **Max LTV**: 50% — borrow up to half the value of deposited collateral\n- **Liquidation Threshold**: 65% — position is liquidatable when debt exceeds 65% of collateral value\n- **Interest Rate**: 2% per epoch (~7 days)\n- **Liquidation Bonus**: 10% — liquidators receive collateral at a 10% discount\n- **Utilization Cap**: 70% — at most 70% of treasury SOL can be lent out at any time\n\n### Collateral Pricing\n\nToken prices are derived from the Raydium pool reserves. The protocol reads the pool's SOL and token balances on-chain and computes the spot price. No external oracles are required — pricing is fully on-chain and permissionless.\n\n### Virtuous Cycle\n\nInterest paid by borrowers flows back into the token treasury, compounding its SOL balance. Community members borrow SOL → buy tokens → generate volume → generate transfer fees → fees harvested and sold to SOL → treasury grows → more SOL available for lending. The treasury becomes a self-reinforcing liquidity engine.\n\n> **Immutable Parameters**: All lending parameters (LTV, liquidation threshold, interest rate, bonus, utilization cap) are set at pool creation and are immutable on-chain. No admin key can change them after deployment.\n\n---\n\n## 7. Protocol Treasury: Rewarding Active Traders\n\nThe protocol level fees don't just go to the development team, they're redistributed to active platform users.\n\n### How It Works\n\nDuring the bonding phase, 1% of every buy goes to the protocol. This is split:\n\n- 90% → Protocol Treasury (for user rewards)\n- 10% → Dev Wallet (for development)\n\nThe Protocol Treasury accumulates SOL and distributes it to active traders every *7 days (1 epoch)*.\n\n### Epoch Reward Distribution\n\n1. **No Reserve Floor**: All accumulated fees are distributed each epoch. No SOL held back.\n2. **Volume Eligibility**: To claim rewards, a user must have traded at least *2 SOL in volume* during the previous epoch.\n3. **Minimum Claim**: Claims below 0.1 SOL are rejected (prevents dust drain).\n4. **Pro-Rata Share**: Eligible users receive rewards proportional to their trading volume:\n   ```\n   user_reward = (user_volume / total_volume) × distributable_amount\n   ```\n5. **Claim**: Users must actively claim their rewards. Unclaimed rewards roll into the next epoch.\n\n### Example\n\nIf the protocol treasury has 500 SOL after an epoch:\n- Distributable: 500 SOL (all of it — no reserve floor)\n\nIf total eligible volume was 50,000 SOL and you traded 5,000 SOL:\n- Your share: 5,000 / 50,000 = 10%\n- Your reward: **50 SOL**\n\nThis mechanism rewards the most active participants on the platform and creates an incentive loop: more trading → more fees → more rewards → more trading.\n\n---\n\n## 8. Token Reclaim and Revival\n\nNot every token succeeds. `torch.market` has mechanisms to handle failed tokens and even give them a second chance.\n\n### Reclaim: Cleaning Up Failed Tokens\n\nIf a token fails to reach its bonding target (50/100/200 SOL depending on tier) and becomes inactive for *7 days*, anyone can trigger a reclaim:\n\n```\nConditions for reclaim:\n  ✓ Bonding not complete (target not reached)\n  ✓ No trading activity for 7+ days\n  ✓ At least 0.01 SOL in reserves (not dust)\n```\n\nWhen reclaimed:\n\n1. All SOL from the bonding curve is transferred to the protocol treasury\n2. All SOL from the token treasury is transferred to the protocol treasury\n3. The token is marked as \"reclaimed\" and trading is disabled\n\nThe reclaimed SOL joins the protocol treasury and is distributed to active traders in the next epoch. Failed tokens become rewards for successful traders.\n\n### Revival: Second Chances\n\nA reclaimed token can be **revived** if the community believes in it. Anyone can contribute SOL to a reclaimed token:\n\n```\nRevival threshold (V27): 3BT/8 (18.75 SOL Spark, 37.5 SOL Flame, 75 SOL Torch)\nLegacy tokens: BT/8 (6.25 SOL Spark, 12.5 SOL Flame, 25 SOL Torch)\n```\n\nContributors are patrons — they do NOT receive tokens for their contribution. They're simply signaling belief that the token deserves another chance. Once the revival threshold is reached:\n\n1. The `reclaimed` flag is removed\n2. Trading is re-enabled\n3. The token continues from where it left off\n\nThis creates a natural market for \"distressed\" tokens. If a token had real community support but just needed more time, revival gives it that chance.\n\n---\n\n## 9. On-Chain Messages\n\nEvery token on `torch.market` has a **message board**. Messages are stored on-chain using the SPL Memo program, making them permanent and censorship-resistant.\n\n### Skin in the Game\n\nMessages can be bundled with trades. When a user buys or sells a token, they can attach a message to the transaction. This ties commentary directly to economic action — every message comes from someone with skin in the game.\n\n### Standalone Messages\n\nUsers can also post standalone messages without trading. These are recorded via the SPL Memo program and associated with the token's message board. Standalone messages still require a wallet signature, ensuring accountability.\n\n### Why On-Chain?\n\n- **Permanence**: Messages cannot be deleted or altered after posting\n- **Attribution**: Every message is signed by the sender's wallet\n- **Context**: Trade-attached messages show what the sender did, not just what they said\n- **Composability**: Any client, bot, or agent can read and post messages using the same on-chain interface\n\n---\n\n## 10. Verification & Trust (SAID Protocol)\n\n`torch.market` integrates the **SAID protocol** — an on-chain identity layer for agents and humans. SAID provides verifiable trust without requiring personal information.\n\n### Trust Tiers\n\nEach verified wallet receives a trust tier based on on-chain activity and verification depth:\n\n| Tier | Color |\n|------|-------|\n| High | Emerald / Green |\n| Medium | Blue |\n| Low | Yellow |\n\n### Where Badges Appear\n\n- Token cards on the explore page\n- Token detail pages (next to the creator wallet)\n- Message boards (next to each message author)\n\n### Reputation Scoring\n\nReputation is earned through on-chain activity on the platform:\n\n- **+15 points**: Launch a token\n- **+5 points**: Execute a trade\n- **+10 points**: Cast a community vote\n\n---\n\n## 11. Built for Agents\n\n`torch.market` is designed for both humans and AI agents. There is no API server between the agent and the protocol. Solana is the compute layer. The Torch SDK builds transactions locally from the on-chain program's Anchor IDL and reads all state directly from Solana RPC. No middleman, no API keys, no trust assumptions beyond the on-chain program itself.\n\n### Direct On-Chain Access\n\nEvery protocol action — buy, sell, lend, govern, message — is an instruction on the Solana program. The SDK constructs these instructions locally using the Anchor IDL, serializes them into unsigned transactions, and submits them to any Solana RPC endpoint. The agent signs with its own keypair. No server processes the request. No intermediary touches the transaction. The path is:\n\n```\nAgent → SDK (local, Anchor IDL) → Solana RPC → On-chain program\n```\n\nThis is a direct consequence of treating Solana as a computing substrate. The program is the API. The accounts are the database. The RPC is the network layer. There is nothing else to trust, nothing else to go down, nothing else to rate-limit.\n\n### Discovery Chain\n\nAgents discover `torch.market` through a standard discovery chain:\n\n```\nllms.txt          → Human/AI-readable overview\n  └── agent.json  → Structured metadata, capabilities, actions\n  └── skill.md    → Machine-readable SDK reference\n  └── openapi.json → Full OpenAPI specification\n```\n\n### Agent Kit Plugin\n\nFor agents built on the Solana Agent Kit, a dedicated plugin is available:\n\n```\nnpm install solana-agent-kit-torch-market\n```\n\nThe plugin wraps the SDK with typed actions (buy, sell, create, vote, lend, message) and handles transaction signing automatically. Humans and agents use the same on-chain program — there is no separate \"bot mode.\"\n\n---\n\n## 12. Protocol Architecture\n\nThe on-chain program is a directed graph of economic relationships. PDA seeds define the edges, handlers define the legal traversals. The topology enforces correctness — relationships between accounts are guaranteed by the Solana runtime, not by application logic.\n\n```\n┌─────────────────────────────────────────────────────────────────────────────────────┐\n│                          TORCH MARKET PROTOCOL v3.7.8                                 │\n├─────────────────────────────────────────────────────────────────────────────────────┤\n│                                                                                      │\n│  ┌─────────────────────────────────────────────────────────────────────────────┐    │\n│  │                           PROTOCOL LAYER                                     │    │\n│  │  ┌─────────────────┐  ┌──────────────────────────────────────┐              │    │\n│  │  │  GlobalConfig   │  │        ProtocolTreasury               │              │    │\n│  │  │  (authority,    │  │  (1% fees + reclaimed SOL,            │              │    │\n│  │  │   settings)     │  │   no floor, epoch rewards)            │              │    │\n│  │  └─────────────────┘  └──────────────────────────────────────┘              │    │\n│  └─────────────────────────────────────────────────────────────────────────────┘    │\n│                                       │                                              │\n│                                       ▼                                              │\n│  ┌─────────────────────────────────────────────────────────────────────────────┐    │\n│  │                           PER-TOKEN LAYER                                    │    │\n│  │                                                                              │    │\n│  │  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐                   │    │\n│  │  │    Token     │    │   Bonding    │    │   Treasury   │                   │    │\n│  │  │   (Mint)     │───▶│    Curve     │───▶│  (lending,   │                   │    │\n│  │  │  Token-2022  │    │  (pricing,   │    │   stars,     │                   │    │\n│  │  │ 0.04% xfer │    │   voting)    │    │   lending)   │                   │    │\n│  │  └──────────────┘    └──────┬───────┘    └──────────────┘                   │    │\n│  │                             │                                                │    │\n│  │         ┌───────────────────┼───────────────────┐                           │    │\n│  │         ▼                   ▼                   ▼                           │    │\n│  │  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐                   │    │\n│  │  │  Token Vault │    │  Treasury's  │    │  Raydium     │                   │    │\n│  │  │  (tradeable  │    │  Token Acct  │    │  CPMM Pool   │                   │    │\n│  │  │   supply)    │    │  (vote vault)│    │  (post-grad) │                   │    │\n│  │  └──────────────┘    └──────────────┘    └──────────────┘                   │    │\n│  └─────────────────────────────────────────────────────────────────────────────┘    │\n│                                       │                                              │\n│                                       ▼                                              │\n│  ┌─────────────────────────────────────────────────────────────────────────────┐    │\n│  │                            USER LAYER                                        │    │\n│  │  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐              │    │\n│  │  │  UserPosition   │  │   UserStats     │  │   StarRecord    │              │    │\n│  │  │  (per-token     │  │  (platform-wide │  │  (per-token     │              │    │\n│  │  │   holdings,     │  │   volume,       │  │   appreciation) │              │    │\n│  │  │   vote)         │  │   rewards)      │  │                 │              │    │\n│  │  └─────────────────┘  └─────────────────┘  └─────────────────┘              │    │\n│  └─────────────────────────────────────────────────────────────────────────────┘    │\n│                                       │                                              │\n│                                       ▼                                              │\n│  ┌─────────────────────────────────────────────────────────────────────────────┐    │\n│  │                    VAULT LAYER (V3.1.0 — Full Custody)                       │    │\n│  │  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐              │    │\n│  │  │   TorchVault    │  │VaultWalletLink  │  │  Vault ATAs     │              │    │\n│  │  │  (per-creator   │◀─│  (per-wallet    │  │  (per-mint      │              │    │\n│  │  │   SOL + token   │  │   reverse       │  │   token accts   │              │    │\n│  │  │   full custody) │  │   pointer)      │  │   owned by PDA) │              │    │\n│  │  └─────────────────┘  └─────────────────┘  └─────────────────┘              │    │\n│  └─────────────────────────────────────────────────────────────────────────────┘    │\n│                                                                                      │\n├─────────────────────────────────────────────────────────────────────────────────────┤\n│  INSTRUCTION HANDLERS (27 total)                                                     │\n│  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐      │\n│  │ admin  │ │ token  │ │ market │ │treasury│ │ dex    │ │rewards │ │reclaim │      │\n│  │        │ │        │ │        │ │/lending│ │migrate │ │        │ │/revival│      │\n│  └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘      │\n│  ┌────────┐ ┌────────┐                                                               │\n│  │ vault  │ │  swap  │                                                               │\n│  │        │ │(V3.1.1)│                                                               │\n│  └────────┘ └────────┘                                                               │\n└─────────────────────────────────────────────────────────────────────────────────────┘\n```\n\n### On-Chain Account Types\n\nThe protocol uses 12 on-chain account types, all deterministic PDAs:\n\n| Account | PDA Seeds | Purpose |\n|---------|-----------|---------|\n| **GlobalConfig** | `[\"global_config\"]` | Protocol-wide settings (authority, fees, pause flag) |\n| **BondingCurve** | `[\"bonding_curve\", mint]` | Per-token pricing state, reserves, votes, bonding target |\n| **Treasury** | `[\"treasury\", mint]` | Per-token treasury (SOL for lending, star balance, fee accumulation) |\n| **TreasuryLock** | `[\"treasury_lock\", mint]` | [V31] Holds 300M locked tokens (30% of supply) |\n| **UserPosition** | `[\"user_position\", bc, user]` | Per-user per-token holdings and vote |\n| **UserStats** | `[\"user_stats\", user]` | Platform-wide volume and reward tracking |\n| **ProtocolTreasury** | `[\"protocol_treasury_v11\"]` | Single treasury: fees + reclaims, no floor, epoch rewards (V32) |\n| **StarRecord** | `[\"star_record\", user, mint]` | Prevents double-starring |\n| **LoanPosition** | `[\"loan\", mint, user]` | Per-user per-token lending position |\n| **TorchVault** | `[\"torch_vault\", creator]` | Per-creator full-custody SOL + token escrow |\n| **VaultWalletLink** | `[\"vault_wallet\", wallet]` | Reverse pointer: wallet → vault (one link per wallet) |\n\n### Instruction Set\n\nThe V3.7.8 program exposes 27 instructions across 9 handler domains:\n\n| Domain | Instructions |\n|--------|-------------|\n| **Admin** | `initialize`, `initialize_protocol_treasury`, `update_dev_wallet` |\n| **Token** | `create_token` |\n| **Market** | `buy`, `sell` |\n| **Treasury** | `harvest_fees`, `swap_fees_to_sol` |\n| **Migration** | `fund_migration_wsol`, `migrate_to_dex` |\n| **Rewards** | `advance_protocol_epoch`, `claim_protocol_rewards`, `star_token` |\n| **Reclaim/Revival** | `reclaim_failed_token`, `contribute_revival` |\n| **Vault** | `create_vault`, `deposit_vault`, `withdraw_vault`, `link_wallet`, `unlink_wallet`, `transfer_authority`, `withdraw_tokens` |\n| **Swap** | `fund_vault_wsol`, `vault_swap` |\n| **Lending** | `borrow`, `repay`, `liquidate` |\n\n> **Note (V3.7.0):** `update_authority` was removed. Minimal admin surface: only `initialize` and `update_dev_wallet` require authority.\n>\n> **Note (V3.7.5):** V31 zero-burn migration. CURVE_SUPPLY 750M→700M, TREASURY_LOCK 250M→300M. Transfer fee 0.1%→0.03%. Vote return → treasury lock.\n>\n> **Note (V3.7.6):** V32 protocol treasury rebalance. Reserve floor removed (0 SOL). Volume eligibility 10→2 SOL. Min claim 0.1 SOL. Fee split 90/10 (was 75/25). 39 Kani proofs.\n>\n> **Note (V3.7.7):** V33 buyback removed, lending extended. `execute_auto_buyback` instruction removed (27 instructions). Lending utilization cap 50%→70%. Treasury simplified to fee harvest → sell → SOL → lending yield + epoch rewards.\n>\n> **Note (V3.7.8):** V34 creator revenue. Three creator income streams: bonding SOL share (0.2%→1% carved from treasury rate), 15% of post-migration fee swap proceeds, star payout (cost reduced 0.05→0.02 SOL). Transfer fee 3→4 bps (new tokens only). `creator` account added to `buy` and `swap_fees_to_sol`. 43 Kani proofs.\n\n### Bonding Curve Formula\n\nThe protocol uses a constant product bonding curve:\n\n```\nBuy:   tokens_out = (virtual_token_reserves × sol_in) / (virtual_sol_reserves + sol_in)\nSell:  sol_out    = (virtual_sol_reserves × token_in) / (virtual_token_reserves + token_in)\nPrice: price      = virtual_sol_reserves / virtual_token_reserves\n```\n\n**Tiered Virtual Reserves (V27):** Each tier has per-tier initial virtual reserves tuned for a consistent ~13.44x multiplier:\n\n| Tier | Target | IVS (3BT/8) | IVT | Curve Supply | Treasury Lock |\n|------|--------|-------------|-----|-------------|---------------|\n| **Spark** | 50 SOL | 18.75 SOL | 756.25M | 700M (70%) | 300M (30%) |\n| **Flame** | 100 SOL | 37.5 SOL | 756.25M | 700M (70%) | 300M (30%) |\n| **Torch** | 200 SOL | 75 SOL | 756.25M | 700M (70%) | 300M (30%) |\n\n### Fee Flow\n\n```\n                              BUYER'S SOL\n                                  │\n                                  ▼\n               ┌──────────────────────────────────────┐\n               │           TOTAL SOL INPUT            │\n               └──────────────────────────────────────┘\n                                  │\n           ┌──────────────────────┼──────────────────────┐\n           │                      │                      │\n           ▼                      ▼                      ▼\n    ┌─────────────┐       ┌─────────────┐       ┌─────────────┐\n    │  1% Protocol│       │ 1% Treasury │       │    98%      │\n    │    Fee      │       │    Fee      │       │  Remaining  │\n    └──────┬──────┘       └──────┬──────┘       └──────┬──────┘\n           │                     │                     │\n      ┌────┴────┐                │              ┌──────┴──────┐\n      │         │                │              │             │\n      ▼         ▼                ▼              ▼             ▼\n┌─────────┐ ┌─────────┐   ┌──────────┐   ┌───────────┐ ┌──────────┐ ┌───────────┐\n│Protocol │ │  Dev    │   │  Token   │   │  Token    │ │ Creator  │ │  Bonding  │\n│Treasury │ │ Wallet  │   │ Treasury │   │ Treasury  │ │ Wallet   │ │   Curve   │\n│  (90%)  │ │  (10%)  │   │  (100%)  │   │(19.8→4%)*│ │(0.2→1%)*│ │(80%→95%)* │\n└─────────┘ └─────────┘   └────┬─────┘   └───────────┘ └──────────┘ └─────┬─────┘\n                               │                                           │\n                               │    *V34: Treasury split 3 ways:           ▼\n                               │    Total 20%→5% (V25 flat decay)   ┌─────────────┐\n                               │    Creator 0.2%→1% (carved out)    │   TOKENS    │\n                               │    Treasury gets remainder         │    OUT      │\n                               │                                    └──────┬──────┘\n                               │                                           │\n                               │                      ┌────────┴────────┐\n                               │                      │                 │\n                               ▼                      ▼                 ▼\n                        ┌─────────────┐        ┌─────────────┐   ┌───────────┐\n                        │  LENDING    │        │   BUYER     │   │ COMMUNITY │\n                        │  (yield)    │        │   (90%)     │   │ TREASURY  │\n                        └─────────────┘        └─────────────┘   │   (10%)   │\n                                                                 └─────┬─────┘\n                                                                       │\n                                                           ┌───────────┴───────────┐\n                                                           │      AT MIGRATION     │\n                                                           │    (based on vote)    │\n                                                           ├───────────────────────┤\n                                                           │ BURN → destroy tokens │\n                                                           │ RETURN → treasury lock│\n                                                           └───────────────────────┘\n```\n\n### Security Model\n\n**Access Control:**\n- **Authority-only:** `initialize`, `update_dev_wallet`\n- **Vault authority-only:** `withdraw_vault`, `link_wallet`, `unlink_wallet`, `transfer_authority`, `withdraw_tokens`\n- **Permissionless cranks:** `advance_protocol_epoch`, `harvest_fees`, `swap_fees_to_sol`, `fund_migration_wsol`, `migrate_to_dex`, `reclaim_failed_token`, `liquidate`\n- **Permissionless deposits:** Anyone can deposit into any vault\n\n**Vault Security (V3.1.0 — Full Custody):**\n- One vault per creator (PDA uniqueness)\n- One link per wallet (PDA uniqueness)\n- Authority separation: `creator` (immutable seed) vs `authority` (transferable admin)\n- All value stays in vault — agent wallet never holds tokens or significant SOL\n- CPI ordering enforced: token CPIs before lamport manipulation in all vault paths\n- Compromised key safety: attacker gets dust, authority unlinks and re-links\n\n**Raydium Pool Validation (V27 — PDA-Based):**\nPool accounts validated via PDA derivation constraints in Anchor contexts (`derive_pool_state`, `derive_pool_vault`, `derive_observation_state`). AMM config hardcoded to prevent fee-tier substitution. Oracle manipulation impossible — an attacker cannot derive a valid PDA pointing to a fake pool.\n\n### Formal Verification\n\nCore arithmetic is formally verified with [Kani](https://model-checking.github.io/kani/) — 43 proof harnesses, all passing, covering every possible input in constrained ranges. Proofs cover: fee calculations, bonding curve pricing, lending formulas (borrow/repay/liquidate lifecycle), reward distribution, sell-cycle ratio math, migration conservation, and V25/V27 token distribution. No SOL can be created from nothing, no tokens can be minted from thin air, and no fees can exceed their stated rates. See [VERIFICATION.md](https://torch.market/verification.md).\n\n### Security Audit History\n\n**V3.2.1 — `harvest_fees` Unconstrained Destination (CRITICAL, Fixed)**\nThe `harvest_fees` instruction did not validate that `treasury_token_account` matched the treasury PDA's ATA. An attacker could substitute their own Token-2022 ATA and steal all accumulated transfer fees. Fixed with Anchor `associated_token` constraints. Independent auditor verified.\n\n**V3.2.1 — Oracle Manipulation via Unconstrained Raydium Pool (Non-Issue)**\nPool accounts were reported as unconstrained. Assessment: `validate_pool_accounts()` already validates pool ownership, vault addresses, and mint composition. V27 further hardens this with PDA-based derivation constraints.\n\n---\n\n## Token Lifecycle\n\n```\nCREATE → BONDING → COMPLETE → VOTE → MIGRATE → DEX\n   │                                              │\n   │                                              ▼\n   │                                   [0.04% Transfer Fee]\n   │                                              │\n   │                                              ▼\n   │                                    HARVEST → SWAP TO SOL → LENDING → YIELD\n   │                                              │\n   │                                     ┌────────┴────────┐\n   │                                     │                  │\n   │                              [TREASURY LENDING]  [MESSAGE BOARD]\n   │                                     │\n   │                              BORROW ↔ REPAY\n   │                                     │\n   │                                LIQUIDATION\n   │\n   ▼ (if 7 days inactive)\nRECLAIM ──────────────────────────────────────────────────────┐\n   │                                                           │\n   ▼                                                           ▼\nREVIVAL (IVS per tier) ──→ TRADING RESUMES          PROTOCOL TREASURY\n                                                              │\n                                                              ▼\n                                                    EPOCH REWARDS TO TRADERS\n```\n\nEvery path in this graph feeds value back into the system. There is no terminal node that extracts value — only cycles that compound it.\n\n---\n\n## Constants Reference\n\n| Parameter | Value | Description |\n|-----------|-------|-------------|\n| Total Supply | 1,000,000,000 | Initial token supply (6 decimals) |\n| Max Wallet | 2% (20,000,000) | Maximum tokens per wallet during bonding |\n| Bonding Target | 50 / 100 / 200 SOL | Spark / Flame / Torch tier (creator chooses at launch) |\n| Community Treasury | 10% | Portion of bought tokens to vote vault |\n| Treasury SOL Share | 20%→5% | Dynamic: decays as bonding progresses |\n| Token Treasury Fee | 1% | Fee on all buys (lifetime) |\n| Protocol Fee | 1% | Fee during bonding (90% treasury, 10% dev) |\n| Transfer Fee | 0.04% (4 bps) | [V34] Post-migration fee on all transfers (immutable per mint, pre-V34 tokens retain 3 bps) |\n| Inactivity Period | 7 days | Time before failed token can be reclaimed |\n| Revival Threshold (V27) | 3BT/8 per tier (18.75 / 37.5 / 75 SOL) | SOL needed to revive a reclaimed token |\n| Voting Duration | ~24 hours | Time for community to vote on burn/return |\n| Epoch Duration | 7 days | Protocol reward distribution cycle |\n| Reward Eligibility | 2 SOL | Minimum epoch volume for protocol rewards |\n| Min Claim | 0.1 SOL | Minimum payout per claim (rejects dust) |\n| Protocol Reserve | 0 SOL | All fees distributed each epoch (no floor) |\n| Max LTV | 50% | Maximum loan-to-value for treasury lending |\n| Liquidation Threshold | 65% | Debt-to-collateral ratio triggering liquidation |\n| Interest Rate | 2% / epoch | Lending interest per ~7-day epoch |\n| Liquidation Bonus | 10% | Discount for liquidators on seized collateral |\n| Utilization Cap | 70% | Max fraction of treasury SOL available for loans |\n| Min Borrow | 0.1 SOL | Minimum borrow amount per loan |\n\n---\n\n## Version History\n\n| Version | Features |\n|---------|----------|\n| V1 | Basic bonding curve, buy/sell |\n| V2 | Treasury, fee accumulation, permanent burn split |\n| V3 | Token-2022 with transfer fees |\n| V4 | Failed token reclaim, platform rewards |\n| V5 | Raydium DEX migration |\n| V8 | Dev wallet split (10% of protocol fee, updated V32 from 25%) |\n| V9 | Ratio-gated sell cycle (buyback removed in V33) |\n| V10 | Simplified star system with auto-payout |\n| V11 | Protocol treasury with epoch rewards (reserve floor removed in V32) |\n| V12 | Token revival |\n| V2.2 | 10% tokens to community treasury, 90% to buyer |\n| V2.3 | Dynamic treasury SOL rate: 20%→5% decay |\n| V2.4 | Treasury lending: borrow SOL against token collateral |\n| V3.0.0 | **Torch Vault — Multi-Wallet Identity.** Per-creator SOL escrow with multi-wallet support. 6 new vault instructions. |\n| V3.1.0 | **Vault Full Custody.** Buy, sell, star, borrow, repay all vault-routed. New `withdraw_tokens` (authority-only). |\n| V3.1.1 | **Vault DEX Swap.** `fund_vault_wsol` + `vault_swap` for Raydium trading via vault. |\n| V3.2.0 | **Platform treasury merged into protocol treasury.** Single reward system. |\n| V3.2.1 | **Security: `harvest_fees` hardened.** Critical vulnerability fixed, auditor verified. |\n| V3.3.0 | **Tiered Bonding Curves.** Spark (50 SOL), Flame (100 SOL), Torch (200 SOL). |\n| V3.5.0 | **V25 Pump-Style Token Distribution.** IVS = BT/8, IVT = 900M tokens, ~81x multiplier. 35 Kani proofs. |\n| V3.6.0 | **V26 Permissionless Migration + Authority Revocation.** Mint and freeze authority revoked permanently at migration. |\n| V3.6.x | **V27 Treasury Lock + PDA Pool Validation.** 250M tokens locked at creation. IVS = 3BT/8, 13.44x multiplier. |\n| V3.7.0 | **V28 `update_authority` Removed.** Authority transfer via multisig tooling. 27 instructions. Minimal admin surface. |\n| V3.7.5 | **V31 Zero-Burn Migration.** CURVE_SUPPLY 750M→700M, TREASURY_LOCK 250M→300M. Transfer fee 0.1%→0.03%. Vote return → treasury lock. |\n| V3.7.6 | **V32 Protocol Treasury Rebalance.** Reserve floor removed. Volume eligibility 10→2 SOL. Min claim 0.1 SOL. Fee split 90/10. 39 Kani proofs. |\n| V3.7.7 | **V33 Buyback Removed, Lending Extended.** `execute_auto_buyback` removed (27 instructions). Lending utilization cap 50%→70%. Treasury simplified to: fee harvest → sell → SOL → lending yield + epoch rewards. |\n| V3.7.8 | **V34 Creator Revenue + Transfer Fee Bump.** Three creator income streams: bonding SOL share (0.2%→1%), post-migration fee share (85/15 treasury/creator), star payout. Star cost 0.05→0.02 SOL. Transfer fee 3→4 bps (new tokens only). 43 Kani proofs. |\n\n---\n\n## Conclusion\n\n`torch.market` is a programmable economic substrate. Every token launched on the protocol receives a complete, self-sustaining economy: a pricing engine, a treasury with lending yield, community governance, creator rewards, a failure-recovery system, and optional privacy — all composed from a small set of on-chain primitives that enforce correctness by topology.\n\nThe protocol is non-extractive by design. There is no configuration that makes it extractive because the graph doesn't have that edge. Fees become lending yield. Lending yield becomes community liquidity. Failed tokens become protocol rewards. Interest from borrowers compounds the treasury. Every outflow is an inflow somewhere else in the system.\n\nThe Torch Vault adds a custody-aware resolution layer that makes every economic flow in the protocol accessible through a single identity — without adding economic complexity. Agents and humans use the same on-chain program, the same API, the same graph.\n\nThe individual pieces — bonding curves, treasuries, lending, governance — are not new. The arrangement is. A closed, positive-sum economic graph where anyone can launch a token and receive a complete financial ecosystem, running on Solana as a distributed computing substrate.\n\n**This is not a zero-sum game. This is not a launchpad. This is a substrate for programmable economies.**\n\n---\n\n*© 2026 Brightside Solutions. All rights reserved.*\n\n[Terms](https://torch.market/terms) | [Privacy](https://torch.market/privacy) | [torch.market](https://torch.market)\n\nFile v4.0.4:agent.json\n\n{\n  \"name\": \"Torch Liquidation Bot\",\n  \"description\": \"Autonomous vault-based liquidation keeper for Torch Market lending on Solana. Scans all migrated tokens for underwater loan positions (LTV > 65%) using the SDK's built-in bulk loan scanner (getAllLoanPositions), builds and executes liquidation transactions through a Torch Vault, and collects a 10% collateral bonus. The agent keypair is generated in-process -- disposable, holds nothing of value. All SOL and collateral tokens route through the vault. The human principal creates the vault, funds it, links the agent, and retains full control. Built on torchsdk v3.7.22 and the Torch Market protocol.\",\n  \"version\": \"4.0.4\",\n  \"type\": \"protocol\",\n  \"disable-model-invocation\": true,\n  \"website\": \"https://torch.market\",\n  \"socials\": {\n    \"twitter\": \"https://twitter.com/torch_market\"\n  },\n  \"distribution\": {\n    \"clawhub\": \"https://clawhub.ai/mrsirg97-rgb/torch-liquidation-bot\",\n    \"kit\": \"https://github.com/mrsirg97-rgb/torch-liquidation-kit\",\n    \"npm_bot\": \"torch-liquidation-bot\",\n    \"npm_sdk\": \"torchsdk\"\n  },\n  \"requires\": {\n    \"env\": [\n      {\n        \"name\": \"SOLANA_RPC_URL\",\n        \"description\": \"Solana RPC endpoint (HTTPS). Fallback: RPC_URL\",\n        \"sensitive\": false,\n        \"required\": true\n      },\n      {\n        \"name\": \"VAULT_CREATOR\",\n        \"description\": \"Vault creator pubkey -- identifies which Torch Vault the bot operates through. Required.\",\n        \"sensitive\": false,\n        \"required\": true\n      },\n      {\n        \"name\": \"SOLANA_PRIVATE_KEY\",\n        \"description\": \"Disposable controller keypair (base58 or byte array JSON). Optional -- the bot generates a fresh keypair in-process if not provided (recommended). If provided, should be a fresh keypair with ~0.01 SOL for gas. Holds no value. All liquidation capital lives in the vault.\",\n        \"sensitive\": true,\n        \"required\": false\n      }\n    ],\n    \"install\": [\n      {\n        \"id\": \"npm-torch-liquidation-bot\",\n        \"kind\": \"npm\",\n        \"package\": \"torch-liquidation-bot@^4.0.2\",\n        \"flags\": [],\n        \"label\": \"Install Torch Liquidation Bot (npm, optional -- SDK is bundled in lib/torchsdk/ and bot source is bundled under lib/kit on clawhub)\"\n      }\n    ]\n  },\n  \"capabilities\": [\n    \"vault-full-custody\",\n    \"vault-escrow\",\n    \"authority-separation\",\n    \"liquidation-keeper\",\n    \"lending-market-scanner\",\n    \"autonomous-scan-loop\",\n    \"in-process-keypair\",\n    \"read-only-mode\",\n    \"said-verification\"\n  ],\n  \"chain\": \"solana\",\n  \"network\": \"mainnet\",\n  \"program_id\": \"8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeT\",\n  \"endpoints\": {\n    \"skill\": \"https://torch.market/skill.md\",\n    \"llms_txt\": \"https://torch.market/llms.txt\",\n    \"docs\": \"https://torch-market-docs.vercel.app\"\n  },\n  \"actions\": [\n    {\n      \"name\": \"TORCH_SCAN_LENDING_MARKETS\",\n      \"description\": \"Discover all migrated tokens and check their lending state for active loans\"\n    },\n    {\n      \"name\": \"TORCH_CHECK_LOAN_HEALTH\",\n      \"description\": \"Check a borrower's loan position -- collateral, debt, interest, LTV, health status\"\n    },\n    {\n      \"name\": \"TORCH_LIQUIDATE\",\n      \"description\": \"Liquidate underwater loan position (LTV > 65%) via vault -- vault SOL pays debt, collateral tokens at 10% discount go to vault ATA\"\n    },\n    {\n      \"name\": \"TORCH_GET_VAULT\",\n      \"description\": \"Get vault state by creator -- SOL balance, linked wallets, authority, token holdings\"\n    },\n    {\n      \"name\": \"TORCH_GET_VAULT_FOR_WALLET\",\n      \"description\": \"Reverse lookup -- find which vault a controller wallet is linked to\"\n    },\n    {\n      \"name\": \"TORCH_GET_LENDING_INFO\",\n      \"description\": \"Get lending configuration and state for a migrated token (rates, caps, active loans)\"\n    },\n    {\n      \"name\": \"TORCH_GET_LOAN\",\n      \"description\": \"Get loan position details for a wallet -- collateral, debt, interest, LTV, health status\"\n    },\n    {\n      \"name\": \"TORCH_LIST_TOKENS\",\n      \"description\": \"List migrated tokens with active lending markets\"\n    },\n    {\n      \"name\": \"TORCH_GET_TOKEN\",\n      \"description\": \"Get detailed token info including price, treasury state, and lending parameters\"\n    },\n    {\n      \"name\": \"TORCH_CONFIRM\",\n      \"description\": \"Confirm transaction on-chain via Solana RPC -- verifies signer, checks Torch instructions, determines event type. Does NOT contact SAID Protocol.\"\n    }\n  ],\n  \"constants\": {\n    \"lending_max_ltv_percent\": 50,\n    \"lending_liquidation_threshold_percent\": 65,\n    \"lending_interest_rate_per_epoch_percent\": 2,\n    \"lending_liquidation_bonus_percent\": 10,\n    \"lending_utilization_cap_percent\": 70,\n    \"min_borrow_sol\": 0.1,\n    \"default_scan_interval_ms\": 30000,\n    \"min_scan_interval_ms\": 5000\n  },\n  \"safety\": {\n    \"vault_full_custody\": true,\n    \"controller_holds_no_value\": true,\n    \"private_key_optional\": true,\n    \"in_process_keypair_generation\": true,\n    \"local_transaction_building\": true,\n    \"no_api_dependency\": true,\n    \"keys_never_transmitted\": true,\n    \"signing_is_local_only\": true,\n    \"vault_closed_economic_loop\": true,\n    \"vault_authority_only_withdrawals\": true,\n    \"vault_instant_revocation\": true,\n    \"transaction_expiry_seconds\": 60,\n    \"open_source\": true,\n    \"sdk_audited\": true,\n    \"rpc_timeout_seconds\": 30\n  },\n  \"tags\": [\n    \"solana\",\n    \"defi\",\n    \"liquidation\",\n    \"liquidation-bot\",\n    \"liquidation-keeper\",\n    \"collateral-lending\",\n    \"vault-custody\",\n    \"ai-agents\",\n    \"agent-wallet\",\n    \"agent-safety\",\n    \"treasury-lending\",\n    \"bonding-curve\",\n    \"fair-launch\",\n    \"token-2022\",\n    \"raydium\",\n    \"community-treasury\",\n    \"protocol-rewards\",\n    \"solana-agent-kit\",\n    \"escrow\",\n    \"anchor\",\n    \"pda\",\n    \"on-chain\",\n    \"autonomous-agent\",\n    \"keeper-bot\",\n    \"torch-market\"\n  ],\n  \"verification\": {\n    \"said\": {\n      \"wallet\": \"8cpWmV4kGdvxVYYNBEMPNwsJSRVQw5MQ9NXn4t293nMa\",\n      \"pda\": \"2rNknLxB7nWYJRgr2tZrNoc7PNDy3PKwKZa9YStbLMmb\",\n      \"verified\": true,\n      \"trust_tier\": \"medium\",\n      \"badge\": \"https://api.saidprotocol.com/api/badge/8cpWmV4kGdvxVYYNBEMPNwsJSRVQw5MQ9NXn4t293nMa.svg\"\n    }\n  }\n}\n\nFile v4.0.4:lib/torchsdk/torch_market.json\n\n{\n    \"address\": \"8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeT\",\n    \"metadata\": {\n        \"name\": \"torch_market\",\n        \"version\": \"3.7.8\",\n        \"spec\": \"0.1.0\",\n        \"description\": \"torch.market\"\n    },\n    \"instructions\": [\n        {\n            \"name\": \"advance_protocol_epoch\",\n            \"docs\": [\n                \"[V11] Advance the protocol treasury epoch.\",\n                \"Permissionless crank - calculates distributable amount above reserve floor.\"\n            ],\n            \"discriminator\": [\n                215,\n                39,\n                184,\n                104,\n                13,\n                104,\n                63,\n                21\n            ],\n            \"accounts\": [\n                {\n                    \"name\": \"payer\",\n                    \"writable\": true,\n                    \"signer\": true\n                },\n                {\n                    \"name\": \"protocol_treasury\",\n                    \"writable\": true,\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"const\",\n                                \"value\": [\n                                    112,\n                                    114,\n                                    111,\n                                    116,\n                                    111,\n                                    99,\n                                    111,\n                                    108,\n                                    95,\n                                    116,\n                                    114,\n                                    101,\n                                    97,\n                                    115,\n                                    117,\n                                    114,\n                                    121,\n                                    95,\n                                    118,\n                                    49,\n                                    49\n                                ]\n                            }\n                        ]\n                    }\n                }\n            ],\n            \"args\": []\n        },\n        {\n            \"name\": \"borrow\",\n            \"docs\": [\n                \"[V2.4] Borrow SOL from treasury using tokens as collateral.\",\n                \"Lock tokens in collateral vault, receive SOL up to 50% of collateral value.\"\n            ],\n            \"discriminator\": [\n                228,\n                253,\n                131,\n                202,\n                207,\n                116,\n                89,\n                18\n            ],\n            \"accounts\": [\n                {\n                    \"name\": \"borrower\",\n                    \"writable\": true,\n                    \"signer\": true\n                },\n                {\n                    \"name\": \"mint\"\n                },\n                {\n                    \"name\": \"bonding_curve\",\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"const\",\n                                \"value\": [\n                                    98,\n                                    111,\n                                    110,\n                                    100,\n                                    105,\n                                    110,\n                                    103,\n                                    95,\n                                    99,\n                                    117,\n                                    114,\n                                    118,\n                                    101\n                                ]\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"mint\"\n                            }\n                        ]\n                    }\n                },\n                {\n                    \"name\": \"treasury\",\n                    \"writable\": true,\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"const\",\n                                \"value\": [\n                                    116,\n                                    114,\n                                    101,\n                                    97,\n                                    115,\n                                    117,\n                                    114,\n                                    121\n                                ]\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"mint\"\n                            }\n                        ]\n                    }\n                },\n                {\n                    \"name\": \"collateral_vault\",\n                    \"docs\": [\n                        \"Collateral vault - holds locked tokens. Created on first borrow for this token.\"\n                    ],\n                    \"writable\": true,\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"const\",\n                                \"value\": [\n                                    99,\n                                    111,\n                                    108,\n                                    108,\n                                    97,\n                                    116,\n                                    101,\n                                    114,\n                                    97,\n                                    108,\n                                    95,\n                                    118,\n                                    97,\n                                    117,\n                                    108,\n                                    116\n                                ]\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"mint\"\n                            }\n                        ]\n                    }\n                },\n                {\n                    \"name\": \"borrower_token_account\",\n                    \"docs\": [\n                        \"Borrower's token account (source of collateral)\"\n                    ],\n                    \"writable\": true,\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"borrower\"\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"token_program\"\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"mint\"\n                            }\n                        ],\n                        \"program\": {\n                            \"kind\": \"const\",\n                            \"value\": [\n                                140,\n                                151,\n                                37,\n                                143,\n                                78,\n                                36,\n                                137,\n                                241,\n                                187,\n                                61,\n                                16,\n                                41,\n                                20,\n                                142,\n                                13,\n                                131,\n                                11,\n                                90,\n                                19,\n                                153,\n                                218,\n                                255,\n                                16,\n                                132,\n                                4,\n                                142,\n                                123,\n                                216,\n                                219,\n                                233,\n                                248,\n                                89\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"name\": \"loan_position\",\n                    \"docs\": [\n                        \"Loan position PDA - created on first borrow\"\n                    ],\n                    \"writable\": true,\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"const\",\n                                \"value\": [\n                                    108,\n                                    111,\n                                    97,\n                                    110\n                                ]\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"mint\"\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"borrower\"\n                            }\n                        ]\n                    }\n                },\n                {\n                    \"name\": \"pool_state\",\n                    \"docs\": [\n                        \"[V27] Raydium pool state — constrained via PDA derivation\"\n                    ]\n                },\n                {\n                    \"name\": \"token_vault_0\",\n                    \"docs\": [\n                        \"[V27] Pool token vault 0 — constrained via PDA derivation\"\n                    ]\n                },\n                {\n                    \"name\": \"token_vault_1\",\n                    \"docs\": [\n                        \"[V27] Pool token vault 1 — constrained via PDA derivation\"\n                    ]\n                },\n                {\n                    \"name\": \"torch_vault\",\n                    \"docs\": [\n                        \"[V18] Optional: Torch vault — collateral comes from vault ATA, SOL goes to vault\"\n                    ],\n                    \"writable\": true,\n                    \"optional\": true\n                },\n                {\n                    \"name\": \"vault_wallet_link\",\n                    \"docs\": [\n                        \"[V18] Optional: Proves borrower is authorized to use the vault\"\n                    ],\n                    \"optional\": true,\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"const\",\n                                \"value\": [\n                                    118,\n                                    97,\n                                    117,\n                                    108,\n                                    116,\n                                    95,\n                                    119,\n                                    97,\n                                    108,\n                                    108,\n                                    101,\n                                    116\n                                ]\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"borrower\"\n                            }\n                        ]\n                    }\n                },\n                {\n                    \"name\": \"vault_token_account\",\n                    \"docs\": [\n                        \"[V18] Optional: Vault's token ATA — collateral taken from here\"\n                    ],\n                    \"writable\": true,\n                    \"optional\": true,\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"torch_vault\"\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"token_program\"\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"mint\"\n                            }\n                        ],\n                        \"program\": {\n                            \"kind\": \"const\",\n                            \"value\": [\n                                140,\n                                151,\n                                37,\n                                143,\n                                78,\n                                36,\n                                137,\n                                241,\n                                187,\n                                61,\n                                16,\n                                41,\n                                20,\n                                142,\n                                13,\n                                131,\n                                11,\n                                90,\n                                19,\n                                153,\n                                218,\n                                255,\n                                16,\n                                132,\n                                4,\n                                142,\n                                123,\n                                216,\n                                219,\n                                233,\n                                248,\n                                89\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"name\": \"token_program\"\n                },\n                {\n                    \"name\": \"system_program\",\n                    \"address\": \"11111111111111111111111111111111\"\n                }\n            ],\n            \"args\": [\n                {\n                    \"name\": \"args\",\n                    \"type\": {\n                        \"defined\": {\n                            \"name\": \"BorrowArgs\"\n                        }\n                    }\n                }\n            ]\n        },\n        {\n            \"name\": \"buy\",\n            \"docs\": [\n                \"Buy tokens from the bonding curve.\"\n            ],\n            \"discriminator\": [\n                102,\n                6,\n                61,\n                18,\n                1,\n                218,\n                235,\n                234\n            ],\n            \"accounts\": [\n                {\n                    \"name\": \"buyer\",\n                    \"writable\": true,\n                    \"signer\": true\n                },\n                {\n                    \"name\": \"global_config\",\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"const\",\n                                \"value\": [\n                                    103,\n                                    108,\n                                    111,\n                                    98,\n                                    97,\n                                    108,\n                                    95,\n                                    99,\n                                    111,\n                                    110,\n                                    102,\n                                    105,\n                                    103\n                                ]\n                            }\n                        ]\n                    }\n                },\n                {\n                    \"name\": \"dev_wallet\",\n                    \"writable\": true\n                },\n                {\n                    \"name\": \"mint\",\n                    \"writable\": true\n                },\n                {\n                    \"name\": \"bonding_curve\",\n                    \"writable\": true,\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"const\",\n                                \"value\": [\n                                    98,\n                                    111,\n                                    110,\n                                    100,\n                                    105,\n                                    110,\n                                    103,\n                                    95,\n                                    99,\n                                    117,\n                                    114,\n                                    118,\n                                    101\n                                ]\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"mint\"\n                            }\n                        ]\n                    }\n                },\n                {\n                    \"name\": \"token_vault\",\n                    \"writable\": true,\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"bonding_curve\"\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"token_program\"\n                            },\n                            {\n                                \"kind\": \"account\",\n                                \"path\": \"mint\"\n                            }\n                        ],\n                        \"program\": {\n                            \"kind\": \"const\",\n                            \"value\": [\n                                140,\n                                151,\n                                37,\n                                143,\n                                78,\n                                36,\n                                137,\n                                241,\n                                187,\n                                61,\n                                16,\n                                41,\n                                20,\n                                142,\n                                13,\n                                131,\n                                11,\n                                90,\n                                19,\n                                153,\n                                218,\n                                255,\n                                16,\n                                132,\n                                4,\n                                142,\n                                123,\n                                216,\n                                219,\n                                233,\n                                248,\n                                89\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"name\": \"token_treasury\",\n                    \"docs\": [\n                        \"Per-token treasury for buybacks [V2]\"\n                    ],\n                    \"writable\": true,\n                    \"pda\": {\n                        \"seeds\": [\n                            {\n                                \"kind\": \"const\",\n                                \"value\": [\n                                    116,\n   \n\nArchive v4.0.3: 22 files, 94814 bytes\n\nFiles: agent.json (6139b), audit.md (21316b), design.md (12214b), lib/kit/config.js (1577b), lib/kit/index.js (7088b), lib/kit/types.js (182b), lib/kit/utils.js (1987b), lib/torchsdk/constants.js (6651b), lib/torchsdk/ephemeral.js (1330b), lib/torchsdk/gateway.js (1581b), lib/torchsdk/index.js (7875b), lib/torchsdk/program.js (12750b), lib/torchsdk/quotes.js (3751b), lib/torchsdk/said.js (3617b), lib/torchsdk/tokens.js (35336b), lib/torchsdk/torch_market.json (224333b), lib/torchsdk/transactions.js (65753b), lib/torchsdk/types.js (144b), SKILL.md (19765b), verification.md (16919b), whitepaper.md (48897b), _meta.json (138b)","readmeExcerpt":"Skill: Torch Liquidation Bot Owner: mrsirg97-rgb Summary: Autonomous vault-based liquidation keeper for Torch Market lending on Solana. Scans all migrated tokens for underwater loan positions (LTV > 65%) using the S... Tags: latest:4.0.4 Version history: v4.0.4 | 2026-02-28T15:16:50.792Z | user No user-facing changes detected in this release. Version bump only. - Version number updated to 4.0.4. - No changes to files","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"┌──────────────────────────────────────────────────────────┐\n│                  LIQUIDATION LOOP                          │\n│                                                           │\n│  1. Discover migrated tokens (getTokens)                  │\n│  2. For each token, scan all loans (getAllLoanPositions)   │\n│     — single RPC call, returns positions sorted by health │\n│     — liquidatable → at_risk → healthy                    │\n│  3. Skip tokens with no active loans                      │\n│  4. For each liquidatable position:                       │\n│     → buildLiquidateTransaction(vault=creator)            │\n│     → sign with agent keypair                             │\n│     → submit and confirm                                  │\n│     → break when health != 'liquidatable' (pre-sorted)    │\n│  5. Sleep SCAN_INTERVAL_MS, repeat                        │\n│                                                           │\n│  All SOL comes from vault. All collateral goes to vault.  │\n│  Agent wallet holds nothing. Vault is the boundary.       │\n└──────────────────────────────────────────────────────────┘"},{"language":"text","snippet":"--- ACTION REQUIRED ---\nagent wallet is NOT linked to the vault.\nlink it by running (from your authority wallet):\n\n  buildLinkWalletTransaction(connection, {\n    authority: \"<your-authority-pubkey>\",\n    vault_creator: \"<your-vault-creator>\",\n    wallet_to_link: \"<agent-pubkey>\"\n  })\n\nthen restart the bot.\n-----------------------"},{"language":"bash","snippet":"npm install torch-liquidation-bot@4.0.2"},{"language":"typescript","snippet":"import { Connection } from \"@solana/web3.js\";\nimport {\n  buildCreateVaultTransaction,\n  buildDepositVaultTransaction,\n} from \"./lib/torchsdk/index.js\";\n\nconst connection = new Connection(process.env.SOLANA_RPC_URL);\n\n// Create vault\nconst { transaction: createTx } = await buildCreateVaultTransaction(connection, {\n  creator: authorityPubkey,\n});\n// sign and submit with authority wallet...\n\n// Fund vault with SOL for liquidations\nconst { transaction: depositTx } = await buildDepositVaultTransaction(connection, {\n  depositor: authorityPubkey,\n  vault_creator: authorityPubkey,\n  amount_sol: 5_000_000_000, // 5 SOL\n});\n// sign and submit with authority wallet..."},{"language":"bash","snippet":"VAULT_CREATOR=<your-vault-creator-pubkey> SOLANA_RPC_URL=<rpc-url> npx torch-liquidation-bot"},{"language":"text","snippet":"packages/bot/src/\n├── index.ts    — entry point: keypair generation, vault verification, scan loop\n├── config.ts   — loadConfig(): validates SOLANA_RPC_URL, VAULT_CREATOR, SOLANA_PRIVATE_KEY, SCAN_INTERVAL_MS, LOG_LEVEL\n├── types.ts    — BotConfig, LogLevel interfaces\n└── utils.ts    — sol(), bpsToPercent(), withTimeout(), createLogger()"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: torch-liquidation-bot\nversion: \"4.0.4\"\ndescription: Autonomous vault-based liquidation keeper for Torch Market lending on Solana. Scans all migrated tokens for underwater loan positions (LTV > 65%) using the SDK's built-in bulk loan scanner (getAllLoanPositions), builds and executes liquidation transactions through a Torch Vault, and collects a 10% collateral bonus. The agent keypair is generated in-process -- disposable, holds nothing of value. All SOL and collateral tokens route through the vault. The human principal creates the vault, funds it, links the agent, and retains full control. Built on torchsdk v3.7.22 and the Torch Market protocol.\nlicense: MIT\ndisable-model-invocation: true\nrequires:\n  env:\n    - name: SOLANA_RPC_URL\n      required: true\n    - name: VAULT_CREATOR\n      required: true\n    - name: SOLANA_PRIVATE_KEY\n      required: false\nmetadata:\n  clawdbot:\n    requires:\n      env:\n        - name: SOLANA_RPC_URL\n          required: true\n        - name: VAULT_CREATOR\n          required: true\n        - name: SOLANA_PRIVATE_KEY\n          required: false\n  openclaw:\n    requires:\n      env:\n        - name: SOLANA_RPC_URL\n          required: true\n        - name: VAULT_CREATOR\n          required: true\n        - name: SOLANA_PRIVATE_KEY\n          required: false\n    install:\n      - id: npm-torch-liquidation-bot\n        kind: npm\n        package: torch-liquidation-bot@^4.0.2\n        flags: []\n        label: \"Install Torch Liquidation Bot (npm, optional -- SDK is bundled in lib/torchsdk/ and bot source is bundled under lib/kit on clawhub)\"\n  author: torch-market\n  version: \"4.0.4\"\n  clawhub: https://clawhub.ai/mrsirg97-rgb/torch-liquidation-bot\n  kit-source: https://github.com/mrsirg97-rgb/torch-liquidation-kit\n  website: https://torch.market\n  program-id: 8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeT\n  keywords:\n    - solana\n    - defi\n    - liquidation\n    - liquidation-bot\n    - liquidation-keeper\n    - collateral-lending\n    - vault-custody\n    - ai-agents\n    - agent-wallet\n    - agent-safety\n    - treasury-lending\n    - bonding-curve\n    - fair-launch\n    - token-2022\n    - raydium\n    - community-treasury\n    - protocol-rewards\n    - solana-agent-kit\n    - escrow\n    - anchor\n    - pda\n    - on-chain\n    - autonomous-agent\n    - keeper-bot\n    - torch-market\n  categories:\n    - solana-protocols\n    - defi-primitives\n    - lending-markets\n    - agent-infrastructure\n    - custody-solutions\n    - liquidation-keepers\ncompatibility: >-\n  REQUIRED: SOLANA_RPC_URL (HTTPS Solana RPC endpoint)\n  REQUIRED: VAULT_CREATOR (vault creator pubkey).\n  OPTIONAL: SOLANA_PRIVATE_KEY -- the bot generates a fresh disposable keypair in-process if not provided. The agent wallet holds nothing of value (~0.01 SOL for gas). All liquidation proceeds (collateral tokens) route to the vault. The vault can be created and funded entirely by the human principal. \n  This skill sets disable-model-invocation: true -- it must not be invoked autonomously withou"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7a0ff82yxwmqsge7kh9kdgqn80hpbf\",\n  \"slug\": \"torchliquidationbot\",\n  \"version\": \"4.0.4\",\n  \"publishedAt\": 1772291810792\n}"},{"path":"audit.md","content":"# Torch Liquidation Bot — Security Audit\n\n**Audit Date:** February 27, 2026\n**Auditor:** Claude Opus 4.6 (Anthropic)\n**Bot Version:** 4.0.2\n**Kit Version:** 2.0.0\n**SDK Version:** torchsdk 3.7.22\n**On-Chain Program:** `8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeT` (V3.7.7, 27 instructions)\n**Language:** TypeScript\n**Test Result:** 9 passed, 0 failed (Surfpool mainnet fork)\n\n---\n\n## Table of Contents\n\n1. [Executive Summary](#executive-summary)\n2. [Scope](#scope)\n3. [Methodology](#methodology)\n4. [What Changed (v3.0.2 → v4.0.0)](#what-changed-v302--v400)\n5. [Keypair Safety Review](#keypair-safety-review)\n6. [Vault Integration Review](#vault-integration-review)\n7. [Scan Loop Security](#scan-loop-security)\n8. [Configuration Validation](#configuration-validation)\n9. [Dependency Analysis](#dependency-analysis)\n10. [Threat Model](#threat-model)\n11. [Findings](#findings)\n12. [Resolved Findings from v3.0.2](#resolved-findings-from-v302)\n13. [Conclusion](#conclusion)\n\n---\n\n## Executive Summary\n\nThis audit covers the Torch Liquidation Bot v4.0.0, an autonomous keeper that scans Torch Market lending positions and liquidates underwater loans through a Torch Vault. The bot was reviewed for key safety, vault integration correctness, error handling, and dependency surface.\n\nThe major change in v4.0.0 is the replacement of the N+1 scan pattern (`getLendingInfo` → `getHolders` → per-holder `getLoanPosition`) with a single `getAllLoanPositions()` call per token. This reduces RPC calls from 2 + N per token to 1 per token, eliminates the 20-holder discovery ceiling from the previous version, and leverages the SDK's pre-sorted output to break early once all liquidatable positions are processed.\n\nThe bot remains **vault-first** (all value routes through the vault PDA), **disposable-key** (agent keypair generated in-process, holds nothing), and **single-purpose** (scan and liquidate only — no trading, borrowing, or token creation).\n\n### Overall Assessment\n\n| Category | Rating | Notes |\n|----------|--------|-------|\n| Key Safety | **PASS** | In-process `Keypair.generate()`, no key files, no key logging |\n| Vault Integration | **PASS** | `vault` param correctly passed to `buildLiquidateTransaction` |\n| Error Handling | **PASS** | Cycle-level catch, per-token try/catch, per-liquidation try/catch, 30s RPC timeout |\n| Config Validation | **PASS** | Required env vars checked, scan interval floored at 5000ms |\n| Dependencies | **MINIMAL** | 2 runtime deps, both pinned exact |\n| Supply Chain | **LOW RISK** | No post-install hooks, no remote code fetching |\n\n### Finding Summary\n\n| Severity | Count |\n|----------|-------|\n| Critical | 0 |\n| High | 0 |\n| Medium | 0 |\n| Low | 0 (1 resolved) |\n| Informational | 2 |\n\n---\n\n## Scope\n\n### Files Reviewed\n\n| File | Lines | Role |\n|------|-------|------|\n| `packages/bot/src/index.ts` | 192 | Entry point: keypair load/generate, vault check, scan loop |\n| `packages/bot/src/config.ts` | 36 | Environment variable validation |\n| `packages/bot/sr"},{"path":"design.md","content":"# Torch Liquidation Bot — Design Document\n\n> Autonomous vault-based liquidation keeper for Torch Market lending on Solana. Version 4.0.2.\n\n## Overview\n\nThe Torch Liquidation Bot is a single-purpose keeper that scans Torch Market lending positions and liquidates underwater loans through a Torch Vault. It generates a disposable agent keypair in-process, verifies vault linkage, and runs a continuous scan-liquidate loop. All SOL and collateral tokens route through the vault — the agent wallet holds nothing of value.\n\nThe bot is built on `torchsdk@3.7.22` and targets the Torch Market on-chain program (`8hbUkonssSEEtkqzwM7ZcZrD9evacM92TcWSooVF4BeT`). It uses the SDK's bulk loan scanner (`getAllLoanPositions`) to discover liquidatable positions and the vault-routed `buildLiquidateTransaction` to execute them.\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────┐\n│                    LIQUIDATION BOT                         │\n│                                                           │\n│  main()                                                   │\n│    ├── loadConfig()         → validate env vars            │\n│    ├── Keypair.generate()   → disposable agent keypair     │\n│    ├── getVault()           → verify vault exists           │\n│    ├── getVaultForWallet()  → verify agent linked to vault  │\n│    └── while (true)                                        │\n│         └── scanAndLiquidate()                             │\n│              ├── getTokens({ status: 'migrated' })         │\n│              ├── getAllLoanPositions(mint)                  │\n│              │    → returns positions sorted by health      │\n│              │    → break at first non-liquidatable         │\n│              ├── buildLiquidateTransaction(vault=creator)   │\n│              ├── transaction.sign(agentKeypair)             │\n│              ├── connection.sendRawTransaction()            │\n│              └── confirmTransaction()                      │\n└──────────────────────────┬───────────────────────────────┘\n                           │\n                           ▼\n┌──────────────────────────────────────────────────────────┐\n│                    torchsdk v3.7.22                        │\n│                                                           │\n│  Read-only queries:                                       │\n│    getTokens, getAllLoanPositions                          │\n│    getVault, getVaultForWallet                             │\n│                                                           │\n│  Transaction builder:                                     │\n│    buildLiquidateTransaction (vault-routed)                │\n│                                                           │\n│  Confirmation:                                            │\n│    confirmTransaction (on-chain via RPC)                   │\n└──────────────────────────┬───────────────────────────────┘\n                           │\n                           ▼\n┌───────────────────────────────────────"},{"path":"verification.md","content":"# Formal Verification Report\n\n## TL;DR\n\nWe used [Kani](https://model-checking.github.io/kani/), a formal verification tool from AWS, to mathematically prove that torch.market's core math is correct -- not just tested, but **proven for every possible input**. This covers all fee calculations, bonding curve pricing, lending formulas, and reward distribution. No SOL can be created from nothing, no tokens can be minted from thin air, and no fees can exceed their stated rates.\n\nThis is **not** a security audit. It proves the arithmetic is correct, but does not cover access control, account validation, or economic attacks. See [What Is NOT Verified](#what-is-not-verified) for full scope limitations.\n\n**43 proof harnesses. All passing. Zero failures.**\n\n---\n\n## Overview\n\ntorch_market's core arithmetic has been formally verified using [Kani](https://model-checking.github.io/kani/), a Rust model checker backed by the CBMC bounded model checker. Kani exhaustively proves properties hold for **all** valid inputs within constrained ranges -- not just sampled test cases.\n\n**Tool:** Kani Rust Verifier 0.67.0 / CBMC 6.8.0\n**Target:** `torch_market` v3.7.8\n**Harnesses:** 43 proof harnesses, all passing\n**Source:** `programs/torch_market/src/kani_proofs.rs`\n\n## What Is Formally Verified\n\nThe proofs cover the **pure arithmetic layer** -- every fee calculation, bonding curve formula, lending math function, and reward distribution used by the on-chain program. Each proof harness uses symbolic (unconstrained) inputs bounded to realistic protocol ranges, and Kani exhaustively checks all possible values within those bounds.\n\n### Buy Flow (Harnesses 1-8)\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_buy_fee_conservation` | `protocol_fee + treasury_fee + after_fees == sol_amount` | 0.001-200 SOL |\n| `verify_protocol_fee_split` | `dev_share + protocol_portion == protocol_fee_total` | 0.001-200 SOL |\n| `verify_treasury_rate_bounds` | `rate in [500, 2000]` (5-20%) flat across all tiers | 0-target SOL reserves |\n| `verify_treasury_rate_monotonic` | More reserves -> lower treasury rate | 0-target SOL (two symbolic) |\n| `verify_sol_distribution_conservation` | `curve + treasury + creator + dev + protocol == sol_amount` (zero SOL created or lost, V34 5-way sum) | 0.001-10 SOL per trade, 0-target SOL reserves |\n| `verify_curve_tokens_bounded_legacy` | `tokens_out < virtual_token_reserves` (can't mint from thin air) | Legacy pool state space (IVT=107.3T) |\n| `verify_curve_tokens_bounded_v25` | Same property for V27 per-tier reserves | V27 pool state space (IVT=756.25M tokens) |\n| `verify_token_split_conservation` | `tokens_to_buyer + tokens_to_treasury == tokens_out` | 0 to TOTAL_SUPPLY |\n\n### Sell Flow (Harnesses 9-10)\n\n| Harness | Property | Input Range |\n|---------|----------|-------------|\n| `verify_sell_sol_bounded_legacy` | `sol_out < virtual_sol_reserves` (can't drain more SOL than exists) | Legacy pool state, max wallet cap |\n| `verif"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2105,"uniquenessScore":42,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-09T19:13:57.467Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}