@gvnrdao/dh-sdk 0.0.300 → 0.0.301
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/browser/dist/browser.js +1 -1
- package/dist/deployments.js +14 -0
- package/dist/deployments.mjs +14 -0
- package/dist/index.js +416 -601
- package/dist/index.mjs +325 -510
- package/dist/utils/chunks/eip1559-broadcast.utils.d.ts +15 -24
- package/dist/utils/quantum-revert.utils.d.ts +9 -0
- package/dist/utils/quantum-submission.utils.d.ts +93 -0
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -422,6 +422,20 @@ var init_deployment_addresses = __esm({
|
|
|
422
422
|
upgradedAt: "2026-06-16T17:53:24.979Z",
|
|
423
423
|
upgradedBy: "0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f",
|
|
424
424
|
reason: "Initial PSM deploy / artifact sync"
|
|
425
|
+
},
|
|
426
|
+
CollateralManagerModule: {
|
|
427
|
+
previousImplementation: "0x1919860e528Cd2AbbD31a17858c986b8aCc8C185",
|
|
428
|
+
newImplementation: "0x55110B9dd6B2c9f812564e7a1ef42b3c76E1A3Bb",
|
|
429
|
+
upgradedAt: "2026-07-08T20:33:59Z",
|
|
430
|
+
upgradedBy: "AdminModule generic-op 0x740efe0cfe85044479cbd8ee3058aa244057d90703dd2b37044dd6787cbf3485 (3-of-5 ADMIN_ROLE Safes, 24h timelock; executed by 0xfb3B8cbeFB7D666A6Af34C53e189EdC31862a7be in tx 0x430c8e450f12d3d9359cde356ac5e2ef39661d7a89884b5674a596c1090f6cff)",
|
|
431
|
+
reason: "Validator gas fix (#420): BitcoinAddressValidator packed-table lookups; VERSION 1.3.0 -> 1.3.1"
|
|
432
|
+
},
|
|
433
|
+
BitcoinWithdrawalAddressRegistry: {
|
|
434
|
+
previousImplementation: "0x11731bFEC3068F2cc19D016381dfEA3B93013b1C",
|
|
435
|
+
newImplementation: "0x190c08300Ae650fb88ed8156445BBeb13bE9E8a3",
|
|
436
|
+
upgradedAt: "2026-07-08T20:33:59Z",
|
|
437
|
+
upgradedBy: "AdminModule generic-op 0x2603a486c0f34554b864cc1d909b325c7e105331da10ec0fd7e0b9373fa76207 (3-of-5 ADMIN_ROLE Safes, 24h timelock; executed by 0xfb3B8cbeFB7D666A6Af34C53e189EdC31862a7be in tx 0x430c8e450f12d3d9359cde356ac5e2ef39661d7a89884b5674a596c1090f6cff)",
|
|
438
|
+
reason: "Validator gas fix (#420): BitcoinAddressValidator packed-table lookups; VERSION 1.0.0 -> 1.0.1"
|
|
425
439
|
}
|
|
426
440
|
},
|
|
427
441
|
latestEnv: {
|
|
@@ -1196,17 +1210,17 @@ var require_pkg_src = __commonJS({
|
|
|
1196
1210
|
}
|
|
1197
1211
|
},
|
|
1198
1212
|
btcTransactionSigner: {
|
|
1199
|
-
cid: "
|
|
1213
|
+
cid: "QmcPG9C5Yx9JGrBKCfSVWbKuiRXn8XFwb91yNxQqY4VSJD",
|
|
1200
1214
|
authorizedCidHex: cidToHex(
|
|
1201
|
-
"
|
|
1215
|
+
"QmcPG9C5Yx9JGrBKCfSVWbKuiRXn8XFwb91yNxQqY4VSJD"
|
|
1202
1216
|
),
|
|
1203
1217
|
name: "Btc Transaction Signer",
|
|
1204
1218
|
description: "Production Btc Transaction Signer",
|
|
1205
|
-
version: "1.0.
|
|
1219
|
+
version: "1.0.1",
|
|
1206
1220
|
deployed: true,
|
|
1207
|
-
deployedAt:
|
|
1208
|
-
size:
|
|
1209
|
-
hash: "
|
|
1221
|
+
deployedAt: 1783451891948,
|
|
1222
|
+
size: 43688,
|
|
1223
|
+
hash: "1ea0f0ac66cc68fc9b098dabb3c5e3ba96c25f13b133b95a06eac477028fdb1a"
|
|
1210
1224
|
},
|
|
1211
1225
|
ucdMintValidator: {
|
|
1212
1226
|
cid: "QmPir8F8jmJ4ssQpEC3xFxkEnZxMHcgS6VxBQE1jkTLj5K",
|
|
@@ -2146,7 +2160,7 @@ ${errorReport}`);
|
|
|
2146
2160
|
}
|
|
2147
2161
|
init_debug_logger();
|
|
2148
2162
|
init_session_signature_cache();
|
|
2149
|
-
var
|
|
2163
|
+
var import_ethers16 = __require("ethers");
|
|
2150
2164
|
var EXPIRED_LOAN_MIN_LIQUIDATION_THRESHOLD_BPS = 11e3;
|
|
2151
2165
|
var GRACE_PERIOD_DAYS = 30;
|
|
2152
2166
|
var SATOSHIS_PER_BITCOIN = 100000000n;
|
|
@@ -4381,12 +4395,12 @@ ${auth.clientId}`;
|
|
|
4381
4395
|
}
|
|
4382
4396
|
async function executeVaultSnapshot(params) {
|
|
4383
4397
|
global.ethers = {
|
|
4384
|
-
...
|
|
4398
|
+
...import_ethers16.ethers,
|
|
4385
4399
|
providers: {
|
|
4386
|
-
StaticJsonRpcProvider:
|
|
4400
|
+
StaticJsonRpcProvider: import_ethers16.ethers.JsonRpcProvider
|
|
4387
4401
|
},
|
|
4388
|
-
Contract:
|
|
4389
|
-
utils:
|
|
4402
|
+
Contract: import_ethers16.ethers.Contract,
|
|
4403
|
+
utils: import_ethers16.ethers
|
|
4390
4404
|
// v6 moved utils to top level
|
|
4391
4405
|
};
|
|
4392
4406
|
global.Lit = {
|
|
@@ -4837,7 +4851,7 @@ var init_network_configs = __esm({
|
|
|
4837
4851
|
});
|
|
4838
4852
|
|
|
4839
4853
|
// src/modules/diamond-hands-sdk.ts
|
|
4840
|
-
import { Contract as Contract6, Interface as Interface4, JsonRpcProvider, AbiCoder, keccak256 as keccak2565, solidityPackedKeccak256 as solidityPackedKeccak2564, toUtf8Bytes as toUtf8Bytes5, zeroPadValue as zeroPadValue4, toBeHex as toBeHex2, parseEther, formatEther, formatUnits, computeAddress, Signature, ZeroHash, ZeroAddress as ZeroAddress3, MaxUint256 } from "ethers";
|
|
4854
|
+
import { Contract as Contract6, Interface as Interface4, JsonRpcProvider, AbiCoder as AbiCoder2, keccak256 as keccak2565, solidityPackedKeccak256 as solidityPackedKeccak2564, toUtf8Bytes as toUtf8Bytes5, zeroPadValue as zeroPadValue4, toBeHex as toBeHex2, parseEther, formatEther, formatUnits, computeAddress, Signature, ZeroHash, ZeroAddress as ZeroAddress3, MaxUint256 } from "ethers";
|
|
4841
4855
|
|
|
4842
4856
|
// src/types/result.ts
|
|
4843
4857
|
function success(value) {
|
|
@@ -5221,22 +5235,12 @@ var SDKError = class _SDKError extends Error {
|
|
|
5221
5235
|
|
|
5222
5236
|
// src/utils/chunks/eip1559-broadcast.utils.ts
|
|
5223
5237
|
import { parseUnits } from "ethers";
|
|
5224
|
-
var MINT_UCD_GAS_CEILING = BigInt(
|
|
5238
|
+
var MINT_UCD_GAS_CEILING = BigInt(13e5);
|
|
5225
5239
|
var WITHDRAW_BTC_GAS_CEILING = BigInt(3e6);
|
|
5226
5240
|
var MAKE_PAYMENT_GAS_CEILING = BigInt(1e6);
|
|
5227
5241
|
var EXTEND_POSITION_GAS_CEILING = BigInt(1e6);
|
|
5228
5242
|
var LIQUIDATION_COMMIT_GAS_CEILING = BigInt(1e6);
|
|
5229
5243
|
var LIQUIDATION_REVEAL_GAS_CEILING = BigInt(2e6);
|
|
5230
|
-
var MINT_UCD_ESTIMATE_MARGIN_BPS = 2500;
|
|
5231
|
-
async function estimateContractCallGasWithMargin(provider, from, to, data, marginBps, ceiling) {
|
|
5232
|
-
try {
|
|
5233
|
-
const estimated = await provider.estimateGas({ from, to, data });
|
|
5234
|
-
const withMargin = estimated * BigInt(1e4 + marginBps) / 10000n;
|
|
5235
|
-
return withMargin > ceiling ? ceiling : withMargin;
|
|
5236
|
-
} catch {
|
|
5237
|
-
return null;
|
|
5238
|
-
}
|
|
5239
|
-
}
|
|
5240
5244
|
async function resolveEip1559FeeFields(provider) {
|
|
5241
5245
|
const feeData = await provider.getFeeData();
|
|
5242
5246
|
let maxFeePerGas = feeData.maxFeePerGas ?? void 0;
|
|
@@ -5840,7 +5844,10 @@ var ServerSession = class {
|
|
|
5840
5844
|
};
|
|
5841
5845
|
|
|
5842
5846
|
// src/utils/quantum-revert.utils.ts
|
|
5847
|
+
import { AbiCoder } from "ethers";
|
|
5843
5848
|
var DEAD_ZONE_VIOLATION_SELECTOR = "0xbe4b82c1";
|
|
5849
|
+
var ERROR_STRING_SELECTOR = "0x08c379a0";
|
|
5850
|
+
var PANIC_SELECTOR = "0x4e487b71";
|
|
5844
5851
|
var QUANTUM_REVERT_NAMES = {
|
|
5845
5852
|
"0xbe4b82c1": "DeadZoneViolation()",
|
|
5846
5853
|
"0x137f3b70": "InDeadZone()",
|
|
@@ -5864,10 +5871,94 @@ function decodeQuantumRevert(e) {
|
|
|
5864
5871
|
e?.error?.data?.data ?? e?.error?.data ?? e?.error?.error?.data;
|
|
5865
5872
|
const data = typeof raw === "string" && raw.startsWith("0x") ? raw : null;
|
|
5866
5873
|
const selector = data && data.length >= 10 ? data.slice(0, 10) : null;
|
|
5867
|
-
|
|
5874
|
+
let name = selector ? QUANTUM_REVERT_NAMES[selector] ?? null : null;
|
|
5875
|
+
if (!name && selector && data) {
|
|
5876
|
+
try {
|
|
5877
|
+
if (selector === ERROR_STRING_SELECTOR) {
|
|
5878
|
+
const [message] = AbiCoder.defaultAbiCoder().decode(
|
|
5879
|
+
["string"],
|
|
5880
|
+
"0x" + data.slice(10)
|
|
5881
|
+
);
|
|
5882
|
+
name = `Error("${message}")`;
|
|
5883
|
+
} else if (selector === PANIC_SELECTOR) {
|
|
5884
|
+
const [code] = AbiCoder.defaultAbiCoder().decode(
|
|
5885
|
+
["uint256"],
|
|
5886
|
+
"0x" + data.slice(10)
|
|
5887
|
+
);
|
|
5888
|
+
name = `Panic(0x${code.toString(16)})`;
|
|
5889
|
+
}
|
|
5890
|
+
} catch {
|
|
5891
|
+
}
|
|
5892
|
+
}
|
|
5868
5893
|
return { data, selector, name };
|
|
5869
5894
|
}
|
|
5870
5895
|
|
|
5896
|
+
// src/utils/quantum-submission.utils.ts
|
|
5897
|
+
var MAX_DEADZONE_RESIMULATIONS = 3;
|
|
5898
|
+
var QuantumRevertError = class extends Error {
|
|
5899
|
+
constructor(errorName, selector, data, cause) {
|
|
5900
|
+
super(
|
|
5901
|
+
`Pre-send simulation reverted: ${errorName ?? selector ?? "unknown"}`
|
|
5902
|
+
);
|
|
5903
|
+
this.errorName = errorName;
|
|
5904
|
+
this.selector = selector;
|
|
5905
|
+
this.data = data;
|
|
5906
|
+
this.cause = cause;
|
|
5907
|
+
this.name = "QuantumRevertError";
|
|
5908
|
+
}
|
|
5909
|
+
};
|
|
5910
|
+
async function assertSafeQuantumSubmission(opts) {
|
|
5911
|
+
const { provider, to, from, data, quantumTimestamp } = opts;
|
|
5912
|
+
const maxResimulations = opts.maxResimulations ?? MAX_DEADZONE_RESIMULATIONS;
|
|
5913
|
+
const now = opts.now ?? (() => Math.floor(Date.now() / 1e3));
|
|
5914
|
+
const onDebug = opts.onDebug ?? (() => {
|
|
5915
|
+
});
|
|
5916
|
+
const gateOpts = {
|
|
5917
|
+
now,
|
|
5918
|
+
...opts.sleep ? { sleep: opts.sleep } : {}
|
|
5919
|
+
};
|
|
5920
|
+
await awaitSafeSubmissionWindow(quantumTimestamp, gateOpts);
|
|
5921
|
+
for (let sim = 1; ; sim++) {
|
|
5922
|
+
try {
|
|
5923
|
+
await provider.call({ to, from, data });
|
|
5924
|
+
break;
|
|
5925
|
+
} catch (simError) {
|
|
5926
|
+
const decoded = decodeQuantumRevert(simError);
|
|
5927
|
+
if (decoded.selector === DEAD_ZONE_VIOLATION_SELECTOR && sim <= maxResimulations) {
|
|
5928
|
+
const sigQuantum = Math.floor(quantumTimestamp / QUANTUM_WINDOW_SECONDS) * QUANTUM_WINDOW_SECONDS;
|
|
5929
|
+
const realCurrentQuantum = Math.floor(now() / QUANTUM_WINDOW_SECONDS) * QUANTUM_WINDOW_SECONDS;
|
|
5930
|
+
if (sigQuantum === realCurrentQuantum) {
|
|
5931
|
+
onDebug(
|
|
5932
|
+
"\u21AA\uFE0F Simulated DeadZoneViolation is a stale-latest-block artifact (signature is the current quantum) \u2014 proceeding to broadcast"
|
|
5933
|
+
);
|
|
5934
|
+
break;
|
|
5935
|
+
}
|
|
5936
|
+
const gate = await awaitSafeSubmissionWindow(quantumTimestamp, gateOpts);
|
|
5937
|
+
if (gate.waited) {
|
|
5938
|
+
onDebug(
|
|
5939
|
+
`\u{1F501} Re-simulating after crossing the quantum boundary (attempt ${sim}/${maxResimulations})`
|
|
5940
|
+
);
|
|
5941
|
+
continue;
|
|
5942
|
+
}
|
|
5943
|
+
}
|
|
5944
|
+
if (!decoded.data) {
|
|
5945
|
+
const label = simError instanceof Error ? simError.message : String(simError);
|
|
5946
|
+
onDebug(
|
|
5947
|
+
`\u26A0\uFE0F Pre-send simulation failed without revert data (${label}) \u2014 proceeding to broadcast`
|
|
5948
|
+
);
|
|
5949
|
+
break;
|
|
5950
|
+
}
|
|
5951
|
+
throw new QuantumRevertError(
|
|
5952
|
+
decoded.name,
|
|
5953
|
+
decoded.selector,
|
|
5954
|
+
decoded.data,
|
|
5955
|
+
simError
|
|
5956
|
+
);
|
|
5957
|
+
}
|
|
5958
|
+
}
|
|
5959
|
+
await awaitSafeSubmissionWindow(quantumTimestamp, gateOpts);
|
|
5960
|
+
}
|
|
5961
|
+
|
|
5871
5962
|
// src/utils/btc-withdrawal-message.ts
|
|
5872
5963
|
import { keccak256 as keccak2563, toUtf8Bytes as toUtf8Bytes3, solidityPackedKeccak256 as solidityPackedKeccak2563, getBytes as getBytes3, zeroPadValue } from "ethers";
|
|
5873
5964
|
var QUANTUM_SECONDS = 60;
|
|
@@ -16223,8 +16314,8 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
16223
16314
|
throw new Error(`Position not found: ${request.positionId}`);
|
|
16224
16315
|
}
|
|
16225
16316
|
const currentDebt = position.ucdDebt.toString();
|
|
16226
|
-
const ucdDebtHash = keccak2565(
|
|
16227
|
-
const contractHash = keccak2565(
|
|
16317
|
+
const ucdDebtHash = keccak2565(AbiCoder2.defaultAbiCoder().encode(["uint256"], [currentDebt]));
|
|
16318
|
+
const contractHash = keccak2565(AbiCoder2.defaultAbiCoder().encode(
|
|
16228
16319
|
["address", "address", "address", "address"],
|
|
16229
16320
|
[
|
|
16230
16321
|
positionManagerAddress,
|
|
@@ -16285,214 +16376,6 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
16285
16376
|
{}
|
|
16286
16377
|
);
|
|
16287
16378
|
}
|
|
16288
|
-
if (this.config.debug) {
|
|
16289
|
-
log.info("\u{1F50D} PREFLIGHT: Attempting diagnostic gas estimation...", {});
|
|
16290
|
-
}
|
|
16291
|
-
try {
|
|
16292
|
-
const iface = new Interface4(positionManagerAbi);
|
|
16293
|
-
const signatureHex = finalSignature.startsWith("0x") ? finalSignature : "0x" + finalSignature;
|
|
16294
|
-
if (this.config.debug) {
|
|
16295
|
-
log.info("\u{1F50D} DEBUG: Signature details:", {
|
|
16296
|
-
finalSignature: finalSignature ? `${finalSignature.substring(0, 20)}... (length: ${finalSignature.length})` : "UNDEFINED/EMPTY",
|
|
16297
|
-
signatureHex: signatureHex ? `${signatureHex.substring(0, 22)}... (length: ${signatureHex.length})` : "UNDEFINED/EMPTY"
|
|
16298
|
-
});
|
|
16299
|
-
}
|
|
16300
|
-
const calldata = iface.encodeFunctionData("mintUCD", [
|
|
16301
|
-
positionIdBytes32,
|
|
16302
|
-
validationResponse.mintAmount,
|
|
16303
|
-
validationResponse.mintFee,
|
|
16304
|
-
validationResponse.newDebt,
|
|
16305
|
-
validationResponse.newCollateral,
|
|
16306
|
-
validationResponse.btcPrice,
|
|
16307
|
-
validationResponse.authorizedSpendsHash,
|
|
16308
|
-
ucdDebtHash,
|
|
16309
|
-
contractHash,
|
|
16310
|
-
validationResponse.timestamp,
|
|
16311
|
-
signatureHex
|
|
16312
|
-
]);
|
|
16313
|
-
if (this.config.debug) {
|
|
16314
|
-
log.info("\u{1F50D} DEBUG: Encoded calldata:", {
|
|
16315
|
-
length: calldata.length,
|
|
16316
|
-
signaturePortion: calldata.substring(650, 670)
|
|
16317
|
-
});
|
|
16318
|
-
}
|
|
16319
|
-
const provider = this.getSignerOrThrow().provider;
|
|
16320
|
-
if (!provider) {
|
|
16321
|
-
throw new Error("Provider not available");
|
|
16322
|
-
}
|
|
16323
|
-
const signerAddress = await this.getSignerOrThrow().getAddress();
|
|
16324
|
-
if (this.config.debug) {
|
|
16325
|
-
log.info(" Executing diagnostic eth_call...", {});
|
|
16326
|
-
}
|
|
16327
|
-
await provider.call({
|
|
16328
|
-
to: positionManagerAddress,
|
|
16329
|
-
from: signerAddress,
|
|
16330
|
-
data: calldata
|
|
16331
|
-
});
|
|
16332
|
-
if (this.config.debug) {
|
|
16333
|
-
log.info(" \u2705 Diagnostic eth_call succeeded!", {});
|
|
16334
|
-
}
|
|
16335
|
-
} catch (preflightError) {
|
|
16336
|
-
if (this.config.debug) {
|
|
16337
|
-
log.error(
|
|
16338
|
-
"\u274C PREFLIGHT CHECK FAILED - Diagnostic eth_call reverted",
|
|
16339
|
-
{}
|
|
16340
|
-
);
|
|
16341
|
-
log.error(` Error message: ${preflightError?.message}`, {});
|
|
16342
|
-
log.error(` Error code: ${preflightError?.code}`, {});
|
|
16343
|
-
log.error(` Error data: ${preflightError?.data || "none"}`, {});
|
|
16344
|
-
log.error(` Error reason: ${preflightError?.reason || "none"}`, {});
|
|
16345
|
-
log.error(
|
|
16346
|
-
` Error.error: ${JSON.stringify(preflightError?.error || {})}`,
|
|
16347
|
-
{}
|
|
16348
|
-
);
|
|
16349
|
-
}
|
|
16350
|
-
let errorData = preflightError?.data || preflightError?.info?.error?.data || preflightError?.error?.data?.data || preflightError?.error?.data || preflightError?.error?.error?.data;
|
|
16351
|
-
const errorMessage = preflightError?.reason || preflightError?.error?.reason || preflightError?.error?.error?.reason || preflightError?.message || "Unknown error";
|
|
16352
|
-
let requireMessage;
|
|
16353
|
-
if (errorData && typeof errorData === "string" && errorData.startsWith("0x") && errorData.length > 138) {
|
|
16354
|
-
try {
|
|
16355
|
-
const errorSelector = errorData.slice(0, 10);
|
|
16356
|
-
if (errorSelector === "0x08c379a0") {
|
|
16357
|
-
const iface = new Interface4([
|
|
16358
|
-
"function Error(string)"
|
|
16359
|
-
]);
|
|
16360
|
-
const decoded = iface.decodeFunctionData("Error", errorData);
|
|
16361
|
-
requireMessage = decoded[0];
|
|
16362
|
-
}
|
|
16363
|
-
} catch (e) {
|
|
16364
|
-
}
|
|
16365
|
-
}
|
|
16366
|
-
const isDeadZonePreflightArtifact = decodeQuantumRevert(preflightError).selector === DEAD_ZONE_VIOLATION_SELECTOR;
|
|
16367
|
-
if (isDeadZonePreflightArtifact) {
|
|
16368
|
-
const nowSec = Math.floor(Date.now() / 1e3);
|
|
16369
|
-
const sigQuantum2 = Math.floor(Number(validationResponse.timestamp) / 60) * 60;
|
|
16370
|
-
const realCurrentQuantum = Math.floor(nowSec / 60) * 60;
|
|
16371
|
-
if (sigQuantum2 === realCurrentQuantum) {
|
|
16372
|
-
if (this.config.debug) {
|
|
16373
|
-
log.info(
|
|
16374
|
-
"\u21AA\uFE0F Preflight DeadZoneViolation is a stale-latest-block artifact (signature is the current quantum) \u2014 proceeding to broadcast",
|
|
16375
|
-
{}
|
|
16376
|
-
);
|
|
16377
|
-
}
|
|
16378
|
-
} else {
|
|
16379
|
-
if (this.config.debug) {
|
|
16380
|
-
log.info(
|
|
16381
|
-
"\u{1F501} Preflight DeadZoneViolation near the boundary \u2014 deferring across it, then proceeding",
|
|
16382
|
-
{}
|
|
16383
|
-
);
|
|
16384
|
-
}
|
|
16385
|
-
await awaitSafeSubmissionWindow(
|
|
16386
|
-
Number(validationResponse.timestamp)
|
|
16387
|
-
);
|
|
16388
|
-
}
|
|
16389
|
-
}
|
|
16390
|
-
if (requireMessage && !isDeadZonePreflightArtifact) {
|
|
16391
|
-
throw new Error(
|
|
16392
|
-
`Preflight check failed - mintUCD would revert:
|
|
16393
|
-
${requireMessage}
|
|
16394
|
-
Context: Quantum timestamp=${validationResponse.timestamp}, Position=${request.positionId}`
|
|
16395
|
-
);
|
|
16396
|
-
}
|
|
16397
|
-
if (errorData && typeof errorData === "string" && errorData.startsWith("0x") && errorData.length > 10) {
|
|
16398
|
-
const selector = errorData.slice(0, 10);
|
|
16399
|
-
const knownErrors = {
|
|
16400
|
-
"0x8baa579f": "InvalidSignature()",
|
|
16401
|
-
"0xd92e233d": "ValidationFailed()",
|
|
16402
|
-
"0x3ee5aeb5": "OperationNotAuthorized()",
|
|
16403
|
-
"0x70f4b32a": "UnauthorizedSigner()",
|
|
16404
|
-
"0x48f5c3ed": "Unauthorized()",
|
|
16405
|
-
"0x36bfdeea": "StateHashMismatch()",
|
|
16406
|
-
"0x131d9a21": "QuantumExpired()",
|
|
16407
|
-
"0x52ce5d58": "QuantumAlreadyUsed()",
|
|
16408
|
-
"0x137f3b70": "InDeadZone()",
|
|
16409
|
-
"0xbe4b82c1": "DeadZoneViolation()",
|
|
16410
|
-
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
16411
|
-
"0x62278171": "InvalidValidatorSignature()",
|
|
16412
|
-
"0xb9d419a7": "DebtUpdateVerificationFailed()",
|
|
16413
|
-
"0xc7e20553": "DebtUpdateVerificationFailedDetailed(bytes32,uint256,uint256,uint256,uint256,uint256)",
|
|
16414
|
-
"0x0cfd2a97": "MintVerificationMismatch(uint256,uint256)",
|
|
16415
|
-
"0x07637bd8": "MintFailed()"
|
|
16416
|
-
};
|
|
16417
|
-
const errorName = knownErrors[selector] || `Unknown error ${selector}`;
|
|
16418
|
-
const mintDebtDiagnostics = selector === "0xb9d419a7" || selector === "0xc7e20553" || selector === "0x0cfd2a97" || selector === "0x07637bd8" ? `
|
|
16419
|
-
|
|
16420
|
-
Mint/debt diagnostics (LoanOperationsManager mint path \u2192 increaseDebtFromMint):
|
|
16421
|
-
positionId: ${request.positionId}
|
|
16422
|
-
on-chain ucdDebt before tx: ${currentDebt}
|
|
16423
|
-
Lit newDebt: ${validationResponse.newDebt}
|
|
16424
|
-
Lit mintAmount: ${validationResponse.mintAmount}
|
|
16425
|
-
Lit mintFee: ${validationResponse.mintFee}
|
|
16426
|
-
Call path: mintUCD -> mintUCDWithAuthorization -> increaseDebtFromMint -> finalizeMintDebtIncrease
|
|
16427
|
-
Contract expects UCD supply increase to match mintAmount+mintFee and debt update to newDebt.
|
|
16428
|
-
` : "";
|
|
16429
|
-
let quantumContext = "";
|
|
16430
|
-
if (selector === "0x131d9a21" || selector === "0x52ce5d58" || selector === "0x137f3b70" || selector === "0xbe4b82c1" || selector === "0x3e76a3c9") {
|
|
16431
|
-
const currentTime2 = Math.floor(Date.now() / 1e3);
|
|
16432
|
-
const currentQuantum = Math.floor(currentTime2 / 60) * 60;
|
|
16433
|
-
const sigQuantum2 = Math.floor(validationResponse.timestamp / 60) * 60;
|
|
16434
|
-
const timeDiff = currentTime2 - validationResponse.timestamp;
|
|
16435
|
-
quantumContext = `
|
|
16436
|
-
|
|
16437
|
-
Quantum Timing Analysis:
|
|
16438
|
-
Signature created: ${validationResponse.timestamp} (${new Date(
|
|
16439
|
-
validationResponse.timestamp * 1e3
|
|
16440
|
-
).toISOString()})
|
|
16441
|
-
Current time: ${currentTime2} (${new Date(
|
|
16442
|
-
currentTime2 * 1e3
|
|
16443
|
-
).toISOString()})
|
|
16444
|
-
Time elapsed: ${timeDiff} seconds
|
|
16445
|
-
Signature quantum: ${sigQuantum2}
|
|
16446
|
-
Current quantum: ${currentQuantum}
|
|
16447
|
-
Quantum window: 60 seconds
|
|
16448
|
-
Status: ${sigQuantum2 < currentQuantum ? "\u274C EXPIRED - Signature created in older quantum window" : "\u2705 VALID"}
|
|
16449
|
-
Note: QuantumOutsideWindow can also occur if the tx is mined outside the accepted past/current/next quantum set.`;
|
|
16450
|
-
}
|
|
16451
|
-
if (!isDeadZonePreflightArtifact) {
|
|
16452
|
-
throw new Error(
|
|
16453
|
-
`Preflight check failed - mintUCD would revert:
|
|
16454
|
-
Error: ${errorName}
|
|
16455
|
-
Selector: ${selector}
|
|
16456
|
-
Message: ${errorMessage}
|
|
16457
|
-
Data: ${errorData}${quantumContext}${mintDebtDiagnostics}`
|
|
16458
|
-
);
|
|
16459
|
-
}
|
|
16460
|
-
} else {
|
|
16461
|
-
const currentTime2 = Math.floor(Date.now() / 1e3);
|
|
16462
|
-
const timeSinceSig = currentTime2 - validationResponse.timestamp;
|
|
16463
|
-
const currentQuantum = Math.floor(currentTime2 / 60) * 60;
|
|
16464
|
-
const sigQuantum2 = Math.floor(validationResponse.timestamp / 60) * 60;
|
|
16465
|
-
throw new Error(
|
|
16466
|
-
`Preflight check failed - mintUCD would revert:
|
|
16467
|
-
${errorMessage}
|
|
16468
|
-
|
|
16469
|
-
Error Details:
|
|
16470
|
-
Error data: ${errorData || "0x (empty - no custom error)"}
|
|
16471
|
-
Error code: ${preflightError?.code || "none"}
|
|
16472
|
-
|
|
16473
|
-
Quantum Timing Analysis:
|
|
16474
|
-
Signature created: ${validationResponse.timestamp} (${new Date(
|
|
16475
|
-
validationResponse.timestamp * 1e3
|
|
16476
|
-
).toISOString()})
|
|
16477
|
-
Current time: ${currentTime2} (${new Date(
|
|
16478
|
-
currentTime2 * 1e3
|
|
16479
|
-
).toISOString()})
|
|
16480
|
-
Time elapsed: ${timeSinceSig} seconds
|
|
16481
|
-
Signature quantum: ${sigQuantum2}
|
|
16482
|
-
Current quantum: ${currentQuantum}
|
|
16483
|
-
Status: ${sigQuantum2 < currentQuantum ? "\u274C EXPIRED - Signature too old" : "\u2705 VALID"}
|
|
16484
|
-
|
|
16485
|
-
Possible Causes (when error data is empty):
|
|
16486
|
-
\u2022 Quantum signature expired (current=${currentQuantum}, signature=${sigQuantum2})
|
|
16487
|
-
\u2022 Contract paused or circuit breaker active
|
|
16488
|
-
\u2022 Position state changed since LIT Action signed
|
|
16489
|
-
\u2022 Authorization registry validation failed
|
|
16490
|
-
\u2022 RPC provider not returning detailed revert data
|
|
16491
|
-
|
|
16492
|
-
Position: ${request.positionId}`
|
|
16493
|
-
);
|
|
16494
|
-
}
|
|
16495
|
-
}
|
|
16496
16379
|
try {
|
|
16497
16380
|
const coreAddress = this.getContractAddressesOrThrow().positionManagerCore;
|
|
16498
16381
|
if (!coreAddress) {
|
|
@@ -16510,7 +16393,7 @@ Position: ${request.positionId}`
|
|
|
16510
16393
|
positionIdBytes32
|
|
16511
16394
|
);
|
|
16512
16395
|
const currentDebtHash = keccak2565(
|
|
16513
|
-
|
|
16396
|
+
AbiCoder2.defaultAbiCoder().encode(
|
|
16514
16397
|
["uint256"],
|
|
16515
16398
|
[currentPosition.ucdDebt]
|
|
16516
16399
|
)
|
|
@@ -16688,146 +16571,121 @@ Position: ${request.positionId}`
|
|
|
16688
16571
|
signatureHexMint
|
|
16689
16572
|
]);
|
|
16690
16573
|
const fromAddress = await signer.getAddress();
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
positionManagerAddress,
|
|
16695
|
-
mintCalldata,
|
|
16696
|
-
MINT_UCD_ESTIMATE_MARGIN_BPS,
|
|
16697
|
-
MINT_UCD_GAS_CEILING
|
|
16698
|
-
);
|
|
16699
|
-
let tx;
|
|
16700
|
-
if (estimatedGas !== null) {
|
|
16701
|
-
if (this.config.debug) {
|
|
16702
|
-
log.info(
|
|
16703
|
-
`\u{1F4DD} Broadcasting mintUCD (gasLimit=${estimatedGas.toString()})`,
|
|
16704
|
-
{}
|
|
16705
|
-
);
|
|
16706
|
-
}
|
|
16707
|
-
await awaitSafeSubmissionWindow(Number(validationResponse.timestamp));
|
|
16708
|
-
tx = await sendEip1559Transaction({
|
|
16709
|
-
signer,
|
|
16574
|
+
try {
|
|
16575
|
+
await assertSafeQuantumSubmission({
|
|
16576
|
+
provider: signerProvider,
|
|
16710
16577
|
to: positionManagerAddress,
|
|
16578
|
+
from: fromAddress,
|
|
16711
16579
|
data: mintCalldata,
|
|
16712
|
-
|
|
16580
|
+
quantumTimestamp: Number(validationResponse.timestamp),
|
|
16581
|
+
onDebug: this.config.debug ? (msg) => log.info(msg, {}) : void 0
|
|
16713
16582
|
});
|
|
16714
|
-
}
|
|
16715
|
-
if (
|
|
16716
|
-
|
|
16717
|
-
|
|
16718
|
-
|
|
16719
|
-
|
|
16720
|
-
|
|
16721
|
-
|
|
16722
|
-
|
|
16723
|
-
|
|
16724
|
-
|
|
16725
|
-
|
|
16726
|
-
|
|
16727
|
-
|
|
16728
|
-
|
|
16729
|
-
|
|
16730
|
-
|
|
16731
|
-
|
|
16732
|
-
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
16738
|
-
|
|
16739
|
-
|
|
16740
|
-
|
|
16741
|
-
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
|
|
16748
|
-
|
|
16749
|
-
|
|
16750
|
-
"0x70f4b32a": "UnauthorizedSigner()",
|
|
16751
|
-
"0x48f5c3ed": "Unauthorized()",
|
|
16752
|
-
"0x36bfdeea": "StateHashMismatch()",
|
|
16753
|
-
"0x131d9a21": "QuantumExpired()",
|
|
16754
|
-
"0x52ce5d58": "QuantumAlreadyUsed()",
|
|
16755
|
-
"0x137f3b70": "InDeadZone()",
|
|
16756
|
-
"0xbe4b82c1": "DeadZoneViolation()",
|
|
16757
|
-
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
16758
|
-
"0x62278171": "InvalidValidatorSignature()",
|
|
16759
|
-
"0xb9d419a7": "DebtUpdateVerificationFailed()",
|
|
16760
|
-
"0xc7e20553": "DebtUpdateVerificationFailedDetailed(bytes32,uint256,uint256,uint256,uint256,uint256)",
|
|
16761
|
-
"0x0cfd2a97": "MintVerificationMismatch(uint256,uint256)",
|
|
16762
|
-
"0x07637bd8": "MintFailed()"
|
|
16763
|
-
};
|
|
16764
|
-
const errorName = knownErrors[selector] || `Unknown error ${selector}`;
|
|
16765
|
-
throw new Error(
|
|
16766
|
-
`mintUCD reverted: ${errorName}
|
|
16767
|
-
Error selector: ${selector}
|
|
16768
|
-
Error data: ${errorData}
|
|
16769
|
-
Call path: mintUCD -> mintUCDWithAuthorization -> increaseDebtFromMint -> finalizeMintDebtIncrease
|
|
16770
|
-
Message: ${errorMessage}`
|
|
16771
|
-
);
|
|
16772
|
-
}
|
|
16773
|
-
if (errorData === "0x" || !errorData) {
|
|
16774
|
-
const viewsAddress = this.config.contractAddresses?.positionManagerViews;
|
|
16775
|
-
if (viewsAddress) {
|
|
16776
|
-
try {
|
|
16777
|
-
const views = new Contract6(
|
|
16778
|
-
viewsAddress,
|
|
16779
|
-
[
|
|
16780
|
-
"function diagnoseMintUCD(bytes32,uint256,uint256,uint256,uint256,uint256,bytes32,bytes32,bytes32,uint256,bytes) view returns (string)"
|
|
16781
|
-
],
|
|
16782
|
-
signerProvider
|
|
16783
|
-
);
|
|
16784
|
-
const diagnosis = await views["diagnoseMintUCD"](
|
|
16785
|
-
request.positionId,
|
|
16786
|
-
validationResponse.mintAmount,
|
|
16787
|
-
validationResponse.mintFee,
|
|
16788
|
-
validationResponse.newDebt,
|
|
16789
|
-
validationResponse.newCollateral,
|
|
16790
|
-
validationResponse.btcPrice,
|
|
16791
|
-
validationResponse.authorizedSpendsHash,
|
|
16792
|
-
ucdDebtHash,
|
|
16793
|
-
contractHash,
|
|
16794
|
-
validationResponse.timestamp,
|
|
16795
|
-
signatureHexMint
|
|
16796
|
-
);
|
|
16797
|
-
throw new Error(
|
|
16798
|
-
`mintUCD reverted with empty data; diagnosis: ${diagnosis}`
|
|
16583
|
+
} catch (simError) {
|
|
16584
|
+
if (!(simError instanceof QuantumRevertError)) {
|
|
16585
|
+
throw simError;
|
|
16586
|
+
}
|
|
16587
|
+
const simCause = simError.cause;
|
|
16588
|
+
const causeMessage = simCause?.reason ?? simCause?.shortMessage ?? (simCause instanceof Error ? simCause.message : String(simCause));
|
|
16589
|
+
if (!simError.data) {
|
|
16590
|
+
const viewsAddress = this.config.contractAddresses?.positionManagerViews;
|
|
16591
|
+
if (viewsAddress) {
|
|
16592
|
+
let diagnosis = null;
|
|
16593
|
+
try {
|
|
16594
|
+
const views = new Contract6(
|
|
16595
|
+
viewsAddress,
|
|
16596
|
+
[
|
|
16597
|
+
"function diagnoseMintUCD(bytes32,uint256,uint256,uint256,uint256,uint256,bytes32,bytes32,bytes32,uint256,bytes) view returns (string)"
|
|
16598
|
+
],
|
|
16599
|
+
signerProvider
|
|
16600
|
+
);
|
|
16601
|
+
diagnosis = await views["diagnoseMintUCD"](
|
|
16602
|
+
request.positionId,
|
|
16603
|
+
validationResponse.mintAmount,
|
|
16604
|
+
validationResponse.mintFee,
|
|
16605
|
+
validationResponse.newDebt,
|
|
16606
|
+
validationResponse.newCollateral,
|
|
16607
|
+
validationResponse.btcPrice,
|
|
16608
|
+
validationResponse.authorizedSpendsHash,
|
|
16609
|
+
ucdDebtHash,
|
|
16610
|
+
contractHash,
|
|
16611
|
+
validationResponse.timestamp,
|
|
16612
|
+
signatureHexMint
|
|
16613
|
+
);
|
|
16614
|
+
} catch (diagErr) {
|
|
16615
|
+
if (this.config.debug) {
|
|
16616
|
+
log.info(
|
|
16617
|
+
` diagnoseMintUCD unavailable or failed: ${diagErr?.message || diagErr}`,
|
|
16618
|
+
{}
|
|
16799
16619
|
);
|
|
16800
|
-
} catch (diagErr) {
|
|
16801
|
-
if (this.config.debug) {
|
|
16802
|
-
log.info(
|
|
16803
|
-
` diagnoseMintUCD unavailable or failed: ${diagErr?.message || diagErr}`,
|
|
16804
|
-
{}
|
|
16805
|
-
);
|
|
16806
|
-
}
|
|
16807
16620
|
}
|
|
16808
16621
|
}
|
|
16622
|
+
if (diagnosis !== null) {
|
|
16623
|
+
throw new Error(
|
|
16624
|
+
`mintUCD reverted with empty data; diagnosis: ${diagnosis}`
|
|
16625
|
+
);
|
|
16626
|
+
}
|
|
16809
16627
|
}
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
|
|
16813
|
-
Error data: ${errorData || "none"}`
|
|
16814
|
-
);
|
|
16815
|
-
}
|
|
16816
|
-
}
|
|
16817
|
-
if (this.config.debug) {
|
|
16818
|
-
log.info(
|
|
16819
|
-
"\u2705 Static call clear \u2014 broadcasting mintUCD with fixed gas ceiling",
|
|
16820
|
-
{}
|
|
16628
|
+
throw new Error(
|
|
16629
|
+
`mintUCD would revert (pre-send simulation): ${causeMessage}
|
|
16630
|
+
Error data: none`
|
|
16821
16631
|
);
|
|
16822
16632
|
}
|
|
16823
|
-
|
|
16824
|
-
|
|
16825
|
-
|
|
16826
|
-
|
|
16827
|
-
|
|
16828
|
-
|
|
16829
|
-
|
|
16633
|
+
const selector = simError.selector;
|
|
16634
|
+
const errorName = simError.errorName ?? (selector ? `Unknown error ${selector}` : "unknown");
|
|
16635
|
+
const mintDebtDiagnostics = selector === "0xb9d419a7" || // DebtUpdateVerificationFailed()
|
|
16636
|
+
selector === "0xc7e20553" || // DebtUpdateVerificationFailedDetailed(...)
|
|
16637
|
+
selector === "0x0cfd2a97" || // MintVerificationMismatch(uint256,uint256)
|
|
16638
|
+
selector === "0x07637bd8" ? `
|
|
16639
|
+
|
|
16640
|
+
Mint/debt diagnostics (LoanOperationsManager mint path \u2192 increaseDebtFromMint):
|
|
16641
|
+
positionId: ${request.positionId}
|
|
16642
|
+
on-chain ucdDebt before tx: ${currentDebt}
|
|
16643
|
+
Lit newDebt: ${validationResponse.newDebt}
|
|
16644
|
+
Lit mintAmount: ${validationResponse.mintAmount}
|
|
16645
|
+
Lit mintFee: ${validationResponse.mintFee}
|
|
16646
|
+
Call path: mintUCD -> mintUCDWithAuthorization -> increaseDebtFromMint -> finalizeMintDebtIncrease
|
|
16647
|
+
Contract expects UCD supply increase to match mintAmount+mintFee and debt update to newDebt.
|
|
16648
|
+
` : "";
|
|
16649
|
+
let quantumContext = "";
|
|
16650
|
+
if (selector === "0x131d9a21" || // QuantumExpired()
|
|
16651
|
+
selector === "0x52ce5d58" || // QuantumAlreadyUsed()
|
|
16652
|
+
selector === "0x137f3b70" || // InDeadZone()
|
|
16653
|
+
selector === "0xbe4b82c1" || // DeadZoneViolation()
|
|
16654
|
+
selector === "0x3e76a3c9") {
|
|
16655
|
+
const nowSecs = Math.floor(Date.now() / 1e3);
|
|
16656
|
+
const nowQuantum = Math.floor(nowSecs / 60) * 60;
|
|
16657
|
+
const signedQuantum = Math.floor(Number(validationResponse.timestamp) / 60) * 60;
|
|
16658
|
+
const timeDiff = nowSecs - Number(validationResponse.timestamp);
|
|
16659
|
+
quantumContext = `
|
|
16660
|
+
|
|
16661
|
+
Quantum Timing Analysis:
|
|
16662
|
+
Signature created: ${validationResponse.timestamp} (${new Date(
|
|
16663
|
+
Number(validationResponse.timestamp) * 1e3
|
|
16664
|
+
).toISOString()})
|
|
16665
|
+
Current time: ${nowSecs} (${new Date(
|
|
16666
|
+
nowSecs * 1e3
|
|
16667
|
+
).toISOString()})
|
|
16668
|
+
Time elapsed: ${timeDiff} seconds
|
|
16669
|
+
Signature quantum: ${signedQuantum}
|
|
16670
|
+
Current quantum: ${nowQuantum}
|
|
16671
|
+
Quantum window: 60 seconds
|
|
16672
|
+
Status: ${signedQuantum < nowQuantum ? "\u274C EXPIRED - Signature created in older quantum window" : "\u2705 VALID"}
|
|
16673
|
+
Note: QuantumOutsideWindow can also occur if the tx is mined outside the accepted past/current/next quantum set.`;
|
|
16674
|
+
}
|
|
16675
|
+
throw new Error(
|
|
16676
|
+
`mintUCD would revert (pre-send simulation): ${errorName}
|
|
16677
|
+
Error selector: ${selector}
|
|
16678
|
+
Error data: ${simError.data}
|
|
16679
|
+
Call path: mintUCD -> mintUCDWithAuthorization -> increaseDebtFromMint -> finalizeMintDebtIncrease
|
|
16680
|
+
Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
16681
|
+
);
|
|
16830
16682
|
}
|
|
16683
|
+
const tx = await sendEip1559Transaction({
|
|
16684
|
+
signer,
|
|
16685
|
+
to: positionManagerAddress,
|
|
16686
|
+
data: mintCalldata,
|
|
16687
|
+
gasLimit: MINT_UCD_GAS_CEILING
|
|
16688
|
+
});
|
|
16831
16689
|
const receipt = await signerProvider.waitForTransaction(
|
|
16832
16690
|
tx.hash,
|
|
16833
16691
|
1,
|
|
@@ -17991,26 +17849,43 @@ Error data: ${errorData || "none"}`
|
|
|
17991
17849
|
if (!signatureBytes.startsWith("0x")) {
|
|
17992
17850
|
signatureBytes = "0x" + signatureBytes;
|
|
17993
17851
|
}
|
|
17994
|
-
const
|
|
17995
|
-
|
|
17996
|
-
|
|
17997
|
-
|
|
17998
|
-
`Failed to get PositionManager: ${positionManagerResult.error.message}`
|
|
17999
|
-
);
|
|
18000
|
-
}
|
|
18001
|
-
const positionManager = positionManagerResult.value;
|
|
18002
|
-
await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
18003
|
-
const extendPositionFn = positionManager["extendPosition"];
|
|
18004
|
-
const tx = await extendPositionFn(
|
|
17852
|
+
const extendIface = new Interface4([
|
|
17853
|
+
"function extendPosition(bytes32 positionId, uint256 selectedTerm, uint256 quantumTimestamp, uint256 btcPrice, uint256 availableBTCBalance, uint256 proRataRenewalFee, bytes calldata extensionValidatorSignature) external returns (bool)"
|
|
17854
|
+
]);
|
|
17855
|
+
const extendCalldata = extendIface.encodeFunctionData("extendPosition", [
|
|
18005
17856
|
positionIdBytes32,
|
|
18006
17857
|
BigInt(_selectedTerm),
|
|
18007
17858
|
quantumTimestamp,
|
|
18008
17859
|
btcPrice,
|
|
18009
17860
|
availableBTCBalance,
|
|
18010
17861
|
proRataRenewalFee,
|
|
18011
|
-
signatureBytes
|
|
18012
|
-
|
|
18013
|
-
);
|
|
17862
|
+
signatureBytes
|
|
17863
|
+
]);
|
|
17864
|
+
const extendTo = this.getContractAddressesOrThrow().positionManager;
|
|
17865
|
+
const extendSigner = this.getSignerOrThrow();
|
|
17866
|
+
try {
|
|
17867
|
+
await assertSafeQuantumSubmission({
|
|
17868
|
+
provider: this.getProviderOrThrow(),
|
|
17869
|
+
to: extendTo,
|
|
17870
|
+
from: await extendSigner.getAddress(),
|
|
17871
|
+
data: extendCalldata,
|
|
17872
|
+
quantumTimestamp: Number(quantumTimestamp),
|
|
17873
|
+
onDebug: this.config.debug ? (msg) => log.info(msg, {}) : void 0
|
|
17874
|
+
});
|
|
17875
|
+
} catch (simError) {
|
|
17876
|
+
if (!(simError instanceof QuantumRevertError)) {
|
|
17877
|
+
throw simError;
|
|
17878
|
+
}
|
|
17879
|
+
throw new Error(
|
|
17880
|
+
`extendPosition would revert (pre-send simulation): ${simError.errorName ?? simError.selector ?? "unknown"}`
|
|
17881
|
+
);
|
|
17882
|
+
}
|
|
17883
|
+
const tx = await sendEip1559Transaction({
|
|
17884
|
+
signer: extendSigner,
|
|
17885
|
+
to: extendTo,
|
|
17886
|
+
data: extendCalldata,
|
|
17887
|
+
gasLimit: EXTEND_POSITION_GAS_CEILING
|
|
17888
|
+
});
|
|
18014
17889
|
const txWithProvider = tx;
|
|
18015
17890
|
if (!txWithProvider.provider) {
|
|
18016
17891
|
const signer2 = this.getSignerOrThrow();
|
|
@@ -18870,7 +18745,6 @@ Error data: ${errorData || "none"}`
|
|
|
18870
18745
|
quantumTimestamp: quantumTimestamp.toString()
|
|
18871
18746
|
});
|
|
18872
18747
|
}
|
|
18873
|
-
await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
18874
18748
|
const paymentAmountStr = paymentAmountWei.toString();
|
|
18875
18749
|
const quantumTimestampStr = quantumTimestamp.toString();
|
|
18876
18750
|
const btcPriceStr = btcPrice.toString();
|
|
@@ -18888,58 +18762,30 @@ Error data: ${errorData || "none"}`
|
|
|
18888
18762
|
btcPriceStr,
|
|
18889
18763
|
signature
|
|
18890
18764
|
]);
|
|
18891
|
-
|
|
18892
|
-
|
|
18893
|
-
|
|
18894
|
-
|
|
18895
|
-
|
|
18896
|
-
|
|
18897
|
-
|
|
18898
|
-
|
|
18899
|
-
|
|
18900
|
-
|
|
18901
|
-
|
|
18902
|
-
|
|
18903
|
-
|
|
18904
|
-
|
|
18905
|
-
|
|
18906
|
-
|
|
18907
|
-
|
|
18908
|
-
if (decoded === "DeadZoneViolation()" && sim <= MAX_DEADZONE_RESIMULATIONS) {
|
|
18909
|
-
const nowSec = Math.floor(Date.now() / 1e3);
|
|
18910
|
-
const sigQuantum = Math.floor(Number(quantumTimestamp) / 60) * 60;
|
|
18911
|
-
const realCurrentQuantum = Math.floor(nowSec / 60) * 60;
|
|
18912
|
-
if (sigQuantum === realCurrentQuantum) {
|
|
18913
|
-
if (this.config.debug) {
|
|
18914
|
-
log.info(
|
|
18915
|
-
"\u21AA\uFE0F Simulated DeadZoneViolation is a stale-latest-block artifact (signature is the current quantum) \u2014 proceeding to broadcast",
|
|
18916
|
-
{}
|
|
18917
|
-
);
|
|
18918
|
-
}
|
|
18919
|
-
break;
|
|
18920
|
-
}
|
|
18921
|
-
const gate = await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
18922
|
-
if (gate.waited) {
|
|
18923
|
-
if (this.config.debug) {
|
|
18924
|
-
log.info(
|
|
18925
|
-
`\u{1F501} Re-simulating makePayment after crossing the quantum boundary (attempt ${sim}/${MAX_DEADZONE_RESIMULATIONS})`,
|
|
18926
|
-
{}
|
|
18927
|
-
);
|
|
18928
|
-
}
|
|
18929
|
-
continue;
|
|
18930
|
-
}
|
|
18931
|
-
}
|
|
18932
|
-
const label = decoded ?? simError?.reason ?? simError?.shortMessage ?? (simError instanceof Error ? simError.message : String(simError));
|
|
18933
|
-
if (this.config.debug) {
|
|
18934
|
-
log.error("\u274C makePayment pre-send simulation reverted", { error: label });
|
|
18935
|
-
}
|
|
18936
|
-
return {
|
|
18937
|
-
success: false,
|
|
18938
|
-
error: `Payment would revert (pre-send simulation): ${label}`,
|
|
18939
|
-
positionId: request.positionId,
|
|
18940
|
-
paymentAmountUCD: request.paymentAmount
|
|
18941
|
-
};
|
|
18765
|
+
try {
|
|
18766
|
+
await assertSafeQuantumSubmission({
|
|
18767
|
+
provider: paymentProvider,
|
|
18768
|
+
to: paymentContractAddress,
|
|
18769
|
+
from: paymentFrom,
|
|
18770
|
+
data: paymentCalldata,
|
|
18771
|
+
quantumTimestamp: Number(quantumTimestamp),
|
|
18772
|
+
onDebug: this.config.debug ? (msg) => log.info(msg, {}) : void 0
|
|
18773
|
+
});
|
|
18774
|
+
} catch (simError) {
|
|
18775
|
+
if (!(simError instanceof QuantumRevertError)) {
|
|
18776
|
+
throw simError;
|
|
18777
|
+
}
|
|
18778
|
+
const simCause = simError.cause;
|
|
18779
|
+
const label = simError.errorName ?? (simError.selector ? `Unknown error ${simError.selector}` : null) ?? simCause?.reason ?? simCause?.shortMessage ?? (simCause instanceof Error ? simCause.message : String(simCause));
|
|
18780
|
+
if (this.config.debug) {
|
|
18781
|
+
log.error("\u274C makePayment pre-send simulation reverted", { error: label });
|
|
18942
18782
|
}
|
|
18783
|
+
return {
|
|
18784
|
+
success: false,
|
|
18785
|
+
error: `Payment would revert (pre-send simulation): ${label}`,
|
|
18786
|
+
positionId: request.positionId,
|
|
18787
|
+
paymentAmountUCD: request.paymentAmount
|
|
18788
|
+
};
|
|
18943
18789
|
}
|
|
18944
18790
|
const tx = await sendEip1559Transaction({
|
|
18945
18791
|
signer: paymentSigner,
|
|
@@ -19613,13 +19459,6 @@ Error data: ${errorData || "none"}`
|
|
|
19613
19459
|
error: "PositionManager address not configured"
|
|
19614
19460
|
};
|
|
19615
19461
|
}
|
|
19616
|
-
const positionManagerContract = new Contract6(
|
|
19617
|
-
positionManagerAddress,
|
|
19618
|
-
[
|
|
19619
|
-
"function withdrawBTC((bytes32 positionId, bytes32 actionHash, bytes32 authorizedSpendsHash, bytes32 ucdDebtHash, bytes32 contractBundleHash, string withdrawalAddress, uint256 totalDeduction, uint256 newCollateral, uint256 quantumTimestamp, uint256 btcPrice, string utxoTxid, uint32 utxoVout) params, bytes withdrawalValidatorSignature, bytes btcSpendAuthSignature) external returns (bool)"
|
|
19620
|
-
],
|
|
19621
|
-
this.getSignerOrThrow()
|
|
19622
|
-
);
|
|
19623
19462
|
const withdrawalParams = {
|
|
19624
19463
|
positionId: positionIdBytes32,
|
|
19625
19464
|
actionHash: validationResponse.actionHash,
|
|
@@ -19652,86 +19491,56 @@ Error data: ${errorData || "none"}`
|
|
|
19652
19491
|
utxoVout: withdrawalParams.utxoVout
|
|
19653
19492
|
});
|
|
19654
19493
|
}
|
|
19655
|
-
|
|
19494
|
+
const withdrawIface = new Interface4([
|
|
19495
|
+
"function withdrawBTC((bytes32 positionId, bytes32 actionHash, bytes32 authorizedSpendsHash, bytes32 ucdDebtHash, bytes32 contractBundleHash, string withdrawalAddress, uint256 totalDeduction, uint256 newCollateral, uint256 quantumTimestamp, uint256 btcPrice, string utxoTxid, uint32 utxoVout) params, bytes withdrawalValidatorSignature, bytes btcSpendAuthSignature) external returns (bool)"
|
|
19496
|
+
]);
|
|
19497
|
+
const withdrawCalldata = withdrawIface.encodeFunctionData("withdrawBTC", [
|
|
19498
|
+
withdrawalParams,
|
|
19499
|
+
signatureBytes,
|
|
19500
|
+
btcSpendAuthBytes
|
|
19501
|
+
]);
|
|
19502
|
+
const withdrawSigner = this.getSignerOrThrow();
|
|
19656
19503
|
let tx;
|
|
19657
19504
|
try {
|
|
19658
|
-
|
|
19659
|
-
|
|
19660
|
-
|
|
19661
|
-
|
|
19662
|
-
|
|
19663
|
-
|
|
19505
|
+
await assertSafeQuantumSubmission({
|
|
19506
|
+
provider: this.getProviderOrThrow(),
|
|
19507
|
+
to: positionManagerAddress,
|
|
19508
|
+
from: await withdrawSigner.getAddress(),
|
|
19509
|
+
data: withdrawCalldata,
|
|
19510
|
+
quantumTimestamp: Number(withdrawalParams.quantumTimestamp),
|
|
19511
|
+
onDebug: this.config.debug ? (msg) => log.info(msg, {}) : void 0
|
|
19512
|
+
});
|
|
19513
|
+
tx = await sendEip1559Transaction({
|
|
19514
|
+
signer: withdrawSigner,
|
|
19515
|
+
to: positionManagerAddress,
|
|
19516
|
+
data: withdrawCalldata,
|
|
19517
|
+
gasLimit: WITHDRAW_BTC_GAS_CEILING
|
|
19518
|
+
});
|
|
19664
19519
|
} catch (txError) {
|
|
19665
|
-
const txErrorMsg = txError instanceof Error ? txError.message : String(txError);
|
|
19520
|
+
const txErrorMsg = txError instanceof QuantumRevertError ? `Withdrawal would revert (pre-send simulation): ${txError.errorName ?? txError.selector ?? "unknown"}` : txError instanceof Error ? txError.message : String(txError);
|
|
19666
19521
|
if (this.config.debug) {
|
|
19667
|
-
log.
|
|
19668
|
-
|
|
19669
|
-
|
|
19670
|
-
|
|
19522
|
+
log.error("\u274C withdrawBTC transaction submission failed", {
|
|
19523
|
+
error: txErrorMsg,
|
|
19524
|
+
withdrawalParams,
|
|
19525
|
+
signatureBytesLength: signatureBytes.length
|
|
19526
|
+
});
|
|
19671
19527
|
}
|
|
19672
19528
|
try {
|
|
19673
|
-
const
|
|
19674
|
-
const
|
|
19675
|
-
|
|
19676
|
-
|
|
19677
|
-
|
|
19678
|
-
|
|
19679
|
-
|
|
19680
|
-
btcSpendAuthBytes
|
|
19681
|
-
]);
|
|
19682
|
-
const signer = this.getSignerOrThrow();
|
|
19683
|
-
const fromAddress = await signer.getAddress();
|
|
19684
|
-
const estimatedGas = await estimateContractCallGasWithMargin(
|
|
19685
|
-
this.getProviderOrThrow(),
|
|
19686
|
-
fromAddress,
|
|
19687
|
-
contractAddress,
|
|
19688
|
-
calldata,
|
|
19689
|
-
MINT_UCD_ESTIMATE_MARGIN_BPS,
|
|
19690
|
-
WITHDRAW_BTC_GAS_CEILING
|
|
19691
|
-
);
|
|
19692
|
-
const gasLimit = estimatedGas ?? WITHDRAW_BTC_GAS_CEILING;
|
|
19693
|
-
await awaitSafeSubmissionWindow(
|
|
19694
|
-
Number(withdrawalParams.quantumTimestamp)
|
|
19529
|
+
const position = await this.getPosition(positionId);
|
|
19530
|
+
const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
|
|
19531
|
+
const message = formatBTCWithdrawalFailureMessage(
|
|
19532
|
+
btcAmount,
|
|
19533
|
+
position?.vaultAddress || "unknown",
|
|
19534
|
+
withdrawalAddress,
|
|
19535
|
+
positionId
|
|
19695
19536
|
);
|
|
19696
|
-
|
|
19697
|
-
|
|
19698
|
-
data: calldata,
|
|
19699
|
-
value: "0x0",
|
|
19700
|
-
gasLimit
|
|
19701
|
-
});
|
|
19702
|
-
if (this.config.debug) {
|
|
19703
|
-
log.info("\u2705 withdrawBTC raw transaction fallback succeeded", {
|
|
19704
|
-
txHash: tx.hash,
|
|
19705
|
-
gasLimit: gasLimit.toString(),
|
|
19706
|
-
estimated: estimatedGas !== null
|
|
19707
|
-
});
|
|
19708
|
-
}
|
|
19709
|
-
} catch (rawError) {
|
|
19710
|
-
const rawErrorMsg = rawError instanceof Error ? rawError.message : String(rawError);
|
|
19711
|
-
if (this.config.debug) {
|
|
19712
|
-
log.error("\u274C withdrawBTC transaction failed (raw fallback also failed)", {
|
|
19713
|
-
error: rawErrorMsg,
|
|
19714
|
-
withdrawalParams,
|
|
19715
|
-
signatureBytesLength: signatureBytes.length
|
|
19716
|
-
});
|
|
19717
|
-
}
|
|
19718
|
-
try {
|
|
19719
|
-
const position = await this.getPosition(positionId);
|
|
19720
|
-
const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
|
|
19721
|
-
const message = formatBTCWithdrawalFailureMessage(
|
|
19722
|
-
btcAmount,
|
|
19723
|
-
position?.vaultAddress || "unknown",
|
|
19724
|
-
withdrawalAddress,
|
|
19725
|
-
positionId
|
|
19726
|
-
);
|
|
19727
|
-
await this._relayNotification(message);
|
|
19728
|
-
} catch {
|
|
19729
|
-
}
|
|
19730
|
-
return {
|
|
19731
|
-
success: false,
|
|
19732
|
-
error: `Transaction submission failed: ${rawErrorMsg}`
|
|
19733
|
-
};
|
|
19537
|
+
await this._relayNotification(message);
|
|
19538
|
+
} catch {
|
|
19734
19539
|
}
|
|
19540
|
+
return {
|
|
19541
|
+
success: false,
|
|
19542
|
+
error: `Transaction submission failed: ${txErrorMsg}`
|
|
19543
|
+
};
|
|
19735
19544
|
}
|
|
19736
19545
|
if (this.config.debug) {
|
|
19737
19546
|
log.info("\u2705 Transaction submitted, waiting for confirmation:", {
|
|
@@ -19754,6 +19563,12 @@ Error data: ${errorData || "none"}`
|
|
|
19754
19563
|
error: `Transaction confirmation failed: ${waitErrorMsg}`
|
|
19755
19564
|
};
|
|
19756
19565
|
}
|
|
19566
|
+
if (!receipt) {
|
|
19567
|
+
return {
|
|
19568
|
+
success: false,
|
|
19569
|
+
error: `Transaction confirmation returned no receipt. Hash: ${tx.hash}`
|
|
19570
|
+
};
|
|
19571
|
+
}
|
|
19757
19572
|
if (this.config.debug) {
|
|
19758
19573
|
log.info("\u2705 BTC withdrawal confirmed", {
|
|
19759
19574
|
blockNumber: receipt.blockNumber,
|