Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 229 additions & 0 deletions src/content/cre-templates/ai-audit-firewall.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
---
title: "AI Smart Contract Audit Firewall"
description: "Automatically analyze and screen smart contract interactions before execution to detect and block malicious transactions, while preserving the confidentiality of chain scanner and LLM reasoning API credentials."
author: "Chainlink Labs"
excerpt: "Gate transactions with dual-model AI audits inside a TEE and deliver the verdict onchain."
image: "thumbnail.jpg"
tags:
- "confidential"
- "ai"
- "security"
githubUrl: "https://github.com/smartcontractkit/confidential-compute-examples/tree/main/ai-audit-firewall"
githubRepoLinks:
- label: "TypeScript"
url: "https://github.com/smartcontractkit/confidential-compute-examples/tree/main/ai-audit-firewall"
datePublished: "2026-08-04"
lastModified: "2026-08-04"
---

import { Aside, Accordion } from "@components"

## What This Template Does

This workflow runs inside a **Trusted Execution Environment (TEE)** and acts as a confidential gate for proposed token interactions. Contract source, transaction details, and model prompts never leave the confidential runtime.

On every cron execution the workflow:

1. Fetches a **proposed transaction**
2. Fetches the **token and protocol contract artifacts** from a scanner service
3. Runs **two independent LLM audits** — the second receives the first analysis as prior context
4. Merges the risk flags and decides **ALLOW**, **DENY**, or **MANUAL_REVIEW**
5. Writes an audit log entry and a firewall action
6. Optionally writes the verdict onchain with `EVMClient`

<Aside type="note" title="Confidential execution">
The cron handler is registered with `handlerInTee(...)` and pinned to an AWS Nitro enclave region, so unverified
contract source and model interaction stay inside the enclave for the whole run. See [Confidential
Workflows](https://docs.chain.link/cre/concepts/confidential-workflows) for the underlying feature, and [Hello
Confidential Workflows](/cre-templates/hello-confidential-workflows) for the minimal version of this pattern.
</Aside>

## Risk Flags

Both models are asked to evaluate the same four checks:

| Flag | What it detects |
| --------------------- | ------------------------------------------------------------------ |
| `obfuscatedTax` | Hidden or dynamically-adjustable transfer fees |
| `privilegeEscalation` | Owner or admin functions that can seize funds or change core rules |
| `externalCallRisk` | Untrusted external calls and reentrancy surface |
| `logicBomb` | Conditional logic that changes behavior after a trigger is reached |

## Verdict Logic

The `determineVerdict` function merges both analyses:

- **DENY** — any malicious risk flag is set in the merged flag set
- **MANUAL_REVIEW** — either model recommends `review`, either model's confidence is below `0.7`, or the two models disagree
- **ALLOW** — both models agree, both are confident, and no risk flag fired

<Aside type="caution" title="Two models, one verdict">
Disagreement between the two models never resolves to `ALLOW`. Any divergence or low confidence escalates to
`MANUAL_REVIEW`, so a single compromised or hallucinating model cannot wave a transaction through.
</Aside>

## Prerequisites

- **[Bun](https://bun.com/docs/installation)** — the repository is configured as a Bun workspace
- **[Chainlink CRE CLI](https://docs.chain.link/cre/getting-started/cli-installation)** installed and configured
- **Git** for cloning the repository
- **A funded wallet on Ethereum Sepolia** — only if you want to test the optional onchain delivery path

## Setup

<Accordion title="Clone the repository and install dependencies" number={1}>

```bash
git clone https://github.com/smartcontractkit/confidential-compute-examples.git
cd confidential-compute-examples
bun install
```

`bun install` at the repository root installs dependencies for every workflow because the repo is a Bun workspace.

</Accordion>

<Accordion title="Prepare environment variables" number={2}>

From the repository root:

```bash
cp .env.example .env
```

Set the values you want to use. The mock keys are used by both the workflow and the shared demo server:

```bash
MOCK_PORT=8787
MOCK_SCANNER_API_KEY=mock-scanner-key
MOCK_PRIMARY_LLM_API_KEY=mock-primary-llm-key
MOCK_SECONDARY_LLM_API_KEY=mock-secondary-llm-key
```

`secrets.yaml` at the repository root maps the logical secret IDs to these environment variables.

</Accordion>

<Accordion title="Review the simulation config" number={3}>

Open `ai-audit-firewall/config.staging.json`:

```json
{
"schedule": "0 */5 * * * *",
"mock_base_url": "http://127.0.0.1:8787/audit-firewall",
"scanner_url": "http://127.0.0.1:8787/audit-firewall/scanner",
"primary_llm_url": "http://127.0.0.1:8787/audit-firewall/v1/analysis/primary",
"secondary_llm_url": "http://127.0.0.1:8787/audit-firewall/v1/analysis/secondary",
"secrets_ids": {
"scanner_api_key_id": "scanner_api_key",
"primary_llm_api_key_id": "primary_llm_api_key",
"secondary_llm_api_key_id": "secondary_llm_api_key"
}
}
```

1. Keep the default values if you are using the shared mock server on port `8787`
2. Update `mock_base_url`, `scanner_url`, `primary_llm_url`, and `secondary_llm_url` if you are using a different port or host
3. Keep `secrets_ids` aligned with `secrets.yaml`
4. If you do not want to test onchain delivery yet, remove or clear the `evms` entry

</Accordion>

<Accordion title="Run typecheck and tests" number={4}>

```bash
cd ai-audit-firewall
bun run typecheck
bun run test
```

</Accordion>

<Accordion title="Start the shared mock server" number={5}>

From the repository root:

```bash
bun run mock:server
```

The server listens on `http://127.0.0.1:8787` and serves this workflow's routes under the `/audit-firewall/*` namespace — transaction proposals, contract artifact lookups, the two audit model endpoints, and the logging and action endpoints.

</Accordion>

<Accordion title="Simulate the workflow" number={6}>

In a new terminal, from the repository root:

```bash
cre workflow simulate ./ai-audit-firewall --target=staging-settings
```

The workflow logs each stage (`audit-firewall-onchain-report-start`, `audit-firewall-complete`) and returns a JSON result containing the verdict, reasoning, merged risk flags, both model analyses, the audit log ID, and the firewall action ID.

</Accordion>

## Secrets

`config.staging.json` expects these secret IDs in `secrets_ids`:

- `scanner_api_key`
- `primary_llm_api_key`
- `secondary_llm_api_key`

## Optional Onchain Delivery

The workflow can encode the verdict as a CRE report and write it to a consumer contract.

<Accordion title="Deploy the consumer contract" number={1}>

Deploy `contracts/AuditFirewallConsumer.sol`. It extends `contracts/ReceiverTemplate.sol`, which validates that reports arrive from the Chainlink Forwarder.

Forwarder mode must match your environment:

- **Simulation** uses the Mock Forwarder
- **Production** uses the Keystone Forwarder

Deploy or configure the consumer with the forwarder address that matches the mode you are running. See [Forwarder Addresses](https://docs.chain.link/cre/supported-networks-ts#forwarder-addresses) for the correct address.

</Accordion>

<Accordion title="Configure the EVM write target" number={2}>

Set `evms[0]` in your config file:

```json
"evms": [
{
"chain_selector_name": "ethereum-testnet-sepolia",
"consumer_address": "0xYourConsumer",
"gas_limit": "500000"
}
]
```

1. Set `evms[0].consumer_address` to the deployed consumer address
2. Keep `evms[0].chain_selector_name` aligned with the target network in `project.yaml`
3. Increase `evms[0].gas_limit` if your deployed contract needs more gas

</Accordion>

<Aside type="note" title="Onchain delivery is optional">
If `evms` is absent or cleared, the workflow completes normally and simply omits `onchainTxHash` from its result.
</Aside>

## Production Checklist

1. Replace the example URLs in `config.production.json` with real endpoints
2. Set real secret values for the scanner and both model providers
3. Deploy the consumer contract
4. Update `config.production.json` so `evms[0].consumer_address`, `evms[0].chain_selector_name`, and `evms[0].gas_limit` match the deployed target
5. Confirm the consumer's forwarder address matches your environment

## Troubleshooting

- **401 responses from the APIs** usually indicate a secret mismatch between `.env`, `secrets.yaml`, and `secrets_ids` in the config file
- **Simulation failures tied to RPC config** usually come from incorrect `project.yaml` target values
- **Model responses that fail to parse** mean your configured endpoint is not returning the expected JSON payload shape — the workflow expects `riskFlags`, `recommendation`, `confidence`, and `reasoning`
- **Onchain write failures** mean the consumer rejected the report; confirm the forwarder address configured on the contract matches the mode you are simulating or deploying in
Loading
Loading