What this template does
This CRE workflow implements a confidential pre-execution security firewall for smart contract interactions. Before a proposed transaction is allowed to proceed, the workflow fetches token and protocol contract artifacts from a blockchain scanner, submits them to two independent AI reasoning models, and enforces a security verdict. All scanner and LLM credentials remain protected inside confidential execution throughout the process.
Data flow:
- Receive a candidate transaction containing token and protocol contract addresses.
- Validate scanner credential scopes (
verification:read,contracts:read) before trusting fetched data. - Fetch source and ABI artifacts for both contracts through the scanner.
- Verify that both contracts are on-chain verified. Unverified contracts result in an immediate denial.
- Submit each contract to independent primary and secondary reasoning models in sequence, using primary analysis results as prior context for the secondary model.
- Merge risk flags from both models using OR logic and determine the final verdict.
- Post audit and firewall action records to the database log.
- Optionally deliver the signed verdict on-chain to a consumer contract.
Risk Flags and Verdict Logic
Risk flags
Both models independently classify contract behavior into four structured risk signals:
| Flag | Description |
|---|---|
obfuscatedTax | Hidden fee or tax mechanism detected in the contract |
privilegeEscalation | Owner or operator can drain funds or alter critical parameters |
externalCallRisk | Calls to external contracts that can alter contract behavior |
logicBomb | Dormant code that activates under a specific condition |
Risk flags from both models are merged with OR logic: if either model sets a flag, it is included in the final risk assessment.
Verdict logic
| Verdict | Condition |
|---|---|
DENY | Either contract is unverified, or any merged risk flag is true |
MANUAL_REVIEW | Either model recommends review, either model has confidence below 0.7, or the two models disagree on their recommendation |
ALLOW | No risk flags detected, both models recommend allow, and both models have confidence ≥ 0.7 |
Prerequisites
- Bun runtime
- CRE CLI (
cre) - A blockchain scanner account with an API key that has
verification:readandcontracts:readscopes - API keys for two LLM reasoning endpoints (primary and secondary)
Configuration
The workflow ships with two config files:
ai-audit-firewall-ts/config.staging.json(TypeScript) andai-audit-firewall-go/config.staging.json(Go): targets mock server endpoints and Ethereum Sepolia testnetai-audit-firewall-ts/config.production.json(TypeScript) andai-audit-firewall-go/config.production.json(Go): same structure with empty URLs for you to populate
Key fields:
| Field | Description |
|---|---|
schedule | Cron expression for execution frequency. Default: 0 */5 * * * * (every 5 minutes) |
scanner_url | Scanner API endpoint for contract metadata and verification |
primary_llm_url | Primary reasoning model endpoint |
secondary_llm_url | Secondary reasoning model endpoint |
secrets_ids.scanner_api_key_id | Secret ID for scanner credentials |
secrets_ids.primary_llm_api_key_id | Secret ID for primary model credentials |
secrets_ids.secondary_llm_api_key_id | Secret ID for secondary model credentials |
mock_base_url | Base URL used for audit log and firewall action posts. Required even in production. |
evms[].chain_selector_name | Target chain for on-chain verdict delivery. Remove the evms array to disable. |
evms[].consumer_address | Deployed AuditFirewallConsumer contract address |
evms[].gas_limit | Gas limit for on-chain verdict writes |
Secrets
Copy .env.example to .env and populate all values before running locally.
| Environment variable | Secret ID | Purpose |
|---|---|---|
MOCK_SCANNER_API_KEY | scanner_api_key | Authenticates requests to the blockchain scanner |
MOCK_PRIMARY_LLM_API_KEY | primary_llm_api_key | Authenticates requests to the primary reasoning model |
MOCK_SECONDARY_LLM_API_KEY | secondary_llm_api_key | Authenticates requests to the secondary reasoning model |
CRE_ETH_PRIVATE_KEY | (framework-level) | Signs transactions for on-chain verdict delivery. Optional for local simulation. |
Secret IDs are referenced in secrets.yaml and mapped to their corresponding secret IDs in config.staging.json under secrets_ids. For production, register each secret with the CRE secrets manager using those IDs.
Quick start
TypeScript
Run all commands from the ai-audit-firewall directory (the project root).
-
Install dependencies
cd ai-audit-firewall-ts && bun install && cd .. -
Create environment file
cp .env.example .env -
Start mock server
cd ai-audit-firewall-ts && bun run mock:server -
In another terminal, run checks and simulate
cd ai-audit-firewall-ts bun run typecheck bun run test cd .. && cre workflow simulate ./ai-audit-firewall-ts --project-root ./ --target=staging-settings --env ./.env
Go
Run all commands from the ai-audit-firewall directory (the project root).
-
Create environment file
cp .env.example .env -
Start the mock server from the TypeScript directory (requires Node or Bun)
cd ai-audit-firewall-ts && bun run mock:server -
In another terminal, run checks and simulate
cd ai-audit-firewall-go go vet ./... go test ./... cd .. && cre workflow simulate ./ai-audit-firewall-go --project-root ./ --target=staging-settings --env ./.env
Production checklist
- Populate
config.production.jsonwith realscanner_url,primary_llm_url,secondary_llm_url, andmock_base_url. - Register
scanner_api_key,primary_llm_api_key, andsecondary_llm_api_keyin the CRE secrets manager. - Confirm the scanner API key has both
verification:readandcontracts:readscopes. The workflow validates this at runtime and fails fast if scopes are missing. - Set
CRE_ETH_PRIVATE_KEYif on-chain verdict delivery is enabled. - Deploy
AuditFirewallConsumer.soland set its address inconfig.production.jsonunderevms[].consumer_address. - Run
bun run typecheck && bun run test(TypeScript) orgo vet ./... && go test ./...(Go) before registering. - Run
cre workflow simulateagainst production endpoints to validate end-to-end behavior before going live. - Register the workflow:
- TypeScript:
cre workflow register ./ai-audit-firewall-ts --project-root ./ --target=production-settings - Go:
cre workflow register ./ai-audit-firewall-go --project-root ./ --target=production-settings
- TypeScript:
Troubleshooting
Scanner credential validation fails
The workflow validates scopes before making any scanner calls. If you see a scope-related error, confirm your scanner API key has verification:read and contracts:read permissions. The error message includes the detected scopes for diagnosis.
Verdict is DENY for an unverified contract
Unverified contracts are denied without running LLM analysis. If you are testing with a contract that is not on-chain verified, use the mock server (which returns mock verification status) or switch to a verified contract address.
LLM response cannot be parsed
If you see invalid json response or a parsing error, the reasoning endpoint returned a malformed body. Confirm that the LLM URL and API key are correct and that the model returns a JSON object with recommendation, confidence, and riskFlags fields.
On-chain write fails
Confirm that CRE_ETH_PRIVATE_KEY is set and the consumer contract is deployed on the target chain. The workflow logs audit-firewall-onchain tx_hash=... on success. A failed transaction throws an error with the transaction status.
Capability limit errors
The workflow enforces a cap of 10 total capability calls per invocation (8 HTTP, 1 Report/consensus, and optionally 1 EVM write when on-chain delivery is enabled). If you extend the workflow with additional HTTP calls, update the pre-hook capability limits accordingly.
Optional on-chain delivery
After each audit, the workflow can write a signed verdict to an on-chain consumer contract. On-chain delivery is controlled by the evms array in the config. Remove the array or leave it empty to run the workflow without any on-chain writes.
Verdict encoding
Verdicts are ABI-encoded as (uint8 verdictCode, uint8 riskMask, uint64 chainSelector):
| Field | Value | Meaning |
|---|---|---|
verdictCode | 1 | ALLOW |
verdictCode | 2 | DENY |
verdictCode | 3 | MANUAL_REVIEW |
Risk flags are packed into riskMask as a single bitmask byte: bit 0 = obfuscatedTax, bit 1 = privilegeEscalation, bit 2 = externalCallRisk, bit 3 = logicBomb.
Consumer contract
The included AuditFirewallConsumer.sol extends ReceiverTemplate and exposes the latest verdict, risk mask, and chain selector as public state variables. It emits a VerdictReceived event on each report. Deploy this contract and set its address in config.production.json under evms[].consumer_address.
Deployment target
The staging config targets Ethereum Sepolia (ethereum-testnet-sepolia). For mainnet delivery, update chain_selector_name to ethereum-mainnet and redeploy the consumer contract to that network.
CREATED BY CHAINLINK LABS