# VMGuardian

> VMGuardian, NeuroChain's AI contract auditor — the five bytecode rules, the embedded neural network and how it is blended, the deploy gate every validator runs, signed attestations, certificates, continuous monitoring and the on-chain model registry.

Source: https://docs.nro.world/ai/vmguardian

VMGuardian audits WebAssembly bytecode. It runs in three places with **the same code**, so a contract gets the same score everywhere:

| Where | When |
|-------|------|
| The browser (WASM module) | Instantly, before you send a deploy |
| Every validator, in consensus | On every deploy transaction — the gate |
| Every node, in the background | Continuously, on every deployed contract |

## How a score is made

### 1. Rules (heuristics)

The analyzer decodes the code section instruction by instruction (one linear pass, so even a 512 KiB contract is analyzed quickly) and checks five patterns. Each match adds risk; the total is capped at 1.0.

| Rule | Severity | Adds | Triggers on |
|------|----------|------|-------------|
| `reentrancy` | critical | 0.40 | A dynamic `call_indirect` followed by a storage write |
| `uncapped_loop` | critical | 0.35 | A loop with no conditional branch out of it |
| `unbounded_memory` | warning | 0.20 | More than 8 `memory.grow` instructions |
| `unchecked_call` | warning | 0.15 | A call whose result is dropped |
| `large_import_surface` | info | 0.10 | More than 20 imported host functions |

A score below 0.5 is reported as `safe`.

### 2. Neural network

A small embedded network (10 inputs → 32 → 16 → 1, 897 parameters) scores the same bytecode from ten features: share of uncapped loops, reentrancy pattern, dropped calls, density of `memory.grow`, imports, indirect calls, stores, loops and arithmetic, and code size. It runs inside the node without any ML runtime.

### 3. Blend

```
if |network − rules| > 0.25:   risk = rules                 (model: "heuristic")
else:                          risk = 0.3 × network + 0.7 × rules   (model: "ml+heuristic")
```

The network gets the smaller weight and is ignored when it disagrees strongly — it is trained mostly on synthetic data plus real, safe contracts from a public CosmWasm chain, and needs real exploit data before it can be trusted more.

The **security score** shown everywhere is `100 − risk × 100`.

## The deploy gate

Every validator runs the gate on each deploy transaction — see [Deploy contracts](/build/deploy#_4-what-every-validator-does):

| Case | Result |
|------|--------|
| Bytecode hash on the trusted list (official templates such as NRC-20) | Score 100, no analysis |
| Gate switched off by governance (`deploy_security_enabled = 0`) | Neutral score 70 |
| `risk ≥ deploy_risk_threshold` (default 0.80) | Deploy fails, no fee; logged with its violations; counted in `nc_deploy_rejected_total` |
| Otherwise | Contract created with its score |

## Check a contract yourself

```bash
curl -s -X POST "$NODE_RPC/api/v1/contracts/analyze" \
  -H 'Content-Type: application/json' -d "{\"bytecode_hex\":\"$HEX\"}"
```

```json
{
  "risk_score": 0,
  "security_score": 100,
  "safe": true,
  "ml_score": 0.439,
  "model": "heuristic",
  "violations": [],
  "gas_estimate": 34550
}
```

(Here the network said 0.44 while the rules said 0, so the rules alone decided.)

Through the gateway, use `POST /api/v1/contracts/audit` with the same body. The gateway never scores contracts itself; it only forwards to the node.

## Signed attestation

`POST /api/v1/contracts/attest` runs the same analysis and signs the result with the node's ML-DSA-65 key:

```json
{
  "score": 100,
  "risk_score": 0,
  "bytecode_hash": "18642df0…",
  "timestamp": 1791200887,
  "signature": "665a7ab2…",
  "pubkey": "6e80bab8…",
  "model": "heuristic",
  "ml_score": 0.439,
  "violations": []
}
```

The signed message is `"nc-attest|" ‖ score (4 bytes, big-endian) ‖ SHA3-256(bytecode) (32 bytes) ‖ timestamp (8 bytes, big-endian)`. The browser verifies it with the same WASM module the wallet uses, and the deploy page then shows the attested score.

An attestation proves *which node* computed the score. Proving that the score was computed correctly, without trusting the node, is the goal of the ZKML work below.

## Certificates

Contracts receive an on-chain security certificate by score:

| Tier | Score |
|------|-------|
| Gold | 90 and above |
| Silver | 75 – 89 |
| Bronze | below 75 |

Certificates are records of the `ncert.app` system contract, deployed at genesis, and indexed for the API: `GET /api/v1/certificates`, `/certificates/:id`, `/certificates/contract/:address`.

## Continuous monitoring

Each node re-analyzes deployed contracts every `MONITOR_INTERVAL_SECS` (20 s). When a score moves by `MONITOR_SCORE_THRESHOLD` (10) points or more — typically after a new model version is activated — the node issues a certificate update through consensus, and the oracle log records `score_degraded` or `score_improved`.

The gateway adds activity alerts on top (`contract_alert` over [WebSocket](/reference/websocket)): unusual call spikes, and low-score contracts that start being called.

## Model versions

Model weights are versioned on chain, so all validators run the same model:

1. A validator registers a new version (`POST /api/v1/models/register`, validators only) — it enters `voting` for 2 000 blocks.
2. Other validators fetch the weights over P2P, check their hash against the registration, and confirm.
3. With confirmations from `2f + 1` validators the version becomes `active` and replaces the previous one; without them it is `rejected` at the deadline.

Registry: `GET /api/v1/models/registry`. Prometheus: `nc_model_active_count`, `nc_model_voting_count`, `nc_model_version{…}`.

## Verifiable AI <Badge type="warning" text="experimental" />

The plan is to prove VMGuardian's result with a zero-knowledge virtual machine (RISC Zero / SP1): a proof that *this score is `analyze_v2(bytecode)` under the weights the chain approved*, checkable by anyone — including another chain — without trusting any node. The models are small enough for this to be practical.

**How it is tested:** the design and a prover scaffold are in the repository (`docs/zkml-poc.md`, `neurochain/zkml/`). Building the prover needs the RISC Zero / SP1 toolchain, which has not yet been run in the project's build environment; there is no on-chain verification yet.

## Limits

- Trained on synthetic data and real *safe* contracts only — it has not yet seen real exploits in WASM.
- Byte offsets of findings and custom rule sets are not available yet.
- A clean score means no known risky pattern was found, not that the contract is correct.
