@callcium/sdk 0.1.0 → 0.3.0
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/LICENSE +21 -0
- package/README.md +17 -0
- package/dist/index.d.ts +112 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +174 -119
- package/dist/index.js.map +1 -1
- package/package.json +2 -5
package/dist/index.js
CHANGED
|
@@ -20,19 +20,27 @@ var CallciumError = class CallciumError extends Error {
|
|
|
20
20
|
* Thrown by `PolicyEnforcer.enforce` when calldata fails policy enforcement.
|
|
21
21
|
* Distinct from `CallciumError("VALIDATION_ERROR")`, which signals static
|
|
22
22
|
* issues in the policy itself.
|
|
23
|
-
*
|
|
23
|
+
*
|
|
24
|
+
* Carries the full list of structured violations (one per failed group). The
|
|
25
|
+
* `Error.message` is a minimal non-lossy diagnostic summary built from the
|
|
26
|
+
* first violation's structured fields — not a presentation contract. Consumers
|
|
27
|
+
* rendering violations to users should iterate `violations` directly.
|
|
24
28
|
*/
|
|
25
29
|
var PolicyViolationError = class PolicyViolationError extends Error {
|
|
26
30
|
violations;
|
|
27
31
|
constructor(violations) {
|
|
28
|
-
|
|
29
|
-
const msg = first ? `Policy violation: ${first.message}` : "Policy violation";
|
|
30
|
-
super(msg);
|
|
32
|
+
super(formatDiagnostic(violations[0]));
|
|
31
33
|
this.name = "PolicyViolationError";
|
|
32
34
|
this.violations = violations;
|
|
33
35
|
Object.setPrototypeOf(this, PolicyViolationError.prototype);
|
|
34
36
|
}
|
|
35
37
|
};
|
|
38
|
+
/** Build a stack-trace-friendly diagnostic line from a violation's code and coordinates. */
|
|
39
|
+
function formatDiagnostic(violation) {
|
|
40
|
+
if (!violation) return "Policy violation";
|
|
41
|
+
const location = "group" in violation ? ` at group ${violation.group} rule ${violation.rule}` : "";
|
|
42
|
+
return `Policy violation: ${violation.code}${location}`;
|
|
43
|
+
}
|
|
36
44
|
//#endregion
|
|
37
45
|
//#region src/bytes.ts
|
|
38
46
|
/** Regex that matches a valid hex body (even number of hex chars). */
|
|
@@ -1404,6 +1412,35 @@ function toBigInt(bytes, offset = 0) {
|
|
|
1404
1412
|
function isSigned(typeCode) {
|
|
1405
1413
|
return typeCode >= TypeCode.INT_MIN && typeCode <= TypeCode.INT_MAX;
|
|
1406
1414
|
}
|
|
1415
|
+
/**
|
|
1416
|
+
* Canonicalize a raw 256-bit calldata word to its ABI value for the declared type (Policy Spec §7.8).
|
|
1417
|
+
* A scalar loaded from untrusted calldata may carry bits outside the declared width; masking
|
|
1418
|
+
* unsigned/address/bool/function/bytesN to width and sign-extending signed integers makes the
|
|
1419
|
+
* comparison use the canonical ABI value rather than the raw bytes.
|
|
1420
|
+
* @param value - The raw 256-bit word loaded from calldata.
|
|
1421
|
+
* @param typeCode - The declared type code of the value.
|
|
1422
|
+
* @returns The canonicalized 256-bit value.
|
|
1423
|
+
*/
|
|
1424
|
+
function canonicalize(value, typeCode) {
|
|
1425
|
+
if (typeCode <= TypeCode.UINT_MAX) {
|
|
1426
|
+
const bits = BigInt((typeCode + 1) * 8);
|
|
1427
|
+
return bits === 256n ? value : value & (1n << bits) - 1n;
|
|
1428
|
+
}
|
|
1429
|
+
if (typeCode <= TypeCode.INT_MAX) {
|
|
1430
|
+
const bits = (typeCode - TypeCode.INT_MIN + 1) * 8;
|
|
1431
|
+
return bits === 256 ? value : BigInt.asUintN(256, BigInt.asIntN(bits, value));
|
|
1432
|
+
}
|
|
1433
|
+
if (typeCode === TypeCode.ADDRESS) return value & (1n << 160n) - 1n;
|
|
1434
|
+
if (typeCode === TypeCode.BOOL) return value & 1n;
|
|
1435
|
+
if (typeCode === TypeCode.FUNCTION) return value >> 64n << 64n;
|
|
1436
|
+
if (typeCode >= TypeCode.FIXED_BYTES_MIN && typeCode <= TypeCode.FIXED_BYTES_MAX) {
|
|
1437
|
+
const n = typeCode - TypeCode.FIXED_BYTES_MIN + 1;
|
|
1438
|
+
if (n === 32) return value;
|
|
1439
|
+
const padBits = BigInt((32 - n) * 8);
|
|
1440
|
+
return value >> padBits << padBits;
|
|
1441
|
+
}
|
|
1442
|
+
return value;
|
|
1443
|
+
}
|
|
1407
1444
|
/** Return true when the operator code (with or without NOT flag) is a LENGTH_* variant. */
|
|
1408
1445
|
function isLengthOp(opCode) {
|
|
1409
1446
|
const base = opCode & ~Op.NOT;
|
|
@@ -2707,11 +2744,11 @@ function locate(tree, callData, pathBytes, baseOffset) {
|
|
|
2707
2744
|
for (let i = 0; i < paramIndex; i++) head += headContribution(tree[i]);
|
|
2708
2745
|
let base = baseOffset;
|
|
2709
2746
|
let node = tree[paramIndex];
|
|
2710
|
-
for (let
|
|
2711
|
-
const step = readStep(pathBytes,
|
|
2747
|
+
for (let stepIndex = 1; stepIndex < stepCount; stepIndex++) {
|
|
2748
|
+
const step = readStep(pathBytes, stepIndex);
|
|
2712
2749
|
if (isQuantifier(step)) {
|
|
2713
|
-
const remaining = pathBytes.subarray((
|
|
2714
|
-
for (let
|
|
2750
|
+
const remaining = pathBytes.subarray((stepIndex + 1) * 2);
|
|
2751
|
+
for (let remainingStepIndex = 0; remainingStepIndex < remaining.length / 2; remainingStepIndex++) if (isQuantifier(readStep(remaining, remainingStepIndex))) throw new CallciumError("INVALID_QUANTIFIER", "Nested quantifiers are not supported.");
|
|
2715
2752
|
return {
|
|
2716
2753
|
ok: true,
|
|
2717
2754
|
type: "quantifier",
|
|
@@ -2887,8 +2924,8 @@ function loadSlice(callData, location) {
|
|
|
2887
2924
|
function descendPath(callData, location, pathBytes) {
|
|
2888
2925
|
const stepCount = pathBytes.length / 2;
|
|
2889
2926
|
let { head, base, node } = location;
|
|
2890
|
-
for (let
|
|
2891
|
-
const step = readStep(pathBytes,
|
|
2927
|
+
for (let stepIndex = 0; stepIndex < stepCount; stepIndex++) {
|
|
2928
|
+
const step = readStep(pathBytes, stepIndex);
|
|
2892
2929
|
const result = descend(node, callData, head, base, step);
|
|
2893
2930
|
if (result.type === "violation") return {
|
|
2894
2931
|
ok: false,
|
|
@@ -2916,38 +2953,27 @@ function addressToBigInt(hex) {
|
|
|
2916
2953
|
padded.set(bytes, 32 - bytes.length);
|
|
2917
2954
|
return toBigInt(padded, 0);
|
|
2918
2955
|
}
|
|
2919
|
-
/**
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
else if (operands === "range") {
|
|
2941
|
-
const min = toBigInt(operandData, 0);
|
|
2942
|
-
const max = toBigInt(operandData, 32);
|
|
2943
|
-
formattedOperands = `[${formatOperandValue(min, opCode)}, ${formatOperandValue(max, opCode)}]`;
|
|
2944
|
-
} else formattedOperands = formatOperandValue(toBigInt(operandData, 0), opCode);
|
|
2945
|
-
return `${op} ${formattedOperands}`;
|
|
2946
|
-
}
|
|
2947
|
-
/** Build a self-contained VALUE_MISMATCH message for a scalar or length comparison. */
|
|
2948
|
-
function mismatchMessage(opCode, actual, operandData) {
|
|
2949
|
-
const display = typeof actual === "number" ? String(actual) : truncateHexForMessage(compactHex(actual));
|
|
2950
|
-
return `constraint ${formatConstraint(opCode, operandData)} violated by ${display}`;
|
|
2956
|
+
/**
|
|
2957
|
+
* Walk a descriptor subtree through path steps and return the terminal leaf type code.
|
|
2958
|
+
*
|
|
2959
|
+
* Used only for violation metadata. Valid policies have structurally valid
|
|
2960
|
+
* quantifier suffixes (enforced by `PolicyValidator`); if a hand-crafted blob
|
|
2961
|
+
* violates that invariant, return the last resolvable node's type code as
|
|
2962
|
+
* best-effort diagnostic context.
|
|
2963
|
+
*/
|
|
2964
|
+
function resolveLeafTypeCode(elementNode, remainingPath) {
|
|
2965
|
+
let node = elementNode;
|
|
2966
|
+
const stepCount = remainingPath.length / 2;
|
|
2967
|
+
for (let step = 0; step < stepCount; step++) {
|
|
2968
|
+
const childIndex = readU16(remainingPath, step * 2);
|
|
2969
|
+
if (node.type === "tuple") {
|
|
2970
|
+
const field = node.fields[childIndex];
|
|
2971
|
+
if (!field) break;
|
|
2972
|
+
node = field;
|
|
2973
|
+
} else if (node.type === "staticArray" || node.type === "dynamicArray") node = node.element;
|
|
2974
|
+
else break;
|
|
2975
|
+
}
|
|
2976
|
+
return node.typeCode;
|
|
2951
2977
|
}
|
|
2952
2978
|
/**
|
|
2953
2979
|
* Check a policy against ABI-encoded call data without throwing on violations.
|
|
@@ -2963,10 +2989,7 @@ function check(policy, callData, context) {
|
|
|
2963
2989
|
if (!decoded.isSelectorless) {
|
|
2964
2990
|
if (callDataBytes.length < 4) return {
|
|
2965
2991
|
ok: false,
|
|
2966
|
-
violations: [{
|
|
2967
|
-
code: "MISSING_SELECTOR",
|
|
2968
|
-
message: "Calldata too short to contain a selector"
|
|
2969
|
-
}]
|
|
2992
|
+
violations: [{ code: "MISSING_SELECTOR" }]
|
|
2970
2993
|
};
|
|
2971
2994
|
const expectedSelector = decoded.selector.value;
|
|
2972
2995
|
const actualSelector = bytesToHex(callDataBytes.subarray(0, 4));
|
|
@@ -2974,8 +2997,8 @@ function check(policy, callData, context) {
|
|
|
2974
2997
|
ok: false,
|
|
2975
2998
|
violations: [{
|
|
2976
2999
|
code: "SELECTOR_MISMATCH",
|
|
2977
|
-
|
|
2978
|
-
|
|
3000
|
+
resolvedValue: actualSelector,
|
|
3001
|
+
expectedValue: expectedSelector
|
|
2979
3002
|
}]
|
|
2980
3003
|
};
|
|
2981
3004
|
}
|
|
@@ -3028,8 +3051,10 @@ function evaluateRule(rule, tree, callDataBytes, baseOffset, groupIndex, ruleInd
|
|
|
3028
3051
|
group: groupIndex,
|
|
3029
3052
|
rule: ruleIndex,
|
|
3030
3053
|
code: locResult.code,
|
|
3031
|
-
|
|
3032
|
-
path: rule.path.value
|
|
3054
|
+
scope: Scope.CALLDATA,
|
|
3055
|
+
path: rule.path.value,
|
|
3056
|
+
opCode,
|
|
3057
|
+
operandData: rule.data.value
|
|
3033
3058
|
};
|
|
3034
3059
|
if (locResult.type === "quantifier") return evaluateQuantifier(locResult.quantifier, callDataBytes, opCode, operandData, groupIndex, ruleIndex, rule.path.value);
|
|
3035
3060
|
return evaluateLeaf(locResult.location, callDataBytes, opCode, operandData, groupIndex, ruleIndex, rule.path.value);
|
|
@@ -3044,23 +3069,33 @@ function evaluateContextRule(pathBytes, opCode, operandData, groupIndex, ruleInd
|
|
|
3044
3069
|
group: groupIndex,
|
|
3045
3070
|
rule: ruleIndex,
|
|
3046
3071
|
code: "MISSING_CONTEXT",
|
|
3047
|
-
|
|
3048
|
-
path: pathHex
|
|
3072
|
+
scope: Scope.CONTEXT,
|
|
3073
|
+
path: pathHex,
|
|
3074
|
+
typeCode: propInfo.typeCode
|
|
3049
3075
|
};
|
|
3050
3076
|
let value;
|
|
3051
3077
|
if (typeof contextValue === "string") value = addressToBigInt(contextValue);
|
|
3052
3078
|
else value = contextValue;
|
|
3053
|
-
if (!applyOperator(opCode, value, 32, operandData,
|
|
3079
|
+
if (!applyOperator(opCode, value, 32, operandData, propInfo.typeCode)) return {
|
|
3054
3080
|
group: groupIndex,
|
|
3055
3081
|
rule: ruleIndex,
|
|
3056
3082
|
code: "VALUE_MISMATCH",
|
|
3057
|
-
|
|
3083
|
+
scope: Scope.CONTEXT,
|
|
3058
3084
|
path: pathHex,
|
|
3085
|
+
opCode,
|
|
3086
|
+
operandData: bytesToHex(operandData),
|
|
3087
|
+
typeCode: propInfo.typeCode,
|
|
3059
3088
|
resolvedValue: bigintToHex(value)
|
|
3060
3089
|
};
|
|
3061
3090
|
return null;
|
|
3062
3091
|
}
|
|
3063
|
-
/**
|
|
3092
|
+
/**
|
|
3093
|
+
* Load a value from calldata at the given location and apply the operator.
|
|
3094
|
+
*
|
|
3095
|
+
* `resolvedValue` is normalised at the decision point: length operators encode
|
|
3096
|
+
* the byte/element count as a hex bigint; scalar operators preserve the full
|
|
3097
|
+
* 32-byte ABI word so downstream rendering can decode left-aligned `bytesN` faithfully.
|
|
3098
|
+
*/
|
|
3064
3099
|
function applyLeafOperator(callDataBytes, location, opCode, operandData) {
|
|
3065
3100
|
const { node } = location;
|
|
3066
3101
|
if (isLengthOp(opCode)) {
|
|
@@ -3072,61 +3107,69 @@ function applyLeafOperator(callDataBytes, location, opCode, operandData) {
|
|
|
3072
3107
|
} else valueLength = node.staticSize;
|
|
3073
3108
|
return {
|
|
3074
3109
|
passed: applyOperator(opCode, 0n, valueLength, operandData, node.typeCode),
|
|
3075
|
-
|
|
3110
|
+
resolvedValue: bigintToHex(BigInt(valueLength))
|
|
3076
3111
|
};
|
|
3077
3112
|
}
|
|
3078
3113
|
const result = loadScalar(callDataBytes, location);
|
|
3079
3114
|
if (!result.ok) return { error: result.code };
|
|
3080
|
-
const value = toBigInt(result.value, 0);
|
|
3115
|
+
const value = canonicalize(toBigInt(result.value, 0), node.typeCode);
|
|
3081
3116
|
return {
|
|
3082
3117
|
passed: applyOperator(opCode, value, 32, operandData, node.typeCode),
|
|
3083
|
-
value
|
|
3118
|
+
resolvedValue: bigintToHex(value)
|
|
3084
3119
|
};
|
|
3085
3120
|
}
|
|
3086
3121
|
/** Evaluate a leaf rule, producing a violation on failure or null on pass. */
|
|
3087
3122
|
function evaluateLeaf(location, callDataBytes, opCode, operandData, groupIndex, ruleIndex, pathHex) {
|
|
3088
3123
|
const result = applyLeafOperator(callDataBytes, location, opCode, operandData);
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3124
|
+
const typeCode = location.node.typeCode;
|
|
3125
|
+
if ("error" in result) return {
|
|
3126
|
+
group: groupIndex,
|
|
3127
|
+
rule: ruleIndex,
|
|
3128
|
+
code: result.error,
|
|
3129
|
+
scope: Scope.CALLDATA,
|
|
3130
|
+
path: pathHex,
|
|
3131
|
+
opCode,
|
|
3132
|
+
operandData: bytesToHex(operandData),
|
|
3133
|
+
typeCode
|
|
3134
|
+
};
|
|
3135
|
+
if (!result.passed) return {
|
|
3136
|
+
group: groupIndex,
|
|
3137
|
+
rule: ruleIndex,
|
|
3138
|
+
code: "VALUE_MISMATCH",
|
|
3139
|
+
scope: Scope.CALLDATA,
|
|
3140
|
+
path: pathHex,
|
|
3141
|
+
opCode,
|
|
3142
|
+
operandData: bytesToHex(operandData),
|
|
3143
|
+
typeCode,
|
|
3144
|
+
resolvedValue: result.resolvedValue
|
|
3145
|
+
};
|
|
3110
3146
|
return null;
|
|
3111
3147
|
}
|
|
3112
3148
|
/** Evaluate a quantified rule by iterating over array elements with ALL/ANY semantics. */
|
|
3113
3149
|
function evaluateQuantifier(qResult, callDataBytes, opCode, operandData, groupIndex, ruleIndex, pathHex) {
|
|
3114
3150
|
const { quantifier, location: arrayLocation, remainingPath } = qResult;
|
|
3151
|
+
const operandHex = bytesToHex(operandData);
|
|
3152
|
+
const arrayNode = arrayLocation.node;
|
|
3153
|
+
const leafTypeCode = resolveLeafTypeCode(arrayNode.type === "staticArray" || arrayNode.type === "dynamicArray" ? arrayNode.element : arrayNode, remainingPath);
|
|
3115
3154
|
const shapeResult = arrayShape(callDataBytes, arrayLocation);
|
|
3116
3155
|
if (!shapeResult.ok) return {
|
|
3117
3156
|
group: groupIndex,
|
|
3118
3157
|
rule: ruleIndex,
|
|
3119
3158
|
code: shapeResult.code,
|
|
3120
|
-
|
|
3121
|
-
path: pathHex
|
|
3159
|
+
scope: Scope.CALLDATA,
|
|
3160
|
+
path: pathHex,
|
|
3161
|
+
opCode,
|
|
3162
|
+
operandData: operandHex,
|
|
3163
|
+
typeCode: leafTypeCode
|
|
3122
3164
|
};
|
|
3123
3165
|
const shape = shapeResult.shape;
|
|
3124
3166
|
if (shape.length > Limits.MAX_QUANTIFIED_ARRAY_LENGTH) return {
|
|
3125
3167
|
group: groupIndex,
|
|
3126
3168
|
rule: ruleIndex,
|
|
3127
3169
|
code: "QUANTIFIER_LIMIT_EXCEEDED",
|
|
3128
|
-
|
|
3129
|
-
path: pathHex
|
|
3170
|
+
scope: Scope.CALLDATA,
|
|
3171
|
+
path: pathHex,
|
|
3172
|
+
resolvedValue: bigintToHex(BigInt(shape.length))
|
|
3130
3173
|
};
|
|
3131
3174
|
if (shape.length === 0) {
|
|
3132
3175
|
if (quantifier === Quantifier.ALL_OR_EMPTY) return null;
|
|
@@ -3134,7 +3177,7 @@ function evaluateQuantifier(qResult, callDataBytes, opCode, operandData, groupIn
|
|
|
3134
3177
|
group: groupIndex,
|
|
3135
3178
|
rule: ruleIndex,
|
|
3136
3179
|
code: "QUANTIFIER_EMPTY_ARRAY",
|
|
3137
|
-
|
|
3180
|
+
scope: Scope.CALLDATA,
|
|
3138
3181
|
path: pathHex
|
|
3139
3182
|
};
|
|
3140
3183
|
}
|
|
@@ -3147,70 +3190,82 @@ function evaluateQuantifier(qResult, callDataBytes, opCode, operandData, groupIn
|
|
|
3147
3190
|
group: groupIndex,
|
|
3148
3191
|
rule: ruleIndex,
|
|
3149
3192
|
code: elemResult.code,
|
|
3150
|
-
|
|
3151
|
-
path: pathHex
|
|
3193
|
+
scope: Scope.CALLDATA,
|
|
3194
|
+
path: pathHex,
|
|
3195
|
+
opCode,
|
|
3196
|
+
operandData: operandHex,
|
|
3197
|
+
typeCode: leafTypeCode,
|
|
3198
|
+
elementIndex: elemIndex
|
|
3152
3199
|
};
|
|
3153
3200
|
continue;
|
|
3154
3201
|
}
|
|
3155
3202
|
const elemLocation = elemResult.location;
|
|
3156
|
-
let
|
|
3203
|
+
let leafLocation;
|
|
3157
3204
|
if (hasSuffix) {
|
|
3158
|
-
const
|
|
3159
|
-
if (!
|
|
3160
|
-
if (isUniversal) return {
|
|
3161
|
-
group: groupIndex,
|
|
3162
|
-
rule: ruleIndex,
|
|
3163
|
-
code: leafResult.code,
|
|
3164
|
-
message: `Quantifier element ${elemIndex} navigation failed: ${leafResult.code}`,
|
|
3165
|
-
path: pathHex
|
|
3166
|
-
};
|
|
3167
|
-
continue;
|
|
3168
|
-
}
|
|
3169
|
-
elemPassed = evaluateLeafValue(leafResult.location, callDataBytes, opCode, operandData);
|
|
3170
|
-
} else {
|
|
3171
|
-
const leafResult = applyLeafOperator(callDataBytes, elemLocation, opCode, operandData);
|
|
3172
|
-
if ("error" in leafResult) {
|
|
3205
|
+
const navResult = descendPath(callDataBytes, elemLocation, remainingPath);
|
|
3206
|
+
if (!navResult.ok) {
|
|
3173
3207
|
if (isUniversal) return {
|
|
3174
3208
|
group: groupIndex,
|
|
3175
3209
|
rule: ruleIndex,
|
|
3176
|
-
code:
|
|
3177
|
-
|
|
3178
|
-
path: pathHex
|
|
3210
|
+
code: navResult.code,
|
|
3211
|
+
scope: Scope.CALLDATA,
|
|
3212
|
+
path: pathHex,
|
|
3213
|
+
opCode,
|
|
3214
|
+
operandData: operandHex,
|
|
3215
|
+
typeCode: leafTypeCode,
|
|
3216
|
+
elementIndex: elemIndex
|
|
3179
3217
|
};
|
|
3180
3218
|
continue;
|
|
3181
3219
|
}
|
|
3182
|
-
|
|
3220
|
+
leafLocation = navResult.location;
|
|
3221
|
+
} else leafLocation = elemLocation;
|
|
3222
|
+
const applied = applyLeafOperator(callDataBytes, leafLocation, opCode, operandData);
|
|
3223
|
+
if ("error" in applied) {
|
|
3224
|
+
if (isUniversal) return {
|
|
3225
|
+
group: groupIndex,
|
|
3226
|
+
rule: ruleIndex,
|
|
3227
|
+
code: applied.error,
|
|
3228
|
+
scope: Scope.CALLDATA,
|
|
3229
|
+
path: pathHex,
|
|
3230
|
+
opCode,
|
|
3231
|
+
operandData: operandHex,
|
|
3232
|
+
typeCode: leafTypeCode,
|
|
3233
|
+
elementIndex: elemIndex
|
|
3234
|
+
};
|
|
3235
|
+
continue;
|
|
3183
3236
|
}
|
|
3184
|
-
if (isUniversal && !
|
|
3237
|
+
if (isUniversal && !applied.passed) return {
|
|
3185
3238
|
group: groupIndex,
|
|
3186
3239
|
rule: ruleIndex,
|
|
3187
3240
|
code: "VALUE_MISMATCH",
|
|
3188
|
-
|
|
3189
|
-
path: pathHex
|
|
3241
|
+
scope: Scope.CALLDATA,
|
|
3242
|
+
path: pathHex,
|
|
3243
|
+
opCode,
|
|
3244
|
+
operandData: operandHex,
|
|
3245
|
+
typeCode: leafTypeCode,
|
|
3246
|
+
resolvedValue: applied.resolvedValue,
|
|
3247
|
+
elementIndex: elemIndex
|
|
3190
3248
|
};
|
|
3191
|
-
if (!isUniversal &&
|
|
3249
|
+
if (!isUniversal && applied.passed) return null;
|
|
3192
3250
|
}
|
|
3193
3251
|
if (isUniversal) return null;
|
|
3194
3252
|
return {
|
|
3195
3253
|
group: groupIndex,
|
|
3196
3254
|
rule: ruleIndex,
|
|
3197
3255
|
code: "VALUE_MISMATCH",
|
|
3198
|
-
|
|
3199
|
-
path: pathHex
|
|
3256
|
+
scope: Scope.CALLDATA,
|
|
3257
|
+
path: pathHex,
|
|
3258
|
+
opCode,
|
|
3259
|
+
operandData: operandHex,
|
|
3260
|
+
typeCode: leafTypeCode
|
|
3200
3261
|
};
|
|
3201
3262
|
}
|
|
3202
|
-
/** Apply a leaf operator and return a boolean. Returns false on calldata read failure. */
|
|
3203
|
-
function evaluateLeafValue(location, callDataBytes, opCode, operandData) {
|
|
3204
|
-
const result = applyLeafOperator(callDataBytes, location, opCode, operandData);
|
|
3205
|
-
if ("error" in result) return false;
|
|
3206
|
-
return result.passed;
|
|
3207
|
-
}
|
|
3208
3263
|
/** Check and enforce policies against ABI-encoded call data. */
|
|
3209
3264
|
const PolicyEnforcer = {
|
|
3210
3265
|
check,
|
|
3211
3266
|
enforce
|
|
3212
3267
|
};
|
|
3213
3268
|
//#endregion
|
|
3214
|
-
export { CallciumError, ContextProperty, Descriptor, DescriptorCoder, Limits, Op, PolicyBuilder, PolicyCoder, PolicyEnforcer, PolicyValidator, PolicyViolationError, Quantifier, Scope, TypeCode, arg, blockNumber, blockTimestamp, bytesToHex, chainId, hexToBytes, isOpAllowed, isQuantifier, lookupContextProperty, lookupOp, lookupQuantifier, lookupScope, lookupTypeCode, msgSender, msgValue, parsePathSteps, toAddress, txOrigin };
|
|
3269
|
+
export { CallciumError, ContextProperty, Descriptor, DescriptorCoder, Limits, Op, PolicyBuilder, PolicyCoder, PolicyEnforcer, PolicyValidator, PolicyViolationError, Quantifier, Scope, TypeCode, arg, blockNumber, blockTimestamp, bytesToHex, chainId, hexToBytes, isLengthOp, isOpAllowed, isQuantifier, lookupContextProperty, lookupOp, lookupQuantifier, lookupScope, lookupTypeCode, msgSender, msgValue, parsePathSteps, toAddress, txOrigin };
|
|
3215
3270
|
|
|
3216
3271
|
//# sourceMappingURL=index.js.map
|