What you will learn
- The 8 stages of the transaction pipeline
- What each stage does and what can go wrong
- How stages are correlated in the audit trail
Pipeline overview
Every fund-affecting operation flows through the same pipeline. No stage can be skipped.Stage 1: Intent received
The pipeline begins when an adapter submits a TxIntent to ISCL Core viaPOST /v1/tx/approve-request.
The TxIntent is a declarative JSON document describing what the agent wants to do. It specifies the action type, parameters, constraints, and metadata — but never raw calldata or signing instructions.
Audit event: intent_received
Stage 2: Schema validation
The intent is validated against the TxIntent v1 JSON Schema using AJV in strict mode:- All required fields must be present (
version,id,timestamp,chain,wallet,action,constraints) additionalProperties: falseat every level — no undocumented fields- Addresses must match
^0x[0-9a-fA-F]{40}$ - Amounts must be numeric strings (
^[0-9]+$) action.typemust be one of:transfer,transfer_native,approve,swap_exact_in,swap_exact_out
Stage 3: Policy evaluation
The PolicyEngine evaluates the intent against configurable rules, in order:| # | Rule | Outcome |
|---|---|---|
| 1 | Chain not in allowedChains | deny |
| 2 | Token not in tokenAllowlist | deny |
| 3 | Contract not in contractAllowlist | deny |
| 4 | Value exceeds maxValueWei | deny |
| 5 | Approval amount exceeds maxApprovalAmount | deny |
| 6 | Recipient not in recipientAllowlist | deny |
| 7 | Risk score exceeds maxRiskScore | require_approval |
| 8 | Rate limit exceeded (maxTxPerHour) | deny |
deny stops evaluation. If no denials, the decision is allow or require_approval.
Audit event: policy_evaluated
Failure: HTTP 403 with policy_denied and reasons array.
Stage 4: Transaction build
The TxBuilder constructs a concrete EVM transaction from the intent’s typed parameters:| Action | Builder Output |
|---|---|
transfer | ERC-20 transfer(address,uint256) calldata |
transfer_native | Plain ETH value transfer (no calldata) |
approve | ERC-20 approve(address,uint256) calldata |
swap_exact_in | Uniswap V3 exactInputSingle or 1inch API calldata |
swap_exact_out | Uniswap V3 exactOutputSingle calldata |
to, data, value, chainId, type (EIP-1559). Gas parameters are estimated later.
Audit event: tx_built
Stage 5: Preflight simulation
The PreflightService simulates the transaction usingeth_call on the target chain’s RPC endpoint:
- Simulate execution — run
eth_callwith the built transaction - Estimate gas — call
eth_estimateGas - Compute risk score — 7-factor analysis (value magnitude, recipient history, contract risk, gas anomaly, approval risk, chain risk, source trust)
- Check balance — verify the wallet can cover the transfer + gas
require_approval even if the value is below the threshold.
Audit event: preflight_simulated
Failure: HTTP 502 if no RPC endpoint is configured.
Stage 6: Approval
Based on the policy decision and risk score:- allow — Transaction proceeds without human confirmation
- require_approval — The approval service prompts the operator
| Mode | Mechanism |
|---|---|
cli | Readline prompt in the ISCL Core terminal |
web | Pending request in the web dashboard + HTTP API for programmatic approval |
auto | Auto-approved (testing only — never use in production) |
approval_requested, approval_decided
Failure: HTTP 403 with user_declined if the operator denies.
Stage 7: Signing + broadcast
Thesign-and-send endpoint performs final execution:
- Policy re-check — Policy is re-evaluated to prevent TOCTOU attacks
- Token validation — Approval token is verified: correct hash binding, not expired, not consumed
- Token consumption — Token is marked as used (single-use enforcement)
- Key unlock — The encrypted key is decrypted in memory using scrypt
- Signing — ECDSA signature via viem’s
signTransaction - Broadcast —
eth_sendRawTransactionto the configured RPC endpoint
signed, broadcast
Failure: HTTP 403 with signing_failed, approval_required, or invalid_approval_token.
Stage 8: Audit logging
Every stage writes to the append-only SQLite audit trail. All events for one transaction share the sameintentId, enabling full lifecycle reconstruction:
Error recovery
| Stage | Error | Recovery |
|---|---|---|
| Validation | Schema error | Fix the TxIntent and resubmit |
| Policy | Denied | Adjust policy config or use different parameters |
| Preflight | Simulation revert | Check balance, allowances, deadline |
| Approval | User declined | Resubmit if the operator changes their mind |
| Signing | Token expired | Get a new approval token |
| Broadcast | Nonce conflict | Retry (auto-corrects on next attempt) |
Next steps
- Policy Engine — Deep dive into policy rules
- Approval Model — Approval modes and token mechanics
- REST API — Endpoint details for each pipeline stage