analyze_transaction_post_conditions
Analyze contract calls to determine required post-conditions for transaction security. Essential for identifying necessary safeguards in complex blockchain transactions.
Instructions
Analyze a contract call to determine what post-conditions are required for security. Essential for complex transactions.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| contractAddress | Yes | The contract address being called | |
| contractName | Yes | The contract name being called | |
| expectedTransfers | Yes | Expected asset transfers in the transaction | |
| functionName | Yes | The function being called |
Implementation Reference
- Full implementation of the analyze_transaction_post_conditions tool handler, including the execute function that processes transaction details, analyzes expected transfers, generates security analysis, and provides TypeScript code for post-conditions.export const analyzeTransactionPostConditionsTool: Tool<undefined, typeof TransactionAnalysisScheme> = { name: "analyze_transaction_post_conditions", description: "Analyze a contract call to determine what post-conditions are required for security. Essential for complex transactions.", parameters: TransactionAnalysisScheme, execute: async (args, context) => { try { await recordTelemetry({ action: "analyze_transaction_post_conditions" }, context); let analysis = `# Post-Condition Analysis ## Transaction Details - **Contract**: ${args.contractAddress}.${args.contractName} - **Function**: ${args.functionName} ## Required Post-Conditions `; let postConditionCount = 0; let tsCode = `// Complete TypeScript implementation import { openContractCall, PostConditionMode, makeStandardFungiblePostCondition, makeStandardNonFungiblePostCondition, makeStandardSTXPostCondition, FungibleConditionCode, NonFungibleConditionCode, createAssetInfo, uintCV } from '@stacks/connect'; const postConditions = [ `; for (const transfer of args.expectedTransfers) { postConditionCount++; if (transfer.type === "fungible") { analysis += `### ${postConditionCount}. Fungible Token Transfer - **From**: ${transfer.from || 'Unknown'} - **To**: ${transfer.to || 'Unknown'} - **Amount**: ${transfer.amount || 'Unknown'} base units - **Asset**: ${transfer.asset || 'Unknown'} `; if (transfer.from && transfer.amount && transfer.asset) { const [contractAddr, contractName, assetName] = transfer.asset.includes('.') ? transfer.asset.split('.') : ['CONTRACT_ADDRESS', 'CONTRACT_NAME', transfer.asset]; tsCode += ` makeStandardFungiblePostCondition( '${transfer.from}', FungibleConditionCode.Equal, ${transfer.amount}, createAssetInfo('${contractAddr}', '${contractName}', '${assetName}') ), `; } } else if (transfer.type === "non-fungible") { analysis += `### ${postConditionCount}. NFT Transfer - **From**: ${transfer.from || 'Unknown'} - **To**: ${transfer.to || 'Unknown'} - **Token ID**: ${transfer.tokenId || 'Unknown'} - **Asset**: ${transfer.asset || 'Unknown'} `; if (transfer.from && transfer.tokenId && transfer.asset) { const [contractAddr, contractName, assetName] = transfer.asset.includes('.') ? transfer.asset.split('.') : ['CONTRACT_ADDRESS', 'CONTRACT_NAME', transfer.asset]; tsCode += ` makeStandardNonFungiblePostCondition( '${transfer.from}', NonFungibleConditionCode.DoesNotOwn, createAssetInfo('${contractAddr}', '${contractName}', '${assetName}'), uintCV(${transfer.tokenId}) ), `; } } else if (transfer.type === "stx") { analysis += `### ${postConditionCount}. STX Transfer - **From**: ${transfer.from || 'Unknown'} - **To**: ${transfer.to || 'Unknown'} - **Amount**: ${transfer.amount || 'Unknown'} microSTX `; if (transfer.from && transfer.amount) { tsCode += ` makeStandardSTXPostCondition( '${transfer.from}', FungibleConditionCode.Equal, ${transfer.amount} ), `; } } } tsCode += `]; await openContractCall({ contractAddress: '${args.contractAddress}', contractName: '${args.contractName}', functionName: '${args.functionName}', functionArgs: [ // Add your function arguments here ], postConditions, postConditionMode: PostConditionMode.Deny, // CRITICAL for security onFinish: (data) => { console.log('Transaction completed:', data.txId); }, });`; analysis += ` ## Security Assessment - **Total Post-Conditions Required**: ${postConditionCount} - **Risk Level**: ${postConditionCount === 0 ? '🔴 HIGH - No post-conditions!' : postConditionCount < 3 ? '🟡 MEDIUM' : '🟢 LOW'} - **Compliance**: ${postConditionCount > 0 ? '✅ SIP compliant' : '❌ Missing required post-conditions'} ## Implementation \`\`\`typescript ${tsCode} \`\`\` ## Critical Security Notes ${postConditionCount === 0 ? ` ⚠️ **WARNING**: This transaction has no post-conditions, which is DANGEROUS! - Users are vulnerable to unexpected token movements - Transaction may not behave as expected - VIOLATES SIP-009 and SIP-010 requirements ` : ` ✅ **SECURE**: This transaction includes proper post-conditions - Users are protected from unexpected behavior - Transaction guarantees are explicit - Compliant with SIP standards `} ## Best Practices 1. Always use PostConditionMode.Deny 2. Include post-conditions for ALL asset movements 3. Test post-conditions thoroughly 4. Show post-conditions to users before signing 5. Use exact amounts (FungibleConditionCode.Equal) when possible`; return analysis; } catch (error) { return `❌ Failed to analyze transaction post-conditions: ${error}`; } }, };
- Zod schema defining input parameters for the tool: contract details and expected asset transfers.const TransactionAnalysisScheme = z.object({ contractAddress: z.string().describe("The contract address being called"), contractName: z.string().describe("The contract name being called"), functionName: z.string().describe("The function being called"), expectedTransfers: z.array(z.object({ type: PostConditionTypeScheme, from: z.string().optional(), to: z.string().optional(), amount: z.number().optional(), tokenId: z.number().optional(), asset: z.string().optional(), })).describe("Expected asset transfers in the transaction"), });
- src/tools/index.ts:62-64 (registration)Registration of the analyzeTransactionPostConditionsTool (and related post-condition tools) to the FastMCP server.server.addTool(generateSTXPostConditionTool); server.addTool(analyzeTransactionPostConditionsTool); server.addTool(generatePostConditionTemplateTool);
- src/tools/index.ts:19-24 (registration)Import of the analyzeTransactionPostConditionsTool from its implementation file.generateFungiblePostConditionTool, generateNonFungiblePostConditionTool, generateSTXPostConditionTool, analyzeTransactionPostConditionsTool, generatePostConditionTemplateTool } from "./stacks_blockchain/security/post_conditions.js";