@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/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
|
-
|
|
526
|
-
|
|
527
|
-
|
|
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
|
|
548
|
-
if (
|
|
549
|
-
const address = getAddress(`0x${bytesToHex(
|
|
550
|
-
if (
|
|
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
|
|
559
|
+
const field = fields[2];
|
|
556
560
|
let cursor = 20;
|
|
557
|
-
const gasBump = readBigEndian(
|
|
561
|
+
const gasBump = readBigEndian(field, cursor, 3);
|
|
558
562
|
cursor += 3;
|
|
559
|
-
const gasPrice = readBigEndian(
|
|
563
|
+
const gasPrice = readBigEndian(field, cursor, 4);
|
|
560
564
|
cursor += 4;
|
|
561
|
-
const auctionStart = readBigEndian(
|
|
565
|
+
const auctionStart = readBigEndian(field, cursor, 4);
|
|
562
566
|
cursor += 4;
|
|
563
|
-
const duration = readBigEndian(
|
|
567
|
+
const duration = readBigEndian(field, cursor, 3);
|
|
564
568
|
cursor += 3;
|
|
565
|
-
const initialRateBump = readBigEndian(
|
|
569
|
+
const initialRateBump = readBigEndian(field, cursor, 3);
|
|
566
570
|
cursor += 3;
|
|
567
|
-
const pointCount = bigintToNumber(readBigEndian(
|
|
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(
|
|
576
|
+
points.push([readBigEndian(field, cursor, 3), readBigEndian(field, cursor + 3, 2)]);
|
|
573
577
|
cursor += 5;
|
|
574
578
|
}
|
|
575
|
-
const integratorFee = readBigEndian(
|
|
579
|
+
const integratorFee = readBigEndian(field, cursor, 2);
|
|
576
580
|
cursor += 2;
|
|
577
|
-
const integratorShare = readBigEndian(
|
|
581
|
+
const integratorShare = readBigEndian(field, cursor, 1);
|
|
578
582
|
cursor += 1;
|
|
579
|
-
const resolverFee = readBigEndian(
|
|
583
|
+
const resolverFee = readBigEndian(field, cursor, 2);
|
|
580
584
|
cursor += 2;
|
|
581
|
-
const whitelistDiscount = readBigEndian(
|
|
585
|
+
const whitelistDiscount = readBigEndian(field, cursor, 1);
|
|
582
586
|
cursor += 1;
|
|
583
|
-
const getterWhitelistCount = bigintToNumber(readBigEndian(
|
|
587
|
+
const getterWhitelistCount = bigintToNumber(readBigEndian(field, cursor, 1));
|
|
584
588
|
cursor += 1;
|
|
585
|
-
if (getterWhitelistCount !== 1 || cursor + getterWhitelistCount * 10 !==
|
|
589
|
+
if (getterWhitelistCount !== 1 || cursor + getterWhitelistCount * 10 !== field.length) {
|
|
586
590
|
throw new Error("omniston: malformed EVM amount-getter whitelist");
|
|
587
591
|
}
|
|
588
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
636
|
-
if (
|
|
637
|
-
|
|
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.
|
|
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-
|
|
2387
|
+
//# sourceMappingURL=chunk-R6B2CV5Z.js.map
|