@gvnrdao/dh-sdk 0.0.299 → 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 +442 -571
- package/dist/index.mjs +351 -480
- package/dist/utils/chunks/eip1559-broadcast.utils.d.ts +15 -24
- package/dist/utils/quantum-revert.utils.d.ts +41 -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;
|
|
@@ -5839,6 +5843,122 @@ var ServerSession = class {
|
|
|
5839
5843
|
}
|
|
5840
5844
|
};
|
|
5841
5845
|
|
|
5846
|
+
// src/utils/quantum-revert.utils.ts
|
|
5847
|
+
import { AbiCoder } from "ethers";
|
|
5848
|
+
var DEAD_ZONE_VIOLATION_SELECTOR = "0xbe4b82c1";
|
|
5849
|
+
var ERROR_STRING_SELECTOR = "0x08c379a0";
|
|
5850
|
+
var PANIC_SELECTOR = "0x4e487b71";
|
|
5851
|
+
var QUANTUM_REVERT_NAMES = {
|
|
5852
|
+
"0xbe4b82c1": "DeadZoneViolation()",
|
|
5853
|
+
"0x137f3b70": "InDeadZone()",
|
|
5854
|
+
"0x131d9a21": "QuantumExpired()",
|
|
5855
|
+
"0x52ce5d58": "QuantumAlreadyUsed()",
|
|
5856
|
+
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
5857
|
+
"0x8baa579f": "InvalidSignature()",
|
|
5858
|
+
"0x62278171": "InvalidValidatorSignature()",
|
|
5859
|
+
"0x3ee5aeb5": "OperationNotAuthorized()",
|
|
5860
|
+
"0x48f5c3ed": "Unauthorized()",
|
|
5861
|
+
"0x70f4b32a": "UnauthorizedSigner()",
|
|
5862
|
+
"0xd92e233d": "ValidationFailed()",
|
|
5863
|
+
"0x36bfdeea": "StateHashMismatch()",
|
|
5864
|
+
"0xb9d419a7": "DebtUpdateVerificationFailed()",
|
|
5865
|
+
"0xc7e20553": "DebtUpdateVerificationFailedDetailed(bytes32,uint256,uint256,uint256,uint256,uint256)",
|
|
5866
|
+
"0x0cfd2a97": "MintVerificationMismatch(uint256,uint256)",
|
|
5867
|
+
"0x07637bd8": "MintFailed()"
|
|
5868
|
+
};
|
|
5869
|
+
function decodeQuantumRevert(e) {
|
|
5870
|
+
const raw = e?.data ?? e?.info?.error?.data ?? // ethers v6 BrowserProvider (MetaMask)
|
|
5871
|
+
e?.error?.data?.data ?? e?.error?.data ?? e?.error?.error?.data;
|
|
5872
|
+
const data = typeof raw === "string" && raw.startsWith("0x") ? raw : null;
|
|
5873
|
+
const selector = data && data.length >= 10 ? data.slice(0, 10) : null;
|
|
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
|
+
}
|
|
5893
|
+
return { data, selector, name };
|
|
5894
|
+
}
|
|
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
|
+
|
|
5842
5962
|
// src/utils/btc-withdrawal-message.ts
|
|
5843
5963
|
import { keccak256 as keccak2563, toUtf8Bytes as toUtf8Bytes3, solidityPackedKeccak256 as solidityPackedKeccak2563, getBytes as getBytes3, zeroPadValue } from "ethers";
|
|
5844
5964
|
var QUANTUM_SECONDS = 60;
|
|
@@ -16194,8 +16314,8 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
16194
16314
|
throw new Error(`Position not found: ${request.positionId}`);
|
|
16195
16315
|
}
|
|
16196
16316
|
const currentDebt = position.ucdDebt.toString();
|
|
16197
|
-
const ucdDebtHash = keccak2565(
|
|
16198
|
-
const contractHash = keccak2565(
|
|
16317
|
+
const ucdDebtHash = keccak2565(AbiCoder2.defaultAbiCoder().encode(["uint256"], [currentDebt]));
|
|
16318
|
+
const contractHash = keccak2565(AbiCoder2.defaultAbiCoder().encode(
|
|
16199
16319
|
["address", "address", "address", "address"],
|
|
16200
16320
|
[
|
|
16201
16321
|
positionManagerAddress,
|
|
@@ -16256,188 +16376,6 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
16256
16376
|
{}
|
|
16257
16377
|
);
|
|
16258
16378
|
}
|
|
16259
|
-
if (this.config.debug) {
|
|
16260
|
-
log.info("\u{1F50D} PREFLIGHT: Attempting diagnostic gas estimation...", {});
|
|
16261
|
-
}
|
|
16262
|
-
try {
|
|
16263
|
-
const iface = new Interface4(positionManagerAbi);
|
|
16264
|
-
const signatureHex = finalSignature.startsWith("0x") ? finalSignature : "0x" + finalSignature;
|
|
16265
|
-
if (this.config.debug) {
|
|
16266
|
-
log.info("\u{1F50D} DEBUG: Signature details:", {
|
|
16267
|
-
finalSignature: finalSignature ? `${finalSignature.substring(0, 20)}... (length: ${finalSignature.length})` : "UNDEFINED/EMPTY",
|
|
16268
|
-
signatureHex: signatureHex ? `${signatureHex.substring(0, 22)}... (length: ${signatureHex.length})` : "UNDEFINED/EMPTY"
|
|
16269
|
-
});
|
|
16270
|
-
}
|
|
16271
|
-
const calldata = iface.encodeFunctionData("mintUCD", [
|
|
16272
|
-
positionIdBytes32,
|
|
16273
|
-
validationResponse.mintAmount,
|
|
16274
|
-
validationResponse.mintFee,
|
|
16275
|
-
validationResponse.newDebt,
|
|
16276
|
-
validationResponse.newCollateral,
|
|
16277
|
-
validationResponse.btcPrice,
|
|
16278
|
-
validationResponse.authorizedSpendsHash,
|
|
16279
|
-
ucdDebtHash,
|
|
16280
|
-
contractHash,
|
|
16281
|
-
validationResponse.timestamp,
|
|
16282
|
-
signatureHex
|
|
16283
|
-
]);
|
|
16284
|
-
if (this.config.debug) {
|
|
16285
|
-
log.info("\u{1F50D} DEBUG: Encoded calldata:", {
|
|
16286
|
-
length: calldata.length,
|
|
16287
|
-
signaturePortion: calldata.substring(650, 670)
|
|
16288
|
-
});
|
|
16289
|
-
}
|
|
16290
|
-
const provider = this.getSignerOrThrow().provider;
|
|
16291
|
-
if (!provider) {
|
|
16292
|
-
throw new Error("Provider not available");
|
|
16293
|
-
}
|
|
16294
|
-
const signerAddress = await this.getSignerOrThrow().getAddress();
|
|
16295
|
-
if (this.config.debug) {
|
|
16296
|
-
log.info(" Executing diagnostic eth_call...", {});
|
|
16297
|
-
}
|
|
16298
|
-
await provider.call({
|
|
16299
|
-
to: positionManagerAddress,
|
|
16300
|
-
from: signerAddress,
|
|
16301
|
-
data: calldata
|
|
16302
|
-
});
|
|
16303
|
-
if (this.config.debug) {
|
|
16304
|
-
log.info(" \u2705 Diagnostic eth_call succeeded!", {});
|
|
16305
|
-
}
|
|
16306
|
-
} catch (preflightError) {
|
|
16307
|
-
if (this.config.debug) {
|
|
16308
|
-
log.error(
|
|
16309
|
-
"\u274C PREFLIGHT CHECK FAILED - Diagnostic eth_call reverted",
|
|
16310
|
-
{}
|
|
16311
|
-
);
|
|
16312
|
-
log.error(` Error message: ${preflightError?.message}`, {});
|
|
16313
|
-
log.error(` Error code: ${preflightError?.code}`, {});
|
|
16314
|
-
log.error(` Error data: ${preflightError?.data || "none"}`, {});
|
|
16315
|
-
log.error(` Error reason: ${preflightError?.reason || "none"}`, {});
|
|
16316
|
-
log.error(
|
|
16317
|
-
` Error.error: ${JSON.stringify(preflightError?.error || {})}`,
|
|
16318
|
-
{}
|
|
16319
|
-
);
|
|
16320
|
-
}
|
|
16321
|
-
let errorData = preflightError?.data || preflightError?.error?.data?.data || preflightError?.error?.data || preflightError?.error?.error?.data;
|
|
16322
|
-
const errorMessage = preflightError?.reason || preflightError?.error?.reason || preflightError?.error?.error?.reason || preflightError?.message || "Unknown error";
|
|
16323
|
-
let requireMessage;
|
|
16324
|
-
if (errorData && typeof errorData === "string" && errorData.startsWith("0x") && errorData.length > 138) {
|
|
16325
|
-
try {
|
|
16326
|
-
const errorSelector = errorData.slice(0, 10);
|
|
16327
|
-
if (errorSelector === "0x08c379a0") {
|
|
16328
|
-
const iface = new Interface4([
|
|
16329
|
-
"function Error(string)"
|
|
16330
|
-
]);
|
|
16331
|
-
const decoded = iface.decodeFunctionData("Error", errorData);
|
|
16332
|
-
requireMessage = decoded[0];
|
|
16333
|
-
}
|
|
16334
|
-
} catch (e) {
|
|
16335
|
-
}
|
|
16336
|
-
}
|
|
16337
|
-
if (requireMessage) {
|
|
16338
|
-
throw new Error(
|
|
16339
|
-
`Preflight check failed - mintUCD would revert:
|
|
16340
|
-
${requireMessage}
|
|
16341
|
-
Context: Quantum timestamp=${validationResponse.timestamp}, Position=${request.positionId}`
|
|
16342
|
-
);
|
|
16343
|
-
}
|
|
16344
|
-
if (errorData && typeof errorData === "string" && errorData.startsWith("0x") && errorData.length > 10) {
|
|
16345
|
-
const selector = errorData.slice(0, 10);
|
|
16346
|
-
const knownErrors = {
|
|
16347
|
-
"0x8baa579f": "InvalidSignature()",
|
|
16348
|
-
"0xd92e233d": "ValidationFailed()",
|
|
16349
|
-
"0x3ee5aeb5": "OperationNotAuthorized()",
|
|
16350
|
-
"0x70f4b32a": "UnauthorizedSigner()",
|
|
16351
|
-
"0x48f5c3ed": "Unauthorized()",
|
|
16352
|
-
"0x36bfdeea": "StateHashMismatch()",
|
|
16353
|
-
"0x131d9a21": "QuantumExpired()",
|
|
16354
|
-
"0x52ce5d58": "QuantumAlreadyUsed()",
|
|
16355
|
-
"0x137f3b70": "InDeadZone()",
|
|
16356
|
-
"0xbe4b82c1": "DeadZoneViolation()",
|
|
16357
|
-
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
16358
|
-
"0x62278171": "InvalidValidatorSignature()",
|
|
16359
|
-
"0xb9d419a7": "DebtUpdateVerificationFailed()",
|
|
16360
|
-
"0xc7e20553": "DebtUpdateVerificationFailedDetailed(bytes32,uint256,uint256,uint256,uint256,uint256)",
|
|
16361
|
-
"0x0cfd2a97": "MintVerificationMismatch(uint256,uint256)",
|
|
16362
|
-
"0x07637bd8": "MintFailed()"
|
|
16363
|
-
};
|
|
16364
|
-
const errorName = knownErrors[selector] || `Unknown error ${selector}`;
|
|
16365
|
-
const mintDebtDiagnostics = selector === "0xb9d419a7" || selector === "0xc7e20553" || selector === "0x0cfd2a97" || selector === "0x07637bd8" ? `
|
|
16366
|
-
|
|
16367
|
-
Mint/debt diagnostics (LoanOperationsManager mint path \u2192 increaseDebtFromMint):
|
|
16368
|
-
positionId: ${request.positionId}
|
|
16369
|
-
on-chain ucdDebt before tx: ${currentDebt}
|
|
16370
|
-
Lit newDebt: ${validationResponse.newDebt}
|
|
16371
|
-
Lit mintAmount: ${validationResponse.mintAmount}
|
|
16372
|
-
Lit mintFee: ${validationResponse.mintFee}
|
|
16373
|
-
Call path: mintUCD -> mintUCDWithAuthorization -> increaseDebtFromMint -> finalizeMintDebtIncrease
|
|
16374
|
-
Contract expects UCD supply increase to match mintAmount+mintFee and debt update to newDebt.
|
|
16375
|
-
` : "";
|
|
16376
|
-
let quantumContext = "";
|
|
16377
|
-
if (selector === "0x131d9a21" || selector === "0x52ce5d58" || selector === "0x137f3b70" || selector === "0xbe4b82c1" || selector === "0x3e76a3c9") {
|
|
16378
|
-
const currentTime2 = Math.floor(Date.now() / 1e3);
|
|
16379
|
-
const currentQuantum = Math.floor(currentTime2 / 60) * 60;
|
|
16380
|
-
const sigQuantum2 = Math.floor(validationResponse.timestamp / 60) * 60;
|
|
16381
|
-
const timeDiff = currentTime2 - validationResponse.timestamp;
|
|
16382
|
-
quantumContext = `
|
|
16383
|
-
|
|
16384
|
-
Quantum Timing Analysis:
|
|
16385
|
-
Signature created: ${validationResponse.timestamp} (${new Date(
|
|
16386
|
-
validationResponse.timestamp * 1e3
|
|
16387
|
-
).toISOString()})
|
|
16388
|
-
Current time: ${currentTime2} (${new Date(
|
|
16389
|
-
currentTime2 * 1e3
|
|
16390
|
-
).toISOString()})
|
|
16391
|
-
Time elapsed: ${timeDiff} seconds
|
|
16392
|
-
Signature quantum: ${sigQuantum2}
|
|
16393
|
-
Current quantum: ${currentQuantum}
|
|
16394
|
-
Quantum window: 60 seconds
|
|
16395
|
-
Status: ${sigQuantum2 < currentQuantum ? "\u274C EXPIRED - Signature created in older quantum window" : "\u2705 VALID"}
|
|
16396
|
-
Note: QuantumOutsideWindow can also occur if the tx is mined outside the accepted past/current/next quantum set.`;
|
|
16397
|
-
}
|
|
16398
|
-
throw new Error(
|
|
16399
|
-
`Preflight check failed - mintUCD would revert:
|
|
16400
|
-
Error: ${errorName}
|
|
16401
|
-
Selector: ${selector}
|
|
16402
|
-
Message: ${errorMessage}
|
|
16403
|
-
Data: ${errorData}${quantumContext}${mintDebtDiagnostics}`
|
|
16404
|
-
);
|
|
16405
|
-
} else {
|
|
16406
|
-
const currentTime2 = Math.floor(Date.now() / 1e3);
|
|
16407
|
-
const timeSinceSig = currentTime2 - validationResponse.timestamp;
|
|
16408
|
-
const currentQuantum = Math.floor(currentTime2 / 60) * 60;
|
|
16409
|
-
const sigQuantum2 = Math.floor(validationResponse.timestamp / 60) * 60;
|
|
16410
|
-
throw new Error(
|
|
16411
|
-
`Preflight check failed - mintUCD would revert:
|
|
16412
|
-
${errorMessage}
|
|
16413
|
-
|
|
16414
|
-
Error Details:
|
|
16415
|
-
Error data: ${errorData || "0x (empty - no custom error)"}
|
|
16416
|
-
Error code: ${preflightError?.code || "none"}
|
|
16417
|
-
|
|
16418
|
-
Quantum Timing Analysis:
|
|
16419
|
-
Signature created: ${validationResponse.timestamp} (${new Date(
|
|
16420
|
-
validationResponse.timestamp * 1e3
|
|
16421
|
-
).toISOString()})
|
|
16422
|
-
Current time: ${currentTime2} (${new Date(
|
|
16423
|
-
currentTime2 * 1e3
|
|
16424
|
-
).toISOString()})
|
|
16425
|
-
Time elapsed: ${timeSinceSig} seconds
|
|
16426
|
-
Signature quantum: ${sigQuantum2}
|
|
16427
|
-
Current quantum: ${currentQuantum}
|
|
16428
|
-
Status: ${sigQuantum2 < currentQuantum ? "\u274C EXPIRED - Signature too old" : "\u2705 VALID"}
|
|
16429
|
-
|
|
16430
|
-
Possible Causes (when error data is empty):
|
|
16431
|
-
\u2022 Quantum signature expired (current=${currentQuantum}, signature=${sigQuantum2})
|
|
16432
|
-
\u2022 Contract paused or circuit breaker active
|
|
16433
|
-
\u2022 Position state changed since LIT Action signed
|
|
16434
|
-
\u2022 Authorization registry validation failed
|
|
16435
|
-
\u2022 RPC provider not returning detailed revert data
|
|
16436
|
-
|
|
16437
|
-
Position: ${request.positionId}`
|
|
16438
|
-
);
|
|
16439
|
-
}
|
|
16440
|
-
}
|
|
16441
16379
|
try {
|
|
16442
16380
|
const coreAddress = this.getContractAddressesOrThrow().positionManagerCore;
|
|
16443
16381
|
if (!coreAddress) {
|
|
@@ -16455,7 +16393,7 @@ Position: ${request.positionId}`
|
|
|
16455
16393
|
positionIdBytes32
|
|
16456
16394
|
);
|
|
16457
16395
|
const currentDebtHash = keccak2565(
|
|
16458
|
-
|
|
16396
|
+
AbiCoder2.defaultAbiCoder().encode(
|
|
16459
16397
|
["uint256"],
|
|
16460
16398
|
[currentPosition.ucdDebt]
|
|
16461
16399
|
)
|
|
@@ -16632,137 +16570,122 @@ Position: ${request.positionId}`
|
|
|
16632
16570
|
validationResponse.timestamp,
|
|
16633
16571
|
signatureHexMint
|
|
16634
16572
|
]);
|
|
16635
|
-
await awaitSafeSubmissionWindow(Number(validationResponse.timestamp));
|
|
16636
16573
|
const fromAddress = await signer.getAddress();
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
positionManagerAddress,
|
|
16641
|
-
mintCalldata,
|
|
16642
|
-
MINT_UCD_ESTIMATE_MARGIN_BPS,
|
|
16643
|
-
MINT_UCD_GAS_CEILING
|
|
16644
|
-
);
|
|
16645
|
-
let tx;
|
|
16646
|
-
if (estimatedGas !== null) {
|
|
16647
|
-
if (this.config.debug) {
|
|
16648
|
-
log.info(
|
|
16649
|
-
`\u{1F4DD} Broadcasting mintUCD (gasLimit=${estimatedGas.toString()})`,
|
|
16650
|
-
{}
|
|
16651
|
-
);
|
|
16652
|
-
}
|
|
16653
|
-
tx = await sendEip1559Transaction({
|
|
16654
|
-
signer,
|
|
16574
|
+
try {
|
|
16575
|
+
await assertSafeQuantumSubmission({
|
|
16576
|
+
provider: signerProvider,
|
|
16655
16577
|
to: positionManagerAddress,
|
|
16578
|
+
from: fromAddress,
|
|
16656
16579
|
data: mintCalldata,
|
|
16657
|
-
|
|
16580
|
+
quantumTimestamp: Number(validationResponse.timestamp),
|
|
16581
|
+
onDebug: this.config.debug ? (msg) => log.info(msg, {}) : void 0
|
|
16658
16582
|
});
|
|
16659
|
-
}
|
|
16660
|
-
if (
|
|
16661
|
-
|
|
16662
|
-
|
|
16663
|
-
|
|
16664
|
-
|
|
16665
|
-
|
|
16666
|
-
|
|
16667
|
-
|
|
16668
|
-
|
|
16669
|
-
|
|
16670
|
-
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
|
|
16674
|
-
|
|
16675
|
-
|
|
16676
|
-
|
|
16677
|
-
|
|
16678
|
-
|
|
16679
|
-
|
|
16680
|
-
|
|
16681
|
-
|
|
16682
|
-
|
|
16683
|
-
|
|
16684
|
-
|
|
16685
|
-
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
|
|
16689
|
-
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
16696
|
-
"0x62278171": "InvalidValidatorSignature()",
|
|
16697
|
-
"0xb9d419a7": "DebtUpdateVerificationFailed()",
|
|
16698
|
-
"0xc7e20553": "DebtUpdateVerificationFailedDetailed(bytes32,uint256,uint256,uint256,uint256,uint256)",
|
|
16699
|
-
"0x0cfd2a97": "MintVerificationMismatch(uint256,uint256)",
|
|
16700
|
-
"0x07637bd8": "MintFailed()"
|
|
16701
|
-
};
|
|
16702
|
-
const errorName = knownErrors[selector] || `Unknown error ${selector}`;
|
|
16703
|
-
throw new Error(
|
|
16704
|
-
`mintUCD reverted: ${errorName}
|
|
16705
|
-
Error selector: ${selector}
|
|
16706
|
-
Error data: ${errorData}
|
|
16707
|
-
Call path: mintUCD -> mintUCDWithAuthorization -> increaseDebtFromMint -> finalizeMintDebtIncrease
|
|
16708
|
-
Message: ${errorMessage}`
|
|
16709
|
-
);
|
|
16710
|
-
}
|
|
16711
|
-
if (errorData === "0x" || !errorData) {
|
|
16712
|
-
const viewsAddress = this.config.contractAddresses?.positionManagerViews;
|
|
16713
|
-
if (viewsAddress) {
|
|
16714
|
-
try {
|
|
16715
|
-
const views = new Contract6(
|
|
16716
|
-
viewsAddress,
|
|
16717
|
-
[
|
|
16718
|
-
"function diagnoseMintUCD(bytes32,uint256,uint256,uint256,uint256,uint256,bytes32,bytes32,bytes32,uint256,bytes) view returns (string)"
|
|
16719
|
-
],
|
|
16720
|
-
signerProvider
|
|
16721
|
-
);
|
|
16722
|
-
const diagnosis = await views["diagnoseMintUCD"](
|
|
16723
|
-
request.positionId,
|
|
16724
|
-
validationResponse.mintAmount,
|
|
16725
|
-
validationResponse.mintFee,
|
|
16726
|
-
validationResponse.newDebt,
|
|
16727
|
-
validationResponse.newCollateral,
|
|
16728
|
-
validationResponse.btcPrice,
|
|
16729
|
-
validationResponse.authorizedSpendsHash,
|
|
16730
|
-
ucdDebtHash,
|
|
16731
|
-
contractHash,
|
|
16732
|
-
validationResponse.timestamp,
|
|
16733
|
-
signatureHexMint
|
|
16734
|
-
);
|
|
16735
|
-
throw new Error(
|
|
16736
|
-
`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
|
+
{}
|
|
16737
16619
|
);
|
|
16738
|
-
} catch (diagErr) {
|
|
16739
|
-
if (this.config.debug) {
|
|
16740
|
-
log.info(
|
|
16741
|
-
` diagnoseMintUCD unavailable or failed: ${diagErr?.message || diagErr}`,
|
|
16742
|
-
{}
|
|
16743
|
-
);
|
|
16744
|
-
}
|
|
16745
16620
|
}
|
|
16746
16621
|
}
|
|
16622
|
+
if (diagnosis !== null) {
|
|
16623
|
+
throw new Error(
|
|
16624
|
+
`mintUCD reverted with empty data; diagnosis: ${diagnosis}`
|
|
16625
|
+
);
|
|
16626
|
+
}
|
|
16747
16627
|
}
|
|
16748
16628
|
throw new Error(
|
|
16749
|
-
`mintUCD
|
|
16750
|
-
Error data:
|
|
16629
|
+
`mintUCD would revert (pre-send simulation): ${causeMessage}
|
|
16630
|
+
Error data: none`
|
|
16751
16631
|
);
|
|
16752
16632
|
}
|
|
16753
|
-
|
|
16754
|
-
|
|
16755
|
-
|
|
16756
|
-
|
|
16757
|
-
|
|
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.`;
|
|
16758
16674
|
}
|
|
16759
|
-
|
|
16760
|
-
|
|
16761
|
-
|
|
16762
|
-
|
|
16763
|
-
|
|
16764
|
-
|
|
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
|
+
);
|
|
16765
16682
|
}
|
|
16683
|
+
const tx = await sendEip1559Transaction({
|
|
16684
|
+
signer,
|
|
16685
|
+
to: positionManagerAddress,
|
|
16686
|
+
data: mintCalldata,
|
|
16687
|
+
gasLimit: MINT_UCD_GAS_CEILING
|
|
16688
|
+
});
|
|
16766
16689
|
const receipt = await signerProvider.waitForTransaction(
|
|
16767
16690
|
tx.hash,
|
|
16768
16691
|
1,
|
|
@@ -17926,26 +17849,43 @@ Error data: ${errorData || "none"}`
|
|
|
17926
17849
|
if (!signatureBytes.startsWith("0x")) {
|
|
17927
17850
|
signatureBytes = "0x" + signatureBytes;
|
|
17928
17851
|
}
|
|
17929
|
-
const
|
|
17930
|
-
|
|
17931
|
-
|
|
17932
|
-
|
|
17933
|
-
`Failed to get PositionManager: ${positionManagerResult.error.message}`
|
|
17934
|
-
);
|
|
17935
|
-
}
|
|
17936
|
-
const positionManager = positionManagerResult.value;
|
|
17937
|
-
await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
17938
|
-
const extendPositionFn = positionManager["extendPosition"];
|
|
17939
|
-
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", [
|
|
17940
17856
|
positionIdBytes32,
|
|
17941
17857
|
BigInt(_selectedTerm),
|
|
17942
17858
|
quantumTimestamp,
|
|
17943
17859
|
btcPrice,
|
|
17944
17860
|
availableBTCBalance,
|
|
17945
17861
|
proRataRenewalFee,
|
|
17946
|
-
signatureBytes
|
|
17947
|
-
|
|
17948
|
-
);
|
|
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
|
+
});
|
|
17949
17889
|
const txWithProvider = tx;
|
|
17950
17890
|
if (!txWithProvider.provider) {
|
|
17951
17891
|
const signer2 = this.getSignerOrThrow();
|
|
@@ -18805,7 +18745,6 @@ Error data: ${errorData || "none"}`
|
|
|
18805
18745
|
quantumTimestamp: quantumTimestamp.toString()
|
|
18806
18746
|
});
|
|
18807
18747
|
}
|
|
18808
|
-
await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
18809
18748
|
const paymentAmountStr = paymentAmountWei.toString();
|
|
18810
18749
|
const quantumTimestampStr = quantumTimestamp.toString();
|
|
18811
18750
|
const btcPriceStr = btcPrice.toString();
|
|
@@ -18823,71 +18762,30 @@ Error data: ${errorData || "none"}`
|
|
|
18823
18762
|
btcPriceStr,
|
|
18824
18763
|
signature
|
|
18825
18764
|
]);
|
|
18826
|
-
|
|
18827
|
-
|
|
18828
|
-
|
|
18829
|
-
|
|
18830
|
-
|
|
18831
|
-
|
|
18832
|
-
|
|
18833
|
-
|
|
18834
|
-
|
|
18835
|
-
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
|
|
18839
|
-
|
|
18840
|
-
|
|
18841
|
-
|
|
18842
|
-
|
|
18843
|
-
return map2[selector] ?? `Unknown error ${selector}`;
|
|
18844
|
-
};
|
|
18845
|
-
const MAX_DEADZONE_RESIMULATIONS = 3;
|
|
18846
|
-
for (let sim = 1; ; sim++) {
|
|
18847
|
-
try {
|
|
18848
|
-
await paymentProvider.call({
|
|
18849
|
-
to: paymentContractAddress,
|
|
18850
|
-
from: paymentFrom,
|
|
18851
|
-
data: paymentCalldata
|
|
18852
|
-
});
|
|
18853
|
-
break;
|
|
18854
|
-
} catch (simError) {
|
|
18855
|
-
const decoded = decodePaymentRevert(simError);
|
|
18856
|
-
if (decoded === "DeadZoneViolation()" && sim <= MAX_DEADZONE_RESIMULATIONS) {
|
|
18857
|
-
const nowSec = Math.floor(Date.now() / 1e3);
|
|
18858
|
-
const sigQuantum = Math.floor(Number(quantumTimestamp) / 60) * 60;
|
|
18859
|
-
const realCurrentQuantum = Math.floor(nowSec / 60) * 60;
|
|
18860
|
-
if (sigQuantum === realCurrentQuantum) {
|
|
18861
|
-
if (this.config.debug) {
|
|
18862
|
-
log.info(
|
|
18863
|
-
"\u21AA\uFE0F Simulated DeadZoneViolation is a stale-latest-block artifact (signature is the current quantum) \u2014 proceeding to broadcast",
|
|
18864
|
-
{}
|
|
18865
|
-
);
|
|
18866
|
-
}
|
|
18867
|
-
break;
|
|
18868
|
-
}
|
|
18869
|
-
const gate = await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
18870
|
-
if (gate.waited) {
|
|
18871
|
-
if (this.config.debug) {
|
|
18872
|
-
log.info(
|
|
18873
|
-
`\u{1F501} Re-simulating makePayment after crossing the quantum boundary (attempt ${sim}/${MAX_DEADZONE_RESIMULATIONS})`,
|
|
18874
|
-
{}
|
|
18875
|
-
);
|
|
18876
|
-
}
|
|
18877
|
-
continue;
|
|
18878
|
-
}
|
|
18879
|
-
}
|
|
18880
|
-
const label = decoded ?? simError?.reason ?? simError?.shortMessage ?? (simError instanceof Error ? simError.message : String(simError));
|
|
18881
|
-
if (this.config.debug) {
|
|
18882
|
-
log.error("\u274C makePayment pre-send simulation reverted", { error: label });
|
|
18883
|
-
}
|
|
18884
|
-
return {
|
|
18885
|
-
success: false,
|
|
18886
|
-
error: `Payment would revert (pre-send simulation): ${label}`,
|
|
18887
|
-
positionId: request.positionId,
|
|
18888
|
-
paymentAmountUCD: request.paymentAmount
|
|
18889
|
-
};
|
|
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 });
|
|
18890
18782
|
}
|
|
18783
|
+
return {
|
|
18784
|
+
success: false,
|
|
18785
|
+
error: `Payment would revert (pre-send simulation): ${label}`,
|
|
18786
|
+
positionId: request.positionId,
|
|
18787
|
+
paymentAmountUCD: request.paymentAmount
|
|
18788
|
+
};
|
|
18891
18789
|
}
|
|
18892
18790
|
const tx = await sendEip1559Transaction({
|
|
18893
18791
|
signer: paymentSigner,
|
|
@@ -19561,13 +19459,6 @@ Error data: ${errorData || "none"}`
|
|
|
19561
19459
|
error: "PositionManager address not configured"
|
|
19562
19460
|
};
|
|
19563
19461
|
}
|
|
19564
|
-
const positionManagerContract = new Contract6(
|
|
19565
|
-
positionManagerAddress,
|
|
19566
|
-
[
|
|
19567
|
-
"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)"
|
|
19568
|
-
],
|
|
19569
|
-
this.getSignerOrThrow()
|
|
19570
|
-
);
|
|
19571
19462
|
const withdrawalParams = {
|
|
19572
19463
|
positionId: positionIdBytes32,
|
|
19573
19464
|
actionHash: validationResponse.actionHash,
|
|
@@ -19600,82 +19491,56 @@ Error data: ${errorData || "none"}`
|
|
|
19600
19491
|
utxoVout: withdrawalParams.utxoVout
|
|
19601
19492
|
});
|
|
19602
19493
|
}
|
|
19603
|
-
|
|
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();
|
|
19604
19503
|
let tx;
|
|
19605
19504
|
try {
|
|
19606
|
-
|
|
19607
|
-
|
|
19608
|
-
|
|
19609
|
-
|
|
19610
|
-
|
|
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
|
+
});
|
|
19611
19519
|
} catch (txError) {
|
|
19612
|
-
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);
|
|
19613
19521
|
if (this.config.debug) {
|
|
19614
|
-
log.
|
|
19615
|
-
|
|
19616
|
-
|
|
19617
|
-
|
|
19522
|
+
log.error("\u274C withdrawBTC transaction submission failed", {
|
|
19523
|
+
error: txErrorMsg,
|
|
19524
|
+
withdrawalParams,
|
|
19525
|
+
signatureBytesLength: signatureBytes.length
|
|
19526
|
+
});
|
|
19618
19527
|
}
|
|
19619
19528
|
try {
|
|
19620
|
-
const
|
|
19621
|
-
const
|
|
19622
|
-
|
|
19623
|
-
|
|
19624
|
-
|
|
19625
|
-
|
|
19626
|
-
|
|
19627
|
-
btcSpendAuthBytes
|
|
19628
|
-
]);
|
|
19629
|
-
const signer = this.getSignerOrThrow();
|
|
19630
|
-
const fromAddress = await signer.getAddress();
|
|
19631
|
-
const estimatedGas = await estimateContractCallGasWithMargin(
|
|
19632
|
-
this.getProviderOrThrow(),
|
|
19633
|
-
fromAddress,
|
|
19634
|
-
contractAddress,
|
|
19635
|
-
calldata,
|
|
19636
|
-
MINT_UCD_ESTIMATE_MARGIN_BPS,
|
|
19637
|
-
WITHDRAW_BTC_GAS_CEILING
|
|
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
|
|
19638
19536
|
);
|
|
19639
|
-
|
|
19640
|
-
|
|
19641
|
-
to: contractAddress,
|
|
19642
|
-
data: calldata,
|
|
19643
|
-
value: "0x0",
|
|
19644
|
-
gasLimit
|
|
19645
|
-
});
|
|
19646
|
-
if (this.config.debug) {
|
|
19647
|
-
log.info("\u2705 withdrawBTC raw transaction fallback succeeded", {
|
|
19648
|
-
txHash: tx.hash,
|
|
19649
|
-
gasLimit: gasLimit.toString(),
|
|
19650
|
-
estimated: estimatedGas !== null
|
|
19651
|
-
});
|
|
19652
|
-
}
|
|
19653
|
-
} catch (rawError) {
|
|
19654
|
-
const rawErrorMsg = rawError instanceof Error ? rawError.message : String(rawError);
|
|
19655
|
-
if (this.config.debug) {
|
|
19656
|
-
log.error("\u274C withdrawBTC transaction failed (raw fallback also failed)", {
|
|
19657
|
-
error: rawErrorMsg,
|
|
19658
|
-
withdrawalParams,
|
|
19659
|
-
signatureBytesLength: signatureBytes.length
|
|
19660
|
-
});
|
|
19661
|
-
}
|
|
19662
|
-
try {
|
|
19663
|
-
const position = await this.getPosition(positionId);
|
|
19664
|
-
const btcAmount = (Number(withdrawalAmount) / 1e8).toFixed(8);
|
|
19665
|
-
const message = formatBTCWithdrawalFailureMessage(
|
|
19666
|
-
btcAmount,
|
|
19667
|
-
position?.vaultAddress || "unknown",
|
|
19668
|
-
withdrawalAddress,
|
|
19669
|
-
positionId
|
|
19670
|
-
);
|
|
19671
|
-
await this._relayNotification(message);
|
|
19672
|
-
} catch {
|
|
19673
|
-
}
|
|
19674
|
-
return {
|
|
19675
|
-
success: false,
|
|
19676
|
-
error: `Transaction submission failed: ${rawErrorMsg}`
|
|
19677
|
-
};
|
|
19537
|
+
await this._relayNotification(message);
|
|
19538
|
+
} catch {
|
|
19678
19539
|
}
|
|
19540
|
+
return {
|
|
19541
|
+
success: false,
|
|
19542
|
+
error: `Transaction submission failed: ${txErrorMsg}`
|
|
19543
|
+
};
|
|
19679
19544
|
}
|
|
19680
19545
|
if (this.config.debug) {
|
|
19681
19546
|
log.info("\u2705 Transaction submitted, waiting for confirmation:", {
|
|
@@ -19698,6 +19563,12 @@ Error data: ${errorData || "none"}`
|
|
|
19698
19563
|
error: `Transaction confirmation failed: ${waitErrorMsg}`
|
|
19699
19564
|
};
|
|
19700
19565
|
}
|
|
19566
|
+
if (!receipt) {
|
|
19567
|
+
return {
|
|
19568
|
+
success: false,
|
|
19569
|
+
error: `Transaction confirmation returned no receipt. Hash: ${tx.hash}`
|
|
19570
|
+
};
|
|
19571
|
+
}
|
|
19701
19572
|
if (this.config.debug) {
|
|
19702
19573
|
log.info("\u2705 BTC withdrawal confirmed", {
|
|
19703
19574
|
blockNumber: receipt.blockNumber,
|