@anywalletkit/protocol-swap2-omniston 0.3.1 → 0.4.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/README.md CHANGED
@@ -62,6 +62,19 @@ Every route is fail-closed until its allowlists and validators are configured:
62
62
  engine then signs only an `Order` whose verifying contract is a pinned
63
63
  spender, whose maker is this account and that sells exactly the swap's input
64
64
  of the source token; a `Permit` or any other typed message is refused.
65
+ The rest of the order is the app's to check, and the engine signs a remote
66
+ typed order only with `verifyBuild`: `remoteProvider({name: "omniston",
67
+ baseUrl, ...omnistonPins(AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS), verifyBuild:
68
+ omnistonVerifyBuild({...createOmnistonTonValidators()})})`. The build carries
69
+ the `orderExtension` the order's salt commits to, and `omnistonVerifyBuild`
70
+ opens both: the v4 domain on a trusted order protocol, the exact Order schema,
71
+ `takingAmount` at least the quote's minimum, a single-fill order with no
72
+ allowed sender and an expiry minutes away, the pinned v1beta8 auction and fee
73
+ terms, one trusted escrow factory (`trustedSettlementContracts`, default the
74
+ audited table) as the extension target, the whitelisted resolver as the
75
+ order's receiver, the destination chain and token, the audited timelocks, the
76
+ TON token and recipient and the quote id. The hashlock is the server's: the
77
+ server holds the HTLC secret. The same applies to EVM → EVM.
65
78
  `validateEvmTypedOrder` is exported for apps that hold the settlement data.
66
79
  - **EVM → EVM** (gasless order, same order protocol as EVM → TON): the signed
67
80
  extension's ExtraDataArgs name the destination chain, token and deposit and
@@ -0,0 +1,37 @@
1
+ // src/validators/settlement.ts
2
+ var AUDITED_OMNISTON_SETTLEMENT_CONTRACTS = {
3
+ "ton:-239": ["EQAbWJ3Y1HgIIvcMq1prG1anlDC0T3cZlAU7luPT6LmTpmrZ"],
4
+ "eip155:1": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
5
+ "eip155:56": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
6
+ "eip155:137": ["0x41A392062A4307a6961d48e30FF20bF6823715B8"],
7
+ "eip155:4663": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
8
+ "eip155:8453": ["0xACa3E2F9b61a44892926bC6c3e104192E7D1c3cd"],
9
+ "eip155:42161": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
10
+ "eip155:43114": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
11
+ // 2026-10-20: one factory address on X Layer, HyperEVM and Plasma. Runtime
12
+ // bytecode equals Ethereum's 0xafCF… byte for byte except the immutable slots
13
+ // (escrow implementations, its order protocol, domain hash); it references
14
+ // the order protocol trusted below on the same chain.
15
+ "eip155:196": ["0xd602079AFa5c38F550510a2a988CbFa698Fa0189"],
16
+ "eip155:999": ["0xd602079AFa5c38F550510a2a988CbFa698Fa0189"],
17
+ "eip155:9745": ["0xd602079AFa5c38F550510a2a988CbFa698Fa0189"]
18
+ };
19
+ var AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS = {
20
+ "eip155:1": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
21
+ "eip155:56": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
22
+ "eip155:137": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
23
+ "eip155:8453": ["0xe7405fAcDEDB2512e91F2886BDff13231343aF5E"],
24
+ "eip155:42161": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
25
+ "eip155:43114": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
26
+ // 2026-10-20: bytecode equals Ethereum's 0xb581… except immutables (wrapped
27
+ // native, own address, chain id 196 / 9745 / 999 at the chain-id slot).
28
+ "eip155:196": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
29
+ "eip155:9745": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
30
+ "eip155:999": ["0xD84778bbeEC5D2a8d17c6424249C438EC0b1ABE3"]
31
+ };
32
+
33
+ export {
34
+ AUDITED_OMNISTON_SETTLEMENT_CONTRACTS,
35
+ AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS
36
+ };
37
+ //# sourceMappingURL=chunk-JWYDIW4V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/validators/settlement.ts"],"sourcesContent":["/**\n * Settlement contracts this deployment trusts for Omniston, per CAIP-2 chain.\n * Audited public addresses — no secret — so both the server wiring and the\n * browser-side provider import them from here.\n * See how-to-project/OMNISTON-NETWORK-ONBOARDING.md before adding a network.\n */\nexport const AUDITED_OMNISTON_SETTLEMENT_CONTRACTS: Record<string, string[]> = {\n \"ton:-239\": [\"EQAbWJ3Y1HgIIvcMq1prG1anlDC0T3cZlAU7luPT6LmTpmrZ\"],\n \"eip155:1\": [\"0xafCF681272AF10959736f45616eeCBC22D7095E2\"],\n \"eip155:56\": [\"0xafCF681272AF10959736f45616eeCBC22D7095E2\"],\n \"eip155:137\": [\"0x41A392062A4307a6961d48e30FF20bF6823715B8\"],\n \"eip155:4663\": [\"0xafCF681272AF10959736f45616eeCBC22D7095E2\"],\n \"eip155:8453\": [\"0xACa3E2F9b61a44892926bC6c3e104192E7D1c3cd\"],\n \"eip155:42161\": [\"0xafCF681272AF10959736f45616eeCBC22D7095E2\"],\n \"eip155:43114\": [\"0xafCF681272AF10959736f45616eeCBC22D7095E2\"],\n // 2026-10-20: one factory address on X Layer, HyperEVM and Plasma. Runtime\n // bytecode equals Ethereum's 0xafCF… byte for byte except the immutable slots\n // (escrow implementations, its order protocol, domain hash); it references\n // the order protocol trusted below on the same chain.\n \"eip155:196\": [\"0xd602079AFa5c38F550510a2a988CbFa698Fa0189\"],\n \"eip155:999\": [\"0xd602079AFa5c38F550510a2a988CbFa698Fa0189\"],\n \"eip155:9745\": [\"0xd602079AFa5c38F550510a2a988CbFa698Fa0189\"],\n};\n\n/**\n * EVM order protocols (Omniston's fork of the 1inch Limit Order Protocol v4 —\n * NOT the canonical 1inch deployment) an EVM→TON order is signed against. The\n * wallet approves this contract for the input amount and signs an EIP-712\n * order whose domain names it; on fill it moves the input into the escrow the\n * factory above deploys. One address, different roles per chain (0xafCF… is\n * the factory elsewhere and the order protocol on Polygon), so this table is\n * separate from the factory table and CAIP-scoped. Runtime code hashes are in\n * how-to-project/OMNISTON-NETWORK-ONBOARDING.md (snapshot 2026-10-16).\n */\nexport const AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS: Record<string, string[]> = {\n \"eip155:1\": [\"0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9\"],\n \"eip155:56\": [\"0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9\"],\n \"eip155:137\": [\"0xafCF681272AF10959736f45616eeCBC22D7095E2\"],\n \"eip155:8453\": [\"0xe7405fAcDEDB2512e91F2886BDff13231343aF5E\"],\n \"eip155:42161\": [\"0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9\"],\n \"eip155:43114\": [\"0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9\"],\n // 2026-10-20: bytecode equals Ethereum's 0xb581… except immutables (wrapped\n // native, own address, chain id 196 / 9745 / 999 at the chain-id slot).\n \"eip155:196\": [\"0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9\"],\n \"eip155:9745\": [\"0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9\"],\n \"eip155:999\": [\"0xD84778bbeEC5D2a8d17c6424249C438EC0b1ABE3\"],\n};\n"],"mappings":";AAMO,IAAM,wCAAkE;AAAA,EAC7E,YAAY,CAAC,kDAAkD;AAAA,EAC/D,YAAY,CAAC,4CAA4C;AAAA,EACzD,aAAa,CAAC,4CAA4C;AAAA,EAC1D,cAAc,CAAC,4CAA4C;AAAA,EAC3D,eAAe,CAAC,4CAA4C;AAAA,EAC5D,eAAe,CAAC,4CAA4C;AAAA,EAC5D,gBAAgB,CAAC,4CAA4C;AAAA,EAC7D,gBAAgB,CAAC,4CAA4C;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7D,cAAc,CAAC,4CAA4C;AAAA,EAC3D,cAAc,CAAC,4CAA4C;AAAA,EAC3D,eAAe,CAAC,4CAA4C;AAC9D;AAYO,IAAM,uCAAiE;AAAA,EAC5E,YAAY,CAAC,4CAA4C;AAAA,EACzD,aAAa,CAAC,4CAA4C;AAAA,EAC1D,cAAc,CAAC,4CAA4C;AAAA,EAC3D,eAAe,CAAC,4CAA4C;AAAA,EAC5D,gBAAgB,CAAC,4CAA4C;AAAA,EAC7D,gBAAgB,CAAC,4CAA4C;AAAA;AAAA;AAAA,EAG7D,cAAc,CAAC,4CAA4C;AAAA,EAC3D,eAAe,CAAC,4CAA4C;AAAA,EAC5D,cAAc,CAAC,4CAA4C;AAC7D;","names":[]}
@@ -4,6 +4,10 @@ import {
4
4
  import {
5
5
  describeOmnistonActivity
6
6
  } from "./chunk-AIWAM7BS.js";
7
+ import {
8
+ AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS,
9
+ AUDITED_OMNISTON_SETTLEMENT_CONTRACTS
10
+ } from "./chunk-JWYDIW4V.js";
7
11
 
8
12
  // src/provider.ts
9
13
  import { Address as TonAddress, Cell as TonCell } from "@ton/core";
@@ -522,9 +526,9 @@ function validEvmAddress(value) {
522
526
  }
523
527
  }
524
528
  var EVM_DEST_PROTOCOL_FEE_RECIPIENTS = /* @__PURE__ */ new Set(["0x076268146b4ec6d21fc49c27586cfa91b9079a00"]);
525
- async function validateEvmToTonOrderExtension(extension, expected) {
526
- const evmDest = expected.dstChainId !== void 0;
527
- if (evmDest && (!Number.isSafeInteger(expected.dstChainId) || expected.dstChainId <= 0)) throw new Error("omniston: invalid EVM destination chain id");
529
+ var EVM_AUCTION_POINTS = [[800000n, 100n], [700000n, 100n], [600000n, 100n], [500000n, 100n], [400000n, 100n]];
530
+ var EVM_TIMELOCKS = [1n, 120n, 240n, 300n, 1n, 120n, 180n, 0n].reduce((packed, value, index) => packed | value << BigInt(index * 32), 0n);
531
+ function readEvmOrderExtension(extension) {
528
532
  if (extension.length < 32) throw new Error("omniston: malformed EVM order extension");
529
533
  const view = new DataView(extension.buffer, extension.byteOffset, extension.byteLength);
530
534
  const fields = [];
@@ -544,54 +548,48 @@ async function validateEvmToTonOrderExtension(extension, expected) {
544
548
  }
545
549
  let target;
546
550
  for (const index of [2, 3, 7]) {
547
- const field = fields[index];
548
- if (field.length <= 20) throw new Error("omniston: incomplete EVM order extension program");
549
- const address = getAddress(`0x${bytesToHex(field.slice(0, 20))}`);
550
- if (!expected.trustedTarget(address) || target !== void 0 && getAddress(target) !== address) {
551
+ const field2 = fields[index];
552
+ if (field2.length <= 20) throw new Error("omniston: incomplete EVM order extension program");
553
+ const address = getAddress(`0x${bytesToHex(field2.slice(0, 20))}`);
554
+ if (target !== void 0 && getAddress(target) !== address) {
551
555
  throw new Error("omniston: EVM order extension target is not independently trusted");
552
556
  }
553
557
  target = address;
554
558
  }
555
- const getter = fields[2];
559
+ const field = fields[2];
556
560
  let cursor = 20;
557
- const gasBump = readBigEndian(getter, cursor, 3);
561
+ const gasBump = readBigEndian(field, cursor, 3);
558
562
  cursor += 3;
559
- const gasPrice = readBigEndian(getter, cursor, 4);
563
+ const gasPrice = readBigEndian(field, cursor, 4);
560
564
  cursor += 4;
561
- const auctionStart = readBigEndian(getter, cursor, 4);
565
+ const auctionStart = readBigEndian(field, cursor, 4);
562
566
  cursor += 4;
563
- const duration = readBigEndian(getter, cursor, 3);
567
+ const duration = readBigEndian(field, cursor, 3);
564
568
  cursor += 3;
565
- const initialRateBump = readBigEndian(getter, cursor, 3);
569
+ const initialRateBump = readBigEndian(field, cursor, 3);
566
570
  cursor += 3;
567
- const pointCount = bigintToNumber(readBigEndian(getter, cursor, 1));
571
+ const pointCount = bigintToNumber(readBigEndian(field, cursor, 1));
568
572
  cursor += 1;
569
573
  if (pointCount !== 5) throw new Error("omniston: unsupported EVM auction profile");
570
574
  const points = [];
571
575
  for (let index = 0; index < pointCount; index++) {
572
- points.push([readBigEndian(getter, cursor, 3), readBigEndian(getter, cursor + 3, 2)]);
576
+ points.push([readBigEndian(field, cursor, 3), readBigEndian(field, cursor + 3, 2)]);
573
577
  cursor += 5;
574
578
  }
575
- const integratorFee = readBigEndian(getter, cursor, 2);
579
+ const integratorFee = readBigEndian(field, cursor, 2);
576
580
  cursor += 2;
577
- const integratorShare = readBigEndian(getter, cursor, 1);
581
+ const integratorShare = readBigEndian(field, cursor, 1);
578
582
  cursor += 1;
579
- const resolverFee = readBigEndian(getter, cursor, 2);
583
+ const resolverFee = readBigEndian(field, cursor, 2);
580
584
  cursor += 2;
581
- const whitelistDiscount = readBigEndian(getter, cursor, 1);
585
+ const whitelistDiscount = readBigEndian(field, cursor, 1);
582
586
  cursor += 1;
583
- const getterWhitelistCount = bigintToNumber(readBigEndian(getter, cursor, 1));
587
+ const getterWhitelistCount = bigintToNumber(readBigEndian(field, cursor, 1));
584
588
  cursor += 1;
585
- if (getterWhitelistCount !== 1 || cursor + getterWhitelistCount * 10 !== getter.length) {
589
+ if (getterWhitelistCount !== 1 || cursor + getterWhitelistCount * 10 !== field.length) {
586
590
  throw new Error("omniston: malformed EVM amount-getter whitelist");
587
591
  }
588
- const getterResolver = readBigEndian(getter, cursor, 10);
589
- const expectedPoints = [[800000n, 100n], [700000n, 100n], [600000n, 100n], [500000n, 100n], [400000n, 100n]];
590
- const quoteResolverFee = expected.protocolFeePips % 10 === 0 ? BigInt(expected.protocolFeePips / 10) : -1n;
591
- const resolverLow80 = BigInt(getAddress(expected.initialResolverAddress)) & (1n << 80n) - 1n;
592
- if (gasBump !== 0n || gasPrice !== 0n || !within(auctionStart, expected.quoteTimestamp, 5, 5) || duration !== 1800n || initialRateBump !== 900000n || points.some((point, index) => point[0] !== expectedPoints[index][0] || point[1] !== expectedPoints[index][1]) || expected.integratorFeePips !== 0 || integratorFee !== 0n || integratorShare !== 100n || quoteResolverFee < 0n || resolverFee !== quoteResolverFee || whitelistDiscount !== 50n || getterResolver !== resolverLow80) {
593
- throw new Error("omniston: EVM amount-getter terms do not match the pinned v1beta8 profile");
594
- }
592
+ const getter = { gasBump, gasPrice, auctionStart, duration, initialRateBump, points, integratorFee, integratorShare, resolverFee, whitelistDiscount, resolver: readBigEndian(field, cursor, 10) };
595
593
  const post = fields[7];
596
594
  cursor = 20;
597
595
  const integratorRecipient = post.slice(cursor, cursor + 20);
@@ -617,28 +615,51 @@ async function validateEvmToTonOrderExtension(extension, expected) {
617
615
  cursor += 10;
618
616
  const resolverTimeDelta = readBigEndian(post, cursor, 2);
619
617
  cursor += 2;
620
- if (!zeroBytes(integratorRecipient) || !(zeroBytes(protocolRecipient) || evmDest && EVM_DEST_PROTOCOL_FEE_RECIPIENTS.has(`0x${bytesToHex(protocolRecipient)}`)) || postIntegratorFee !== 0n || postIntegratorShare !== 100n || postResolverFee !== quoteResolverFee || postDiscount !== 50n || !within(allowedTime, expected.quoteTimestamp, 60, 5) || postResolver !== resolverLow80 || resolverTimeDelta !== 0n) {
621
- throw new Error("omniston: EVM post-interaction terms do not match the pinned v1beta8 profile");
622
- }
623
618
  const extra = Array.from({ length: 5 }, () => {
624
619
  const value = readBigEndian(post, cursor, 32);
625
620
  cursor += 32;
626
621
  return value;
627
622
  });
623
+ const customData = extension.slice(32 + begin);
624
+ if (customData.length !== 131) throw new Error("omniston: malformed EVM order extension custom data");
625
+ return {
626
+ target,
627
+ getter,
628
+ post: { integratorRecipient, protocolRecipient, integratorFee: postIntegratorFee, integratorShare: postIntegratorShare, resolverFee: postResolverFee, discount: postDiscount, allowedTime, resolver: postResolver, resolverTimeDelta },
629
+ extra,
630
+ customData
631
+ };
632
+ }
633
+ async function validateEvmToTonOrderExtension(extension, expected) {
634
+ const evmDest = expected.dstChainId !== void 0;
635
+ if (evmDest && (!Number.isSafeInteger(expected.dstChainId) || expected.dstChainId <= 0)) throw new Error("omniston: invalid EVM destination chain id");
636
+ const { target, getter, post, extra, customData } = readEvmOrderExtension(extension);
637
+ if (!expected.trustedTarget(target)) throw new Error("omniston: EVM order extension target is not independently trusted");
638
+ const quoteResolverFee = expected.protocolFeePips % 10 === 0 ? BigInt(expected.protocolFeePips / 10) : -1n;
639
+ const resolverLow80 = BigInt(getAddress(expected.initialResolverAddress)) & (1n << 80n) - 1n;
640
+ if (getter.gasBump !== 0n || getter.gasPrice !== 0n || !within(getter.auctionStart, expected.quoteTimestamp, 5, 5) || getter.duration !== 1800n || getter.initialRateBump !== 900000n || getter.points.some((point, index) => point[0] !== EVM_AUCTION_POINTS[index][0] || point[1] !== EVM_AUCTION_POINTS[index][1]) || expected.integratorFeePips !== 0 || getter.integratorFee !== 0n || getter.integratorShare !== 100n || quoteResolverFee < 0n || getter.resolverFee !== quoteResolverFee || getter.whitelistDiscount !== 50n || getter.resolver !== resolverLow80) {
641
+ throw new Error("omniston: EVM amount-getter terms do not match the pinned v1beta8 profile");
642
+ }
643
+ if (!zeroBytes(post.integratorRecipient) || !(zeroBytes(post.protocolRecipient) || evmDest && EVM_DEST_PROTOCOL_FEE_RECIPIENTS.has(`0x${bytesToHex(post.protocolRecipient)}`)) || post.integratorFee !== 0n || post.integratorShare !== 100n || post.resolverFee !== quoteResolverFee || post.discount !== 50n || !within(post.allowedTime, expected.quoteTimestamp, 60, 5) || post.resolver !== resolverLow80 || post.resolverTimeDelta !== 0n) {
644
+ throw new Error("omniston: EVM post-interaction terms do not match the pinned v1beta8 profile");
645
+ }
628
646
  const hashlock2 = readBigEndian(expected.secretHash, 0, expected.secretHash.length);
629
647
  const dstToken = evmDest ? BigInt(getAddress(expected.outputTokenAddress)) : BigInt(getAddress(expected.takerAsset));
630
648
  const deposits = BigInt(expected.srcSecurityDepositUnits) << 128n | BigInt(expected.dstSecurityDepositUnits);
631
- const timelocks = [1n, 120n, 240n, 300n, 1n, 120n, 180n, 0n].reduce((packed, value, index) => packed | value << BigInt(index * 32), 0n);
632
- if (expected.secretHash.length !== 32 || extra[0] !== hashlock2 || extra[1] !== (evmDest ? BigInt(expected.dstChainId) : 0n) || extra[2] !== dstToken || extra[3] !== deposits || extra[4] !== timelocks) {
649
+ if (expected.secretHash.length !== 32 || extra[0] !== hashlock2 || extra[1] !== (evmDest ? BigInt(expected.dstChainId) : 0n) || extra[2] !== dstToken || extra[3] !== deposits || extra[4] !== EVM_TIMELOCKS) {
633
650
  throw new Error("omniston: signed EVM HTLC terms do not match the validated order details");
634
651
  }
635
- const customData = extension.slice(32 + begin);
636
- if (customData.length !== 131) throw new Error("omniston: malformed EVM order extension custom data");
637
- if (evmDest) {
652
+ await checkOrderCustomData(customData, { evmDest, outputToken: expected.outputTokenAddress, traderDst: expected.traderDstAddress, quoteId: expected.quoteId });
653
+ if (expected.tradeStartDeadline < expected.quoteTimestamp) {
654
+ throw new Error("omniston: invalid EVM order quote deadline");
655
+ }
656
+ }
657
+ async function checkOrderCustomData(customData, expected) {
658
+ if (expected.evmDest) {
638
659
  if (!zeroBytes(customData.slice(0, 66))) throw new Error("omniston: unexpected TON addresses in an EVM-destination order");
639
660
  } else {
640
661
  const { Address: Address2 } = await import("@ton/core");
641
- const expectedTon = [expected.outputTokenAddress, expected.traderDstAddress].map((value) => Address2.parse(value));
662
+ const expectedTon = [expected.outputToken, expected.traderDst].map((value) => Address2.parse(value));
642
663
  for (let index = 0; index < expectedTon.length; index++) {
643
664
  const offset = index * 33;
644
665
  const workchain = customData[offset] === 255 ? -1 : customData[offset];
@@ -654,9 +675,6 @@ async function validateEvmToTonOrderExtension(extension, expected) {
654
675
  if (!QUOTE_ID.test(quoteId) || !sliceEqual(customData.slice(99), hexToBytes(quoteId.padStart(64, "0")))) {
655
676
  throw new Error("omniston: EVM order extension custom data is not bound to the quote id");
656
677
  }
657
- if (expected.tradeStartDeadline < expected.quoteTimestamp) {
658
- throw new Error("omniston: invalid EVM order quote deadline");
659
- }
660
678
  }
661
679
  function validateEvmTypedOrder(td, expected) {
662
680
  const value = td;
@@ -1108,8 +1126,101 @@ function omnistonPins(trustedEvmOrderProtocols) {
1108
1126
  const byChain = new Map(Object.entries(trustedEvmOrderProtocols).map(([chain, list]) => [chain, list.map((a) => getAddress(a))]));
1109
1127
  return Object.freeze({ callTargets: () => [], spenders: (chain) => byChain.get(chain) ?? [] });
1110
1128
  }
1129
+ var MAX_EVM_ORDER_LIFETIME_S = 900;
1130
+ async function checkRemoteEvmOrder(quote, tx, params, trusted) {
1131
+ const chainId = evmRef(params.sourceChain);
1132
+ if (chainId === null || !params.sourceChain.startsWith("eip155:")) return "a typed order needs an EVM source";
1133
+ const intent = decodeIntent(quote.intentId.replace(/~[0-9a-f]{32}$/, ""));
1134
+ if (!intent || intent.kind !== "order" || intent.srcChain !== params.sourceChain) return "the quote's intent is not an order from this chain";
1135
+ if (!tx.orderExtension || !/^0x(?:[0-9a-fA-F]{2})+$/.test(tx.orderExtension)) return "the build carries no order extension to check";
1136
+ const source = ccAsset(params.sourceChain, params.sourceToken);
1137
+ if (!source?.contract) return "unknown source token";
1138
+ const tonDest = isTon(params.destChain);
1139
+ const destChainId = tonDest ? null : evmRef(params.destChain);
1140
+ if (!tonDest && (destChainId === null || !params.destChain.startsWith("eip155:"))) return "the destination is neither TON nor an EVM chain";
1141
+ const outputToken = ccAssetByToken(params.destChain, params.destToken)?.contract ?? params.destToken;
1142
+ const listed = (table, chain, address) => typeof address === "string" && validEvmAddress(address) && (table[chain] ?? []).some((a) => validEvmAddress(a) && getAddress(a) === getAddress(address));
1143
+ let td;
1144
+ try {
1145
+ td = JSON.parse(tx.typedData ?? "");
1146
+ } catch {
1147
+ return "the typed data is not JSON";
1148
+ }
1149
+ const domain = td.domain ?? {};
1150
+ const contract = domain.verifyingContract;
1151
+ if (domain.name !== "1inch Limit Order Protocol" || domain.version !== "4") return "the domain is not the 1inch Limit Order Protocol v4";
1152
+ if (!listed(trusted.orderProtocols, params.sourceChain, contract) || !tx.approvalAddress || getAddress(tx.approvalAddress) !== getAddress(String(contract))) {
1153
+ return `${String(contract)} is not a trusted order protocol on ${params.sourceChain}`;
1154
+ }
1155
+ if (Number(domain.chainId) !== chainId || tx.chainId !== void 0 && tx.chainId !== chainId) return "the domain chainId is not the source chain";
1156
+ const order = td.types?.Order;
1157
+ const message = td.message;
1158
+ if (td.primaryType !== "Order" || !Array.isArray(order) || order.length !== ORDER_FIELDS.length || !order.every((field, i) => field.name === ORDER_FIELDS[i][0] && field.type === ORDER_FIELDS[i][1]) || !message || Object.keys(message).length !== ORDER_FIELDS.length || !ORDER_FIELDS.every(([name]) => Object.hasOwn(message, name)) || !ORDER_FIELDS.every(([name, type]) => type === "address" ? validEvmAddress(message[name]) : validUint256(message[name]))) {
1159
+ return "the typed data is not exactly a v4 Order";
1160
+ }
1161
+ if (!validEvmAddress(intent.trader) || getAddress(String(message.maker)) !== getAddress(intent.trader)) return "the maker is not the trader";
1162
+ if (getAddress(String(message.makerAsset)) !== getAddress(source.contract)) return "the makerAsset is not the source token";
1163
+ if (BigInt(message.makingAmount) !== BigInt(quote.sourceAmount)) return "the makingAmount is not the input";
1164
+ if (getAddress(String(message.takerAsset)) === getAddress(String(message.makerAsset))) return "the takerAsset is the makerAsset";
1165
+ const floor = [quote.minDestAmount, params.minAmountOut ?? "0"].filter((v) => /^\d{1,80}$/.test(v)).map((v) => BigInt(v)).reduce((a, b) => a > b ? a : b, 0n);
1166
+ if (floor <= 0n || BigInt(message.takingAmount) < floor) return `takingAmount ${String(message.takingAmount)} is below the quote's minimum ${floor}`;
1167
+ const traits = BigInt(message.makerTraits);
1168
+ const flags = traits & (1n << 56n) - 1n << 200n;
1169
+ const baseFlags = 1n << 251n | 1n << 249n;
1170
+ if (flags !== baseFlags && flags !== (baseFlags | 1n << 255n)) return "the makerTraits flags are not a single-fill order with its extension";
1171
+ if ((traits & (1n << 80n) - 1n) !== 0n || (traits >> 160n & (1n << 40n) - 1n) !== 0n) return "the makerTraits restrict the taker or the series";
1172
+ const now = BigInt(Math.floor(Date.now() / 1e3));
1173
+ const expiration = traits >> 80n & (1n << 40n) - 1n;
1174
+ if (expiration <= now || expiration > now + BigInt(MAX_EVM_ORDER_LIFETIME_S)) return "the order's expiry is not minutes away";
1175
+ const extension = viemHexToBytes(tx.orderExtension);
1176
+ const mask = (1n << 160n) - 1n;
1177
+ if ((BigInt(message.salt) & mask) !== (BigInt(keccak256(extension)) & mask)) return "the salt does not commit the order extension";
1178
+ let parsed;
1179
+ try {
1180
+ parsed = readEvmOrderExtension(extension);
1181
+ } catch (e) {
1182
+ return e instanceof Error ? e.message.replace(/^omniston: /, "") : String(e);
1183
+ }
1184
+ const { target, getter, post, extra, customData } = parsed;
1185
+ if (!listed(trusted.factories, params.sourceChain, target)) return `the extension targets ${target}, not a trusted escrow factory on ${params.sourceChain}`;
1186
+ const receiverLow80 = BigInt(getAddress(String(message.receiver))) & (1n << 80n) - 1n;
1187
+ if (getter.resolver !== receiverLow80 || post.resolver !== receiverLow80) return "the order's receiver is not the resolver its extension whitelists";
1188
+ if (getter.gasBump !== 0n || getter.gasPrice !== 0n || getter.duration !== 1800n || getter.initialRateBump !== 900000n || getter.points.some((point, index) => point[0] !== EVM_AUCTION_POINTS[index][0] || point[1] !== EVM_AUCTION_POINTS[index][1]) || getter.integratorFee !== 0n || getter.integratorShare !== 100n || getter.whitelistDiscount !== 50n || !within(getter.auctionStart, bigintToNumber(now), MAX_EVM_ORDER_LIFETIME_S, 60)) {
1189
+ return "the amount-getter terms do not match the pinned v1beta8 profile";
1190
+ }
1191
+ if (!zeroBytes(post.integratorRecipient) || !(zeroBytes(post.protocolRecipient) || !tonDest && EVM_DEST_PROTOCOL_FEE_RECIPIENTS.has(`0x${bytesToHex(post.protocolRecipient)}`)) || post.integratorFee !== 0n || post.integratorShare !== 100n || post.resolverFee !== getter.resolverFee || post.discount !== 50n || post.resolverTimeDelta !== 0n || !within(post.allowedTime, bigintToNumber(getter.auctionStart), 60, 5)) {
1192
+ return "the post-interaction terms do not match the pinned v1beta8 profile";
1193
+ }
1194
+ let dstToken;
1195
+ try {
1196
+ dstToken = tonDest ? BigInt(getAddress(String(message.takerAsset))) : BigInt(getAddress(outputToken));
1197
+ } catch {
1198
+ return "the destination token is not an EVM address";
1199
+ }
1200
+ if (extra[1] !== (tonDest ? 0n : BigInt(destChainId)) || extra[2] !== dstToken || extra[4] !== EVM_TIMELOCKS) {
1201
+ return "the signed HTLC terms name another destination chain or token, or other timelocks";
1202
+ }
1203
+ try {
1204
+ await checkOrderCustomData(customData, { evmDest: !tonDest, outputToken, traderDst: params.destAddress, quoteId: intent.quoteId });
1205
+ } catch (e) {
1206
+ return e instanceof Error ? e.message.replace(/^omniston: /, "") : String(e);
1207
+ }
1208
+ return null;
1209
+ }
1111
1210
  function omnistonVerifyBuild(hooks) {
1211
+ const trusted = {
1212
+ orderProtocols: hooks.trustedEvmOrderProtocols ?? AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS,
1213
+ factories: hooks.trustedSettlementContracts ?? AUDITED_OMNISTON_SETTLEMENT_CONTRACTS
1214
+ };
1112
1215
  return async (quote, tx, params) => {
1216
+ if (tx.typedData !== void 0) {
1217
+ if (!params) return "the request this quote answered is unknown";
1218
+ try {
1219
+ return await checkRemoteEvmOrder(quote, tx, params, trusted);
1220
+ } catch {
1221
+ return "the typed order could not be checked";
1222
+ }
1223
+ }
1113
1224
  if (tx.bodyBoc === void 0) return null;
1114
1225
  if (!params) return "the request this quote answered is unknown";
1115
1226
  if (quote.providerData?.settlement !== "swap") {
@@ -1799,7 +1910,7 @@ function omnistonProvider(opts = {}) {
1799
1910
  }
1800
1911
  });
1801
1912
  const orderProtocol = getAddress(protocol.chain.value);
1802
- return { chain: srcChain, to: orderProtocol, value: "0", chainId, approvalAddress: orderProtocol, typedData };
1913
+ return { chain: srcChain, to: orderProtocol, value: "0", chainId, approvalAddress: orderProtocol, typedData, orderExtension: `0x${bytesToHex(payload.orderExtension)}` };
1803
1914
  }
1804
1915
  return {
1805
1916
  name: "omniston",
@@ -2273,4 +2384,4 @@ export {
2273
2384
  omnistonVerifyBuild,
2274
2385
  omnistonProvider
2275
2386
  };
2276
- //# sourceMappingURL=chunk-HOTFZYSW.js.map
2387
+ //# sourceMappingURL=chunk-R6B2CV5Z.js.map