Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"dotenv": "^17.0.0",
"ethers": "^6.13.4",
"fs-extra": "^11.3.0",
"genlayer-js": "^0.11.0",
"genlayer-js": "^0.16.0",
"inquirer": "^12.0.0",
"keytar": "^7.9.0",
"node-fetch": "^3.0.0",
Expand Down
33 changes: 33 additions & 0 deletions src/commands/contracts/code.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {BaseAction} from "../../lib/actions/BaseAction";
import type {Address} from "genlayer-js/types";
Comment on lines +1 to +2

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Validate address, handle EOAs explicitly, and exit non‑zero on failures.

Prevents remote calls with bad inputs, gives clear EOA feedback, and ensures CI-friendly exit codes.

 import {BaseAction} from "../../lib/actions/BaseAction";
 import type {Address} from "genlayer-js/types";
+import { isAddress, getAddress } from "viem";

   async code({
     contractAddress,
     rpc,
   }: {
     contractAddress: string;
     rpc?: string;
   }): Promise<void> {
     const client = await this.getClient(rpc, true);
     await client.initializeConsensusSmartContract();
-    this.startSpinner(`Getting code for contract at ${contractAddress}...`);
+    const target = contractAddress.trim();
+    if (!isAddress(target)) {
+      this.failSpinner("Invalid contract address format", { contractAddress });
+      process.exitCode = 1;
+      return;
+    }
+    const normalized = getAddress(target);
+    this.startSpinner(`Getting code for contract at ${normalized}...`);

     try {
-      const result = await client.getContractCode(contractAddress as Address);
+      const result = await client.getContractCode(normalized as Address);
+      if (!result || result === "0x") {
+        this.failSpinner("No contract code found at address (EOA or not deployed)");
+        process.exitCode = 1;
+        return;
+      }
       this.succeedSpinner("Contract code retrieved successfully", result);
     } catch (error) {
       this.failSpinner("Error retrieving contract code", error);
+      process.exitCode = 1;
     }
   }

Also applies to: 13-30


export interface CodeOptions {
rpc?: string;
}

export class CodeAction extends BaseAction {
constructor() {
super();
}

async code({
contractAddress,
rpc,
}: {
contractAddress: string;
rpc?: string;
}): Promise<void> {
const client = await this.getClient(rpc, true);
await client.initializeConsensusSmartContract();
this.startSpinner(`Getting code for contract at ${contractAddress}...`);

try {
const result = await client.getContractCode(contractAddress as Address);
this.succeedSpinner("Contract code retrieved successfully", result);
} catch (error) {
this.failSpinner("Error retrieving contract code", error);
}
}
}


10 changes: 10 additions & 0 deletions src/commands/contracts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {DeployAction, DeployOptions, DeployScriptsOptions} from "./deploy";
import {CallAction, CallOptions} from "./call";
import {WriteAction, WriteOptions} from "./write";
import {SchemaAction, SchemaOptions} from "./schema";
import {CodeAction, CodeOptions} from "./code";

function parseArg(value: string, previous: any[] = []): any[] {
if (value === "true") return [...previous, true];
Expand Down Expand Up @@ -72,5 +73,14 @@ export function initializeContractsCommands(program: Command) {
await schemaAction.schema({contractAddress, ...options});
});

program
.command("code <contractAddress>")
.description("Get the bytecode/source for a deployed contract")
Comment thread
epsjunior marked this conversation as resolved.
Outdated
.option("--rpc <rpcUrl>", "RPC URL for the network")
.action(async (contractAddress: string, options: CodeOptions) => {
const codeAction = new CodeAction();
await codeAction.code({contractAddress, ...options});
});

return program;
}