@callcium/sdk 0.1.0 → 0.2.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 +145 -120
- package/dist/index.js.map +1 -1
- package/package.json +2 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Provencraft
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# @callcium/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript implementation of the Callcium policy engine.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @callcium/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
12
|
+
|
|
13
|
+
Full documentation at [callcium.dev/docs/sdk](https://callcium.dev/docs/sdk).
|
|
14
|
+
|
|
15
|
+
## License
|
|
16
|
+
|
|
17
|
+
MIT License. See [LICENSE](LICENSE).
|
package/dist/index.d.ts
CHANGED
|
@@ -29,17 +29,110 @@ type EnforceResult = {
|
|
|
29
29
|
ok: false;
|
|
30
30
|
violations: Violation[];
|
|
31
31
|
};
|
|
32
|
-
/**
|
|
33
|
-
type
|
|
34
|
-
/**
|
|
35
|
-
type
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
/** Subset of violation codes emitted by reader/navigation primitives. */
|
|
33
|
+
type NavigationViolationCode = "CALLDATA_OUT_OF_BOUNDS" | "ARRAY_INDEX_OUT_OF_BOUNDS";
|
|
34
|
+
/** Calldata is shorter than the policy's selector slot. */
|
|
35
|
+
type MissingSelectorViolation = {
|
|
36
|
+
code: "MISSING_SELECTOR";
|
|
37
|
+
};
|
|
38
|
+
/** Calldata selector does not match the policy's expected selector. */
|
|
39
|
+
type SelectorMismatchViolation = {
|
|
40
|
+
code: "SELECTOR_MISMATCH"; /** Selector declared by the policy. */
|
|
41
|
+
expectedValue: Hex; /** Selector observed in the calldata. */
|
|
42
|
+
resolvedValue: Hex;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* A context-scoped rule referenced a property not supplied in the execution context.
|
|
46
|
+
*
|
|
47
|
+
* `opCode` and `operandData` may be added in future versions as diagnostic context
|
|
48
|
+
* without breaking the contract; consumers should tolerate their presence.
|
|
49
|
+
*/
|
|
50
|
+
type MissingContextViolation = {
|
|
51
|
+
code: "MISSING_CONTEXT";
|
|
52
|
+
group: number;
|
|
53
|
+
rule: number;
|
|
54
|
+
scope: number;
|
|
55
|
+
path: Hex; /** Declared type of the missing context property. */
|
|
56
|
+
typeCode: number;
|
|
57
|
+
opCode?: number;
|
|
58
|
+
operandData?: Hex;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* A rule's operator returned false against the loaded value.
|
|
62
|
+
*
|
|
63
|
+
* Field combinations:
|
|
64
|
+
* - `resolvedValue` present, `elementIndex` absent — scalar leaf or context value that failed the operator.
|
|
65
|
+
* - `resolvedValue` present, `elementIndex` present — universal-quantifier per-element failure.
|
|
66
|
+
* - `resolvedValue` absent, `elementIndex` absent — existential-aggregate failure (no element satisfied).
|
|
67
|
+
* - `resolvedValue` absent, `elementIndex` present — per-element failure where the leaf could not be loaded.
|
|
68
|
+
*
|
|
69
|
+
* For length operations (`isLengthOp(opCode)`), `resolvedValue` is a hex-encoded count
|
|
70
|
+
* rather than a 32-byte ABI word.
|
|
71
|
+
*/
|
|
72
|
+
type ValueMismatchViolation = {
|
|
73
|
+
code: "VALUE_MISMATCH";
|
|
74
|
+
group: number;
|
|
75
|
+
rule: number;
|
|
76
|
+
scope: number;
|
|
77
|
+
path: Hex; /** Operator code with the `Op.NOT` bit intact. */
|
|
78
|
+
opCode: number; /** Full untruncated operand bytes declared by the rule. */
|
|
79
|
+
operandData: Hex; /** Type code of the failing value's leaf. */
|
|
80
|
+
typeCode: number;
|
|
41
81
|
resolvedValue?: Hex;
|
|
82
|
+
elementIndex?: number;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Single-code shape for a calldata-navigation failure. Internal helper for de-duplication.
|
|
86
|
+
* @internal
|
|
87
|
+
*/
|
|
88
|
+
type CalldataNavigationVariant<C extends NavigationViolationCode> = {
|
|
89
|
+
code: C;
|
|
90
|
+
group: number;
|
|
91
|
+
rule: number;
|
|
92
|
+
scope: number;
|
|
93
|
+
path: Hex;
|
|
94
|
+
opCode?: number;
|
|
95
|
+
operandData?: Hex;
|
|
96
|
+
typeCode?: number;
|
|
97
|
+
elementIndex?: number;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Calldata structure prevented the rule from being evaluated.
|
|
101
|
+
*
|
|
102
|
+
* The operator was never applied; `opCode`, `operandData`, `typeCode`, and `elementIndex`
|
|
103
|
+
* are diagnostic context describing the failing site, not a constraint claim. Renderers
|
|
104
|
+
* must not summarise these as "constraint violated".
|
|
105
|
+
*
|
|
106
|
+
* Encoded as a union of per-code variants so consumers can narrow on a single code via
|
|
107
|
+
* `Extract<Violation, { code: "..." }>`.
|
|
108
|
+
*/
|
|
109
|
+
type CalldataNavigationViolation = CalldataNavigationVariant<"CALLDATA_OUT_OF_BOUNDS"> | CalldataNavigationVariant<"ARRAY_INDEX_OUT_OF_BOUNDS">;
|
|
110
|
+
/** A quantified array exceeded `Limits.MAX_QUANTIFIED_ARRAY_LENGTH`. */
|
|
111
|
+
type QuantifierLimitExceededViolation = {
|
|
112
|
+
code: "QUANTIFIER_LIMIT_EXCEEDED";
|
|
113
|
+
group: number;
|
|
114
|
+
rule: number;
|
|
115
|
+
scope: number;
|
|
116
|
+
path: Hex; /** Hex-encoded element count of the offending array. */
|
|
117
|
+
resolvedValue: Hex;
|
|
42
118
|
};
|
|
119
|
+
/** A quantifier (`ANY` or `ALL`) was applied to an empty array. */
|
|
120
|
+
type QuantifierEmptyArrayViolation = {
|
|
121
|
+
code: "QUANTIFIER_EMPTY_ARRAY";
|
|
122
|
+
group: number;
|
|
123
|
+
rule: number;
|
|
124
|
+
scope: number;
|
|
125
|
+
path: Hex;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Structured details of a single rule failure during enforcement.
|
|
129
|
+
*
|
|
130
|
+
* Carries semantic data only — message strings are the consumer's responsibility.
|
|
131
|
+
* Discriminate on `code` to narrow to the matching variant.
|
|
132
|
+
*/
|
|
133
|
+
type Violation = MissingSelectorViolation | SelectorMismatchViolation | MissingContextViolation | ValueMismatchViolation | CalldataNavigationViolation | QuantifierLimitExceededViolation | QuantifierEmptyArrayViolation;
|
|
134
|
+
/** Machine-readable reason code for an enforcement violation. Derived from `Violation` to prevent drift. */
|
|
135
|
+
type ViolationCode = Violation["code"];
|
|
43
136
|
/** Canonical structured representation of a policy. */
|
|
44
137
|
type PolicyData = {
|
|
45
138
|
isSelectorless: boolean;
|
|
@@ -673,6 +766,10 @@ type TypeCodeInfo = TypeClassInfo & {
|
|
|
673
766
|
*/
|
|
674
767
|
declare function lookupTypeCode(code: number): TypeCodeInfo;
|
|
675
768
|
//#endregion
|
|
769
|
+
//#region src/operators.d.ts
|
|
770
|
+
/** Return true when the operator code (with or without NOT flag) is a LENGTH_* variant. */
|
|
771
|
+
declare function isLengthOp(opCode: number): boolean;
|
|
772
|
+
//#endregion
|
|
676
773
|
//#region src/errors.d.ts
|
|
677
774
|
/** Machine-readable error code for structural decoding and validation failures. */
|
|
678
775
|
type CallciumErrorCode = "UNSUPPORTED_VERSION" | "MALFORMED_HEADER" | "UNEXPECTED_END" | "NODE_OVERFLOW" | "UNKNOWN_TYPE_CODE" | "INVALID_OPERATOR" | "INVALID_ARRAY_LENGTH" | "INVALID_TUPLE_FIELD_COUNT" | "PARAM_COUNT_MISMATCH" | "EMPTY_POLICY" | "EMPTY_GROUP" | "EMPTY_PATH" | "INVALID_CONTEXT_PATH" | "INVALID_CONTEXT_PROPERTY" | "INVALID_QUANTIFIER" | "INVALID_SCOPE" | "RULE_SIZE_MISMATCH" | "GROUP_SIZE_MISMATCH" | "GROUP_OVERFLOW" | "RULE_OVERFLOW" | "TRAILING_BYTES" | "INTERNAL_ERROR" | "INVALID_SIGNATURE" | "INVALID_TYPE_STRING" | "UNKNOWN_TYPE" | "DESCRIPTOR_TOO_LARGE" | "INVALID_PATH" | "DUPLICATE_PATH" | "INVALID_CONSTRAINT" | "INVALID_OPERATOR_DATA" | "EMPTY_SET" | "SET_TOO_LARGE" | "INVALID_RANGE" | "GROUP_COUNT_OVERFLOW" | "RULE_COUNT_OVERFLOW" | "RULE_SIZE_OVERFLOW" | "DESC_LENGTH_OVERFLOW" | "INVALID_HEX" | "VALIDATION_ERROR";
|
|
@@ -690,12 +787,16 @@ declare class CallciumError extends Error {
|
|
|
690
787
|
* Thrown by `PolicyEnforcer.enforce` when calldata fails policy enforcement.
|
|
691
788
|
* Distinct from `CallciumError("VALIDATION_ERROR")`, which signals static
|
|
692
789
|
* issues in the policy itself.
|
|
693
|
-
*
|
|
790
|
+
*
|
|
791
|
+
* Carries the full list of structured violations (one per failed group). The
|
|
792
|
+
* `Error.message` is a minimal non-lossy diagnostic summary built from the
|
|
793
|
+
* first violation's structured fields — not a presentation contract. Consumers
|
|
794
|
+
* rendering violations to users should iterate `violations` directly.
|
|
694
795
|
*/
|
|
695
796
|
declare class PolicyViolationError extends Error {
|
|
696
797
|
readonly violations: Violation[];
|
|
697
798
|
constructor(violations: Violation[]);
|
|
698
799
|
}
|
|
699
800
|
//#endregion
|
|
700
|
-
export { type Address, CallciumError, type CallciumErrorCode, type Constraint, type ConstraintBuilder, type Context, ContextProperty, type ContextPropertyInfo, type DecodedGroup, type DecodedParam, type DecodedPolicy, type DecodedRule, Descriptor, DescriptorCoder, type EnforceResult, type Field, type Hex, type Issue, type IssueCategory, type IssueSeverity, Limits, Op, type OpInfo, type Operands, PolicyBuilder, PolicyCoder, type PolicyData, PolicyEnforcer, PolicyValidator, PolicyViolationError, Quantifier, type QuantifierInfo, type ScalarValue, Scope, type ScopeInfo, type Span, type TypeClass, type TypeClassInfo, TypeCode, type TypeCodeInfo, type TypeInfo, type Violation, type ViolationCode, arg, blockNumber, blockTimestamp, bytesToHex, chainId, hexToBytes, isOpAllowed, isQuantifier, lookupContextProperty, lookupOp, lookupQuantifier, lookupScope, lookupTypeCode, msgSender, msgValue, parsePathSteps, toAddress, txOrigin };
|
|
801
|
+
export { type Address, CallciumError, type CallciumErrorCode, type CalldataNavigationViolation, type Constraint, type ConstraintBuilder, type Context, ContextProperty, type ContextPropertyInfo, type DecodedGroup, type DecodedParam, type DecodedPolicy, type DecodedRule, Descriptor, DescriptorCoder, type EnforceResult, type Field, type Hex, type Issue, type IssueCategory, type IssueSeverity, Limits, type MissingContextViolation, type MissingSelectorViolation, type NavigationViolationCode, Op, type OpInfo, type Operands, PolicyBuilder, PolicyCoder, type PolicyData, PolicyEnforcer, PolicyValidator, PolicyViolationError, Quantifier, type QuantifierEmptyArrayViolation, type QuantifierInfo, type QuantifierLimitExceededViolation, type ScalarValue, Scope, type ScopeInfo, type SelectorMismatchViolation, type Span, type TypeClass, type TypeClassInfo, TypeCode, type TypeCodeInfo, type TypeInfo, type ValueMismatchViolation, type Violation, type ViolationCode, arg, blockNumber, blockTimestamp, bytesToHex, chainId, hexToBytes, isLengthOp, isOpAllowed, isQuantifier, lookupContextProperty, lookupOp, lookupQuantifier, lookupScope, lookupTypeCode, msgSender, msgValue, parsePathSteps, toAddress, txOrigin };
|
|
701
802
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/constraint.ts","../src/policy-builder.ts","../src/policy-coder.ts","../src/descriptor.ts","../src/policy-validator.ts","../src/policy-enforcer.ts","../src/bytes.ts","../src/descriptor-coder.ts","../src/constants.ts","../src/errors.ts"],"mappings":";;KAKY,GAAA;;KAGA,OAAA;;KAGA,IAAA;EAAS,KAAA;EAAe,GAAA;AAAA;;AA+DpC;;;;KAbY,OAAA;EACV,SAAA,GAAY,OAAA;EACZ,QAAA;EACA,cAAA;EACA,WAAA;EACA,OAAA;EACA,QAAA,GAAW,OAAA;AAAA;;KAID,aAAA;EAAkB,EAAA;EAAU,YAAA;AAAA;EAA2B,EAAA;EAAW,UAAA,EAAY,SAAA;AAAA;;KAG9E,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/constraint.ts","../src/policy-builder.ts","../src/policy-coder.ts","../src/descriptor.ts","../src/policy-validator.ts","../src/policy-enforcer.ts","../src/bytes.ts","../src/descriptor-coder.ts","../src/constants.ts","../src/operators.ts","../src/errors.ts"],"mappings":"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"}
|
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). */
|
|
@@ -2707,11 +2715,11 @@ function locate(tree, callData, pathBytes, baseOffset) {
|
|
|
2707
2715
|
for (let i = 0; i < paramIndex; i++) head += headContribution(tree[i]);
|
|
2708
2716
|
let base = baseOffset;
|
|
2709
2717
|
let node = tree[paramIndex];
|
|
2710
|
-
for (let
|
|
2711
|
-
const step = readStep(pathBytes,
|
|
2718
|
+
for (let stepIndex = 1; stepIndex < stepCount; stepIndex++) {
|
|
2719
|
+
const step = readStep(pathBytes, stepIndex);
|
|
2712
2720
|
if (isQuantifier(step)) {
|
|
2713
|
-
const remaining = pathBytes.subarray((
|
|
2714
|
-
for (let
|
|
2721
|
+
const remaining = pathBytes.subarray((stepIndex + 1) * 2);
|
|
2722
|
+
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
2723
|
return {
|
|
2716
2724
|
ok: true,
|
|
2717
2725
|
type: "quantifier",
|
|
@@ -2887,8 +2895,8 @@ function loadSlice(callData, location) {
|
|
|
2887
2895
|
function descendPath(callData, location, pathBytes) {
|
|
2888
2896
|
const stepCount = pathBytes.length / 2;
|
|
2889
2897
|
let { head, base, node } = location;
|
|
2890
|
-
for (let
|
|
2891
|
-
const step = readStep(pathBytes,
|
|
2898
|
+
for (let stepIndex = 0; stepIndex < stepCount; stepIndex++) {
|
|
2899
|
+
const step = readStep(pathBytes, stepIndex);
|
|
2892
2900
|
const result = descend(node, callData, head, base, step);
|
|
2893
2901
|
if (result.type === "violation") return {
|
|
2894
2902
|
ok: false,
|
|
@@ -2916,38 +2924,27 @@ function addressToBigInt(hex) {
|
|
|
2916
2924
|
padded.set(bytes, 32 - bytes.length);
|
|
2917
2925
|
return toBigInt(padded, 0);
|
|
2918
2926
|
}
|
|
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}`;
|
|
2927
|
+
/**
|
|
2928
|
+
* Walk a descriptor subtree through path steps and return the terminal leaf type code.
|
|
2929
|
+
*
|
|
2930
|
+
* Used only for violation metadata. Valid policies have structurally valid
|
|
2931
|
+
* quantifier suffixes (enforced by `PolicyValidator`); if a hand-crafted blob
|
|
2932
|
+
* violates that invariant, return the last resolvable node's type code as
|
|
2933
|
+
* best-effort diagnostic context.
|
|
2934
|
+
*/
|
|
2935
|
+
function resolveLeafTypeCode(elementNode, remainingPath) {
|
|
2936
|
+
let node = elementNode;
|
|
2937
|
+
const stepCount = remainingPath.length / 2;
|
|
2938
|
+
for (let step = 0; step < stepCount; step++) {
|
|
2939
|
+
const childIndex = readU16(remainingPath, step * 2);
|
|
2940
|
+
if (node.type === "tuple") {
|
|
2941
|
+
const field = node.fields[childIndex];
|
|
2942
|
+
if (!field) break;
|
|
2943
|
+
node = field;
|
|
2944
|
+
} else if (node.type === "staticArray" || node.type === "dynamicArray") node = node.element;
|
|
2945
|
+
else break;
|
|
2946
|
+
}
|
|
2947
|
+
return node.typeCode;
|
|
2951
2948
|
}
|
|
2952
2949
|
/**
|
|
2953
2950
|
* Check a policy against ABI-encoded call data without throwing on violations.
|
|
@@ -2963,10 +2960,7 @@ function check(policy, callData, context) {
|
|
|
2963
2960
|
if (!decoded.isSelectorless) {
|
|
2964
2961
|
if (callDataBytes.length < 4) return {
|
|
2965
2962
|
ok: false,
|
|
2966
|
-
violations: [{
|
|
2967
|
-
code: "MISSING_SELECTOR",
|
|
2968
|
-
message: "Calldata too short to contain a selector"
|
|
2969
|
-
}]
|
|
2963
|
+
violations: [{ code: "MISSING_SELECTOR" }]
|
|
2970
2964
|
};
|
|
2971
2965
|
const expectedSelector = decoded.selector.value;
|
|
2972
2966
|
const actualSelector = bytesToHex(callDataBytes.subarray(0, 4));
|
|
@@ -2974,8 +2968,8 @@ function check(policy, callData, context) {
|
|
|
2974
2968
|
ok: false,
|
|
2975
2969
|
violations: [{
|
|
2976
2970
|
code: "SELECTOR_MISMATCH",
|
|
2977
|
-
|
|
2978
|
-
|
|
2971
|
+
resolvedValue: actualSelector,
|
|
2972
|
+
expectedValue: expectedSelector
|
|
2979
2973
|
}]
|
|
2980
2974
|
};
|
|
2981
2975
|
}
|
|
@@ -3028,8 +3022,10 @@ function evaluateRule(rule, tree, callDataBytes, baseOffset, groupIndex, ruleInd
|
|
|
3028
3022
|
group: groupIndex,
|
|
3029
3023
|
rule: ruleIndex,
|
|
3030
3024
|
code: locResult.code,
|
|
3031
|
-
|
|
3032
|
-
path: rule.path.value
|
|
3025
|
+
scope: Scope.CALLDATA,
|
|
3026
|
+
path: rule.path.value,
|
|
3027
|
+
opCode,
|
|
3028
|
+
operandData: rule.data.value
|
|
3033
3029
|
};
|
|
3034
3030
|
if (locResult.type === "quantifier") return evaluateQuantifier(locResult.quantifier, callDataBytes, opCode, operandData, groupIndex, ruleIndex, rule.path.value);
|
|
3035
3031
|
return evaluateLeaf(locResult.location, callDataBytes, opCode, operandData, groupIndex, ruleIndex, rule.path.value);
|
|
@@ -3044,23 +3040,33 @@ function evaluateContextRule(pathBytes, opCode, operandData, groupIndex, ruleInd
|
|
|
3044
3040
|
group: groupIndex,
|
|
3045
3041
|
rule: ruleIndex,
|
|
3046
3042
|
code: "MISSING_CONTEXT",
|
|
3047
|
-
|
|
3048
|
-
path: pathHex
|
|
3043
|
+
scope: Scope.CONTEXT,
|
|
3044
|
+
path: pathHex,
|
|
3045
|
+
typeCode: propInfo.typeCode
|
|
3049
3046
|
};
|
|
3050
3047
|
let value;
|
|
3051
3048
|
if (typeof contextValue === "string") value = addressToBigInt(contextValue);
|
|
3052
3049
|
else value = contextValue;
|
|
3053
|
-
if (!applyOperator(opCode, value, 32, operandData,
|
|
3050
|
+
if (!applyOperator(opCode, value, 32, operandData, propInfo.typeCode)) return {
|
|
3054
3051
|
group: groupIndex,
|
|
3055
3052
|
rule: ruleIndex,
|
|
3056
3053
|
code: "VALUE_MISMATCH",
|
|
3057
|
-
|
|
3054
|
+
scope: Scope.CONTEXT,
|
|
3058
3055
|
path: pathHex,
|
|
3056
|
+
opCode,
|
|
3057
|
+
operandData: bytesToHex(operandData),
|
|
3058
|
+
typeCode: propInfo.typeCode,
|
|
3059
3059
|
resolvedValue: bigintToHex(value)
|
|
3060
3060
|
};
|
|
3061
3061
|
return null;
|
|
3062
3062
|
}
|
|
3063
|
-
/**
|
|
3063
|
+
/**
|
|
3064
|
+
* Load a value from calldata at the given location and apply the operator.
|
|
3065
|
+
*
|
|
3066
|
+
* `resolvedValue` is normalised at the decision point: length operators encode
|
|
3067
|
+
* the byte/element count as a hex bigint; scalar operators preserve the full
|
|
3068
|
+
* 32-byte ABI word so downstream rendering can decode left-aligned `bytesN` faithfully.
|
|
3069
|
+
*/
|
|
3064
3070
|
function applyLeafOperator(callDataBytes, location, opCode, operandData) {
|
|
3065
3071
|
const { node } = location;
|
|
3066
3072
|
if (isLengthOp(opCode)) {
|
|
@@ -3072,61 +3078,68 @@ function applyLeafOperator(callDataBytes, location, opCode, operandData) {
|
|
|
3072
3078
|
} else valueLength = node.staticSize;
|
|
3073
3079
|
return {
|
|
3074
3080
|
passed: applyOperator(opCode, 0n, valueLength, operandData, node.typeCode),
|
|
3075
|
-
|
|
3081
|
+
resolvedValue: bigintToHex(BigInt(valueLength))
|
|
3076
3082
|
};
|
|
3077
3083
|
}
|
|
3078
3084
|
const result = loadScalar(callDataBytes, location);
|
|
3079
3085
|
if (!result.ok) return { error: result.code };
|
|
3080
|
-
const value = toBigInt(result.value, 0);
|
|
3081
3086
|
return {
|
|
3082
|
-
passed: applyOperator(opCode, value, 32, operandData, node.typeCode),
|
|
3083
|
-
value
|
|
3087
|
+
passed: applyOperator(opCode, toBigInt(result.value, 0), 32, operandData, node.typeCode),
|
|
3088
|
+
resolvedValue: bytesToHex(result.value)
|
|
3084
3089
|
};
|
|
3085
3090
|
}
|
|
3086
3091
|
/** Evaluate a leaf rule, producing a violation on failure or null on pass. */
|
|
3087
3092
|
function evaluateLeaf(location, callDataBytes, opCode, operandData, groupIndex, ruleIndex, pathHex) {
|
|
3088
3093
|
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
|
-
|
|
3094
|
+
const typeCode = location.node.typeCode;
|
|
3095
|
+
if ("error" in result) return {
|
|
3096
|
+
group: groupIndex,
|
|
3097
|
+
rule: ruleIndex,
|
|
3098
|
+
code: result.error,
|
|
3099
|
+
scope: Scope.CALLDATA,
|
|
3100
|
+
path: pathHex,
|
|
3101
|
+
opCode,
|
|
3102
|
+
operandData: bytesToHex(operandData),
|
|
3103
|
+
typeCode
|
|
3104
|
+
};
|
|
3105
|
+
if (!result.passed) return {
|
|
3106
|
+
group: groupIndex,
|
|
3107
|
+
rule: ruleIndex,
|
|
3108
|
+
code: "VALUE_MISMATCH",
|
|
3109
|
+
scope: Scope.CALLDATA,
|
|
3110
|
+
path: pathHex,
|
|
3111
|
+
opCode,
|
|
3112
|
+
operandData: bytesToHex(operandData),
|
|
3113
|
+
typeCode,
|
|
3114
|
+
resolvedValue: result.resolvedValue
|
|
3115
|
+
};
|
|
3110
3116
|
return null;
|
|
3111
3117
|
}
|
|
3112
3118
|
/** Evaluate a quantified rule by iterating over array elements with ALL/ANY semantics. */
|
|
3113
3119
|
function evaluateQuantifier(qResult, callDataBytes, opCode, operandData, groupIndex, ruleIndex, pathHex) {
|
|
3114
3120
|
const { quantifier, location: arrayLocation, remainingPath } = qResult;
|
|
3121
|
+
const operandHex = bytesToHex(operandData);
|
|
3122
|
+
const arrayNode = arrayLocation.node;
|
|
3123
|
+
const leafTypeCode = resolveLeafTypeCode(arrayNode.type === "staticArray" || arrayNode.type === "dynamicArray" ? arrayNode.element : arrayNode, remainingPath);
|
|
3115
3124
|
const shapeResult = arrayShape(callDataBytes, arrayLocation);
|
|
3116
3125
|
if (!shapeResult.ok) return {
|
|
3117
3126
|
group: groupIndex,
|
|
3118
3127
|
rule: ruleIndex,
|
|
3119
3128
|
code: shapeResult.code,
|
|
3120
|
-
|
|
3121
|
-
path: pathHex
|
|
3129
|
+
scope: Scope.CALLDATA,
|
|
3130
|
+
path: pathHex,
|
|
3131
|
+
opCode,
|
|
3132
|
+
operandData: operandHex,
|
|
3133
|
+
typeCode: leafTypeCode
|
|
3122
3134
|
};
|
|
3123
3135
|
const shape = shapeResult.shape;
|
|
3124
3136
|
if (shape.length > Limits.MAX_QUANTIFIED_ARRAY_LENGTH) return {
|
|
3125
3137
|
group: groupIndex,
|
|
3126
3138
|
rule: ruleIndex,
|
|
3127
3139
|
code: "QUANTIFIER_LIMIT_EXCEEDED",
|
|
3128
|
-
|
|
3129
|
-
path: pathHex
|
|
3140
|
+
scope: Scope.CALLDATA,
|
|
3141
|
+
path: pathHex,
|
|
3142
|
+
resolvedValue: bigintToHex(BigInt(shape.length))
|
|
3130
3143
|
};
|
|
3131
3144
|
if (shape.length === 0) {
|
|
3132
3145
|
if (quantifier === Quantifier.ALL_OR_EMPTY) return null;
|
|
@@ -3134,7 +3147,7 @@ function evaluateQuantifier(qResult, callDataBytes, opCode, operandData, groupIn
|
|
|
3134
3147
|
group: groupIndex,
|
|
3135
3148
|
rule: ruleIndex,
|
|
3136
3149
|
code: "QUANTIFIER_EMPTY_ARRAY",
|
|
3137
|
-
|
|
3150
|
+
scope: Scope.CALLDATA,
|
|
3138
3151
|
path: pathHex
|
|
3139
3152
|
};
|
|
3140
3153
|
}
|
|
@@ -3147,70 +3160,82 @@ function evaluateQuantifier(qResult, callDataBytes, opCode, operandData, groupIn
|
|
|
3147
3160
|
group: groupIndex,
|
|
3148
3161
|
rule: ruleIndex,
|
|
3149
3162
|
code: elemResult.code,
|
|
3150
|
-
|
|
3151
|
-
path: pathHex
|
|
3163
|
+
scope: Scope.CALLDATA,
|
|
3164
|
+
path: pathHex,
|
|
3165
|
+
opCode,
|
|
3166
|
+
operandData: operandHex,
|
|
3167
|
+
typeCode: leafTypeCode,
|
|
3168
|
+
elementIndex: elemIndex
|
|
3152
3169
|
};
|
|
3153
3170
|
continue;
|
|
3154
3171
|
}
|
|
3155
3172
|
const elemLocation = elemResult.location;
|
|
3156
|
-
let
|
|
3173
|
+
let leafLocation;
|
|
3157
3174
|
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) {
|
|
3175
|
+
const navResult = descendPath(callDataBytes, elemLocation, remainingPath);
|
|
3176
|
+
if (!navResult.ok) {
|
|
3173
3177
|
if (isUniversal) return {
|
|
3174
3178
|
group: groupIndex,
|
|
3175
3179
|
rule: ruleIndex,
|
|
3176
|
-
code:
|
|
3177
|
-
|
|
3178
|
-
path: pathHex
|
|
3180
|
+
code: navResult.code,
|
|
3181
|
+
scope: Scope.CALLDATA,
|
|
3182
|
+
path: pathHex,
|
|
3183
|
+
opCode,
|
|
3184
|
+
operandData: operandHex,
|
|
3185
|
+
typeCode: leafTypeCode,
|
|
3186
|
+
elementIndex: elemIndex
|
|
3179
3187
|
};
|
|
3180
3188
|
continue;
|
|
3181
3189
|
}
|
|
3182
|
-
|
|
3190
|
+
leafLocation = navResult.location;
|
|
3191
|
+
} else leafLocation = elemLocation;
|
|
3192
|
+
const applied = applyLeafOperator(callDataBytes, leafLocation, opCode, operandData);
|
|
3193
|
+
if ("error" in applied) {
|
|
3194
|
+
if (isUniversal) return {
|
|
3195
|
+
group: groupIndex,
|
|
3196
|
+
rule: ruleIndex,
|
|
3197
|
+
code: applied.error,
|
|
3198
|
+
scope: Scope.CALLDATA,
|
|
3199
|
+
path: pathHex,
|
|
3200
|
+
opCode,
|
|
3201
|
+
operandData: operandHex,
|
|
3202
|
+
typeCode: leafTypeCode,
|
|
3203
|
+
elementIndex: elemIndex
|
|
3204
|
+
};
|
|
3205
|
+
continue;
|
|
3183
3206
|
}
|
|
3184
|
-
if (isUniversal && !
|
|
3207
|
+
if (isUniversal && !applied.passed) return {
|
|
3185
3208
|
group: groupIndex,
|
|
3186
3209
|
rule: ruleIndex,
|
|
3187
3210
|
code: "VALUE_MISMATCH",
|
|
3188
|
-
|
|
3189
|
-
path: pathHex
|
|
3211
|
+
scope: Scope.CALLDATA,
|
|
3212
|
+
path: pathHex,
|
|
3213
|
+
opCode,
|
|
3214
|
+
operandData: operandHex,
|
|
3215
|
+
typeCode: leafTypeCode,
|
|
3216
|
+
resolvedValue: applied.resolvedValue,
|
|
3217
|
+
elementIndex: elemIndex
|
|
3190
3218
|
};
|
|
3191
|
-
if (!isUniversal &&
|
|
3219
|
+
if (!isUniversal && applied.passed) return null;
|
|
3192
3220
|
}
|
|
3193
3221
|
if (isUniversal) return null;
|
|
3194
3222
|
return {
|
|
3195
3223
|
group: groupIndex,
|
|
3196
3224
|
rule: ruleIndex,
|
|
3197
3225
|
code: "VALUE_MISMATCH",
|
|
3198
|
-
|
|
3199
|
-
path: pathHex
|
|
3226
|
+
scope: Scope.CALLDATA,
|
|
3227
|
+
path: pathHex,
|
|
3228
|
+
opCode,
|
|
3229
|
+
operandData: operandHex,
|
|
3230
|
+
typeCode: leafTypeCode
|
|
3200
3231
|
};
|
|
3201
3232
|
}
|
|
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
3233
|
/** Check and enforce policies against ABI-encoded call data. */
|
|
3209
3234
|
const PolicyEnforcer = {
|
|
3210
3235
|
check,
|
|
3211
3236
|
enforce
|
|
3212
3237
|
};
|
|
3213
3238
|
//#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 };
|
|
3239
|
+
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
3240
|
|
|
3216
3241
|
//# sourceMappingURL=index.js.map
|