@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 +13 -0
- package/dist/chunk-JWYDIW4V.js +37 -0
- package/dist/chunk-JWYDIW4V.js.map +1 -0
- package/dist/{chunk-HOTFZYSW.js → chunk-R6B2CV5Z.js} +153 -42
- package/dist/chunk-R6B2CV5Z.js.map +1 -0
- package/dist/{chunk-RW4XZWNC.js → chunk-WL7BSEBR.js} +2 -2
- package/dist/index.cjs +180 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -2
- package/dist/protocol.cjs +55 -41
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +1 -1
- package/dist/protocol.d.ts +1 -1
- package/dist/protocol.js +3 -2
- package/dist/{provider-BBG2zhpu.d.cts → provider-D6RXRgf-.d.cts} +8 -1
- package/dist/{provider-BBG2zhpu.d.ts → provider-D6RXRgf-.d.ts} +8 -1
- package/dist/provider.cjs +180 -41
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.d.cts +1 -1
- package/dist/provider.d.ts +1 -1
- package/dist/provider.js +2 -1
- package/dist/validators.d.cts +1 -1
- package/dist/validators.d.ts +1 -1
- package/dist/validators.js +5 -34
- package/dist/validators.js.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-HOTFZYSW.js.map +0 -1
- /package/dist/{chunk-RW4XZWNC.js.map → chunk-WL7BSEBR.js.map} +0 -0
package/dist/protocol.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _anywalletkit_protocol_swap2_core_types from '@anywalletkit/protocol-swap2-core/types';
|
|
2
2
|
import { SingleProviderSwap2 } from '@anywalletkit/protocol-swap2-core/swap2/single';
|
|
3
3
|
import { Swap2EngineConfig, Swap2Account } from '@anywalletkit/protocol-swap2-core/swap2/base';
|
|
4
|
-
import { b as OmnistonProviderOptions } from './provider-
|
|
4
|
+
import { b as OmnistonProviderOptions } from './provider-D6RXRgf-.cjs';
|
|
5
5
|
|
|
6
6
|
interface OmnistonSwap2Config extends Swap2EngineConfig, OmnistonProviderOptions {
|
|
7
7
|
}
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _anywalletkit_protocol_swap2_core_types from '@anywalletkit/protocol-swap2-core/types';
|
|
2
2
|
import { SingleProviderSwap2 } from '@anywalletkit/protocol-swap2-core/swap2/single';
|
|
3
3
|
import { Swap2EngineConfig, Swap2Account } from '@anywalletkit/protocol-swap2-core/swap2/base';
|
|
4
|
-
import { b as OmnistonProviderOptions } from './provider-
|
|
4
|
+
import { b as OmnistonProviderOptions } from './provider-D6RXRgf-.js';
|
|
5
5
|
|
|
6
6
|
interface OmnistonSwap2Config extends Swap2EngineConfig, OmnistonProviderOptions {
|
|
7
7
|
}
|
package/dist/protocol.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
OmnistonSwap2Protocol
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-WL7BSEBR.js";
|
|
4
|
+
import "./chunk-R6B2CV5Z.js";
|
|
5
5
|
import "./chunk-QDXFC6BC.js";
|
|
6
6
|
import "./chunk-AIWAM7BS.js";
|
|
7
|
+
import "./chunk-JWYDIW4V.js";
|
|
7
8
|
export {
|
|
8
9
|
OmnistonSwap2Protocol
|
|
9
10
|
};
|
|
@@ -751,7 +751,10 @@ declare function omnistonPins(trustedEvmOrderProtocols: Readonly<Record<string,
|
|
|
751
751
|
* validators (`validateTonSwapTarget`, `validateTonSwapLeg`);
|
|
752
752
|
* - a TON → EVM escrow body (an Omniston order from TON) goes to `verifyTonEscrowBuild` with what the app knows: the
|
|
753
753
|
* input, the trader's TON address, the destination chain, address and token, and the quote's minimum delivery.
|
|
754
|
-
* EVM typed
|
|
754
|
+
* - an EVM typed order (EVM → TON, EVM → EVM) is opened with the order extension the build carries: price, receiver,
|
|
755
|
+
* traits, salt and the escrow terms are checked against the app's request and the audited contracts
|
|
756
|
+
* (`trustedEvmOrderProtocols`, `trustedSettlementContracts`; default the audited tables), scan 2026-10-28 F6.
|
|
757
|
+
* The reason it fails, or null.
|
|
755
758
|
*/
|
|
756
759
|
declare function omnistonVerifyBuild(hooks: {
|
|
757
760
|
validateTonSwapTarget: (input: {
|
|
@@ -766,6 +769,10 @@ declare function omnistonVerifyBuild(hooks: {
|
|
|
766
769
|
verifyTonEscrowBuild?: (input: TonEscrowBuildExpectation) => string | null | Promise<string | null>;
|
|
767
770
|
/** The integrator your backend's Omniston provider uses: the only referral a body may name. */
|
|
768
771
|
integratorAddress?: string | null;
|
|
772
|
+
/** EVM order protocols an EVM typed order may name, per chain. Default `AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS`. */
|
|
773
|
+
trustedEvmOrderProtocols?: Readonly<Record<string, readonly string[]>>;
|
|
774
|
+
/** Escrow factories an EVM order's extension may target, per chain. Default `AUDITED_OMNISTON_SETTLEMENT_CONTRACTS`. */
|
|
775
|
+
trustedSettlementContracts?: Readonly<Record<string, readonly string[]>>;
|
|
769
776
|
}): (quote: Quote, tx: UnsignedTx, params?: QuoteParams) => Promise<string | null>;
|
|
770
777
|
declare function omnistonProvider(opts?: OmnistonProviderOptions): CrossChainProvider;
|
|
771
778
|
|
|
@@ -751,7 +751,10 @@ declare function omnistonPins(trustedEvmOrderProtocols: Readonly<Record<string,
|
|
|
751
751
|
* validators (`validateTonSwapTarget`, `validateTonSwapLeg`);
|
|
752
752
|
* - a TON → EVM escrow body (an Omniston order from TON) goes to `verifyTonEscrowBuild` with what the app knows: the
|
|
753
753
|
* input, the trader's TON address, the destination chain, address and token, and the quote's minimum delivery.
|
|
754
|
-
* EVM typed
|
|
754
|
+
* - an EVM typed order (EVM → TON, EVM → EVM) is opened with the order extension the build carries: price, receiver,
|
|
755
|
+
* traits, salt and the escrow terms are checked against the app's request and the audited contracts
|
|
756
|
+
* (`trustedEvmOrderProtocols`, `trustedSettlementContracts`; default the audited tables), scan 2026-10-28 F6.
|
|
757
|
+
* The reason it fails, or null.
|
|
755
758
|
*/
|
|
756
759
|
declare function omnistonVerifyBuild(hooks: {
|
|
757
760
|
validateTonSwapTarget: (input: {
|
|
@@ -766,6 +769,10 @@ declare function omnistonVerifyBuild(hooks: {
|
|
|
766
769
|
verifyTonEscrowBuild?: (input: TonEscrowBuildExpectation) => string | null | Promise<string | null>;
|
|
767
770
|
/** The integrator your backend's Omniston provider uses: the only referral a body may name. */
|
|
768
771
|
integratorAddress?: string | null;
|
|
772
|
+
/** EVM order protocols an EVM typed order may name, per chain. Default `AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS`. */
|
|
773
|
+
trustedEvmOrderProtocols?: Readonly<Record<string, readonly string[]>>;
|
|
774
|
+
/** Escrow factories an EVM order's extension may target, per chain. Default `AUDITED_OMNISTON_SETTLEMENT_CONTRACTS`. */
|
|
775
|
+
trustedSettlementContracts?: Readonly<Record<string, readonly string[]>>;
|
|
769
776
|
}): (quote: Quote, tx: UnsignedTx, params?: QuoteParams) => Promise<string | null>;
|
|
770
777
|
declare function omnistonProvider(opts?: OmnistonProviderOptions): CrossChainProvider;
|
|
771
778
|
|
package/dist/provider.cjs
CHANGED
|
@@ -429,6 +429,38 @@ function sameJetton(a, b) {
|
|
|
429
429
|
}
|
|
430
430
|
}
|
|
431
431
|
|
|
432
|
+
// src/validators/settlement.ts
|
|
433
|
+
var AUDITED_OMNISTON_SETTLEMENT_CONTRACTS = {
|
|
434
|
+
"ton:-239": ["EQAbWJ3Y1HgIIvcMq1prG1anlDC0T3cZlAU7luPT6LmTpmrZ"],
|
|
435
|
+
"eip155:1": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
|
|
436
|
+
"eip155:56": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
|
|
437
|
+
"eip155:137": ["0x41A392062A4307a6961d48e30FF20bF6823715B8"],
|
|
438
|
+
"eip155:4663": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
|
|
439
|
+
"eip155:8453": ["0xACa3E2F9b61a44892926bC6c3e104192E7D1c3cd"],
|
|
440
|
+
"eip155:42161": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
|
|
441
|
+
"eip155:43114": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
|
|
442
|
+
// 2026-10-20: one factory address on X Layer, HyperEVM and Plasma. Runtime
|
|
443
|
+
// bytecode equals Ethereum's 0xafCF… byte for byte except the immutable slots
|
|
444
|
+
// (escrow implementations, its order protocol, domain hash); it references
|
|
445
|
+
// the order protocol trusted below on the same chain.
|
|
446
|
+
"eip155:196": ["0xd602079AFa5c38F550510a2a988CbFa698Fa0189"],
|
|
447
|
+
"eip155:999": ["0xd602079AFa5c38F550510a2a988CbFa698Fa0189"],
|
|
448
|
+
"eip155:9745": ["0xd602079AFa5c38F550510a2a988CbFa698Fa0189"]
|
|
449
|
+
};
|
|
450
|
+
var AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS = {
|
|
451
|
+
"eip155:1": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
|
|
452
|
+
"eip155:56": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
|
|
453
|
+
"eip155:137": ["0xafCF681272AF10959736f45616eeCBC22D7095E2"],
|
|
454
|
+
"eip155:8453": ["0xe7405fAcDEDB2512e91F2886BDff13231343aF5E"],
|
|
455
|
+
"eip155:42161": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
|
|
456
|
+
"eip155:43114": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
|
|
457
|
+
// 2026-10-20: bytecode equals Ethereum's 0xb581… except immutables (wrapped
|
|
458
|
+
// native, own address, chain id 196 / 9745 / 999 at the chain-id slot).
|
|
459
|
+
"eip155:196": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
|
|
460
|
+
"eip155:9745": ["0xb5810aCfD45D85Eaa938bF90a5857295513DA7E9"],
|
|
461
|
+
"eip155:999": ["0xD84778bbeEC5D2a8d17c6424249C438EC0b1ABE3"]
|
|
462
|
+
};
|
|
463
|
+
|
|
432
464
|
// src/provider.ts
|
|
433
465
|
var import_core4 = require("@anywalletkit/core");
|
|
434
466
|
var EVM_CASE = {
|
|
@@ -639,9 +671,9 @@ function validEvmAddress(value) {
|
|
|
639
671
|
}
|
|
640
672
|
}
|
|
641
673
|
var EVM_DEST_PROTOCOL_FEE_RECIPIENTS = /* @__PURE__ */ new Set(["0x076268146b4ec6d21fc49c27586cfa91b9079a00"]);
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
674
|
+
var EVM_AUCTION_POINTS = [[800000n, 100n], [700000n, 100n], [600000n, 100n], [500000n, 100n], [400000n, 100n]];
|
|
675
|
+
var EVM_TIMELOCKS = [1n, 120n, 240n, 300n, 1n, 120n, 180n, 0n].reduce((packed, value, index) => packed | value << BigInt(index * 32), 0n);
|
|
676
|
+
function readEvmOrderExtension(extension) {
|
|
645
677
|
if (extension.length < 32) throw new Error("omniston: malformed EVM order extension");
|
|
646
678
|
const view = new DataView(extension.buffer, extension.byteOffset, extension.byteLength);
|
|
647
679
|
const fields = [];
|
|
@@ -661,54 +693,48 @@ async function validateEvmToTonOrderExtension(extension, expected) {
|
|
|
661
693
|
}
|
|
662
694
|
let target;
|
|
663
695
|
for (const index of [2, 3, 7]) {
|
|
664
|
-
const
|
|
665
|
-
if (
|
|
666
|
-
const address = (0, import_viem.getAddress)(`0x${bytesToHex(
|
|
667
|
-
if (
|
|
696
|
+
const field2 = fields[index];
|
|
697
|
+
if (field2.length <= 20) throw new Error("omniston: incomplete EVM order extension program");
|
|
698
|
+
const address = (0, import_viem.getAddress)(`0x${bytesToHex(field2.slice(0, 20))}`);
|
|
699
|
+
if (target !== void 0 && (0, import_viem.getAddress)(target) !== address) {
|
|
668
700
|
throw new Error("omniston: EVM order extension target is not independently trusted");
|
|
669
701
|
}
|
|
670
702
|
target = address;
|
|
671
703
|
}
|
|
672
|
-
const
|
|
704
|
+
const field = fields[2];
|
|
673
705
|
let cursor = 20;
|
|
674
|
-
const gasBump = readBigEndian(
|
|
706
|
+
const gasBump = readBigEndian(field, cursor, 3);
|
|
675
707
|
cursor += 3;
|
|
676
|
-
const gasPrice = readBigEndian(
|
|
708
|
+
const gasPrice = readBigEndian(field, cursor, 4);
|
|
677
709
|
cursor += 4;
|
|
678
|
-
const auctionStart = readBigEndian(
|
|
710
|
+
const auctionStart = readBigEndian(field, cursor, 4);
|
|
679
711
|
cursor += 4;
|
|
680
|
-
const duration = readBigEndian(
|
|
712
|
+
const duration = readBigEndian(field, cursor, 3);
|
|
681
713
|
cursor += 3;
|
|
682
|
-
const initialRateBump = readBigEndian(
|
|
714
|
+
const initialRateBump = readBigEndian(field, cursor, 3);
|
|
683
715
|
cursor += 3;
|
|
684
|
-
const pointCount = (0, import_core4.bigintToNumber)(readBigEndian(
|
|
716
|
+
const pointCount = (0, import_core4.bigintToNumber)(readBigEndian(field, cursor, 1));
|
|
685
717
|
cursor += 1;
|
|
686
718
|
if (pointCount !== 5) throw new Error("omniston: unsupported EVM auction profile");
|
|
687
719
|
const points = [];
|
|
688
720
|
for (let index = 0; index < pointCount; index++) {
|
|
689
|
-
points.push([readBigEndian(
|
|
721
|
+
points.push([readBigEndian(field, cursor, 3), readBigEndian(field, cursor + 3, 2)]);
|
|
690
722
|
cursor += 5;
|
|
691
723
|
}
|
|
692
|
-
const integratorFee = readBigEndian(
|
|
724
|
+
const integratorFee = readBigEndian(field, cursor, 2);
|
|
693
725
|
cursor += 2;
|
|
694
|
-
const integratorShare = readBigEndian(
|
|
726
|
+
const integratorShare = readBigEndian(field, cursor, 1);
|
|
695
727
|
cursor += 1;
|
|
696
|
-
const resolverFee = readBigEndian(
|
|
728
|
+
const resolverFee = readBigEndian(field, cursor, 2);
|
|
697
729
|
cursor += 2;
|
|
698
|
-
const whitelistDiscount = readBigEndian(
|
|
730
|
+
const whitelistDiscount = readBigEndian(field, cursor, 1);
|
|
699
731
|
cursor += 1;
|
|
700
|
-
const getterWhitelistCount = (0, import_core4.bigintToNumber)(readBigEndian(
|
|
732
|
+
const getterWhitelistCount = (0, import_core4.bigintToNumber)(readBigEndian(field, cursor, 1));
|
|
701
733
|
cursor += 1;
|
|
702
|
-
if (getterWhitelistCount !== 1 || cursor + getterWhitelistCount * 10 !==
|
|
734
|
+
if (getterWhitelistCount !== 1 || cursor + getterWhitelistCount * 10 !== field.length) {
|
|
703
735
|
throw new Error("omniston: malformed EVM amount-getter whitelist");
|
|
704
736
|
}
|
|
705
|
-
const
|
|
706
|
-
const expectedPoints = [[800000n, 100n], [700000n, 100n], [600000n, 100n], [500000n, 100n], [400000n, 100n]];
|
|
707
|
-
const quoteResolverFee = expected.protocolFeePips % 10 === 0 ? BigInt(expected.protocolFeePips / 10) : -1n;
|
|
708
|
-
const resolverLow80 = BigInt((0, import_viem.getAddress)(expected.initialResolverAddress)) & (1n << 80n) - 1n;
|
|
709
|
-
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) {
|
|
710
|
-
throw new Error("omniston: EVM amount-getter terms do not match the pinned v1beta8 profile");
|
|
711
|
-
}
|
|
737
|
+
const getter = { gasBump, gasPrice, auctionStart, duration, initialRateBump, points, integratorFee, integratorShare, resolverFee, whitelistDiscount, resolver: readBigEndian(field, cursor, 10) };
|
|
712
738
|
const post = fields[7];
|
|
713
739
|
cursor = 20;
|
|
714
740
|
const integratorRecipient = post.slice(cursor, cursor + 20);
|
|
@@ -734,28 +760,51 @@ async function validateEvmToTonOrderExtension(extension, expected) {
|
|
|
734
760
|
cursor += 10;
|
|
735
761
|
const resolverTimeDelta = readBigEndian(post, cursor, 2);
|
|
736
762
|
cursor += 2;
|
|
737
|
-
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) {
|
|
738
|
-
throw new Error("omniston: EVM post-interaction terms do not match the pinned v1beta8 profile");
|
|
739
|
-
}
|
|
740
763
|
const extra = Array.from({ length: 5 }, () => {
|
|
741
764
|
const value = readBigEndian(post, cursor, 32);
|
|
742
765
|
cursor += 32;
|
|
743
766
|
return value;
|
|
744
767
|
});
|
|
768
|
+
const customData = extension.slice(32 + begin);
|
|
769
|
+
if (customData.length !== 131) throw new Error("omniston: malformed EVM order extension custom data");
|
|
770
|
+
return {
|
|
771
|
+
target,
|
|
772
|
+
getter,
|
|
773
|
+
post: { integratorRecipient, protocolRecipient, integratorFee: postIntegratorFee, integratorShare: postIntegratorShare, resolverFee: postResolverFee, discount: postDiscount, allowedTime, resolver: postResolver, resolverTimeDelta },
|
|
774
|
+
extra,
|
|
775
|
+
customData
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
async function validateEvmToTonOrderExtension(extension, expected) {
|
|
779
|
+
const evmDest = expected.dstChainId !== void 0;
|
|
780
|
+
if (evmDest && (!Number.isSafeInteger(expected.dstChainId) || expected.dstChainId <= 0)) throw new Error("omniston: invalid EVM destination chain id");
|
|
781
|
+
const { target, getter, post, extra, customData } = readEvmOrderExtension(extension);
|
|
782
|
+
if (!expected.trustedTarget(target)) throw new Error("omniston: EVM order extension target is not independently trusted");
|
|
783
|
+
const quoteResolverFee = expected.protocolFeePips % 10 === 0 ? BigInt(expected.protocolFeePips / 10) : -1n;
|
|
784
|
+
const resolverLow80 = BigInt((0, import_viem.getAddress)(expected.initialResolverAddress)) & (1n << 80n) - 1n;
|
|
785
|
+
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) {
|
|
786
|
+
throw new Error("omniston: EVM amount-getter terms do not match the pinned v1beta8 profile");
|
|
787
|
+
}
|
|
788
|
+
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) {
|
|
789
|
+
throw new Error("omniston: EVM post-interaction terms do not match the pinned v1beta8 profile");
|
|
790
|
+
}
|
|
745
791
|
const hashlock2 = readBigEndian(expected.secretHash, 0, expected.secretHash.length);
|
|
746
792
|
const dstToken = evmDest ? BigInt((0, import_viem.getAddress)(expected.outputTokenAddress)) : BigInt((0, import_viem.getAddress)(expected.takerAsset));
|
|
747
793
|
const deposits = BigInt(expected.srcSecurityDepositUnits) << 128n | BigInt(expected.dstSecurityDepositUnits);
|
|
748
|
-
|
|
749
|
-
if (expected.secretHash.length !== 32 || extra[0] !== hashlock2 || extra[1] !== (evmDest ? BigInt(expected.dstChainId) : 0n) || extra[2] !== dstToken || extra[3] !== deposits || extra[4] !== timelocks) {
|
|
794
|
+
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) {
|
|
750
795
|
throw new Error("omniston: signed EVM HTLC terms do not match the validated order details");
|
|
751
796
|
}
|
|
752
|
-
|
|
753
|
-
if (
|
|
754
|
-
|
|
797
|
+
await checkOrderCustomData(customData, { evmDest, outputToken: expected.outputTokenAddress, traderDst: expected.traderDstAddress, quoteId: expected.quoteId });
|
|
798
|
+
if (expected.tradeStartDeadline < expected.quoteTimestamp) {
|
|
799
|
+
throw new Error("omniston: invalid EVM order quote deadline");
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
async function checkOrderCustomData(customData, expected) {
|
|
803
|
+
if (expected.evmDest) {
|
|
755
804
|
if (!zeroBytes(customData.slice(0, 66))) throw new Error("omniston: unexpected TON addresses in an EVM-destination order");
|
|
756
805
|
} else {
|
|
757
806
|
const { Address: Address3 } = await import("@ton/core");
|
|
758
|
-
const expectedTon = [expected.
|
|
807
|
+
const expectedTon = [expected.outputToken, expected.traderDst].map((value) => Address3.parse(value));
|
|
759
808
|
for (let index = 0; index < expectedTon.length; index++) {
|
|
760
809
|
const offset = index * 33;
|
|
761
810
|
const workchain = customData[offset] === 255 ? -1 : customData[offset];
|
|
@@ -771,9 +820,6 @@ async function validateEvmToTonOrderExtension(extension, expected) {
|
|
|
771
820
|
if (!QUOTE_ID.test(quoteId) || !sliceEqual(customData.slice(99), hexToBytes(quoteId.padStart(64, "0")))) {
|
|
772
821
|
throw new Error("omniston: EVM order extension custom data is not bound to the quote id");
|
|
773
822
|
}
|
|
774
|
-
if (expected.tradeStartDeadline < expected.quoteTimestamp) {
|
|
775
|
-
throw new Error("omniston: invalid EVM order quote deadline");
|
|
776
|
-
}
|
|
777
823
|
}
|
|
778
824
|
function validateEvmTypedOrder(td, expected) {
|
|
779
825
|
const value = td;
|
|
@@ -1225,8 +1271,101 @@ function omnistonPins(trustedEvmOrderProtocols) {
|
|
|
1225
1271
|
const byChain = new Map(Object.entries(trustedEvmOrderProtocols).map(([chain, list]) => [chain, list.map((a) => (0, import_viem.getAddress)(a))]));
|
|
1226
1272
|
return Object.freeze({ callTargets: () => [], spenders: (chain) => byChain.get(chain) ?? [] });
|
|
1227
1273
|
}
|
|
1274
|
+
var MAX_EVM_ORDER_LIFETIME_S = 900;
|
|
1275
|
+
async function checkRemoteEvmOrder(quote, tx, params, trusted) {
|
|
1276
|
+
const chainId = evmRef2(params.sourceChain);
|
|
1277
|
+
if (chainId === null || !params.sourceChain.startsWith("eip155:")) return "a typed order needs an EVM source";
|
|
1278
|
+
const intent = decodeIntent(quote.intentId.replace(/~[0-9a-f]{32}$/, ""));
|
|
1279
|
+
if (!intent || intent.kind !== "order" || intent.srcChain !== params.sourceChain) return "the quote's intent is not an order from this chain";
|
|
1280
|
+
if (!tx.orderExtension || !/^0x(?:[0-9a-fA-F]{2})+$/.test(tx.orderExtension)) return "the build carries no order extension to check";
|
|
1281
|
+
const source = (0, import_swap2_assets.ccAsset)(params.sourceChain, params.sourceToken);
|
|
1282
|
+
if (!source?.contract) return "unknown source token";
|
|
1283
|
+
const tonDest = isTon(params.destChain);
|
|
1284
|
+
const destChainId = tonDest ? null : evmRef2(params.destChain);
|
|
1285
|
+
if (!tonDest && (destChainId === null || !params.destChain.startsWith("eip155:"))) return "the destination is neither TON nor an EVM chain";
|
|
1286
|
+
const outputToken = (0, import_swap2_assets.ccAssetByToken)(params.destChain, params.destToken)?.contract ?? params.destToken;
|
|
1287
|
+
const listed = (table, chain, address) => typeof address === "string" && validEvmAddress(address) && (table[chain] ?? []).some((a) => validEvmAddress(a) && (0, import_viem.getAddress)(a) === (0, import_viem.getAddress)(address));
|
|
1288
|
+
let td;
|
|
1289
|
+
try {
|
|
1290
|
+
td = JSON.parse(tx.typedData ?? "");
|
|
1291
|
+
} catch {
|
|
1292
|
+
return "the typed data is not JSON";
|
|
1293
|
+
}
|
|
1294
|
+
const domain = td.domain ?? {};
|
|
1295
|
+
const contract = domain.verifyingContract;
|
|
1296
|
+
if (domain.name !== "1inch Limit Order Protocol" || domain.version !== "4") return "the domain is not the 1inch Limit Order Protocol v4";
|
|
1297
|
+
if (!listed(trusted.orderProtocols, params.sourceChain, contract) || !tx.approvalAddress || (0, import_viem.getAddress)(tx.approvalAddress) !== (0, import_viem.getAddress)(String(contract))) {
|
|
1298
|
+
return `${String(contract)} is not a trusted order protocol on ${params.sourceChain}`;
|
|
1299
|
+
}
|
|
1300
|
+
if (Number(domain.chainId) !== chainId || tx.chainId !== void 0 && tx.chainId !== chainId) return "the domain chainId is not the source chain";
|
|
1301
|
+
const order = td.types?.Order;
|
|
1302
|
+
const message = td.message;
|
|
1303
|
+
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]))) {
|
|
1304
|
+
return "the typed data is not exactly a v4 Order";
|
|
1305
|
+
}
|
|
1306
|
+
if (!validEvmAddress(intent.trader) || (0, import_viem.getAddress)(String(message.maker)) !== (0, import_viem.getAddress)(intent.trader)) return "the maker is not the trader";
|
|
1307
|
+
if ((0, import_viem.getAddress)(String(message.makerAsset)) !== (0, import_viem.getAddress)(source.contract)) return "the makerAsset is not the source token";
|
|
1308
|
+
if (BigInt(message.makingAmount) !== BigInt(quote.sourceAmount)) return "the makingAmount is not the input";
|
|
1309
|
+
if ((0, import_viem.getAddress)(String(message.takerAsset)) === (0, import_viem.getAddress)(String(message.makerAsset))) return "the takerAsset is the makerAsset";
|
|
1310
|
+
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);
|
|
1311
|
+
if (floor <= 0n || BigInt(message.takingAmount) < floor) return `takingAmount ${String(message.takingAmount)} is below the quote's minimum ${floor}`;
|
|
1312
|
+
const traits = BigInt(message.makerTraits);
|
|
1313
|
+
const flags = traits & (1n << 56n) - 1n << 200n;
|
|
1314
|
+
const baseFlags = 1n << 251n | 1n << 249n;
|
|
1315
|
+
if (flags !== baseFlags && flags !== (baseFlags | 1n << 255n)) return "the makerTraits flags are not a single-fill order with its extension";
|
|
1316
|
+
if ((traits & (1n << 80n) - 1n) !== 0n || (traits >> 160n & (1n << 40n) - 1n) !== 0n) return "the makerTraits restrict the taker or the series";
|
|
1317
|
+
const now = BigInt(Math.floor(Date.now() / 1e3));
|
|
1318
|
+
const expiration = traits >> 80n & (1n << 40n) - 1n;
|
|
1319
|
+
if (expiration <= now || expiration > now + BigInt(MAX_EVM_ORDER_LIFETIME_S)) return "the order's expiry is not minutes away";
|
|
1320
|
+
const extension = (0, import_viem.hexToBytes)(tx.orderExtension);
|
|
1321
|
+
const mask = (1n << 160n) - 1n;
|
|
1322
|
+
if ((BigInt(message.salt) & mask) !== (BigInt((0, import_viem.keccak256)(extension)) & mask)) return "the salt does not commit the order extension";
|
|
1323
|
+
let parsed;
|
|
1324
|
+
try {
|
|
1325
|
+
parsed = readEvmOrderExtension(extension);
|
|
1326
|
+
} catch (e) {
|
|
1327
|
+
return e instanceof Error ? e.message.replace(/^omniston: /, "") : String(e);
|
|
1328
|
+
}
|
|
1329
|
+
const { target, getter, post, extra, customData } = parsed;
|
|
1330
|
+
if (!listed(trusted.factories, params.sourceChain, target)) return `the extension targets ${target}, not a trusted escrow factory on ${params.sourceChain}`;
|
|
1331
|
+
const receiverLow80 = BigInt((0, import_viem.getAddress)(String(message.receiver))) & (1n << 80n) - 1n;
|
|
1332
|
+
if (getter.resolver !== receiverLow80 || post.resolver !== receiverLow80) return "the order's receiver is not the resolver its extension whitelists";
|
|
1333
|
+
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, (0, import_core4.bigintToNumber)(now), MAX_EVM_ORDER_LIFETIME_S, 60)) {
|
|
1334
|
+
return "the amount-getter terms do not match the pinned v1beta8 profile";
|
|
1335
|
+
}
|
|
1336
|
+
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, (0, import_core4.bigintToNumber)(getter.auctionStart), 60, 5)) {
|
|
1337
|
+
return "the post-interaction terms do not match the pinned v1beta8 profile";
|
|
1338
|
+
}
|
|
1339
|
+
let dstToken;
|
|
1340
|
+
try {
|
|
1341
|
+
dstToken = tonDest ? BigInt((0, import_viem.getAddress)(String(message.takerAsset))) : BigInt((0, import_viem.getAddress)(outputToken));
|
|
1342
|
+
} catch {
|
|
1343
|
+
return "the destination token is not an EVM address";
|
|
1344
|
+
}
|
|
1345
|
+
if (extra[1] !== (tonDest ? 0n : BigInt(destChainId)) || extra[2] !== dstToken || extra[4] !== EVM_TIMELOCKS) {
|
|
1346
|
+
return "the signed HTLC terms name another destination chain or token, or other timelocks";
|
|
1347
|
+
}
|
|
1348
|
+
try {
|
|
1349
|
+
await checkOrderCustomData(customData, { evmDest: !tonDest, outputToken, traderDst: params.destAddress, quoteId: intent.quoteId });
|
|
1350
|
+
} catch (e) {
|
|
1351
|
+
return e instanceof Error ? e.message.replace(/^omniston: /, "") : String(e);
|
|
1352
|
+
}
|
|
1353
|
+
return null;
|
|
1354
|
+
}
|
|
1228
1355
|
function omnistonVerifyBuild(hooks) {
|
|
1356
|
+
const trusted = {
|
|
1357
|
+
orderProtocols: hooks.trustedEvmOrderProtocols ?? AUDITED_OMNISTON_EVM_ORDER_PROTOCOLS,
|
|
1358
|
+
factories: hooks.trustedSettlementContracts ?? AUDITED_OMNISTON_SETTLEMENT_CONTRACTS
|
|
1359
|
+
};
|
|
1229
1360
|
return async (quote, tx, params) => {
|
|
1361
|
+
if (tx.typedData !== void 0) {
|
|
1362
|
+
if (!params) return "the request this quote answered is unknown";
|
|
1363
|
+
try {
|
|
1364
|
+
return await checkRemoteEvmOrder(quote, tx, params, trusted);
|
|
1365
|
+
} catch {
|
|
1366
|
+
return "the typed order could not be checked";
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1230
1369
|
if (tx.bodyBoc === void 0) return null;
|
|
1231
1370
|
if (!params) return "the request this quote answered is unknown";
|
|
1232
1371
|
if (quote.providerData?.settlement !== "swap") {
|
|
@@ -1916,7 +2055,7 @@ function omnistonProvider(opts = {}) {
|
|
|
1916
2055
|
}
|
|
1917
2056
|
});
|
|
1918
2057
|
const orderProtocol = (0, import_viem.getAddress)(protocol.chain.value);
|
|
1919
|
-
return { chain: srcChain, to: orderProtocol, value: "0", chainId, approvalAddress: orderProtocol, typedData };
|
|
2058
|
+
return { chain: srcChain, to: orderProtocol, value: "0", chainId, approvalAddress: orderProtocol, typedData, orderExtension: `0x${bytesToHex(payload.orderExtension)}` };
|
|
1920
2059
|
}
|
|
1921
2060
|
return {
|
|
1922
2061
|
name: "omniston",
|