Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion scripts/admin/get-outbound-txs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ export const main = async () => {
const CHUNK_SIZE = 5000;
const messageAddedEvents = [];

for (let currentBlock = fromBlock; currentBlock <= toBlock; currentBlock += CHUNK_SIZE) {
for (
let currentBlock = fromBlock;
currentBlock <= toBlock;
currentBlock += CHUNK_SIZE
) {
const chunkEnd = Math.min(currentBlock + CHUNK_SIZE - 1, toBlock);
console.log(`Querying chunk: ${currentBlock} to ${chunkEnd}`);

Expand Down
6 changes: 5 additions & 1 deletion scripts/admin/get-seal-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ export const main = async () => {
const CHUNK_SIZE = 5000;
const sealedEvents = [];

for (let currentBlock = fromBlock; currentBlock <= toBlock; currentBlock += CHUNK_SIZE) {
for (
let currentBlock = fromBlock;
currentBlock <= toBlock;
currentBlock += CHUNK_SIZE
) {
const chunkEnd = Math.min(currentBlock + CHUNK_SIZE - 1, toBlock);
console.log(`Querying chunk: ${currentBlock} to ${chunkEnd}`);

Expand Down
24 changes: 19 additions & 5 deletions scripts/admin/send-attest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ export const main = async () => {
const sourceChain = sourceChainSlug;
const destinationChain = destinationChainSlug;

console.log(`\nProcessing attest for path: ${sourceChain} -> ${destinationChain}\n`);
console.log(
`\nProcessing attest for path: ${sourceChain} -> ${destinationChain}\n`
);

// Get addresses from prod_addresses.json
const destinationAddresses = addresses[destinationChain];
Expand Down Expand Up @@ -139,19 +141,29 @@ export const main = async () => {
const messageHash = keccak256(
defaultAbiCoder.encode(
["address", "uint32", "bytes32", "uint256", "bytes32"],
[switchboardAddress, parseInt(destinationChain), packetId, proposalCount, root]
[
switchboardAddress,
parseInt(destinationChain),
packetId,
proposalCount,
root,
]
)
);

console.log("Message hash:", messageHash);

// Sign with KMS
console.log("\nSigning with AWS KMS...");
const signature = await kmsSigner.signMessage(ethers.utils.arrayify(messageHash));
const signature = await kmsSigner.signMessage(
ethers.utils.arrayify(messageHash)
);
console.log("Signature:", signature);

// Prepare transaction data
const switchboardInterface = new ethers.utils.Interface(FastSwitchboardArtifact.abi);
const switchboardInterface = new ethers.utils.Interface(
FastSwitchboardArtifact.abi
);
const calldata = switchboardInterface.encodeFunctionData("attest", [
packetId,
proposalCount,
Expand Down Expand Up @@ -193,7 +205,9 @@ export const main = async () => {
console.log("Gas used:", receipt.gasUsed.toString());
} else {
console.log("To send the attest transaction, add --sendtx flag");
console.log("You can use the transaction details above to manually send, simulate, or audit the transaction.");
console.log(
"You can use the transaction details above to manually send, simulate, or audit the transaction."
);
}

console.log("\nScript completed.");
Expand Down
69 changes: 49 additions & 20 deletions scripts/admin/send-execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
getAllAddresses,
getOverrides,
} from "../../src";
import { mode, overrides } from "../deploy/config/config";
import { mode } from "../deploy/config/config";
import SocketArtifact from "../../out/Socket.sol/Socket.json";
import { getProviderFromChainSlug } from "../constants";
import { ethers, Wallet } from "ethers";
Expand All @@ -31,7 +31,8 @@ dotenvConfig();
// Configuration object with execution and message details
const EXECUTION_CONFIG = {
executionDetails: {
packetId: "0x0000a4b129ebc834d24af22b9466a4150425354998c3e800000000000000cbe6", // Replace with actual packet ID
packetId:
"0x0000a4b129ebc834d24af22b9466a4150425354998c3e800000000000000cbe6", // Replace with actual packet ID
proposalCount: "0", // Replace with actual proposal count
executionGasLimit: "200000", // Replace with actual gas limit
decapacitorProof: "0x", // Replace with actual proof
Expand All @@ -40,8 +41,10 @@ const EXECUTION_CONFIG = {
msgId: "0x0000a4b126e5ce884875ea3776a57f0b225b1ea8d2e9beeb00000000000608cb", // Replace with actual message ID
executionFee: "0", // Replace with actual execution fee
minMsgGasLimit: "100000", // Replace with actual min gas limit
executionParams: "0x0000000000000000000000000000000000000000000000000000000000000000", // Replace with actual execution params
payload: "0x0000000000000000000000008cb4c89cc297e07c7a309af8b16cc2f5f62a3b1300000000000000000000000000000000000000000000000000000000062ebe4d", // Replace with actual payload
executionParams:
"0x0000000000000000000000000000000000000000000000000000000000000000", // Replace with actual execution params
payload:
"0x0000000000000000000000008cb4c89cc297e07c7a309af8b16cc2f5f62a3b1300000000000000000000000000000000000000000000000000000000062ebe4d", // Replace with actual payload
},
msgValue: "0", // ETH value to send with transaction (in wei)
};
Expand Down Expand Up @@ -71,7 +74,9 @@ const addresses: DeploymentAddresses = getAllAddresses(mode);
export const main = async () => {
const destinationChain = parseInt(destinationChainSlug) as ChainSlug;

console.log(`\nProcessing execute transaction for chain: ${destinationChain}\n`);
console.log(
`\nProcessing execute transaction for chain: ${destinationChain}\n`
);

// Get addresses from prod_addresses.json
const destinationAddresses = addresses[destinationChain];
Expand All @@ -90,21 +95,31 @@ export const main = async () => {
console.log("Execution Configuration:");
console.log(" ExecutionDetails:");
console.log(` Packet ID: ${EXECUTION_CONFIG.executionDetails.packetId}`);
console.log(` Proposal Count: ${EXECUTION_CONFIG.executionDetails.proposalCount}`);
console.log(` Execution Gas Limit: ${EXECUTION_CONFIG.executionDetails.executionGasLimit}`);
console.log(` Decapacitor Proof: ${EXECUTION_CONFIG.executionDetails.decapacitorProof}`);
console.log(
` Proposal Count: ${EXECUTION_CONFIG.executionDetails.proposalCount}`
);
console.log(
` Execution Gas Limit: ${EXECUTION_CONFIG.executionDetails.executionGasLimit}`
);
console.log(
` Decapacitor Proof: ${EXECUTION_CONFIG.executionDetails.decapacitorProof}`
);
console.log(" MessageDetails:");
console.log(` Message ID: ${EXECUTION_CONFIG.messageDetails.msgId}`);
console.log(` Execution Fee: ${EXECUTION_CONFIG.messageDetails.executionFee}`);
console.log(` Min Message Gas Limit: ${EXECUTION_CONFIG.messageDetails.minMsgGasLimit}`);
console.log(` Execution Params: ${EXECUTION_CONFIG.messageDetails.executionParams}`);
console.log(
` Execution Fee: ${EXECUTION_CONFIG.messageDetails.executionFee}`
);
console.log(
` Min Message Gas Limit: ${EXECUTION_CONFIG.messageDetails.minMsgGasLimit}`
);
console.log(
` Execution Params: ${EXECUTION_CONFIG.messageDetails.executionParams}`
);
console.log(` Payload: ${EXECUTION_CONFIG.messageDetails.payload}`);
console.log(` Message Value: ${EXECUTION_CONFIG.msgValue}\n`);

// Get provider
const provider = getProviderFromChainSlug(
destinationChain
);
const provider = getProviderFromChainSlug(destinationChain);

// Get Socket contract to access hasher
const socketContract = new ethers.Contract(
Expand All @@ -119,15 +134,25 @@ export const main = async () => {

// Get hasher contract
const hasherAbi = [
"function packMessage(uint32 srcChainSlug_, address srcPlug_, uint32 dstChainSlug_, address dstPlug_, tuple(bytes32 msgId, uint256 executionFee, uint256 minMsgGasLimit, bytes32 executionParams, bytes payload) messageDetails_) external pure returns (bytes32)"
"function packMessage(uint32 srcChainSlug_, address srcPlug_, uint32 dstChainSlug_, address dstPlug_, tuple(bytes32 msgId, uint256 executionFee, uint256 minMsgGasLimit, bytes32 executionParams, bytes payload) messageDetails_) external pure returns (bytes32)",
];
const hasherContract = new ethers.Contract(hasherAddress, hasherAbi, provider);
const hasherContract = new ethers.Contract(
hasherAddress,
hasherAbi,
provider
);

// Extract chain slug and plug from msgId
// msgId format: chainSlug (32 bits) | plug (160 bits) | messageCount (64 bits)
const msgIdBigInt = BigInt(EXECUTION_CONFIG.messageDetails.msgId);
const srcChainSlug = Number((msgIdBigInt >> BigInt(224)) & BigInt(0xFFFFFFFF));
const dstPlug = "0x" + ((msgIdBigInt >> BigInt(64)) & ((BigInt(1) << BigInt(160)) - BigInt(1))).toString(16).padStart(40, "0");
const srcChainSlug = Number(
(msgIdBigInt >> BigInt(224)) & BigInt(0xffffffff)
);
const dstPlug =
"0x" +
((msgIdBigInt >> BigInt(64)) & ((BigInt(1) << BigInt(160)) - BigInt(1)))
.toString(16)
.padStart(40, "0");

console.log(`\nExtracted from msgId:`);
console.log(` Source Chain Slug: ${srcChainSlug}`);
Expand Down Expand Up @@ -164,7 +189,9 @@ export const main = async () => {

// Sign with KMS
console.log("\nSigning packed message with AWS KMS...");
const signature = await kmsSigner.signMessage(ethers.utils.arrayify(packedMessage));
const signature = await kmsSigner.signMessage(
ethers.utils.arrayify(packedMessage)
);
console.log("Signature:", signature);

// Prepare transaction structs
Expand Down Expand Up @@ -223,7 +250,9 @@ export const main = async () => {
console.log("Gas used:", receipt.gasUsed.toString());
} else {
console.log("To send the execute transaction, add --sendtx flag");
console.log("You can use the transaction details above to manually send, simulate, or audit the transaction.");
console.log(
"You can use the transaction details above to manually send, simulate, or audit the transaction."
);
}

console.log("\nScript completed.");
Expand Down
2 changes: 1 addition & 1 deletion scripts/constants/overrides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export const getOverrides = async (
const block = await provider.getBlock("latest");
const baseFee = block.baseFeePerGas?.toNumber() || 0;
const maxPriorityFeePerGas = Math.max(maxFeePerGas - baseFee, 0);
console.log(chainSlug, gasLimit, maxFeePerGas, maxPriorityFeePerGas, type);
console.log(chainSlug, gasLimit, maxFeePerGas, maxPriorityFeePerGas, type);
return { gasLimit, maxFeePerGas, maxPriorityFeePerGas, type };
} else {
// Legacy transaction (type 0 or 1)
Expand Down
24 changes: 15 additions & 9 deletions scripts/deploy/helpers/send-msg/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ethers } from "ethers";
import Counter from "../../../../out/Counter.sol/Counter.json";
import Socket from "../../../../out/Socket.sol/Socket.json";
import { ChainSlug } from "../../../../src";
import { getAPIBaseURL, getAddresses, relayTx } from "../../utils";
import { getAPIBaseURL, getAddresses, getStatus, relayTx } from "../../utils";
dotenvConfig();

import { formatEther } from "ethers/lib/utils";
Expand Down Expand Up @@ -129,15 +129,21 @@ export const sendCounterBridgeMsg = async (
let response = await relayTx({
to,
data,
value,
gasLimit,
gasPrice,
value: value?.toString(),
gasLimit: gasLimit?.toString(),
gasPrice: gasPrice?.toString(),
type,
chainSlug,
});
console.log(
`Track message here: ${getAPIBaseURL(
mode
)}/messages-from-tx?srcChainSlug=${chainSlug}&srcTxHash=${response?.hash}`
);

console.log(`Tx Id: ${response?.txId}`);
const txHash = await getStatus(response?.txId);

if (txHash) {
console.log(
`Track message here: ${getAPIBaseURL(
mode
)}/messages-from-tx?srcChainSlug=${chainSlug}&srcTxHash=${txHash}`
);
}
Comment on lines +132 to +148
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard against missing txId before status lookup.

Line 139-148 calls getStatus(response?.txId) even when the relay response failed or is undefined, producing /status?txId=undefined and misleading tracking logs. This should bail out early if txId is missing.
As per coding guidelines, Check for resource leaks, race conditions, and unhandled edge cases.

🛠️ Suggested fix
-  console.log(`Tx Id: ${response?.txId}`);
-  const txHash = await getStatus(response?.txId);
+  if (!response?.txId) {
+    console.log("Relay did not return txId; skipping status lookup");
+    return;
+  }
+  console.log(`Tx Id: ${response.txId}`);
+  const txHash = await getStatus(response.txId);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
value: value?.toString(),
gasLimit: gasLimit?.toString(),
gasPrice: gasPrice?.toString(),
type,
chainSlug,
});
console.log(
`Track message here: ${getAPIBaseURL(
mode
)}/messages-from-tx?srcChainSlug=${chainSlug}&srcTxHash=${response?.hash}`
);
console.log(`Tx Id: ${response?.txId}`);
const txHash = await getStatus(response?.txId);
if (txHash) {
console.log(
`Track message here: ${getAPIBaseURL(
mode
)}/messages-from-tx?srcChainSlug=${chainSlug}&srcTxHash=${txHash}`
);
}
value: value?.toString(),
gasLimit: gasLimit?.toString(),
gasPrice: gasPrice?.toString(),
type,
chainSlug,
});
if (!response?.txId) {
console.log("Relay did not return txId; skipping status lookup");
return;
}
console.log(`Tx Id: ${response.txId}`);
const txHash = await getStatus(response.txId);
if (txHash) {
console.log(
`Track message here: ${getAPIBaseURL(
mode
)}/messages-from-tx?srcChainSlug=${chainSlug}&srcTxHash=${txHash}`
);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deploy/helpers/send-msg/utils.ts` around lines 132 - 148, The code
calls getStatus(response?.txId) and builds tracking URLs even when response or
response.txId is missing; update the flow in this function to check for a valid
response.txId (reference response and txId) immediately after receiving the
relay response and before calling getStatus or printing tracking info, bail out
or log an error/return if txId is falsy, and only then call
getStatus(response.txId) and use getAPIBaseURL(mode) with chainSlug to print the
tracking URL; ensure no further status lookup or URL construction occurs when
txId is undefined.

};
24 changes: 21 additions & 3 deletions scripts/deploy/utils/relayer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BigNumber, BigNumberish } from "ethers";
import { getRelayAPIKEY, getRelayUrl } from "./utils";
import { axiosPost } from "@socket.tech/dl-common";
import { axiosGet, axiosPost } from "@socket.tech/dl-common";
import { mode } from "../config/config";
import { ChainSlugToId } from "../../../src";

Expand All @@ -17,7 +17,6 @@ interface RequestObj {
export const relayTx = async (params: RequestObj) => {
try {
let { to, data, chainSlug, gasPrice, value, type, gasLimit } = params;
let url = await getRelayUrl(mode);
let config = {
headers: {
"x-api-key": getRelayAPIKEY(mode),
Expand All @@ -34,7 +33,26 @@ export const relayTx = async (params: RequestObj) => {
sequential: false,
source: "LoadTester",
};
let response = await axiosPost(url!, body, config);
let response = await axiosPost(
`${await getRelayUrl(mode)}/relay`,
body,
config
);
if (response?.success) return response?.data;
else {
console.log("error in relaying tx", response);
return { hash: "" };
}
} catch (error) {
console.log("uncaught error", error);
}
Comment on lines +36 to +48
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find and display the relayer.ts file
find . -name "relayer.ts" -type f | head -20

Repository: SocketDotTech/socket-DL

Length of output: 100


🏁 Script executed:

# Once found, examine the full file
cat -n scripts/deploy/utils/relayer.ts

Repository: SocketDotTech/socket-DL

Length of output: 2078


🏁 Script executed:

# Search for all usages of relayTx and getStatus to understand what callers expect
rg -n "relayTx|getStatus" --type ts --type js -B 2 -A 2 scripts src

Repository: SocketDotTech/socket-DL

Length of output: 2762


🏁 Script executed:

# Also check for txId or txHash usage near relayTx calls
rg -n "txId|txHash|hash" --type ts --type js -B 3 -A 3 | grep -A 5 -B 5 "relayTx\|getStatus"

Repository: SocketDotTech/socket-DL

Length of output: 1391


Both relayTx and getStatus swallow errors and return inconsistent shapes, breaking downstream error handling.

Lines 36-48 and 51-63 return response?.data on success or { hash: "" } on API failure, or implicitly undefined on exceptions. Callers at line 139-140 expect response?.txId, but on failure get an empty hash object or undefined. When relayTx fails, line 140 calls getStatus(response?.txId) with undefined, which silently produces /status?txId=undefined.

This violates the coding guideline to check for edge cases and unhandled errors. Either throw errors so callers can bail out, or return a consistent nullable type with explicit error signals.

🛠️ Suggested fix
-export const relayTx = async (params: RequestObj) => {
+export const relayTx = async (
+  params: RequestObj
+): Promise<{ txId?: string; hash?: string } | null> => {
   try {
@@
-    if (response?.success) return response?.data;
-    else {
-      console.log("error in relaying tx", response);
-      return { hash: "" };
-    }
+    if (!response?.success) {
+      console.log("error in relaying tx", response);
+      return null;
+    }
+    return response.data;
   } catch (error) {
     console.log("uncaught error", error);
+    throw error;
   }
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/deploy/utils/relayer.ts` around lines 36 - 48, relayTx and getStatus
currently swallow errors and return inconsistent shapes (e.g., { hash: "" } or
undefined), causing callers that expect response.txId (e.g.,
getStatus(response?.txId)) to operate on invalid values; update relayTx and
getStatus to either (a) throw a descriptive error on API failure/exception
(include response error details) so callers can bail out, or (b) return a
consistent nullable result type (e.g., null or an object with an explicit error
field) instead of { hash: "" } and ensure callers check for null/error before
calling getStatus; locate and change implementations of relayTx and getStatus to
follow one consistent approach and bubble up or return explicit errors.

};

export const getStatus = async (txId: string) => {
try {
const response = await axiosGet(
`${await getRelayUrl(mode)}/status?txId=${txId}`
);
if (response?.success) return response?.data;
else {
console.log("error in relaying tx", response);
Expand Down
2 changes: 1 addition & 1 deletion scripts/deploy/utils/socket-signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const getSocketSigner = async (
ChainSlugToId[chainSlug],
safeAddress,
safeWrapperAddress,
await getRelayUrl(mode),
`${await getRelayUrl(mode)}/relay`,
getRelayAPIKEY(mode),
wallet,
useSafe,
Expand Down
12 changes: 8 additions & 4 deletions scripts/native-bridge-helpers/arbitrum/l1Tol2Relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@ import { L1ToL2MessageStatus, L1TransactionReceipt } from "@arbitrum/sdk";
// get providers for source and destination

// replace following variables to initiate the txn
const l1Chain = HardhatChainName.GOERLI;
const l2Chain = HardhatChainName.ARBITRUM_GOERLI;
const l1Chain = HardhatChainName.SEPOLIA;
const l2Chain = HardhatChainName.ARBITRUM_SEPOLIA;
const packetId =
"0x00000005feb89935220606f3c3670ae510a74ab5750e810c0000000000000000";
const root =
"0xc8111d45052c1df62037b92c1fab7c23bda80a0854b81432aee514aaf5f6c440";

const walletPrivateKey = process.env.SOCKET_SIGNER_KEY!;
const l1Provider = new providers.JsonRpcProvider(getJsonRpcUrl(l1Chain));
const l2Provider = new providers.JsonRpcProvider(getJsonRpcUrl(l2Chain));
const l1Provider = new providers.JsonRpcProvider(
getJsonRpcUrl(hardhatChainNameToSlug[l1Chain])
);
const l2Provider = new providers.JsonRpcProvider(
getJsonRpcUrl(hardhatChainNameToSlug[l2Chain])
);

const l1Wallet = new Wallet(walletPrivateKey, l1Provider);
const l2Wallet = new Wallet(walletPrivateKey, l2Provider);
Expand Down
14 changes: 9 additions & 5 deletions scripts/native-bridge-helpers/arbitrum/l2tol1Relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@ import {
} from "../../../src";

// https://goerli.arbiscan.io/txsExit to check message status
const l1Chain = HardhatChainName.GOERLI;
const l2Chain = HardhatChainName.ARBITRUM_GOERLI;
const l1Chain = HardhatChainName.SEPOLIA;
const l2Chain = HardhatChainName.ARBITRUM_SEPOLIA;
const sealTxHash =
"0x0113020a1e3b9f814a78791b9719bf583bb0f25075cde1e754af99f1dcf137a7";
"0x4e8f4b180b2fbb5d06d637294776fda71025568bdb0cc31e2a430795e6481d54";

import { mode } from "../../deploy/config/config";

const walletPrivateKey = process.env.SOCKET_SIGNER_KEY!;
const l1Provider = new providers.JsonRpcProvider(getJsonRpcUrl(l1Chain));
const l2Provider = new providers.JsonRpcProvider(getJsonRpcUrl(l2Chain));
const l1Provider = new providers.JsonRpcProvider(
getJsonRpcUrl(hardhatChainNameToSlug[l1Chain])
);
const l2Provider = new providers.JsonRpcProvider(
getJsonRpcUrl(hardhatChainNameToSlug[l2Chain])
);

const l1Wallet = new Wallet(walletPrivateKey, l1Provider);

Expand Down
10 changes: 8 additions & 2 deletions scripts/native-bridge-helpers/optimism/l1Tol2Relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ const ATTEST_GAS_LIMIT = 800000;
const outboundTxHash = "";

const walletPrivateKey = process.env.SOCKET_SIGNER_KEY!;
const l1Provider = new providers.JsonRpcProvider(getJsonRpcUrl(localChain));
const l1Provider = new providers.JsonRpcProvider(
getJsonRpcUrl(hardhatChainNameToSlug[localChain])
);
const l1Wallet = new Wallet(walletPrivateKey, l1Provider);

export const main = async () => {
Expand All @@ -45,7 +47,11 @@ export const main = async () => {

// get socket contracts for both chains
// counter l1, counter l2, seal, execute
const contracts = contractNames("", localChain, remoteChain);
const contracts = contractNames(
"",
hardhatChainNameToSlug[localChain],
hardhatChainNameToSlug[remoteChain]
);

const l1Capacitor: Contract = (
await getInstance(
Expand Down
Loading
Loading