@ilalv3/cli 0.2.12 → 0.2.14
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/commands/swap.js +35 -2
- package/dist/index.js +1 -1
- package/dist/ui.js +3 -0
- package/package.json +1 -1
package/dist/commands/swap.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* --pool-id 0xPOOLID \
|
|
19
19
|
* --chain 84532
|
|
20
20
|
*/
|
|
21
|
-
import { createPublicClient, createWalletClient, decodeAbiParameters, encodeAbiParameters, formatEther, formatUnits, http, isAddress, isHex, parseAbiParameters, parseUnits, } from "viem";
|
|
21
|
+
import { createPublicClient, createWalletClient, decodeAbiParameters, encodeAbiParameters, formatEther, formatUnits, http, isAddress, isHex, parseAbiParameters, parseUnits, recoverTypedDataAddress, } from "viem";
|
|
22
22
|
import { privateKeyToAccount } from "viem/accounts";
|
|
23
23
|
import { base, baseSepolia } from "viem/chains";
|
|
24
24
|
import { fmt, log, header, Spinner, die, dieOnContract, requirePrivateKey } from "../ui.js";
|
|
@@ -86,6 +86,7 @@ const DYNAMIC_FEE_FLAG = 8388608;
|
|
|
86
86
|
const PIPS_DENOMINATOR = 1000000n;
|
|
87
87
|
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
88
88
|
const MAX_UINT256 = 2n ** 256n - 1n;
|
|
89
|
+
const SECP256K1_HALF_ORDER = BigInt("0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0");
|
|
89
90
|
function txUrl(chain, hash) {
|
|
90
91
|
const baseUrl = chain.blockExplorers?.default?.url;
|
|
91
92
|
return baseUrl ? `${baseUrl}/tx/${hash}` : undefined;
|
|
@@ -124,6 +125,17 @@ function allowanceLabel(raw, decimals, symbol) {
|
|
|
124
125
|
function secondsSince(startMs) {
|
|
125
126
|
return `${((Date.now() - startMs) / 1000).toFixed(1)}s`;
|
|
126
127
|
}
|
|
128
|
+
function validateEcdsaSignature(sig) {
|
|
129
|
+
if (!/^0x[0-9a-fA-F]{130}$/.test(sig))
|
|
130
|
+
return "signature must be 65 bytes";
|
|
131
|
+
const s = BigInt(`0x${sig.slice(66, 130)}`);
|
|
132
|
+
const v = Number.parseInt(sig.slice(130, 132), 16);
|
|
133
|
+
if (s > SECP256K1_HALF_ORDER)
|
|
134
|
+
return "signature uses high-s form; re-sign to produce canonical EIP-2 low-s signature";
|
|
135
|
+
if (v !== 27 && v !== 28)
|
|
136
|
+
return "signature recovery id must be 27 or 28";
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
127
139
|
// ─── Main export ──────────────────────────────────────────────────────────────
|
|
128
140
|
export async function swap(opts) {
|
|
129
141
|
const cfg = withConfig(opts);
|
|
@@ -259,7 +271,7 @@ export async function swap(opts) {
|
|
|
259
271
|
if (!isHex(opts.hookData))
|
|
260
272
|
die("--hook-data must be 0x-prefixed ABI-encoded hookData.");
|
|
261
273
|
try {
|
|
262
|
-
const [externalToken] = decodeAbiParameters(HOOK_DATA_ABI, opts.hookData);
|
|
274
|
+
const [externalToken, externalSig] = decodeAbiParameters(HOOK_DATA_ABI, opts.hookData);
|
|
263
275
|
const issues = [];
|
|
264
276
|
if (externalToken.user.toLowerCase() !== account.address.toLowerCase())
|
|
265
277
|
issues.push("user does not match signer wallet");
|
|
@@ -277,6 +289,27 @@ export async function swap(opts) {
|
|
|
277
289
|
issues.push("action is not swap");
|
|
278
290
|
if (externalToken.deadline < BigInt(Math.floor(Date.now() / 1000)))
|
|
279
291
|
issues.push("session deadline has expired");
|
|
292
|
+
const sigIssue = validateEcdsaSignature(externalSig);
|
|
293
|
+
if (sigIssue) {
|
|
294
|
+
issues.push(sigIssue);
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
const recovered = await recoverTypedDataAddress({
|
|
298
|
+
domain: {
|
|
299
|
+
name: "ILAL ComplianceHook",
|
|
300
|
+
version: "1",
|
|
301
|
+
chainId: BigInt(chain.id),
|
|
302
|
+
verifyingContract: cfg.hook,
|
|
303
|
+
},
|
|
304
|
+
types: { SessionToken: SESSION_TOKEN_TYPE },
|
|
305
|
+
primaryType: "SessionToken",
|
|
306
|
+
message: externalToken,
|
|
307
|
+
signature: externalSig,
|
|
308
|
+
});
|
|
309
|
+
if (recovered.toLowerCase() !== externalToken.user.toLowerCase()) {
|
|
310
|
+
issues.push(`signature does not recover to session user ${fmt.addr(externalToken.user)}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
280
313
|
if (issues.length > 0)
|
|
281
314
|
die(`Invalid --hook-data for this swap: ${issues.join("; ")}`);
|
|
282
315
|
sessionNonce = externalToken.nonce;
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ const program = new Command();
|
|
|
19
19
|
program
|
|
20
20
|
.name("ilal")
|
|
21
21
|
.description("ILAL Protocol CLI — Uniswap v4 compliance hook toolkit")
|
|
22
|
-
.version("0.2.
|
|
22
|
+
.version("0.2.14")
|
|
23
23
|
.addHelpText("before", `\n ${fmt.bold(fmt.cyan("◆"))} ${fmt.bold("ILAL Protocol")} ${fmt.gray("Uniswap v4 Compliance Hook")}\n`);
|
|
24
24
|
// ─── init ─────────────────────────────────────────────────────────────────────
|
|
25
25
|
program
|
package/dist/ui.js
CHANGED
|
@@ -178,6 +178,9 @@ const CONTRACT_ERRORS = {
|
|
|
178
178
|
"0xfa9f081c": "Schema hash mismatch",
|
|
179
179
|
"0xb7e9429b": "Issuer hash mismatch",
|
|
180
180
|
"0x0e917e64": "Wallet hash mismatch — wrong wallet key",
|
|
181
|
+
"0x21374865": "Session signature invalid — re-sign hookData with the wallet that owns the CNF",
|
|
182
|
+
"0xd9b2290c": "Session user mismatch — hookData can only be used by the wallet that signed it",
|
|
183
|
+
"0x1fb09b80": "Session nonce already used — sign a fresh session",
|
|
181
184
|
};
|
|
182
185
|
function parseViemError(e) {
|
|
183
186
|
const msg = e instanceof Error ? e.message : String(e);
|