@h3lm_infra/core
v0.1.2
Published
H3lm analysis engine: reads a Solana program upgrade from chain, diffs the Anchor IDL, scores risk across 8 dimensions, and optionally explains it. Bring your own Connection.
Maintainers
Readme
Give it a deployed program and a proposed change. It reads the bytecode and the
upgrade authority from chain, diffs the Anchor IDL, scores the risk across eight
weighted dimensions, and returns a verdict: APPROVE, BLOCK, or ESCALATE.
The decision is deterministic and rule-based. You bring the Connection.
This is the library the H3lm node runs internally. Use it on its own to embed the same checks in your tooling, or to run your own node.
Contents
- Install
- Quick start
- How it decides
- The risk matrix
- Policy
- The report
- Optional explanation
- Run your own node
- Requirements
- Related
Install
npm install @h3lm_infra/coreQuick start
import { Connection } from "@solana/web3.js";
import { analyzeUpgrade } from "@h3lm_infra/core";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const { report } = await analyzeUpgrade(connection, {
programId,
currentIdl, // omit to fetch the published on-chain IDL
newIdl, // the proposed IDL
});
console.log(report.verdict); // APPROVE | BLOCK | ESCALATE
console.log(report.riskScore); // 0–100
console.log(report.dimensions); // per-dimension breakdown
console.log(report.flags); // the discrete risks raisedHow it decides
- Read from chain — the deployed bytecode (hash and size) and the current upgrade authority.
- Diff the IDL — new and removed instructions, account layout shifts, changed signer requirements, new external program references (CPI), and structurally privileged instructions.
- Score — map the findings onto the weighted matrix below to a
0–100score. - Decide — a policy turns the score into
APPROVE/BLOCK/ESCALATE, with hard triggers that always escalate regardless of score.
No model is in this path. The verdict is reproducible from the same inputs.
The risk matrix
| Dimension | Weight | What it inspects | |---|---:|---| | Authority changes | 25 | Upgrade authority added, removed, or moved | | Storage layout shift | 20 | Field reordering, size changes, discriminator mutation | | New CPI targets | 15 | Previously absent cross-program invocation targets | | Behavioral checks | 15 | Structural behavior of the proposed code | | Access control changes | 10 | Signer constraint changes, PDA seed changes | | Arithmetic | 5 | Patterns that risk overflow or precision loss | | Compute budget | 5 | Compute and account-size pressure | | Historical risk | 5 | Prior decisions for the program |
The weights sum to 100. Each dimension contributes 0..weight.
Policy
A policy is a small, protocol-defined object:
{
auto_approve_threshold, // score below this -> APPROVE
auto_block_threshold, // score at/above this -> BLOCK
escalate_on, // fields that always force ESCALATE
escalation_target, // where escalations route, e.g. "multisig:<addr>"
}Between the two thresholds, the verdict is ESCALATE. An escalate_on trigger
(such as authority_changes) escalates no matter the score.
The report
analyzeUpgrade returns the deployed program info, the proposed buffer info
(when given), and a structured RiskReport:
interface RiskReport {
risk_score: number; // 0–100
recommendation: "APPROVE" | "BLOCK" | "ESCALATE";
authority_changes: boolean;
storage_layout_shift: boolean;
new_cpi_targets: string[];
critical_flags: string[];
dimensions: Record<RiskDimensionId, RiskDimension>;
}Optional explanation
The verdict is always rule-based. When you pass an Anthropic API key, a model writes a short plain-English explanation of why the upgrade scored the way it did. It never changes the verdict, and it is off by default.
const { report, explanation } = await analyzeUpgrade(connection, params, {
apiKey: process.env.ANTHROPIC_API_KEY,
});Run your own node
The engine is transport-agnostic: it takes a Connection and returns a report.
Wrap it in your own service to host a node, or call it inline in CI alongside
@h3lm_infra/sdk.
Requirements
Node.js >= 18. A Solana RPC endpoint (a dedicated provider is recommended for mainnet reads).
Related
License
MIT © lynewinter
