Stress Testing
stressTest runs adversarial scenarios against your policy and produces a risk report. Six attack vectors probe different failure modes — timing races, coordinated drains, RPC failures, staleness, boundary conditions, and approval floods.
Installation
npm install @txfence/verifyBasic usage
import { stressTest } from '@txfence/verify'
const report = await stressTest(policy, {
agentCount: 10,
transactionsPerScenario: 20,
timingJitterMs: 100,
timeoutMs: 5000,
})
console.log(`Survival rate: ${report.survivalRate * 100}%`)
console.log(`Recommendation: ${report.recommendation}`)StressTestConfig fields: agentCount, transactionsPerScenario, timingJitterMs, rpcFailureRate, vectors, seed, timeoutMs — all optional.
Six attack vectors
rapid_fire
One agent submits N transactions in rapid succession, each just under the per-tx cap. Tests timing races against the cap lock. Three scenarios: simultaneous burst, jittered burst, multi-agent burst.
coordinated_drain
Multiple agents coordinate to drain a shared cap simultaneously. Tests whether two-phase cap locking prevents collective over-spend. Three scenarios: simultaneous, 1ms-staggered, two-wave.
rpc_failure
Injects RPC failures at simulation and execution stages. Tests that the pipeline returns well-defined results rather than throwing unhandled exceptions. Three scenarios: simulation-stage failure, execution-stage failure, intermittent failure.
stale_simulation
Injects simulation staleness beyond the configured threshold. Tests the simulationStalenessMs check. Two scenarios: 2× threshold, threshold+1.
cap_boundary
Off-by-one tests around maxSpendPerTx. Tests exact cap, cap+1n, cap-1n, and zero amount. Four scenarios.
approval_flood
Multiple agents simultaneously submit transactions above the approval threshold. Tests approval timeout handling. Two scenarios.
chain_reorg (opt-in)
A seventh attack vector exists in the AttackVector type but is not included in DEFAULT_VECTORS. Opt in explicitly via the vectors option if you want to exercise reorg handling — useful when running on chains with frequent reorgs or testing your monitor’s onReorgDetected callback.
RiskReport
type RiskReport = {
policy: Policy
totalScenarios: number
survived: number
failed: number
survivalRate: number // survived / totalScenarios
failedScenarios: ScenarioResult[] // sorted by severity
byVector: Partial<Record<AttackVector, VectorStats>>
bySeverity: Partial<Record<ScenarioSeverity, number>>
generatedAt: number
durationMs: number
recommendation: string // actionable guidance
}recommendation suggests circuit breaker, rate limiting, cap tuning, or other mitigations based on failure patterns.
ScenarioOutcome
type ScenarioOutcome =
| 'survived' // pipeline returned a well-defined ExecutionResult
| 'system_error' // unhandled exception escaped runPipeline
| 'timeout' // scenario exceeded timeoutMs
| 'false_acceptance' // reserved for future detection
| 'false_rejection' // reserved for future detectionsystem_error is the most serious outcome — it means an exception escaped the pipeline boundary.
Selecting vectors
const report = await stressTest(policy, {
vectors: ['rapid_fire', 'cap_boundary'],
})CLI
txfence stress-test --config ./txfence.config.ts \
--agents 10 \
--transactions 20 \
--vectors rapid_fire,cap_boundary \
--only-failures \
--jsonExits 0 when all scenarios survive, 1 when any fail — CI-friendly.