brainblast 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-LOPYKIXE.js → chunk-EYFKA33G.js} +59 -21
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -1042,10 +1042,48 @@ JWKS must come from Privy's published JWKS endpoint for your app.`
|
|
|
1042
1042
|
};
|
|
1043
1043
|
};
|
|
1044
1044
|
|
|
1045
|
+
// src/fixers/literalMultiplierWrongConstant.ts
|
|
1046
|
+
import { SyntaxKind as SyntaxKind11 } from "ts-morph";
|
|
1047
|
+
function callName6(call) {
|
|
1048
|
+
const exp = call.getExpression();
|
|
1049
|
+
if (exp.getKind() === SyntaxKind11.Identifier) return exp.getText();
|
|
1050
|
+
if (exp.getKind() === SyntaxKind11.PropertyAccessExpression) {
|
|
1051
|
+
return exp.asKind(SyntaxKind11.PropertyAccessExpression).getName();
|
|
1052
|
+
}
|
|
1053
|
+
return "";
|
|
1054
|
+
}
|
|
1055
|
+
function findIdentifier(node, name) {
|
|
1056
|
+
if (node.getKind() === SyntaxKind11.Identifier && node.getText() === name) return node;
|
|
1057
|
+
return node.getDescendantsOfKind(SyntaxKind11.Identifier).find((id) => id.getText() === name);
|
|
1058
|
+
}
|
|
1059
|
+
var fixLiteralMultiplierWrongConstant = (c, p, outcome) => {
|
|
1060
|
+
if (outcome.result !== "fail") return void 0;
|
|
1061
|
+
const calls = c.fn.getDescendantsOfKind(SyntaxKind11.CallExpression).filter((call) => callName6(call) === p.call);
|
|
1062
|
+
if (calls.length === 0) return void 0;
|
|
1063
|
+
const arg = calls[0].getArguments()[p.argIndex];
|
|
1064
|
+
if (!arg) return void 0;
|
|
1065
|
+
const forbidden = Array.isArray(p.forbiddenIdentifiers) ? p.forbiddenIdentifiers : [];
|
|
1066
|
+
const forbiddenNode = forbidden.map((name) => findIdentifier(arg, name)).find((n) => n);
|
|
1067
|
+
if (!forbiddenNode) return void 0;
|
|
1068
|
+
const expected = Array.isArray(p.expectedIdentifiers) ? p.expectedIdentifiers : [];
|
|
1069
|
+
const expectedName = expected.find((name) => c.params.includes(name));
|
|
1070
|
+
if (!expectedName) {
|
|
1071
|
+
return {
|
|
1072
|
+
summary: `Scale by the mint's decimals instead of ${forbiddenNode.getText()}`,
|
|
1073
|
+
suggestion: `'${forbiddenNode.getText()}' is the native-SOL lamports constant (1e9), not the mint's decimals. Add a 'decimals: number' parameter to this function (threaded from the mint's configuration) and scale the amount with '10 ** decimals' instead of '${forbiddenNode.getText()}'.`
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
return {
|
|
1077
|
+
summary: `Scale by 10 ** ${expectedName} instead of ${forbiddenNode.getText()}`,
|
|
1078
|
+
diff: buildDiff(forbiddenNode, `10 ** ${expectedName}`)
|
|
1079
|
+
};
|
|
1080
|
+
};
|
|
1081
|
+
|
|
1045
1082
|
// src/fixers/index.ts
|
|
1046
1083
|
var registry2 = {
|
|
1047
1084
|
"positional-arg-identity": fixPositionalArgIdentity,
|
|
1048
|
-
"required-call-with-options": fixRequiredCallWithOptions
|
|
1085
|
+
"required-call-with-options": fixRequiredCallWithOptions,
|
|
1086
|
+
"literal-multiplier-wrong-constant": fixLiteralMultiplierWrongConstant
|
|
1049
1087
|
};
|
|
1050
1088
|
function runFixer(kind, c, params, outcome) {
|
|
1051
1089
|
if (outcome.result !== "fail") return void 0;
|
|
@@ -1995,7 +2033,7 @@ function renderTrustGraphMd(g) {
|
|
|
1995
2033
|
}
|
|
1996
2034
|
|
|
1997
2035
|
// src/costAnalysis.ts
|
|
1998
|
-
import { Project as Project2, SyntaxKind as
|
|
2036
|
+
import { Project as Project2, SyntaxKind as SyntaxKind12 } from "ts-morph";
|
|
1999
2037
|
var LAMPORTS_PER_BYTE_YEAR = 3480;
|
|
2000
2038
|
var EXEMPTION_THRESHOLD = 2;
|
|
2001
2039
|
var OVERHEAD_BYTES = 128;
|
|
@@ -2076,11 +2114,11 @@ var KNOWN_FLOWS = [
|
|
|
2076
2114
|
}
|
|
2077
2115
|
];
|
|
2078
2116
|
var LOOP_NODE_KINDS = /* @__PURE__ */ new Set([
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2117
|
+
SyntaxKind12.ForStatement,
|
|
2118
|
+
SyntaxKind12.ForOfStatement,
|
|
2119
|
+
SyntaxKind12.ForInStatement,
|
|
2120
|
+
SyntaxKind12.WhileStatement,
|
|
2121
|
+
SyntaxKind12.DoStatement
|
|
2084
2122
|
]);
|
|
2085
2123
|
var ARRAY_METHOD_LOOPS = /* @__PURE__ */ new Set(["map", "forEach", "flatMap", "reduce", "filter"]);
|
|
2086
2124
|
function isInsideLoop(node) {
|
|
@@ -2088,12 +2126,12 @@ function isInsideLoop(node) {
|
|
|
2088
2126
|
while (cur) {
|
|
2089
2127
|
const k = cur.getKind?.();
|
|
2090
2128
|
if (k !== void 0 && LOOP_NODE_KINDS.has(k)) {
|
|
2091
|
-
return { scalable: true, note: `call is inside a ${
|
|
2129
|
+
return { scalable: true, note: `call is inside a ${SyntaxKind12[k]} \u2014 cost scales with loop iterations` };
|
|
2092
2130
|
}
|
|
2093
|
-
if (k ===
|
|
2131
|
+
if (k === SyntaxKind12.CallExpression) {
|
|
2094
2132
|
const expr = cur.getExpression?.();
|
|
2095
|
-
if (expr?.getKind?.() ===
|
|
2096
|
-
const name = expr.asKind?.(
|
|
2133
|
+
if (expr?.getKind?.() === SyntaxKind12.PropertyAccessExpression) {
|
|
2134
|
+
const name = expr.asKind?.(SyntaxKind12.PropertyAccessExpression)?.getName?.();
|
|
2097
2135
|
if (name && ARRAY_METHOD_LOOPS.has(name)) {
|
|
2098
2136
|
return { scalable: true, note: `call is inside .${name}() \u2014 cost scales with array length` };
|
|
2099
2137
|
}
|
|
@@ -2107,7 +2145,7 @@ function detectPriorityFee(targetDir) {
|
|
|
2107
2145
|
const project = new Project2({ skipAddingFilesFromTsConfig: true });
|
|
2108
2146
|
for (const file of walk(targetDir)) {
|
|
2109
2147
|
const sf = project.addSourceFileAtPath(file);
|
|
2110
|
-
const calls = sf.getDescendantsOfKind(
|
|
2148
|
+
const calls = sf.getDescendantsOfKind(SyntaxKind12.CallExpression);
|
|
2111
2149
|
for (const ce of calls) {
|
|
2112
2150
|
const expr = ce.getExpression();
|
|
2113
2151
|
const text = expr.getText();
|
|
@@ -2135,22 +2173,22 @@ function detectAccountFlows(targetDir) {
|
|
|
2135
2173
|
const importedModules = new Set(
|
|
2136
2174
|
sf.getImportDeclarations().map((d) => d.getModuleSpecifierValue())
|
|
2137
2175
|
);
|
|
2138
|
-
for (const ce of sf.getDescendantsOfKind(
|
|
2176
|
+
for (const ce of sf.getDescendantsOfKind(SyntaxKind12.CallExpression)) {
|
|
2139
2177
|
const expr = ce.getExpression();
|
|
2140
|
-
let
|
|
2141
|
-
if (expr.getKind() ===
|
|
2142
|
-
|
|
2143
|
-
} else if (expr.getKind() ===
|
|
2144
|
-
|
|
2178
|
+
let callName7 = null;
|
|
2179
|
+
if (expr.getKind() === SyntaxKind12.Identifier) {
|
|
2180
|
+
callName7 = expr.getText();
|
|
2181
|
+
} else if (expr.getKind() === SyntaxKind12.PropertyAccessExpression) {
|
|
2182
|
+
callName7 = expr.asKind(SyntaxKind12.PropertyAccessExpression).getName();
|
|
2145
2183
|
}
|
|
2146
|
-
if (!
|
|
2147
|
-
const known = callIndex.get(
|
|
2184
|
+
if (!callName7) continue;
|
|
2185
|
+
const known = callIndex.get(callName7);
|
|
2148
2186
|
if (!known) continue;
|
|
2149
2187
|
if (!importedModules.has(known.module)) continue;
|
|
2150
2188
|
const lamports = rentExemptMinimum(known.dataLen);
|
|
2151
2189
|
const { scalable, note } = isInsideLoop(ce);
|
|
2152
2190
|
flows.push({
|
|
2153
|
-
call:
|
|
2191
|
+
call: callName7,
|
|
2154
2192
|
module: known.module,
|
|
2155
2193
|
accountType: known.accountType,
|
|
2156
2194
|
file,
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brainblast",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Deterministic auditor for catastrophic AI-integration bugs: scan a repo, find the silent money/auth traps, and generate the behavioral test that proves they're fixed.",
|
|
6
6
|
"keywords": [
|