@seljs/checker 1.3.0-beta.3 → 1.3.0-beta.32
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/environment/codec-registry.cjs +1 -6
- package/dist/environment/codec-registry.mjs +2 -7
- package/dist/environment/hydrate.cjs +3 -3
- package/dist/environment/hydrate.mjs +4 -4
- package/dist/environment/register-types.cjs +81 -4
- package/dist/environment/register-types.d.cts +1 -1
- package/dist/environment/register-types.d.mts +1 -1
- package/dist/environment/register-types.mjs +82 -5
- package/package.json +6 -5
|
@@ -25,12 +25,7 @@ var CelCodecRegistry = class {
|
|
|
25
25
|
this.codecs.set("bool", zod.z.boolean());
|
|
26
26
|
this.codecs.set("string", zod.z.string());
|
|
27
27
|
this.codecs.set("int", zod.z.bigint());
|
|
28
|
-
this.codecs.set("bytes", zod.z.union([zod.z.instanceof(Uint8Array), zod.z.string().transform((s) =>
|
|
29
|
-
const hex = s.startsWith("0x") ? s.slice(2) : s;
|
|
30
|
-
const bytes = new Uint8Array(hex.length / 2);
|
|
31
|
-
for (let i = 0; i < bytes.length; i++) bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
32
|
-
return bytes;
|
|
33
|
-
})]));
|
|
28
|
+
this.codecs.set("bytes", zod.z.union([zod.z.instanceof(Uint8Array), zod.z.string().transform((s) => (0, _seljs_types.hexToBytes)(s))]));
|
|
34
29
|
this.codecs.set("dyn", zod.z.unknown().transform((v) => typeof v === "bigint" ? new _seljs_types.SolidityIntTypeWrapper(v) : v));
|
|
35
30
|
for (const desc of options?.structs ?? []) {
|
|
36
31
|
this.codecs.set(desc.name, this.buildStructCodec(desc));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SolidityAddressTypeWrapper, SolidityIntTypeWrapper } from "@seljs/types";
|
|
1
|
+
import { SolidityAddressTypeWrapper, SolidityIntTypeWrapper, hexToBytes } from "@seljs/types";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
//#region src/environment/codec-registry.ts
|
|
4
4
|
const solidityAddressCodec = z.codec(z.string(), z.instanceof(SolidityAddressTypeWrapper), {
|
|
@@ -24,12 +24,7 @@ var CelCodecRegistry = class {
|
|
|
24
24
|
this.codecs.set("bool", z.boolean());
|
|
25
25
|
this.codecs.set("string", z.string());
|
|
26
26
|
this.codecs.set("int", z.bigint());
|
|
27
|
-
this.codecs.set("bytes", z.union([z.instanceof(Uint8Array), z.string().transform((s) =>
|
|
28
|
-
const hex = s.startsWith("0x") ? s.slice(2) : s;
|
|
29
|
-
const bytes = new Uint8Array(hex.length / 2);
|
|
30
|
-
for (let i = 0; i < bytes.length; i++) bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
31
|
-
return bytes;
|
|
32
|
-
})]));
|
|
27
|
+
this.codecs.set("bytes", z.union([z.instanceof(Uint8Array), z.string().transform((s) => hexToBytes(s))]));
|
|
33
28
|
this.codecs.set("dyn", z.unknown().transform((v) => typeof v === "bigint" ? new SolidityIntTypeWrapper(v) : v));
|
|
34
29
|
for (const desc of options?.structs ?? []) {
|
|
35
30
|
this.codecs.set(desc.name, this.buildStructCodec(desc));
|
|
@@ -50,7 +50,7 @@ const hydrateEnvironment = (env, schema, handler) => {
|
|
|
50
50
|
const returnType = method.returns || "dyn";
|
|
51
51
|
const methodHandler = handler !== void 0 ? async (...args) => {
|
|
52
52
|
const raw = await handler(contract.name, method.name, args.slice(1));
|
|
53
|
-
if (!codecRegistry) throw new
|
|
53
|
+
if (!codecRegistry) throw new _seljs_common.SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
|
|
54
54
|
return codecRegistry.resolve(returnType).parse(raw);
|
|
55
55
|
} : () => void 0;
|
|
56
56
|
try {
|
|
@@ -93,7 +93,7 @@ const hydrateEnvironment = (env, schema, handler) => {
|
|
|
93
93
|
if (!fn.receiverType) continue;
|
|
94
94
|
const fnHandler = handler !== void 0 ? async (...args) => {
|
|
95
95
|
const raw = await handler(fn.receiverType, fn.name, args);
|
|
96
|
-
if (!codecRegistry) throw new
|
|
96
|
+
if (!codecRegistry) throw new _seljs_common.SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
|
|
97
97
|
return codecRegistry.resolve(fn.returns).parse(raw);
|
|
98
98
|
} : () => void 0;
|
|
99
99
|
try {
|
|
@@ -155,7 +155,7 @@ const createRuntimeEnvironment = (schema, handler, options) => {
|
|
|
155
155
|
});
|
|
156
156
|
require_register_types.registerSolidityTypes(env);
|
|
157
157
|
const result = hydrateEnvironment(env, schema, handler);
|
|
158
|
-
if (!result.codecRegistry) throw new
|
|
158
|
+
if (!result.codecRegistry) throw new _seljs_common.SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
|
|
159
159
|
return {
|
|
160
160
|
env,
|
|
161
161
|
contractBindings: result.contractBindings,
|
|
@@ -2,7 +2,7 @@ import { createLogger } from "../debug.mjs";
|
|
|
2
2
|
import { CelCodecRegistry } from "./codec-registry.mjs";
|
|
3
3
|
import { registerSolidityTypes } from "./register-types.mjs";
|
|
4
4
|
import { toCelLiteralType } from "./value-wrappers.mjs";
|
|
5
|
-
import { contractTypeName } from "@seljs/common";
|
|
5
|
+
import { SELConfigError, contractTypeName } from "@seljs/common";
|
|
6
6
|
import { Environment } from "@marcbachmann/cel-js";
|
|
7
7
|
//#region src/environment/hydrate.ts
|
|
8
8
|
const debug = createLogger("hydrate");
|
|
@@ -49,7 +49,7 @@ const hydrateEnvironment = (env, schema, handler) => {
|
|
|
49
49
|
const returnType = method.returns || "dyn";
|
|
50
50
|
const methodHandler = handler !== void 0 ? async (...args) => {
|
|
51
51
|
const raw = await handler(contract.name, method.name, args.slice(1));
|
|
52
|
-
if (!codecRegistry) throw new
|
|
52
|
+
if (!codecRegistry) throw new SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
|
|
53
53
|
return codecRegistry.resolve(returnType).parse(raw);
|
|
54
54
|
} : () => void 0;
|
|
55
55
|
try {
|
|
@@ -92,7 +92,7 @@ const hydrateEnvironment = (env, schema, handler) => {
|
|
|
92
92
|
if (!fn.receiverType) continue;
|
|
93
93
|
const fnHandler = handler !== void 0 ? async (...args) => {
|
|
94
94
|
const raw = await handler(fn.receiverType, fn.name, args);
|
|
95
|
-
if (!codecRegistry) throw new
|
|
95
|
+
if (!codecRegistry) throw new SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
|
|
96
96
|
return codecRegistry.resolve(fn.returns).parse(raw);
|
|
97
97
|
} : () => void 0;
|
|
98
98
|
try {
|
|
@@ -154,7 +154,7 @@ const createRuntimeEnvironment = (schema, handler, options) => {
|
|
|
154
154
|
});
|
|
155
155
|
registerSolidityTypes(env);
|
|
156
156
|
const result = hydrateEnvironment(env, schema, handler);
|
|
157
|
-
if (!result.codecRegistry) throw new
|
|
157
|
+
if (!result.codecRegistry) throw new SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
|
|
158
158
|
return {
|
|
159
159
|
env,
|
|
160
160
|
contractBindings: result.contractBindings,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let _seljs_common = require("@seljs/common");
|
|
2
3
|
let _seljs_types = require("@seljs/types");
|
|
4
|
+
let viem = require("viem");
|
|
3
5
|
//#region src/environment/register-types.ts
|
|
4
6
|
/**
|
|
5
7
|
* Try to register an operator, silently ignoring "already registered" errors.
|
|
@@ -27,12 +29,12 @@ const registerIntegerOperators = (env) => {
|
|
|
27
29
|
env.registerOperator("sol_int * sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) * (0, _seljs_types.toBigInt)(b)));
|
|
28
30
|
env.registerOperator("sol_int / sol_int", (a, b) => {
|
|
29
31
|
const divisor = (0, _seljs_types.toBigInt)(b);
|
|
30
|
-
if (divisor === 0n) throw new
|
|
32
|
+
if (divisor === 0n) throw new _seljs_common.SELEvaluationError("division by zero");
|
|
31
33
|
return toSolInt((0, _seljs_types.toBigInt)(a) / divisor);
|
|
32
34
|
});
|
|
33
35
|
env.registerOperator("sol_int % sol_int", (a, b) => {
|
|
34
36
|
const divisor = (0, _seljs_types.toBigInt)(b);
|
|
35
|
-
if (divisor === 0n) throw new
|
|
37
|
+
if (divisor === 0n) throw new _seljs_common.SELEvaluationError("modulo by zero");
|
|
36
38
|
return toSolInt((0, _seljs_types.toBigInt)(a) % divisor);
|
|
37
39
|
});
|
|
38
40
|
env.registerOperator("-sol_int", (a) => toSolInt(-(0, _seljs_types.toBigInt)(a)));
|
|
@@ -46,12 +48,25 @@ const registerIntegerOperators = (env) => {
|
|
|
46
48
|
tryRegisterOperator(env, "sol_int * int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) * (0, _seljs_types.toBigInt)(b)));
|
|
47
49
|
tryRegisterOperator(env, "sol_int / int", (a, b) => {
|
|
48
50
|
const divisor = (0, _seljs_types.toBigInt)(b);
|
|
49
|
-
if (divisor === 0n) throw new
|
|
51
|
+
if (divisor === 0n) throw new _seljs_common.SELEvaluationError("division by zero");
|
|
50
52
|
return toSolInt((0, _seljs_types.toBigInt)(a) / divisor);
|
|
51
53
|
});
|
|
52
54
|
tryRegisterOperator(env, "sol_int % int", (a, b) => {
|
|
53
55
|
const divisor = (0, _seljs_types.toBigInt)(b);
|
|
54
|
-
if (divisor === 0n) throw new
|
|
56
|
+
if (divisor === 0n) throw new _seljs_common.SELEvaluationError("modulo by zero");
|
|
57
|
+
return toSolInt((0, _seljs_types.toBigInt)(a) % divisor);
|
|
58
|
+
});
|
|
59
|
+
tryRegisterOperator(env, "int + sol_int: sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) + (0, _seljs_types.toBigInt)(b)));
|
|
60
|
+
tryRegisterOperator(env, "int - sol_int: sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) - (0, _seljs_types.toBigInt)(b)));
|
|
61
|
+
tryRegisterOperator(env, "int * sol_int: sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) * (0, _seljs_types.toBigInt)(b)));
|
|
62
|
+
tryRegisterOperator(env, "int / sol_int: sol_int", (a, b) => {
|
|
63
|
+
const divisor = (0, _seljs_types.toBigInt)(b);
|
|
64
|
+
if (divisor === 0n) throw new _seljs_common.SELEvaluationError("division by zero");
|
|
65
|
+
return toSolInt((0, _seljs_types.toBigInt)(a) / divisor);
|
|
66
|
+
});
|
|
67
|
+
tryRegisterOperator(env, "int % sol_int: sol_int", (a, b) => {
|
|
68
|
+
const divisor = (0, _seljs_types.toBigInt)(b);
|
|
69
|
+
if (divisor === 0n) throw new _seljs_common.SELEvaluationError("modulo by zero");
|
|
55
70
|
return toSolInt((0, _seljs_types.toBigInt)(a) % divisor);
|
|
56
71
|
});
|
|
57
72
|
tryRegisterOperator(env, "sol_int == int", (a, b) => (0, _seljs_types.toBigInt)(a) === (0, _seljs_types.toBigInt)(b));
|
|
@@ -78,11 +93,17 @@ const registerSolidityTypes = (env) => {
|
|
|
78
93
|
for (const sig of entry.castSignatures) env.registerFunction(sig, (value) => new Ctor(value));
|
|
79
94
|
}
|
|
80
95
|
env.registerFunction("parseUnits(string, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
96
|
+
env.registerFunction("parseUnits(string, sol_int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
81
97
|
env.registerFunction("parseUnits(int, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
98
|
+
env.registerFunction("parseUnits(int, sol_int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
82
99
|
env.registerFunction("parseUnits(double, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
100
|
+
env.registerFunction("parseUnits(double, sol_int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
83
101
|
env.registerFunction("parseUnits(sol_int, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
102
|
+
env.registerFunction("parseUnits(sol_int, sol_int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
84
103
|
env.registerFunction("formatUnits(sol_int, int): double", (value, decimals) => (0, _seljs_types.formatUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
104
|
+
env.registerFunction("formatUnits(sol_int, sol_int): double", (value, decimals) => (0, _seljs_types.formatUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
85
105
|
env.registerFunction("formatUnits(int, int): double", (value, decimals) => (0, _seljs_types.formatUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
106
|
+
env.registerFunction("formatUnits(int, sol_int): double", (value, decimals) => (0, _seljs_types.formatUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
86
107
|
env.registerFunction("min(sol_int, sol_int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
87
108
|
env.registerFunction("min(sol_int, int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
88
109
|
env.registerFunction("min(int, sol_int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
@@ -99,9 +120,65 @@ const registerSolidityTypes = (env) => {
|
|
|
99
120
|
const v = (0, _seljs_types.toBigInt)(a);
|
|
100
121
|
return toSolInt(v < 0n ? -v : v);
|
|
101
122
|
});
|
|
123
|
+
const registerListSolIntReducer = (name, handler) => {
|
|
124
|
+
env.registerFunction({
|
|
125
|
+
name,
|
|
126
|
+
receiverType: "list<sol_int>",
|
|
127
|
+
returnType: "sol_int",
|
|
128
|
+
params: []
|
|
129
|
+
}, handler);
|
|
130
|
+
};
|
|
131
|
+
registerListSolIntReducer("sum", (list) => {
|
|
132
|
+
let total = 0n;
|
|
133
|
+
for (const item of list) total += (0, _seljs_types.toBigInt)(item);
|
|
134
|
+
return toSolInt(total);
|
|
135
|
+
});
|
|
136
|
+
registerListSolIntReducer("min", (list) => {
|
|
137
|
+
const items = list;
|
|
138
|
+
if (items.length === 0) throw new _seljs_common.SELEvaluationError("list<sol_int>.min(): list is empty");
|
|
139
|
+
let smallest = (0, _seljs_types.toBigInt)(items[0]);
|
|
140
|
+
for (let i = 1; i < items.length; i++) {
|
|
141
|
+
const v = (0, _seljs_types.toBigInt)(items[i]);
|
|
142
|
+
if (v < smallest) smallest = v;
|
|
143
|
+
}
|
|
144
|
+
return toSolInt(smallest);
|
|
145
|
+
});
|
|
146
|
+
registerListSolIntReducer("max", (list) => {
|
|
147
|
+
const items = list;
|
|
148
|
+
if (items.length === 0) throw new _seljs_common.SELEvaluationError("list<sol_int>.max(): list is empty");
|
|
149
|
+
let largest = (0, _seljs_types.toBigInt)(items[0]);
|
|
150
|
+
for (let i = 1; i < items.length; i++) {
|
|
151
|
+
const v = (0, _seljs_types.toBigInt)(items[i]);
|
|
152
|
+
if (v > largest) largest = v;
|
|
153
|
+
}
|
|
154
|
+
return toSolInt(largest);
|
|
155
|
+
});
|
|
102
156
|
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
103
157
|
env.registerFunction("isZeroAddress(sol_address): bool", (addr) => (0, _seljs_types.toAddress)(addr) === ZERO_ADDRESS);
|
|
104
158
|
env.registerFunction("isZeroAddress(string): bool", (addr) => (0, _seljs_types.toAddress)(addr) === ZERO_ADDRESS);
|
|
159
|
+
env.registerFunction("hexBytes(string): bytes", (hex) => (0, _seljs_types.hexToBytes)(hex));
|
|
160
|
+
env.registerFunction("hexBytes(string, int): bytes", (hex, length) => {
|
|
161
|
+
const out = (0, _seljs_types.hexToBytes)(hex);
|
|
162
|
+
const expected = Number((0, _seljs_types.toBigInt)(length));
|
|
163
|
+
if (out.length !== expected) throw new _seljs_common.SELEvaluationError(`hexBytes: expected ${String(expected)} bytes, got ${String(out.length)}`);
|
|
164
|
+
return out;
|
|
165
|
+
});
|
|
166
|
+
env.registerFunction("keccak256(string): bytes", (value) => (0, _seljs_types.hexToBytes)((0, viem.keccak256)((0, viem.toBytes)(value))));
|
|
167
|
+
env.registerFunction("keccak256(bytes): bytes", (value) => (0, _seljs_types.hexToBytes)((0, viem.keccak256)(value)));
|
|
168
|
+
class SelNamespace {}
|
|
169
|
+
const selFields = {};
|
|
170
|
+
const selValues = {};
|
|
171
|
+
for (const constant of _seljs_types.EVM_CONSTANTS) {
|
|
172
|
+
selFields[constant.name] = constant.type;
|
|
173
|
+
if (constant.type === "sol_int") selValues[constant.name] = new _seljs_types.SolidityIntTypeWrapper(constant.value);
|
|
174
|
+
else if (constant.type === "sol_address") selValues[constant.name] = new _seljs_types.SolidityAddressTypeWrapper(constant.value);
|
|
175
|
+
else selValues[constant.name] = constant.value;
|
|
176
|
+
}
|
|
177
|
+
env.registerType("SelNamespace", {
|
|
178
|
+
ctor: SelNamespace,
|
|
179
|
+
fields: selFields
|
|
180
|
+
});
|
|
181
|
+
env.registerConstant("sel", "SelNamespace", Object.assign(new SelNamespace(), selValues));
|
|
105
182
|
};
|
|
106
183
|
//#endregion
|
|
107
184
|
exports.registerSolidityTypes = registerSolidityTypes;
|
|
@@ -6,7 +6,7 @@ import { Environment } from "@marcbachmann/cel-js";
|
|
|
6
6
|
* Mirrors the parameter signatures from Environment but drops the return type
|
|
7
7
|
* to void — registerSolidityTypes never chains the return value.
|
|
8
8
|
*/
|
|
9
|
-
type SolidityTypeHost = { [K in "registerType" | "registerOperator" | "registerFunction"]: (...args: Parameters<Environment[K]>) => void };
|
|
9
|
+
type SolidityTypeHost = { [K in "registerType" | "registerOperator" | "registerFunction" | "registerConstant"]: (...args: Parameters<Environment[K]>) => void };
|
|
10
10
|
/**
|
|
11
11
|
* Register all Solidity primitive types on a CEL Environment.
|
|
12
12
|
*/
|
|
@@ -6,7 +6,7 @@ import { Environment } from "@marcbachmann/cel-js";
|
|
|
6
6
|
* Mirrors the parameter signatures from Environment but drops the return type
|
|
7
7
|
* to void — registerSolidityTypes never chains the return value.
|
|
8
8
|
*/
|
|
9
|
-
type SolidityTypeHost = { [K in "registerType" | "registerOperator" | "registerFunction"]: (...args: Parameters<Environment[K]>) => void };
|
|
9
|
+
type SolidityTypeHost = { [K in "registerType" | "registerOperator" | "registerFunction" | "registerConstant"]: (...args: Parameters<Environment[K]>) => void };
|
|
10
10
|
/**
|
|
11
11
|
* Register all Solidity primitive types on a CEL Environment.
|
|
12
12
|
*/
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SELEvaluationError } from "@seljs/common";
|
|
2
|
+
import { EVM_CONSTANTS, SOLIDITY_TYPES, SolidityAddressTypeWrapper, SolidityIntTypeWrapper, formatUnitsValue, hexToBytes, parseUnitsValue, toAddress, toBigInt } from "@seljs/types";
|
|
3
|
+
import { keccak256, toBytes } from "viem";
|
|
2
4
|
//#region src/environment/register-types.ts
|
|
3
5
|
/**
|
|
4
6
|
* Try to register an operator, silently ignoring "already registered" errors.
|
|
@@ -26,12 +28,12 @@ const registerIntegerOperators = (env) => {
|
|
|
26
28
|
env.registerOperator("sol_int * sol_int", (a, b) => toSolInt(toBigInt(a) * toBigInt(b)));
|
|
27
29
|
env.registerOperator("sol_int / sol_int", (a, b) => {
|
|
28
30
|
const divisor = toBigInt(b);
|
|
29
|
-
if (divisor === 0n) throw new
|
|
31
|
+
if (divisor === 0n) throw new SELEvaluationError("division by zero");
|
|
30
32
|
return toSolInt(toBigInt(a) / divisor);
|
|
31
33
|
});
|
|
32
34
|
env.registerOperator("sol_int % sol_int", (a, b) => {
|
|
33
35
|
const divisor = toBigInt(b);
|
|
34
|
-
if (divisor === 0n) throw new
|
|
36
|
+
if (divisor === 0n) throw new SELEvaluationError("modulo by zero");
|
|
35
37
|
return toSolInt(toBigInt(a) % divisor);
|
|
36
38
|
});
|
|
37
39
|
env.registerOperator("-sol_int", (a) => toSolInt(-toBigInt(a)));
|
|
@@ -45,12 +47,25 @@ const registerIntegerOperators = (env) => {
|
|
|
45
47
|
tryRegisterOperator(env, "sol_int * int", (a, b) => toSolInt(toBigInt(a) * toBigInt(b)));
|
|
46
48
|
tryRegisterOperator(env, "sol_int / int", (a, b) => {
|
|
47
49
|
const divisor = toBigInt(b);
|
|
48
|
-
if (divisor === 0n) throw new
|
|
50
|
+
if (divisor === 0n) throw new SELEvaluationError("division by zero");
|
|
49
51
|
return toSolInt(toBigInt(a) / divisor);
|
|
50
52
|
});
|
|
51
53
|
tryRegisterOperator(env, "sol_int % int", (a, b) => {
|
|
52
54
|
const divisor = toBigInt(b);
|
|
53
|
-
if (divisor === 0n) throw new
|
|
55
|
+
if (divisor === 0n) throw new SELEvaluationError("modulo by zero");
|
|
56
|
+
return toSolInt(toBigInt(a) % divisor);
|
|
57
|
+
});
|
|
58
|
+
tryRegisterOperator(env, "int + sol_int: sol_int", (a, b) => toSolInt(toBigInt(a) + toBigInt(b)));
|
|
59
|
+
tryRegisterOperator(env, "int - sol_int: sol_int", (a, b) => toSolInt(toBigInt(a) - toBigInt(b)));
|
|
60
|
+
tryRegisterOperator(env, "int * sol_int: sol_int", (a, b) => toSolInt(toBigInt(a) * toBigInt(b)));
|
|
61
|
+
tryRegisterOperator(env, "int / sol_int: sol_int", (a, b) => {
|
|
62
|
+
const divisor = toBigInt(b);
|
|
63
|
+
if (divisor === 0n) throw new SELEvaluationError("division by zero");
|
|
64
|
+
return toSolInt(toBigInt(a) / divisor);
|
|
65
|
+
});
|
|
66
|
+
tryRegisterOperator(env, "int % sol_int: sol_int", (a, b) => {
|
|
67
|
+
const divisor = toBigInt(b);
|
|
68
|
+
if (divisor === 0n) throw new SELEvaluationError("modulo by zero");
|
|
54
69
|
return toSolInt(toBigInt(a) % divisor);
|
|
55
70
|
});
|
|
56
71
|
tryRegisterOperator(env, "sol_int == int", (a, b) => toBigInt(a) === toBigInt(b));
|
|
@@ -77,11 +92,17 @@ const registerSolidityTypes = (env) => {
|
|
|
77
92
|
for (const sig of entry.castSignatures) env.registerFunction(sig, (value) => new Ctor(value));
|
|
78
93
|
}
|
|
79
94
|
env.registerFunction("parseUnits(string, int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
|
|
95
|
+
env.registerFunction("parseUnits(string, sol_int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
|
|
80
96
|
env.registerFunction("parseUnits(int, int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
|
|
97
|
+
env.registerFunction("parseUnits(int, sol_int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
|
|
81
98
|
env.registerFunction("parseUnits(double, int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
|
|
99
|
+
env.registerFunction("parseUnits(double, sol_int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
|
|
82
100
|
env.registerFunction("parseUnits(sol_int, int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
|
|
101
|
+
env.registerFunction("parseUnits(sol_int, sol_int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
|
|
83
102
|
env.registerFunction("formatUnits(sol_int, int): double", (value, decimals) => formatUnitsValue(value, Number(toBigInt(decimals))));
|
|
103
|
+
env.registerFunction("formatUnits(sol_int, sol_int): double", (value, decimals) => formatUnitsValue(value, Number(toBigInt(decimals))));
|
|
84
104
|
env.registerFunction("formatUnits(int, int): double", (value, decimals) => formatUnitsValue(value, Number(toBigInt(decimals))));
|
|
105
|
+
env.registerFunction("formatUnits(int, sol_int): double", (value, decimals) => formatUnitsValue(value, Number(toBigInt(decimals))));
|
|
85
106
|
env.registerFunction("min(sol_int, sol_int): sol_int", (a, b) => toBigInt(a) <= toBigInt(b) ? toSolInt(a) : toSolInt(b));
|
|
86
107
|
env.registerFunction("min(sol_int, int): sol_int", (a, b) => toBigInt(a) <= toBigInt(b) ? toSolInt(a) : toSolInt(b));
|
|
87
108
|
env.registerFunction("min(int, sol_int): sol_int", (a, b) => toBigInt(a) <= toBigInt(b) ? toSolInt(a) : toSolInt(b));
|
|
@@ -98,9 +119,65 @@ const registerSolidityTypes = (env) => {
|
|
|
98
119
|
const v = toBigInt(a);
|
|
99
120
|
return toSolInt(v < 0n ? -v : v);
|
|
100
121
|
});
|
|
122
|
+
const registerListSolIntReducer = (name, handler) => {
|
|
123
|
+
env.registerFunction({
|
|
124
|
+
name,
|
|
125
|
+
receiverType: "list<sol_int>",
|
|
126
|
+
returnType: "sol_int",
|
|
127
|
+
params: []
|
|
128
|
+
}, handler);
|
|
129
|
+
};
|
|
130
|
+
registerListSolIntReducer("sum", (list) => {
|
|
131
|
+
let total = 0n;
|
|
132
|
+
for (const item of list) total += toBigInt(item);
|
|
133
|
+
return toSolInt(total);
|
|
134
|
+
});
|
|
135
|
+
registerListSolIntReducer("min", (list) => {
|
|
136
|
+
const items = list;
|
|
137
|
+
if (items.length === 0) throw new SELEvaluationError("list<sol_int>.min(): list is empty");
|
|
138
|
+
let smallest = toBigInt(items[0]);
|
|
139
|
+
for (let i = 1; i < items.length; i++) {
|
|
140
|
+
const v = toBigInt(items[i]);
|
|
141
|
+
if (v < smallest) smallest = v;
|
|
142
|
+
}
|
|
143
|
+
return toSolInt(smallest);
|
|
144
|
+
});
|
|
145
|
+
registerListSolIntReducer("max", (list) => {
|
|
146
|
+
const items = list;
|
|
147
|
+
if (items.length === 0) throw new SELEvaluationError("list<sol_int>.max(): list is empty");
|
|
148
|
+
let largest = toBigInt(items[0]);
|
|
149
|
+
for (let i = 1; i < items.length; i++) {
|
|
150
|
+
const v = toBigInt(items[i]);
|
|
151
|
+
if (v > largest) largest = v;
|
|
152
|
+
}
|
|
153
|
+
return toSolInt(largest);
|
|
154
|
+
});
|
|
101
155
|
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
102
156
|
env.registerFunction("isZeroAddress(sol_address): bool", (addr) => toAddress(addr) === ZERO_ADDRESS);
|
|
103
157
|
env.registerFunction("isZeroAddress(string): bool", (addr) => toAddress(addr) === ZERO_ADDRESS);
|
|
158
|
+
env.registerFunction("hexBytes(string): bytes", (hex) => hexToBytes(hex));
|
|
159
|
+
env.registerFunction("hexBytes(string, int): bytes", (hex, length) => {
|
|
160
|
+
const out = hexToBytes(hex);
|
|
161
|
+
const expected = Number(toBigInt(length));
|
|
162
|
+
if (out.length !== expected) throw new SELEvaluationError(`hexBytes: expected ${String(expected)} bytes, got ${String(out.length)}`);
|
|
163
|
+
return out;
|
|
164
|
+
});
|
|
165
|
+
env.registerFunction("keccak256(string): bytes", (value) => hexToBytes(keccak256(toBytes(value))));
|
|
166
|
+
env.registerFunction("keccak256(bytes): bytes", (value) => hexToBytes(keccak256(value)));
|
|
167
|
+
class SelNamespace {}
|
|
168
|
+
const selFields = {};
|
|
169
|
+
const selValues = {};
|
|
170
|
+
for (const constant of EVM_CONSTANTS) {
|
|
171
|
+
selFields[constant.name] = constant.type;
|
|
172
|
+
if (constant.type === "sol_int") selValues[constant.name] = new SolidityIntTypeWrapper(constant.value);
|
|
173
|
+
else if (constant.type === "sol_address") selValues[constant.name] = new SolidityAddressTypeWrapper(constant.value);
|
|
174
|
+
else selValues[constant.name] = constant.value;
|
|
175
|
+
}
|
|
176
|
+
env.registerType("SelNamespace", {
|
|
177
|
+
ctor: SelNamespace,
|
|
178
|
+
fields: selFields
|
|
179
|
+
});
|
|
180
|
+
env.registerConstant("sel", "SelNamespace", Object.assign(new SelNamespace(), selValues));
|
|
104
181
|
};
|
|
105
182
|
//#endregion
|
|
106
183
|
export { registerSolidityTypes };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seljs/checker",
|
|
3
|
-
"version": "1.3.0-beta.
|
|
3
|
+
"version": "1.3.0-beta.32",
|
|
4
4
|
"repository": {
|
|
5
5
|
"url": "https://github.com/abinnovision/seljs"
|
|
6
6
|
},
|
|
@@ -50,13 +50,14 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@marcbachmann/cel-js": "^7.5.3",
|
|
53
|
-
"@seljs/common": "1.3.0-beta.
|
|
53
|
+
"@seljs/common": "1.3.0-beta.32",
|
|
54
54
|
"@seljs/schema": "1.2.0",
|
|
55
|
-
"@seljs/types": "1.3.0-beta.
|
|
56
|
-
"debug": "^4.4.3"
|
|
55
|
+
"@seljs/types": "1.3.0-beta.32",
|
|
56
|
+
"debug": "^4.4.3",
|
|
57
|
+
"viem": "^2.47.6"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
|
-
"@abinnovision/eslint-config-base": "^3.2.
|
|
60
|
+
"@abinnovision/eslint-config-base": "^3.2.2",
|
|
60
61
|
"@abinnovision/prettier-config": "^2.1.5",
|
|
61
62
|
"@seljs-internal/tsconfig": "^0.0.0",
|
|
62
63
|
"@types/debug": "^4.1.13",
|