gate-evm-tools 1.0.26 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/bin/workflow.cjs +19 -0
- package/dist/core/BytecodeChecker.d.ts.map +1 -1
- package/dist/core/BytecodeChecker.js +16 -1
- package/dist/core/BytecodeChecker.js.map +1 -1
- package/dist/core/legacyProxyArtifact.d.ts +6 -0
- package/dist/core/legacyProxyArtifact.d.ts.map +1 -0
- package/dist/core/legacyProxyArtifact.js +36 -0
- package/dist/core/legacyProxyArtifact.js.map +1 -0
- package/dist-runtime/config/hardhatAdapters.d.ts +7 -0
- package/dist-runtime/config/hardhatAdapters.js +61 -0
- package/dist-runtime/config/hardhatAdapters.js.map +1 -0
- package/dist-runtime/config/networks.d.ts +32 -0
- package/dist-runtime/config/networks.js +275 -0
- package/dist-runtime/config/networks.js.map +1 -0
- package/dist-runtime/config/openzeppelin.d.ts +28 -0
- package/dist-runtime/config/openzeppelin.js +144 -0
- package/dist-runtime/config/openzeppelin.js.map +1 -0
- package/dist-runtime/config/rpc.d.ts +7 -0
- package/dist-runtime/config/rpc.js +19 -0
- package/dist-runtime/config/rpc.js.map +1 -0
- package/dist-runtime/config/zksyncSolcPath.d.ts +1 -0
- package/dist-runtime/config/zksyncSolcPath.js +61 -0
- package/dist-runtime/config/zksyncSolcPath.js.map +1 -0
- package/dist-runtime/migrate.d.ts +13 -0
- package/dist-runtime/migrate.js +208 -0
- package/dist-runtime/migrate.js.map +1 -0
- package/dist-runtime/package.json +1 -0
- package/dist-runtime/projectHardhat.d.ts +4 -0
- package/dist-runtime/projectHardhat.js +16 -0
- package/dist-runtime/projectHardhat.js.map +1 -0
- package/dist-runtime/runtime-identity.json +4 -0
- package/dist-runtime/template-migration.json +293 -0
- package/dist-runtime/workflow/checkCode.d.ts +1 -0
- package/dist-runtime/workflow/checkCode.js +16 -0
- package/dist-runtime/workflow/checkCode.js.map +1 -0
- package/dist-runtime/workflow/checkCodeFinalize.d.ts +1 -0
- package/dist-runtime/workflow/checkCodeFinalize.js +11 -0
- package/dist-runtime/workflow/checkCodeFinalize.js.map +1 -0
- package/dist-runtime/workflow/checkCodePlan.d.ts +1 -0
- package/dist-runtime/workflow/checkCodePlan.js +11 -0
- package/dist-runtime/workflow/checkCodePlan.js.map +1 -0
- package/dist-runtime/workflow/cli.d.ts +1 -0
- package/dist-runtime/workflow/cli.js +302 -0
- package/dist-runtime/workflow/cli.js.map +1 -0
- package/dist-runtime/workflow/commitContractInfo.d.ts +1 -0
- package/dist-runtime/workflow/commitContractInfo.js +64 -0
- package/dist-runtime/workflow/commitContractInfo.js.map +1 -0
- package/dist-runtime/workflow/create2Hashes.d.ts +1 -0
- package/dist-runtime/workflow/create2Hashes.js +76 -0
- package/dist-runtime/workflow/create2Hashes.js.map +1 -0
- package/dist-runtime/workflow/forkSourceProxy.d.ts +1 -0
- package/dist-runtime/workflow/forkSourceProxy.js +151 -0
- package/dist-runtime/workflow/forkSourceProxy.js.map +1 -0
- package/dist-runtime/workflow/importState.d.ts +1 -0
- package/dist-runtime/workflow/importState.js +193 -0
- package/dist-runtime/workflow/importState.js.map +1 -0
- package/dist-runtime/workflow/lib/authority.d.ts +28 -0
- package/dist-runtime/workflow/lib/authority.js +122 -0
- package/dist-runtime/workflow/lib/authority.js.map +1 -0
- package/dist-runtime/workflow/lib/calldata.d.ts +2 -0
- package/dist-runtime/workflow/lib/calldata.js +8 -0
- package/dist-runtime/workflow/lib/calldata.js.map +1 -0
- package/dist-runtime/workflow/lib/calls.d.ts +23 -0
- package/dist-runtime/workflow/lib/calls.js +316 -0
- package/dist-runtime/workflow/lib/calls.js.map +1 -0
- package/dist-runtime/workflow/lib/checkCode/args.d.ts +2 -0
- package/dist-runtime/workflow/lib/checkCode/args.js +68 -0
- package/dist-runtime/workflow/lib/checkCode/args.js.map +1 -0
- package/dist-runtime/workflow/lib/checkCode/command.d.ts +5 -0
- package/dist-runtime/workflow/lib/checkCode/command.js +35 -0
- package/dist-runtime/workflow/lib/checkCode/command.js.map +1 -0
- package/dist-runtime/workflow/lib/checkCode/dependencies.d.ts +6 -0
- package/dist-runtime/workflow/lib/checkCode/dependencies.js +125 -0
- package/dist-runtime/workflow/lib/checkCode/dependencies.js.map +1 -0
- package/dist-runtime/workflow/lib/checkCode/finalize.d.ts +17 -0
- package/dist-runtime/workflow/lib/checkCode/finalize.js +174 -0
- package/dist-runtime/workflow/lib/checkCode/finalize.js.map +1 -0
- package/dist-runtime/workflow/lib/checkCode/index.d.ts +3 -0
- package/dist-runtime/workflow/lib/checkCode/index.js +20 -0
- package/dist-runtime/workflow/lib/checkCode/index.js.map +1 -0
- package/dist-runtime/workflow/lib/checkCode/plan.d.ts +22 -0
- package/dist-runtime/workflow/lib/checkCode/plan.js +145 -0
- package/dist-runtime/workflow/lib/checkCode/plan.js.map +1 -0
- package/dist-runtime/workflow/lib/checkCodeReport.d.ts +25 -0
- package/dist-runtime/workflow/lib/checkCodeReport.js +102 -0
- package/dist-runtime/workflow/lib/checkCodeReport.js.map +1 -0
- package/dist-runtime/workflow/lib/checkCodeRunner.d.ts +87 -0
- package/dist-runtime/workflow/lib/checkCodeRunner.js +964 -0
- package/dist-runtime/workflow/lib/checkCodeRunner.js.map +1 -0
- package/dist-runtime/workflow/lib/cliTool.d.ts +10 -0
- package/dist-runtime/workflow/lib/cliTool.js +25 -0
- package/dist-runtime/workflow/lib/cliTool.js.map +1 -0
- package/dist-runtime/workflow/lib/config.d.ts +33 -0
- package/dist-runtime/workflow/lib/config.js +100 -0
- package/dist-runtime/workflow/lib/config.js.map +1 -0
- package/dist-runtime/workflow/lib/contractInfoCandidates.d.ts +82 -0
- package/dist-runtime/workflow/lib/contractInfoCandidates.js +441 -0
- package/dist-runtime/workflow/lib/contractInfoCandidates.js.map +1 -0
- package/dist-runtime/workflow/lib/controlledMulticallAbi.d.ts +2 -0
- package/dist-runtime/workflow/lib/controlledMulticallAbi.js +10 -0
- package/dist-runtime/workflow/lib/controlledMulticallAbi.js.map +1 -0
- package/dist-runtime/workflow/lib/create2.d.ts +49 -0
- package/dist-runtime/workflow/lib/create2.js +194 -0
- package/dist-runtime/workflow/lib/create2.js.map +1 -0
- package/dist-runtime/workflow/lib/create2Hashes.d.ts +22 -0
- package/dist-runtime/workflow/lib/create2Hashes.js +57 -0
- package/dist-runtime/workflow/lib/create2Hashes.js.map +1 -0
- package/dist-runtime/workflow/lib/deploymentInfo.d.ts +40 -0
- package/dist-runtime/workflow/lib/deploymentInfo.js +240 -0
- package/dist-runtime/workflow/lib/deploymentInfo.js.map +1 -0
- package/dist-runtime/workflow/lib/deploymentRecords.d.ts +137 -0
- package/dist-runtime/workflow/lib/deploymentRecords.js +374 -0
- package/dist-runtime/workflow/lib/deploymentRecords.js.map +1 -0
- package/dist-runtime/workflow/lib/deployments.d.ts +21 -0
- package/dist-runtime/workflow/lib/deployments.js +240 -0
- package/dist-runtime/workflow/lib/deployments.js.map +1 -0
- package/dist-runtime/workflow/lib/erc1967.d.ts +5 -0
- package/dist-runtime/workflow/lib/erc1967.js +29 -0
- package/dist-runtime/workflow/lib/erc1967.js.map +1 -0
- package/dist-runtime/workflow/lib/errors.d.ts +6 -0
- package/dist-runtime/workflow/lib/errors.js +77 -0
- package/dist-runtime/workflow/lib/errors.js.map +1 -0
- package/dist-runtime/workflow/lib/executionId.d.ts +7 -0
- package/dist-runtime/workflow/lib/executionId.js +26 -0
- package/dist-runtime/workflow/lib/executionId.js.map +1 -0
- package/dist-runtime/workflow/lib/executionPlan.d.ts +85 -0
- package/dist-runtime/workflow/lib/executionPlan.js +450 -0
- package/dist-runtime/workflow/lib/executionPlan.js.map +1 -0
- package/dist-runtime/workflow/lib/executionProgress.d.ts +5 -0
- package/dist-runtime/workflow/lib/executionProgress.js +100 -0
- package/dist-runtime/workflow/lib/executionProgress.js.map +1 -0
- package/dist-runtime/workflow/lib/external.d.ts +62 -0
- package/dist-runtime/workflow/lib/external.js +282 -0
- package/dist-runtime/workflow/lib/external.js.map +1 -0
- package/dist-runtime/workflow/lib/externalExecutionScanner.d.ts +64 -0
- package/dist-runtime/workflow/lib/externalExecutionScanner.js +638 -0
- package/dist-runtime/workflow/lib/externalExecutionScanner.js.map +1 -0
- package/dist-runtime/workflow/lib/forkSnapshot.d.ts +34 -0
- package/dist-runtime/workflow/lib/forkSnapshot.js +167 -0
- package/dist-runtime/workflow/lib/forkSnapshot.js.map +1 -0
- package/dist-runtime/workflow/lib/gateTool.d.ts +16 -0
- package/dist-runtime/workflow/lib/gateTool.js +177 -0
- package/dist-runtime/workflow/lib/gateTool.js.map +1 -0
- package/dist-runtime/workflow/lib/gateToolSync.d.ts +22 -0
- package/dist-runtime/workflow/lib/gateToolSync.js +253 -0
- package/dist-runtime/workflow/lib/gateToolSync.js.map +1 -0
- package/dist-runtime/workflow/lib/lock.d.ts +52 -0
- package/dist-runtime/workflow/lib/lock.js +269 -0
- package/dist-runtime/workflow/lib/lock.js.map +1 -0
- package/dist-runtime/workflow/lib/migrationState.d.ts +103 -0
- package/dist-runtime/workflow/lib/migrationState.js +920 -0
- package/dist-runtime/workflow/lib/migrationState.js.map +1 -0
- package/dist-runtime/workflow/lib/operatorExecution.d.ts +28 -0
- package/dist-runtime/workflow/lib/operatorExecution.js +134 -0
- package/dist-runtime/workflow/lib/operatorExecution.js.map +1 -0
- package/dist-runtime/workflow/lib/parameters.d.ts +58 -0
- package/dist-runtime/workflow/lib/parameters.js +323 -0
- package/dist-runtime/workflow/lib/parameters.js.map +1 -0
- package/dist-runtime/workflow/lib/pendingDeploymentReuse.d.ts +29 -0
- package/dist-runtime/workflow/lib/pendingDeploymentReuse.js +277 -0
- package/dist-runtime/workflow/lib/pendingDeploymentReuse.js.map +1 -0
- package/dist-runtime/workflow/lib/proxy.d.ts +18 -0
- package/dist-runtime/workflow/lib/proxy.js +19 -0
- package/dist-runtime/workflow/lib/proxy.js.map +1 -0
- package/dist-runtime/workflow/lib/registryCommit.d.ts +33 -0
- package/dist-runtime/workflow/lib/registryCommit.js +319 -0
- package/dist-runtime/workflow/lib/registryCommit.js.map +1 -0
- package/dist-runtime/workflow/lib/release.d.ts +57 -0
- package/dist-runtime/workflow/lib/release.js +256 -0
- package/dist-runtime/workflow/lib/release.js.map +1 -0
- package/dist-runtime/workflow/lib/releaseFinalize.d.ts +14 -0
- package/dist-runtime/workflow/lib/releaseFinalize.js +571 -0
- package/dist-runtime/workflow/lib/releaseFinalize.js.map +1 -0
- package/dist-runtime/workflow/lib/releaseParameters.d.ts +43 -0
- package/dist-runtime/workflow/lib/releaseParameters.js +184 -0
- package/dist-runtime/workflow/lib/releaseParameters.js.map +1 -0
- package/dist-runtime/workflow/lib/reporter.d.ts +39 -0
- package/dist-runtime/workflow/lib/reporter.js +452 -0
- package/dist-runtime/workflow/lib/reporter.js.map +1 -0
- package/dist-runtime/workflow/lib/resultPaths.d.ts +17 -0
- package/dist-runtime/workflow/lib/resultPaths.js +29 -0
- package/dist-runtime/workflow/lib/resultPaths.js.map +1 -0
- package/dist-runtime/workflow/lib/runtimeVersion.d.ts +10 -0
- package/dist-runtime/workflow/lib/runtimeVersion.js +46 -0
- package/dist-runtime/workflow/lib/runtimeVersion.js.map +1 -0
- package/dist-runtime/workflow/lib/signer.d.ts +10 -0
- package/dist-runtime/workflow/lib/signer.js +105 -0
- package/dist-runtime/workflow/lib/signer.js.map +1 -0
- package/dist-runtime/workflow/lib/signerIdentity.d.ts +1 -0
- package/dist-runtime/workflow/lib/signerIdentity.js +23 -0
- package/dist-runtime/workflow/lib/signerIdentity.js.map +1 -0
- package/dist-runtime/workflow/lib/simulation.d.ts +35 -0
- package/dist-runtime/workflow/lib/simulation.js +282 -0
- package/dist-runtime/workflow/lib/simulation.js.map +1 -0
- package/dist-runtime/workflow/lib/simulationCallers.d.ts +44 -0
- package/dist-runtime/workflow/lib/simulationCallers.js +260 -0
- package/dist-runtime/workflow/lib/simulationCallers.js.map +1 -0
- package/dist-runtime/workflow/lib/sourceRpcPolicy.d.ts +1 -0
- package/dist-runtime/workflow/lib/sourceRpcPolicy.js +43 -0
- package/dist-runtime/workflow/lib/sourceRpcPolicy.js.map +1 -0
- package/dist-runtime/workflow/lib/state.d.ts +6 -0
- package/dist-runtime/workflow/lib/state.js +25 -0
- package/dist-runtime/workflow/lib/state.js.map +1 -0
- package/dist-runtime/workflow/lib/staticValidation.d.ts +22 -0
- package/dist-runtime/workflow/lib/staticValidation.js +124 -0
- package/dist-runtime/workflow/lib/staticValidation.js.map +1 -0
- package/dist-runtime/workflow/lib/zksyncForkCapability.d.ts +27 -0
- package/dist-runtime/workflow/lib/zksyncForkCapability.js +52 -0
- package/dist-runtime/workflow/lib/zksyncForkCapability.js.map +1 -0
- package/dist-runtime/workflow/lib/zksyncForkRunner.d.ts +57 -0
- package/dist-runtime/workflow/lib/zksyncForkRunner.js +344 -0
- package/dist-runtime/workflow/lib/zksyncForkRunner.js.map +1 -0
- package/dist-runtime/workflow/reconcileExternal.d.ts +1 -0
- package/dist-runtime/workflow/reconcileExternal.js +87 -0
- package/dist-runtime/workflow/reconcileExternal.js.map +1 -0
- package/dist-runtime/workflow/reconcileExternalRun.d.ts +1 -0
- package/dist-runtime/workflow/reconcileExternalRun.js +77 -0
- package/dist-runtime/workflow/reconcileExternalRun.js.map +1 -0
- package/dist-runtime/workflow/releaseFinalize.d.ts +1 -0
- package/dist-runtime/workflow/releaseFinalize.js +11 -0
- package/dist-runtime/workflow/releaseFinalize.js.map +1 -0
- package/dist-runtime/workflow/run.d.ts +40 -0
- package/dist-runtime/workflow/run.js +858 -0
- package/dist-runtime/workflow/run.js.map +1 -0
- package/dist-runtime/workflow/staticValidate.d.ts +1 -0
- package/dist-runtime/workflow/staticValidate.js +26 -0
- package/dist-runtime/workflow/staticValidate.js.map +1 -0
- package/dist-runtime/workflow/steps/call.d.ts +3 -0
- package/dist-runtime/workflow/steps/call.js +9 -0
- package/dist-runtime/workflow/steps/call.js.map +1 -0
- package/dist-runtime/workflow/steps/check.d.ts +3 -0
- package/dist-runtime/workflow/steps/check.js +9 -0
- package/dist-runtime/workflow/steps/check.js.map +1 -0
- package/dist-runtime/workflow/steps/custom.d.ts +3 -0
- package/dist-runtime/workflow/steps/custom.js +33 -0
- package/dist-runtime/workflow/steps/custom.js.map +1 -0
- package/dist-runtime/workflow/steps/deploy.d.ts +3 -0
- package/dist-runtime/workflow/steps/deploy.js +596 -0
- package/dist-runtime/workflow/steps/deploy.js.map +1 -0
- package/dist-runtime/workflow/steps/upgrade.d.ts +3 -0
- package/dist-runtime/workflow/steps/upgrade.js +466 -0
- package/dist-runtime/workflow/steps/upgrade.js.map +1 -0
- package/dist-runtime/workflow/steps/view.d.ts +3 -0
- package/dist-runtime/workflow/steps/view.js +9 -0
- package/dist-runtime/workflow/steps/view.js.map +1 -0
- package/docs/direct-package-acceptance.md +20 -0
- package/docs/external-infrastructure-acceptance.md +33 -0
- package/docs/network-runtime-acceptance.md +18 -0
- package/docs/plans/2026-09-09-workflow-extraction.md +16 -0
- package/docs/superpowers/plans/2026-07-22-manifest-bootstrap-transaction.md +50 -0
- package/docs/superpowers/plans/2026-07-22-manifest-review-remediation.md +49 -0
- package/docs/superpowers/plans/2026-08-17-custody-hardhat-signers.md +227 -0
- package/docs/superpowers/plans/2026-09-09-remove-template-infrastructure-contracts.md +11 -0
- package/docs/workflow-reference.md +1181 -0
- package/docs/workflow-runtime-acceptance.md +17 -0
- package/docs/workflow-runtime.md +56 -0
- package/package.json +26 -5
- package/runtime/config/hardhatAdapters.ts +58 -0
- package/runtime/config/networks.ts +305 -0
- package/runtime/config/openzeppelin.ts +173 -0
- package/runtime/config/rpc.ts +27 -0
- package/runtime/config/zksyncSolcPath.ts +59 -0
- package/runtime/hardhat-types.d.ts +2 -0
- package/runtime/migrate.ts +154 -0
- package/runtime/projectHardhat.ts +10 -0
- package/runtime/template-migration.json +293 -0
- package/runtime/workflow/checkCode.ts +13 -0
- package/runtime/workflow/checkCodeFinalize.ts +8 -0
- package/runtime/workflow/checkCodePlan.ts +8 -0
- package/runtime/workflow/cli.ts +356 -0
- package/runtime/workflow/commitContractInfo.ts +63 -0
- package/runtime/workflow/create2Hashes.ts +79 -0
- package/runtime/workflow/forkSourceProxy.ts +193 -0
- package/runtime/workflow/importState.ts +190 -0
- package/runtime/workflow/lib/authority.ts +170 -0
- package/runtime/workflow/lib/calldata.ts +9 -0
- package/runtime/workflow/lib/calls.ts +407 -0
- package/runtime/workflow/lib/checkCode/args.ts +76 -0
- package/runtime/workflow/lib/checkCode/command.ts +36 -0
- package/runtime/workflow/lib/checkCode/dependencies.ts +112 -0
- package/runtime/workflow/lib/checkCode/finalize.ts +198 -0
- package/runtime/workflow/lib/checkCode/index.ts +18 -0
- package/runtime/workflow/lib/checkCode/plan.ts +163 -0
- package/runtime/workflow/lib/checkCodeReport.ts +133 -0
- package/runtime/workflow/lib/checkCodeRunner.ts +1225 -0
- package/runtime/workflow/lib/cliTool.ts +31 -0
- package/runtime/workflow/lib/config.ts +130 -0
- package/runtime/workflow/lib/contractInfoCandidates.ts +690 -0
- package/runtime/workflow/lib/controlledMulticallAbi.ts +6 -0
- package/runtime/workflow/lib/create2.ts +278 -0
- package/runtime/workflow/lib/create2Hashes.ts +83 -0
- package/runtime/workflow/lib/deploymentInfo.ts +286 -0
- package/runtime/workflow/lib/deploymentRecords.ts +576 -0
- package/runtime/workflow/lib/deployments.ts +276 -0
- package/runtime/workflow/lib/erc1967.ts +57 -0
- package/runtime/workflow/lib/errors.ts +95 -0
- package/runtime/workflow/lib/executionId.ts +35 -0
- package/runtime/workflow/lib/executionPlan.ts +550 -0
- package/runtime/workflow/lib/executionProgress.ts +127 -0
- package/runtime/workflow/lib/external.ts +372 -0
- package/runtime/workflow/lib/externalExecutionScanner.ts +892 -0
- package/runtime/workflow/lib/forkSnapshot.ts +231 -0
- package/runtime/workflow/lib/gateTool.ts +261 -0
- package/runtime/workflow/lib/gateToolSync.ts +398 -0
- package/runtime/workflow/lib/lock.ts +388 -0
- package/runtime/workflow/lib/migrationState.ts +1246 -0
- package/runtime/workflow/lib/operatorExecution.ts +174 -0
- package/runtime/workflow/lib/parameters.ts +438 -0
- package/runtime/workflow/lib/pendingDeploymentReuse.ts +428 -0
- package/runtime/workflow/lib/proxy.ts +45 -0
- package/runtime/workflow/lib/registryCommit.ts +455 -0
- package/runtime/workflow/lib/release.ts +329 -0
- package/runtime/workflow/lib/releaseFinalize.ts +711 -0
- package/runtime/workflow/lib/releaseParameters.ts +248 -0
- package/runtime/workflow/lib/reporter.ts +502 -0
- package/runtime/workflow/lib/resultPaths.ts +49 -0
- package/runtime/workflow/lib/runtimeVersion.ts +28 -0
- package/runtime/workflow/lib/signer.ts +124 -0
- package/runtime/workflow/lib/signerIdentity.ts +22 -0
- package/runtime/workflow/lib/simulation.ts +415 -0
- package/runtime/workflow/lib/simulationCallers.ts +335 -0
- package/runtime/workflow/lib/sourceRpcPolicy.ts +41 -0
- package/runtime/workflow/lib/state.ts +25 -0
- package/runtime/workflow/lib/staticValidation.ts +142 -0
- package/runtime/workflow/lib/zksyncForkCapability.ts +80 -0
- package/runtime/workflow/lib/zksyncForkRunner.ts +505 -0
- package/runtime/workflow/reconcileExternal.ts +86 -0
- package/runtime/workflow/reconcileExternalRun.ts +88 -0
- package/runtime/workflow/releaseFinalize.ts +8 -0
- package/runtime/workflow/run.ts +1072 -0
- package/runtime/workflow/staticValidate.ts +23 -0
- package/runtime/workflow/steps/call.ts +10 -0
- package/runtime/workflow/steps/check.ts +10 -0
- package/runtime/workflow/steps/custom.ts +43 -0
- package/runtime/workflow/steps/deploy.ts +772 -0
- package/runtime/workflow/steps/upgrade.ts +599 -0
- package/runtime/workflow/steps/view.ts +10 -0
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.reconcileExternalExecution = void 0;
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const ethers_1 = require("ethers");
|
|
11
|
+
const executionPlan_1 = require("./executionPlan");
|
|
12
|
+
const external_1 = require("./external");
|
|
13
|
+
const operatorExecution_1 = require("./operatorExecution");
|
|
14
|
+
const deploymentRecords_1 = require("./deploymentRecords");
|
|
15
|
+
const config_1 = require("./config");
|
|
16
|
+
const gateToolSync_1 = require("./gateToolSync");
|
|
17
|
+
const SAFE_INTERFACE = new ethers_1.Interface([
|
|
18
|
+
"function execTransaction(address to,uint256 value,bytes data,uint8 operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address payable refundReceiver,bytes signatures) returns (bool success)",
|
|
19
|
+
"function VERSION() view returns (string)",
|
|
20
|
+
"event ExecutionSuccess(bytes32 txHash,uint256 payment)",
|
|
21
|
+
"event ExecutionFailure(bytes32 txHash,uint256 payment)",
|
|
22
|
+
]);
|
|
23
|
+
const MULTISEND_INTERFACE = new ethers_1.Interface([
|
|
24
|
+
"function multiSend(bytes transactions)",
|
|
25
|
+
]);
|
|
26
|
+
const sha256 = (value) => (crypto_1.default.createHash("sha256").update(value).digest("hex"));
|
|
27
|
+
const numberValue = (value, label) => {
|
|
28
|
+
let parsed;
|
|
29
|
+
try {
|
|
30
|
+
parsed = typeof value === "bigint" ? value : BigInt(value);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
throw new Error(`${label} is not an integer`);
|
|
34
|
+
}
|
|
35
|
+
if (parsed < 0n || parsed > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
36
|
+
throw new Error(`${label} is outside the safe integer range`);
|
|
37
|
+
}
|
|
38
|
+
return Number(parsed);
|
|
39
|
+
};
|
|
40
|
+
const address = (value, label) => {
|
|
41
|
+
if (typeof value !== "string" || !/^0x[0-9a-fA-F]{40}$/.test(value)) {
|
|
42
|
+
throw new Error(`${label} is not an EVM address`);
|
|
43
|
+
}
|
|
44
|
+
return value.toLowerCase();
|
|
45
|
+
};
|
|
46
|
+
const calldata = (transaction) => {
|
|
47
|
+
const value = transaction.data ?? transaction.input;
|
|
48
|
+
if (typeof value !== "string" || !/^0x(?:[0-9a-fA-F]{2})*$/.test(value)) {
|
|
49
|
+
throw new Error(`Transaction ${transaction.hash} has invalid calldata`);
|
|
50
|
+
}
|
|
51
|
+
return value.toLowerCase();
|
|
52
|
+
};
|
|
53
|
+
const receiptStatus = (receipt) => {
|
|
54
|
+
const status = numberValue(receipt.status, "receipt status");
|
|
55
|
+
if (status !== 0 && status !== 1)
|
|
56
|
+
throw new Error("receipt status must be 0 or 1");
|
|
57
|
+
return status;
|
|
58
|
+
};
|
|
59
|
+
const relative = (root, filePath) => {
|
|
60
|
+
const value = path_1.default.relative(path_1.default.resolve(root), path_1.default.resolve(filePath));
|
|
61
|
+
if (value.startsWith("..") || path_1.default.isAbsolute(value)) {
|
|
62
|
+
throw new Error("Reconciliation evidence path escapes the project root");
|
|
63
|
+
}
|
|
64
|
+
return value.split(path_1.default.sep).join("/");
|
|
65
|
+
};
|
|
66
|
+
const readJson = (filePath, label) => {
|
|
67
|
+
try {
|
|
68
|
+
return JSON.parse(fs_1.default.readFileSync(filePath, "utf8"));
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
throw new Error(`${label} is invalid: ${error instanceof Error ? error.message : String(error)}`);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const writeJsonAtomic = (filePath, value) => {
|
|
75
|
+
fs_1.default.mkdirSync(path_1.default.dirname(filePath), { recursive: true });
|
|
76
|
+
const temporary = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
77
|
+
try {
|
|
78
|
+
fs_1.default.writeFileSync(temporary, JSON.stringify(value, null, 2) + "\n");
|
|
79
|
+
fs_1.default.renameSync(temporary, filePath);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
if (fs_1.default.existsSync(temporary))
|
|
83
|
+
fs_1.default.unlinkSync(temporary);
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const loadExternalPackage = (input) => {
|
|
88
|
+
const externalTransactions = input.plan.transactions.filter((transaction) => (transaction.route === "external"));
|
|
89
|
+
const filePath = path_1.default.join(input.taskDir, "calldata", input.plan.target, input.plan.executionId, "external-execution.json");
|
|
90
|
+
if (externalTransactions.length === 0) {
|
|
91
|
+
if (fs_1.default.existsSync(filePath)) {
|
|
92
|
+
throw new Error("All-operator execution must not contain an external package");
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
const loaded = (0, external_1.loadExternalExecutionPackage)({ taskDir: input.taskDir, plan: input.plan });
|
|
97
|
+
if (!loaded)
|
|
98
|
+
return undefined;
|
|
99
|
+
return {
|
|
100
|
+
package: loaded.package,
|
|
101
|
+
filePath: loaded.filePath,
|
|
102
|
+
hash: sha256(fs_1.default.readFileSync(loaded.filePath)),
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
const transactionMatches = (transaction, expected, from) => (address(transaction.from, "transaction sender") === address(from, "expected sender")
|
|
106
|
+
&& transaction.to !== null
|
|
107
|
+
&& address(transaction.to, "transaction target") === expected.to
|
|
108
|
+
&& numberValue(transaction.value, "transaction value").toString() === expected.value
|
|
109
|
+
&& calldata(transaction) === expected.data
|
|
110
|
+
&& expected.operation === 0);
|
|
111
|
+
const parseMultisend = (encoded) => {
|
|
112
|
+
const payload = encoded.startsWith("0x") ? encoded.slice(2) : encoded;
|
|
113
|
+
const calls = [];
|
|
114
|
+
let offset = 0;
|
|
115
|
+
while (offset < payload.length) {
|
|
116
|
+
if (payload.length - offset < 2 + 40 + 64 + 64) {
|
|
117
|
+
throw new Error("Safe MultiSend payload is truncated");
|
|
118
|
+
}
|
|
119
|
+
const operation = Number.parseInt(payload.slice(offset, offset + 2), 16);
|
|
120
|
+
offset += 2;
|
|
121
|
+
if (operation !== 0 && operation !== 1)
|
|
122
|
+
throw new Error("Safe MultiSend operation is invalid");
|
|
123
|
+
const to = `0x${payload.slice(offset, offset + 40)}`.toLowerCase();
|
|
124
|
+
offset += 40;
|
|
125
|
+
const value = BigInt(`0x${payload.slice(offset, offset + 64)}`).toString(10);
|
|
126
|
+
offset += 64;
|
|
127
|
+
const length = numberValue(`0x${payload.slice(offset, offset + 64)}`, "MultiSend data length");
|
|
128
|
+
offset += 64;
|
|
129
|
+
const end = offset + length * 2;
|
|
130
|
+
if (end > payload.length)
|
|
131
|
+
throw new Error("Safe MultiSend call data is truncated");
|
|
132
|
+
calls.push({ operation, to, value, data: `0x${payload.slice(offset, end)}`.toLowerCase() });
|
|
133
|
+
offset = end;
|
|
134
|
+
}
|
|
135
|
+
return calls;
|
|
136
|
+
};
|
|
137
|
+
const safeCalls = async (provider, transaction, safeAddress) => {
|
|
138
|
+
if (address(transaction.to, "Safe transaction target") !== safeAddress)
|
|
139
|
+
return [];
|
|
140
|
+
if (!provider.call)
|
|
141
|
+
throw new Error(`Unknown contract-wallet executor ${safeAddress}`);
|
|
142
|
+
try {
|
|
143
|
+
const versionResult = await provider.call({
|
|
144
|
+
to: safeAddress,
|
|
145
|
+
data: SAFE_INTERFACE.encodeFunctionData("VERSION", []),
|
|
146
|
+
});
|
|
147
|
+
SAFE_INTERFACE.decodeFunctionResult("VERSION", versionResult);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
throw new Error(`Unknown contract-wallet executor ${safeAddress}`);
|
|
151
|
+
}
|
|
152
|
+
let decoded;
|
|
153
|
+
try {
|
|
154
|
+
decoded = SAFE_INTERFACE.decodeFunctionData("execTransaction", calldata(transaction));
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
const outer = {
|
|
160
|
+
to: address(decoded[0], "Safe inner target"),
|
|
161
|
+
value: BigInt(decoded[1]).toString(10),
|
|
162
|
+
data: String(decoded[2]).toLowerCase(),
|
|
163
|
+
operation: Number(decoded[3]),
|
|
164
|
+
};
|
|
165
|
+
try {
|
|
166
|
+
const multisend = MULTISEND_INTERFACE.decodeFunctionData("multiSend", outer.data);
|
|
167
|
+
return parseMultisend(String(multisend[0])).map((call, innerCallIndex) => ({
|
|
168
|
+
...call,
|
|
169
|
+
kind: "safe_multisend",
|
|
170
|
+
innerCallIndex,
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return [{ ...outer, kind: "safe_call" }];
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
const assertSafeExecutionSucceeded = (receipt, safeAddress) => {
|
|
178
|
+
let success = false;
|
|
179
|
+
let failure = false;
|
|
180
|
+
for (const log of receipt.logs || []) {
|
|
181
|
+
if (typeof log.address !== "string"
|
|
182
|
+
|| log.address.toLowerCase() !== safeAddress.toLowerCase()
|
|
183
|
+
|| !Array.isArray(log.topics)
|
|
184
|
+
|| typeof log.data !== "string") {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
const parsed = SAFE_INTERFACE.parseLog({ topics: log.topics, data: log.data });
|
|
189
|
+
if (parsed?.name === "ExecutionFailure")
|
|
190
|
+
failure = true;
|
|
191
|
+
if (parsed?.name === "ExecutionSuccess")
|
|
192
|
+
success = true;
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// Ignore unrelated logs emitted by the Safe transaction.
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (failure)
|
|
199
|
+
throw new Error(`Safe ${safeAddress} emitted ExecutionFailure`);
|
|
200
|
+
if (!success)
|
|
201
|
+
throw new Error(`Safe ${safeAddress} receipt is missing ExecutionSuccess`);
|
|
202
|
+
};
|
|
203
|
+
const finalizedHeight = async (provider, confirmations) => {
|
|
204
|
+
try {
|
|
205
|
+
const block = await provider.send("eth_getBlockByNumber", ["finalized", false]);
|
|
206
|
+
if (block?.number !== undefined) {
|
|
207
|
+
return {
|
|
208
|
+
finalizedBlock: numberValue(block.number, "finalized block number"),
|
|
209
|
+
policy: { mode: "rpc_finalized" },
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
// Some EVM RPC providers do not implement the finalized block tag.
|
|
215
|
+
}
|
|
216
|
+
const latest = await provider.getBlockNumber();
|
|
217
|
+
if (!Number.isSafeInteger(latest) || latest < 0) {
|
|
218
|
+
throw new Error("RPC latest block number is invalid");
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
finalizedBlock: Math.max(0, latest - confirmations),
|
|
222
|
+
policy: { mode: "confirmation_depth", confirmations },
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
const receiptMatch = (expected, transaction, receipt, finalizedBlock, details) => {
|
|
226
|
+
const blockNumber = numberValue(receipt.blockNumber, "receipt blockNumber");
|
|
227
|
+
const blockTransactionIndex = numberValue(receipt.index ?? receipt.transactionIndex ?? transaction.index ?? transaction.transactionIndex ?? 0, "receipt transaction index");
|
|
228
|
+
return {
|
|
229
|
+
transactionId: expected.transactionId,
|
|
230
|
+
transactionIndex: expected.transactionIndex,
|
|
231
|
+
route: expected.route,
|
|
232
|
+
executor: expected.executor,
|
|
233
|
+
submittedBy: address(details.submittedBy, "submittedBy"),
|
|
234
|
+
executionKind: details.executionKind,
|
|
235
|
+
transactionHash: transaction.hash.toLowerCase(),
|
|
236
|
+
blockNumber,
|
|
237
|
+
blockHash: receipt.blockHash.toLowerCase(),
|
|
238
|
+
blockTransactionIndex,
|
|
239
|
+
innerCallIndex: details.innerCallIndex,
|
|
240
|
+
receiptStatus: receiptStatus(receipt),
|
|
241
|
+
finalized: blockNumber <= finalizedBlock,
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
const validateCanonicalReceipt = async (provider, receipt) => {
|
|
245
|
+
const blockNumber = numberValue(receipt.blockNumber, "receipt blockNumber");
|
|
246
|
+
const block = await provider.send("eth_getBlockByNumber", [`0x${blockNumber.toString(16)}`, false]);
|
|
247
|
+
if (!block?.hash || block.hash.toLowerCase() !== receipt.blockHash.toLowerCase()) {
|
|
248
|
+
throw new Error("Transaction receipt is no longer in the canonical chain");
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
const reconcileExternalExecution = async (input) => {
|
|
252
|
+
const provider = input.provider;
|
|
253
|
+
const taskDir = path_1.default.join(input.root, "scripts", "tasks", input.taskId);
|
|
254
|
+
const plan = (0, executionPlan_1.loadReleaseExecutionPlan)({
|
|
255
|
+
root: input.root,
|
|
256
|
+
taskDir,
|
|
257
|
+
target: input.network,
|
|
258
|
+
executionId: input.executionId,
|
|
259
|
+
});
|
|
260
|
+
if (plan.taskId !== input.taskId)
|
|
261
|
+
throw new Error("Execution plan taskId mismatch");
|
|
262
|
+
const packageEvidence = loadExternalPackage({ root: input.root, taskDir, plan });
|
|
263
|
+
const operatorResultPath = path_1.default.join(taskDir, "results", plan.target, plan.executionId, "operator-execution.json");
|
|
264
|
+
const operatorResult = fs_1.default.existsSync(operatorResultPath)
|
|
265
|
+
? (0, operatorExecution_1.loadOperatorExecutionResult)({ taskDir, plan })
|
|
266
|
+
: undefined;
|
|
267
|
+
const reportFile = path_1.default.join(taskDir, "results", input.network, input.executionId, "external-reconciliation.json");
|
|
268
|
+
const reportPath = relative(input.root, reportFile);
|
|
269
|
+
const previous = fs_1.default.existsSync(reportFile)
|
|
270
|
+
? readJson(reportFile, "external reconciliation report")
|
|
271
|
+
: undefined;
|
|
272
|
+
if (previous
|
|
273
|
+
&& (previous.version !== 1
|
|
274
|
+
|| previous.taskId !== input.taskId
|
|
275
|
+
|| previous.target !== input.network
|
|
276
|
+
|| previous.executionId !== input.executionId
|
|
277
|
+
|| previous.executionPlanHash !== plan.planHash)) {
|
|
278
|
+
throw new Error("Persisted reconciliation report does not match this execution");
|
|
279
|
+
}
|
|
280
|
+
const target = (0, config_1.resolveTarget)((0, config_1.loadConfig)(input.root), input.network);
|
|
281
|
+
const confirmations = (0, config_1.resolveFinalityConfirmations)(target, input.network);
|
|
282
|
+
const finality = await finalizedHeight(provider, confirmations);
|
|
283
|
+
const { finalizedBlock } = finality;
|
|
284
|
+
const matches = new Map();
|
|
285
|
+
let failure;
|
|
286
|
+
try {
|
|
287
|
+
for (const evidence of operatorResult?.receipts ?? []) {
|
|
288
|
+
const expected = plan.transactions.find((transaction) => (transaction.transactionId === evidence.transactionId));
|
|
289
|
+
if (!expected || expected.route !== "operator") {
|
|
290
|
+
throw new Error(`Operator receipt ${evidence.transactionId} does not match the plan`);
|
|
291
|
+
}
|
|
292
|
+
const transaction = await provider.getTransaction(evidence.transactionHash);
|
|
293
|
+
const receipt = await provider.getTransactionReceipt(evidence.transactionHash);
|
|
294
|
+
if (!transaction || !receipt)
|
|
295
|
+
continue;
|
|
296
|
+
await validateCanonicalReceipt(provider, receipt);
|
|
297
|
+
if (!transactionMatches(transaction, expected, expected.executor)) {
|
|
298
|
+
throw new Error(`Operator transaction ${expected.transactionId} does not match the plan`);
|
|
299
|
+
}
|
|
300
|
+
matches.set(expected.transactionId, receiptMatch(expected, transaction, receipt, finalizedBlock, { executionKind: "eoa", submittedBy: transaction.from }));
|
|
301
|
+
}
|
|
302
|
+
for (const previousMatch of previous?.matches || []) {
|
|
303
|
+
if (previousMatch.route !== "external")
|
|
304
|
+
continue;
|
|
305
|
+
const expected = plan.transactions[previousMatch.transactionIndex];
|
|
306
|
+
if (!expected || expected.transactionId !== previousMatch.transactionId) {
|
|
307
|
+
throw new Error("Persisted external match does not belong to the execution plan");
|
|
308
|
+
}
|
|
309
|
+
const transaction = await provider.getTransaction(previousMatch.transactionHash);
|
|
310
|
+
const receipt = await provider.getTransactionReceipt(previousMatch.transactionHash);
|
|
311
|
+
if (!transaction || !receipt) {
|
|
312
|
+
throw new Error(`Previously matched transaction disappeared: ${previousMatch.transactionHash}`);
|
|
313
|
+
}
|
|
314
|
+
await validateCanonicalReceipt(provider, receipt);
|
|
315
|
+
if (previousMatch.executionKind === "eoa") {
|
|
316
|
+
if (!transactionMatches(transaction, expected, expected.executor)) {
|
|
317
|
+
throw new Error(`Previously matched transaction changed: ${expected.transactionId}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
const decoded = await safeCalls(provider, transaction, expected.executor);
|
|
322
|
+
const call = decoded[previousMatch.innerCallIndex || 0];
|
|
323
|
+
if (!call
|
|
324
|
+
|| call.to !== expected.to
|
|
325
|
+
|| call.value !== expected.value
|
|
326
|
+
|| call.data !== expected.data
|
|
327
|
+
|| call.operation !== expected.operation) {
|
|
328
|
+
throw new Error(`Previously matched Safe transaction changed: ${expected.transactionId}`);
|
|
329
|
+
}
|
|
330
|
+
assertSafeExecutionSucceeded(receipt, expected.executor);
|
|
331
|
+
}
|
|
332
|
+
matches.set(expected.transactionId, receiptMatch(expected, transaction, receipt, finalizedBlock, {
|
|
333
|
+
executionKind: previousMatch.executionKind,
|
|
334
|
+
submittedBy: transaction.from,
|
|
335
|
+
innerCallIndex: previousMatch.innerCallIndex,
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
failure = {
|
|
341
|
+
code: "EVIDENCE_INVALID",
|
|
342
|
+
message: error instanceof Error ? error.message : String(error),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
const external = plan.transactions.filter((transaction) => transaction.route === "external");
|
|
346
|
+
const previousSegments = new Map((previous?.segments ?? []).map((segment) => [
|
|
347
|
+
segment.segmentId,
|
|
348
|
+
segment,
|
|
349
|
+
]));
|
|
350
|
+
const segmentProgress = packageEvidence?.package.segments.map((segment) => {
|
|
351
|
+
const persisted = previousSegments.get(segment.segmentId);
|
|
352
|
+
if (persisted && (persisted.handoffBlock !== segment.handoffBlock
|
|
353
|
+
|| JSON.stringify(persisted.transactionIds) !== JSON.stringify(segment.transactionIds))) {
|
|
354
|
+
throw new Error(`Persisted reconciliation segment ${segment.segmentId} changed`);
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
segmentId: segment.segmentId,
|
|
358
|
+
transactionIds: segment.transactionIds,
|
|
359
|
+
handoffBlock: segment.handoffBlock,
|
|
360
|
+
nextBlock: persisted?.nextBlock ?? segment.handoffBlock,
|
|
361
|
+
};
|
|
362
|
+
});
|
|
363
|
+
if (previousSegments.size > (segmentProgress?.length ?? 0)) {
|
|
364
|
+
throw new Error("External execution package removed a reconciled segment");
|
|
365
|
+
}
|
|
366
|
+
const firstIncompleteBeforeScan = plan.transactions.find((transaction) => {
|
|
367
|
+
const match = matches.get(transaction.transactionId);
|
|
368
|
+
return !match || match.receiptStatus !== 1 || !match.finalized;
|
|
369
|
+
});
|
|
370
|
+
const activeSegment = firstIncompleteBeforeScan?.route === "external"
|
|
371
|
+
? packageEvidence?.package.segments.find((segment) => (segment.transactionIds.includes(firstIncompleteBeforeScan.transactionId)))
|
|
372
|
+
: undefined;
|
|
373
|
+
const activeProgress = activeSegment
|
|
374
|
+
? segmentProgress?.find((segment) => segment.segmentId === activeSegment.segmentId)
|
|
375
|
+
: undefined;
|
|
376
|
+
const writeScanCheckpoint = () => {
|
|
377
|
+
const now = new Date().toISOString();
|
|
378
|
+
const checkpointMatches = [...matches.values()].sort((left, right) => (left.transactionIndex - right.transactionIndex));
|
|
379
|
+
const checkpoint = {
|
|
380
|
+
version: 1,
|
|
381
|
+
status: "waiting_external",
|
|
382
|
+
taskId: input.taskId,
|
|
383
|
+
target: input.network,
|
|
384
|
+
executionId: input.executionId,
|
|
385
|
+
executionPlanHash: plan.planHash,
|
|
386
|
+
packagePath: packageEvidence ? relative(input.root, packageEvidence.filePath) : undefined,
|
|
387
|
+
packageHash: packageEvidence?.hash,
|
|
388
|
+
segments: segmentProgress,
|
|
389
|
+
finalizedBlock,
|
|
390
|
+
finalityPolicy: finality.policy,
|
|
391
|
+
matchedTransactionIds: checkpointMatches.map((match) => match.transactionId),
|
|
392
|
+
matches: checkpointMatches,
|
|
393
|
+
reportPath,
|
|
394
|
+
createdAt: previous?.createdAt || now,
|
|
395
|
+
updatedAt: now,
|
|
396
|
+
};
|
|
397
|
+
writeJsonAtomic(reportFile, checkpoint);
|
|
398
|
+
};
|
|
399
|
+
if (!failure
|
|
400
|
+
&& activeSegment
|
|
401
|
+
&& activeProgress
|
|
402
|
+
&& !matches.has(firstIncompleteBeforeScan.transactionId)) {
|
|
403
|
+
const latest = await provider.getBlockNumber();
|
|
404
|
+
const batchSize = input.batchSize ?? 1000;
|
|
405
|
+
if (!Number.isInteger(batchSize) || batchSize < 1 || batchSize > 1000) {
|
|
406
|
+
throw new Error("Reconciliation batchSize must be between 1 and 1000");
|
|
407
|
+
}
|
|
408
|
+
const start = activeProgress.nextBlock;
|
|
409
|
+
const end = Math.min(latest, start + batchSize - 1);
|
|
410
|
+
const segmentTransactions = activeSegment.transactionIds.map((transactionId) => {
|
|
411
|
+
const transaction = plan.transactions.find((candidate) => (candidate.transactionId === transactionId));
|
|
412
|
+
if (!transaction || transaction.route !== "external") {
|
|
413
|
+
throw new Error(`External segment transaction ${transactionId} is invalid`);
|
|
414
|
+
}
|
|
415
|
+
return transaction;
|
|
416
|
+
});
|
|
417
|
+
for (let blockNumber = start; blockNumber <= end; blockNumber += 1) {
|
|
418
|
+
let block;
|
|
419
|
+
try {
|
|
420
|
+
block = await provider.send("eth_getBlockByNumber", [`0x${blockNumber.toString(16)}`, true]);
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
writeScanCheckpoint();
|
|
424
|
+
throw error;
|
|
425
|
+
}
|
|
426
|
+
try {
|
|
427
|
+
for (const transaction of block?.transactions || []) {
|
|
428
|
+
const remaining = segmentTransactions.filter((candidate) => (!matches.has(candidate.transactionId)));
|
|
429
|
+
const expected = remaining[0];
|
|
430
|
+
if (!expected)
|
|
431
|
+
break;
|
|
432
|
+
const code = await provider.getCode(expected.executor);
|
|
433
|
+
if (!code || code === "0x") {
|
|
434
|
+
if (!transactionMatches(transaction, expected, expected.executor))
|
|
435
|
+
continue;
|
|
436
|
+
const receipt = await provider.getTransactionReceipt(transaction.hash);
|
|
437
|
+
if (!receipt)
|
|
438
|
+
continue;
|
|
439
|
+
await validateCanonicalReceipt(provider, receipt);
|
|
440
|
+
matches.set(expected.transactionId, receiptMatch(expected, transaction, receipt, finalizedBlock, { executionKind: "eoa", submittedBy: transaction.from }));
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
const decoded = await safeCalls(provider, transaction, expected.executor);
|
|
444
|
+
if (decoded.length === 0)
|
|
445
|
+
continue;
|
|
446
|
+
const receipt = await provider.getTransactionReceipt(transaction.hash);
|
|
447
|
+
if (!receipt)
|
|
448
|
+
continue;
|
|
449
|
+
await validateCanonicalReceipt(provider, receipt);
|
|
450
|
+
const matchedCalls = [];
|
|
451
|
+
const remainingCalls = segmentTransactions.filter((item) => (!matches.has(item.transactionId)));
|
|
452
|
+
for (const decodedCall of decoded) {
|
|
453
|
+
const candidate = remainingCalls[matchedCalls.length];
|
|
454
|
+
if (!candidate)
|
|
455
|
+
break;
|
|
456
|
+
if (decodedCall.to !== candidate.to
|
|
457
|
+
|| decodedCall.value !== candidate.value
|
|
458
|
+
|| decodedCall.data !== candidate.data
|
|
459
|
+
|| decodedCall.operation !== candidate.operation
|
|
460
|
+
|| candidate.executor !== expected.executor) {
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
matchedCalls.push({ transaction: candidate, decodedCall });
|
|
464
|
+
}
|
|
465
|
+
if (matchedCalls.length === 0)
|
|
466
|
+
continue;
|
|
467
|
+
assertSafeExecutionSucceeded(receipt, expected.executor);
|
|
468
|
+
for (const { transaction: candidate, decodedCall } of matchedCalls) {
|
|
469
|
+
matches.set(candidate.transactionId, receiptMatch(candidate, transaction, receipt, finalizedBlock, {
|
|
470
|
+
executionKind: decodedCall.kind,
|
|
471
|
+
submittedBy: transaction.from,
|
|
472
|
+
innerCallIndex: decodedCall.innerCallIndex,
|
|
473
|
+
}));
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
activeProgress.nextBlock = blockNumber + 1;
|
|
477
|
+
writeScanCheckpoint();
|
|
478
|
+
}
|
|
479
|
+
catch (error) {
|
|
480
|
+
failure = {
|
|
481
|
+
code: "SCAN_FAILED",
|
|
482
|
+
message: error instanceof Error ? error.message : String(error),
|
|
483
|
+
};
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
const orderedMatches = [...matches.values()].sort((left, right) => (left.transactionIndex - right.transactionIndex));
|
|
489
|
+
const reverted = orderedMatches.find((match) => match.receiptStatus === 0);
|
|
490
|
+
if (reverted) {
|
|
491
|
+
failure = {
|
|
492
|
+
code: "TRANSACTION_REVERTED",
|
|
493
|
+
message: `Transaction ${reverted.transactionHash} reverted`,
|
|
494
|
+
transactionId: reverted.transactionId,
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
const chainOrdered = [...orderedMatches].sort((left, right) => (left.blockNumber - right.blockNumber
|
|
498
|
+
|| left.blockTransactionIndex - right.blockTransactionIndex
|
|
499
|
+
|| (left.innerCallIndex ?? -1) - (right.innerCallIndex ?? -1)));
|
|
500
|
+
if (chainOrdered.some((match, index) => (index > 0 && chainOrdered[index - 1].transactionIndex >= match.transactionIndex))) {
|
|
501
|
+
failure = {
|
|
502
|
+
code: "PLAN_ORDER_VIOLATION",
|
|
503
|
+
message: "Canonical chain execution does not preserve immutable plan order",
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
const firstIncomplete = plan.transactions.find((transaction) => {
|
|
507
|
+
const match = matches.get(transaction.transactionId);
|
|
508
|
+
return !match || match.receiptStatus !== 1 || !match.finalized;
|
|
509
|
+
});
|
|
510
|
+
const incompleteMatch = firstIncomplete
|
|
511
|
+
? matches.get(firstIncomplete.transactionId)
|
|
512
|
+
: undefined;
|
|
513
|
+
const submittedOperatorIds = new Set((operatorResult?.receipts ?? []).map((receipt) => receipt.transactionId));
|
|
514
|
+
const packageContainsIncomplete = Boolean(firstIncomplete?.route === "external"
|
|
515
|
+
&& packageEvidence?.package.segments.some((segment) => (segment.transactionIds.includes(firstIncomplete.transactionId))));
|
|
516
|
+
const status = failure
|
|
517
|
+
? "failed"
|
|
518
|
+
: !firstIncomplete
|
|
519
|
+
? external.length > 0 ? "reconciled" : "not_required"
|
|
520
|
+
: incompleteMatch
|
|
521
|
+
? "waiting_finality"
|
|
522
|
+
: firstIncomplete.route === "operator"
|
|
523
|
+
? submittedOperatorIds.has(firstIncomplete.transactionId)
|
|
524
|
+
? "waiting_finality"
|
|
525
|
+
: "waiting_operator"
|
|
526
|
+
: packageContainsIncomplete
|
|
527
|
+
? "waiting_external"
|
|
528
|
+
: "waiting_operator";
|
|
529
|
+
const now = new Date().toISOString();
|
|
530
|
+
const report = {
|
|
531
|
+
version: 1,
|
|
532
|
+
status,
|
|
533
|
+
taskId: input.taskId,
|
|
534
|
+
target: input.network,
|
|
535
|
+
executionId: input.executionId,
|
|
536
|
+
executionPlanHash: plan.planHash,
|
|
537
|
+
packagePath: packageEvidence ? relative(input.root, packageEvidence.filePath) : undefined,
|
|
538
|
+
packageHash: packageEvidence?.hash,
|
|
539
|
+
segments: segmentProgress,
|
|
540
|
+
finalizedBlock,
|
|
541
|
+
finalityPolicy: finality.policy,
|
|
542
|
+
matchedTransactionIds: orderedMatches.map((match) => match.transactionId),
|
|
543
|
+
matches: orderedMatches,
|
|
544
|
+
failure,
|
|
545
|
+
reportPath,
|
|
546
|
+
createdAt: previous?.createdAt || now,
|
|
547
|
+
updatedAt: now,
|
|
548
|
+
completedAt: status === "reconciled" || status === "not_required" ? now : undefined,
|
|
549
|
+
};
|
|
550
|
+
const gateToolSyncByStep = {};
|
|
551
|
+
if (status === "reconciled") {
|
|
552
|
+
const deployment = (0, deploymentRecords_1.loadDeploymentExecutionRecord)({
|
|
553
|
+
taskDir,
|
|
554
|
+
taskId: input.taskId,
|
|
555
|
+
network: input.network,
|
|
556
|
+
executionId: input.executionId,
|
|
557
|
+
});
|
|
558
|
+
const matchByTransactionId = new Map(orderedMatches.map((match) => [match.transactionId, match]));
|
|
559
|
+
for (const change of deployment.changes) {
|
|
560
|
+
if (change.proxyKind !== "uups")
|
|
561
|
+
continue;
|
|
562
|
+
if (!change.proxyAddress
|
|
563
|
+
|| !change.implementationAddress
|
|
564
|
+
|| !Array.isArray(change.constructorArgs)
|
|
565
|
+
|| !change.proxyTransactionId) {
|
|
566
|
+
throw new Error(`UUPS change ${change.stepId} is missing GateTool sync inputs`);
|
|
567
|
+
}
|
|
568
|
+
const candidates = plan.transactions.filter((transaction) => (transaction.transactionId === change.proxyTransactionId));
|
|
569
|
+
if (candidates.length !== 1) {
|
|
570
|
+
throw new Error(`UUPS change ${change.stepId} has no unique finalized proxy receipt`);
|
|
571
|
+
}
|
|
572
|
+
const transaction = candidates[0];
|
|
573
|
+
if (transaction.stepId !== change.stepId) {
|
|
574
|
+
throw new Error(`UUPS change ${change.stepId} proxy receipt does not match its plan step`);
|
|
575
|
+
}
|
|
576
|
+
if (change.kind === "upgrade"
|
|
577
|
+
&& transaction.to.toLowerCase() !== change.proxyAddress.toLowerCase()) {
|
|
578
|
+
throw new Error(`UUPS change ${change.stepId} receipt does not target its proxy`);
|
|
579
|
+
}
|
|
580
|
+
if (change.kind === "deploy"
|
|
581
|
+
&& (!change.multicall
|
|
582
|
+
|| transaction.to.toLowerCase() !== change.multicall.toLowerCase())) {
|
|
583
|
+
throw new Error(`UUPS change ${change.stepId} receipt does not target its controlled multicall`);
|
|
584
|
+
}
|
|
585
|
+
const match = matchByTransactionId.get(transaction.transactionId);
|
|
586
|
+
if (!match || match.receiptStatus !== 1 || !match.finalized) {
|
|
587
|
+
throw new Error(`UUPS change ${change.stepId} receipt is not finalized`);
|
|
588
|
+
}
|
|
589
|
+
const gateToolSync = await (input.dependencies?.syncGateToolUups ?? gateToolSync_1.syncGateToolUups)({
|
|
590
|
+
root: input.root,
|
|
591
|
+
evidenceDir: path_1.default.join(taskDir, "results", input.network, input.executionId, "gate-tool", "execute"),
|
|
592
|
+
evidenceName: change.stepId,
|
|
593
|
+
scheme: transaction.scheme || "evm",
|
|
594
|
+
network: input.network,
|
|
595
|
+
target: input.network,
|
|
596
|
+
manifestDir: target.openzeppelin.manifestDir,
|
|
597
|
+
proxy: change.proxyAddress,
|
|
598
|
+
implementation: change.implementationAddress,
|
|
599
|
+
contract: change.actualContract,
|
|
600
|
+
constructorArgs: change.constructorArgs,
|
|
601
|
+
transactionHash: match.transactionHash,
|
|
602
|
+
hre: input.gateToolSyncHre,
|
|
603
|
+
});
|
|
604
|
+
if (change.gateToolSync
|
|
605
|
+
&& JSON.stringify(change.gateToolSync) !== JSON.stringify(gateToolSync)) {
|
|
606
|
+
throw new Error(`UUPS change ${change.stepId} stored GateTool sync evidence does not match the finalized receipt`);
|
|
607
|
+
}
|
|
608
|
+
gateToolSyncByStep[change.stepId] = gateToolSync;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
const normalizedReport = JSON.parse(JSON.stringify(report));
|
|
612
|
+
const persistedReport = previous?.status === "reconciled"
|
|
613
|
+
&& normalizedReport.status === "reconciled"
|
|
614
|
+
&& previous.packagePath === normalizedReport.packagePath
|
|
615
|
+
&& previous.packageHash === normalizedReport.packageHash
|
|
616
|
+
&& JSON.stringify(previous.segments) === JSON.stringify(normalizedReport.segments)
|
|
617
|
+
&& JSON.stringify(previous.matchedTransactionIds)
|
|
618
|
+
=== JSON.stringify(normalizedReport.matchedTransactionIds)
|
|
619
|
+
&& JSON.stringify(previous.matches) === JSON.stringify(normalizedReport.matches)
|
|
620
|
+
? previous
|
|
621
|
+
: normalizedReport;
|
|
622
|
+
if (persistedReport !== previous)
|
|
623
|
+
writeJsonAtomic(reportFile, persistedReport);
|
|
624
|
+
if (status === "reconciled") {
|
|
625
|
+
(0, deploymentRecords_1.markDeploymentRecordReconciled)({
|
|
626
|
+
taskDir,
|
|
627
|
+
taskId: input.taskId,
|
|
628
|
+
network: input.network,
|
|
629
|
+
executionId: input.executionId,
|
|
630
|
+
reportPath,
|
|
631
|
+
reportHash: sha256(fs_1.default.readFileSync(reportFile)),
|
|
632
|
+
gateToolSyncByStep,
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
return persistedReport;
|
|
636
|
+
};
|
|
637
|
+
exports.reconcileExternalExecution = reconcileExternalExecution;
|
|
638
|
+
//# sourceMappingURL=externalExecutionScanner.js.map
|