Skip to content

Commit

Permalink
fix: improve logging
Browse files Browse the repository at this point in the history
  • Loading branch information
sakulstra committed Mar 21, 2024
1 parent 3d501f1 commit 597f1eb
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 50 deletions.
98 changes: 84 additions & 14 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ export const VERIFY_VERSION = packageJson.version;

export const VERBOSE = !!process.env.VERBOSE;

type ExplorerConfig = {
export type ExplorerConfig = {
API_URL: string;
SITE_URL?: string;
API_KEY?: string;
};

Expand All @@ -19,22 +20,45 @@ export const NETWORK_CONFIGS: Record<string, NetworkConfig> = {
[Networks.polygon]: {
RPC: process.env.RPC_POLYGON || "",
explorers: [
{ API_URL: "https://api.polygonscan.com/api", API_KEY: process.env.ETHERSCAN_API_KEY_POLYGON || "" },
{
API_URL: "https://api.polygonscan.com/api",
API_KEY: process.env.ETHERSCAN_API_KEY_POLYGON || "",
SITE_URL: "https://polygonscan.com",
},
],
},
[Networks.main]: {
RPC: process.env.RPC_MAINNET || "",
explorers: [{ API_URL: "https://api.etherscan.io/api", API_KEY: process.env.ETHERSCAN_API_KEY_MAINNET || "" }],
explorers: [
{
API_URL: "https://api.etherscan.io/api",
API_KEY: process.env.ETHERSCAN_API_KEY_MAINNET || "",
SITE_URL: "https://etherscan.io",
},
],
},
[Networks.arbitrum]: {
RPC: process.env.RPC_ARBITRUM || "",
explorers: [{ API_URL: "https://api.arbiscan.io/api", API_KEY: process.env.ETHERSCAN_API_KEY_ARBITRUM || "" }],
explorers: [
{
API_URL: "https://api.arbiscan.io/api",
API_KEY: process.env.ETHERSCAN_API_KEY_ARBITRUM || "",
SITE_URL: "https://arbiscan.io",
},
],
},
[Networks.avalanche]: {
RPC: process.env.RPC_AVALANCHE || "",
explorers: [
{ API_URL: "https://api.snowscan.xyz/api", API_KEY: process.env.ETHERSCAN_API_KEY_AVALANCHE || "" },
{ API_URL: "https://api.routescan.io/v2/network/mainnet/evm/43114/etherscan" },
{
API_URL: "https://api.snowscan.xyz/api",
API_KEY: process.env.ETHERSCAN_API_KEY_AVALANCHE || "",
SITE_URL: "https://snowscan.xyz",
},
{
API_URL: "https://api.routescan.io/v2/network/mainnet/evm/43114/etherscan",
SITE_URL: "https://snowtrace.io",
},
],
},
[Networks.optimism]: {
Expand All @@ -43,52 +67,98 @@ export const NETWORK_CONFIGS: Record<string, NetworkConfig> = {
{
API_URL: "https://api-optimistic.etherscan.io/api",
API_KEY: process.env.ETHERSCAN_API_KEY_OPTIMISM || "",
SITE_URL: "https://optimistic.etherscan.io",
},
],
},
[Networks.sepolia]: {
RPC: process.env.RPC_SEPOLIA || "",
explorers: [
{ API_URL: "https://api-sepolia.etherscan.io/api", API_KEY: process.env.ETHERSCAN_API_KEY_SEPOLIA || "" },
{
API_URL: "https://api-sepolia.etherscan.io/api",
API_KEY: process.env.ETHERSCAN_API_KEY_SEPOLIA || "",
SITE_URL: "https://sepolia.etherscan.io",
},
],
},
[Networks.bnb]: {
RPC: process.env.RPC_BNB || "",
explorers: [{ API_URL: "https://api.bscscan.com/api", API_KEY: process.env.ETHERSCAN_API_KEY_BNB || "" }],
explorers: [
{
API_URL: "https://api.bscscan.com/api",
API_KEY: process.env.ETHERSCAN_API_KEY_BNB || "",
SITE_URL: "https://bscscan.com",
},
],
},
[Networks.bnbTestnet]: {
RPC: process.env.RPC_BNB_TESTNET || "",
explorers: [
{
API_URL: "https://api-testnet.bscscan.com/api",
API_KEY: process.env.ETHERSCAN_API_KEY_BNB_TESTNET || "",
SITE_URL: "https://testnet.bscscan.com",
},
],
},
[Networks.base]: {
RPC: process.env.RPC_BASE || "",
explorers: [{ API_URL: "https://api.basescan.org/api", API_KEY: process.env.ETHERSCAN_API_KEY_BASE || "" }],
explorers: [
{
API_URL: "https://api.basescan.org/api",
API_KEY: process.env.ETHERSCAN_API_KEY_BASE || "",
SITE_URL: "https://testnet.bscscan.com",
},
],
},
[Networks.gnosis]: {
RPC: process.env.RPC_GNOSIS || "",
explorers: [{ API_URL: "https://api.gnosisscan.io/api", API_KEY: process.env.ETHERSCAN_API_KEY_GNOSIS || "" }],
explorers: [
{
API_URL: "https://api.gnosisscan.io/api",
API_KEY: process.env.ETHERSCAN_API_KEY_GNOSIS || "",
SITE_URL: "https://gnosisscan.io",
},
],
},
[Networks.scroll]: {
RPC: process.env.RPC_SCROLL || "",
explorers: [{ API_URL: "https://api.scrollscan.com/api", API_KEY: process.env.ETHERSCAN_API_KEY_SCROLL || "" }],
explorers: [
{
API_URL: "https://api.scrollscan.com/api",
API_KEY: process.env.ETHERSCAN_API_KEY_SCROLL || "",
SITE_URL: "https://scrollscan.com",
},
],
},
[Networks.zkevm]: {
RPC: process.env.RPC_ZKEVM || "",
explorers: [
{ API_URL: "https://api-zkevm.polygonscan.com/api", API_KEY: process.env.ETHERSCAN_API_KEY_ZKEVM || "" },
{
API_URL: "https://api-zkevm.polygonscan.com/api",
API_KEY: process.env.ETHERSCAN_API_KEY_ZKEVM || "",
SITE_URL: "https://zkevm.polygonscan.com",
},
],
},
[Networks.celo]: {
RPC: process.env.RPC_CELO || "",
explorers: [{ API_URL: "https://api.celoscan.io/api", API_KEY: process.env.ETHERSCAN_API_KEY_CELO || "" }],
explorers: [
{
API_URL: "https://api.celoscan.io/api",
API_KEY: process.env.ETHERSCAN_API_KEY_CELO || "",
SITE_URL: "https://celoscan.io",
},
],
},
[Networks.metis]: {
RPC: process.env.RPC_METIS || "",
explorers: [{ API_URL: "https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan" }],
explorers: [
{
API_URL: "https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan",
SITE_URL: "https://explorer.metis.io",
},
{ API_URL: "https://andromeda-explorer.metis.io/api ", SITE_URL: "https://andromeda-explorer.metis.io" },
],
},
};
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const main = async () => {
const trace = await getTxInternalCalls(tx.hash, networkConfig.RPC);
for (const explorer of networkConfig.explorers) {
try {
await callTraceVerifier(trace.result, artifacts, buildInfos, explorer.API_URL, explorer.API_KEY);
await callTraceVerifier(trace.result, artifacts, buildInfos, explorer);
} catch (error) {
console.error("[Verification Error]", error);
}
Expand Down
31 changes: 13 additions & 18 deletions src/utils/calltrace-verifier.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,50 @@
import { ExplorerConfig } from "../config";

Check failure on line 1 in src/utils/calltrace-verifier.ts

View workflow job for this annotation

GitHub Actions / Lint

All these imports are only used as types.
import { checkIfVerified, checkVerificationStatus, submitVerification, waitTillVisible } from "./explorer-api";
import { getSettingsByArtifact } from "./foundry-ffi";
import { delay } from "./misc";

export const callTraceVerifier = async (
call: any,
artifacts: any[],
buildInfos: any[],
explorerUrl: string,
etherscanApiKey?: string,
) => {
import { delay, renderExplorerUrl } from "./misc";

export const callTraceVerifier = async (call: any, artifacts: any[], buildInfos: any[], explorer: ExplorerConfig) => {
const deployOpcodes = ["CREATE", "CREATE2"];

// Perform nested call tracing verification in each internal call
if (call.calls) {
for (const c of call.calls) {
await callTraceVerifier(c, artifacts, buildInfos, explorerUrl, etherscanApiKey);
await callTraceVerifier(c, artifacts, buildInfos, explorer);
}
}

if (!deployOpcodes.includes(call.type)) return;

await waitTillVisible(call.to, explorerUrl, etherscanApiKey);
await waitTillVisible(call.to, explorer);

const verified = await checkIfVerified(call.to, explorerUrl, etherscanApiKey);
const verified = await checkIfVerified(call.to, explorer);

if (verified) {
console.log(`(${call.to}) is already verified, skipping.`);
console.log(`(${renderExplorerUrl(call.to, explorer)}) is already verified, skipping.`);
return;
}

// if the tx has subdeployments get the deployed bytecode from the last deployment in order to
// compare the bytecode and deployed bytecode strings, resulting in the constructor params

const verificationReq = await getSettingsByArtifact(artifacts, buildInfos, call.input, call.to, etherscanApiKey);
const verificationReq = await getSettingsByArtifact(artifacts, buildInfos, call.input, call.to, explorer.API_KEY);
if (!verificationReq) {
console.log("Couldn't get the params for the verification request");
return;
}

const { result: guid, message, status }: any = await submitVerification(verificationReq, explorerUrl);
const { result: guid, message, status }: any = await submitVerification(verificationReq, explorer.API_URL);

if (!status || guid.includes("Max rate limit reached")) {
console.log(`Couldn't verify ${call.to} `, guid);
console.log(`Couldn't verify ${renderExplorerUrl(call.to, explorer)} `, guid);
return;
}

console.log(`Verifying contract ${call.to}, with guid: ${guid}`);
console.log(`Verifying contract ${renderExplorerUrl(call.to, explorer)}, with guid: ${guid}`);

for (let i = 0; i < 30; i++) {
await delay(1000);
const { status, message } = await checkVerificationStatus(guid, explorerUrl, etherscanApiKey);
const { status, message } = await checkVerificationStatus(guid, explorer);

if (status !== 2) {
console.log(message);
Expand Down
29 changes: 12 additions & 17 deletions src/utils/explorer-api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { VERBOSE } from "../config";
import { ExplorerConfig, VERBOSE } from "../config";

Check failure on line 1 in src/utils/explorer-api.ts

View workflow job for this annotation

GitHub Actions / Lint

Some named imports are only used as types.
import { delay } from "./misc";

export const submitVerification = async (verificationInfo: any, explorerUrl: string) => {
Expand All @@ -17,9 +17,9 @@ export const submitVerification = async (verificationInfo: any, explorerUrl: str
};

// checks if the smart contract is already verified before trying to verify it
export const checkIfVerified = async (deploymentAddress: string, etherscanApi: string, etherscanApiKey?: string) => {
export const checkIfVerified = async (deploymentAddress: string, explorer: ExplorerConfig) => {
const params = {
apikey: etherscanApiKey || "",
apikey: explorer.API_KEY || "",
address: deploymentAddress,
module: "contract",
action: "getabi",
Expand All @@ -28,7 +28,7 @@ export const checkIfVerified = async (deploymentAddress: string, etherscanApi: s
const formattedParams = new URLSearchParams(params).toString();

try {
const request = await fetch(`${etherscanApi}?${formattedParams}`);
const request = await fetch(`${explorer.API_URL}?${formattedParams}`);

const { status, result }: any = await request.json();

Expand All @@ -42,9 +42,9 @@ export const checkIfVerified = async (deploymentAddress: string, etherscanApi: s
}
};

export const checkIfVisible = async (deploymentAddress: string, etherscanApiUrl: string, etherscanApiKey?: string) => {
export const checkIfVisible = async (deploymentAddress: string, explorer: ExplorerConfig) => {
const params = {
apikey: etherscanApiKey || "",
apikey: explorer.API_KEY || "",
contractaddresses: deploymentAddress,
module: "contract",
action: "getcontractcreation",
Expand All @@ -53,24 +53,20 @@ export const checkIfVisible = async (deploymentAddress: string, etherscanApiUrl:
const formattedParams = new URLSearchParams(params).toString();

await delay(100);
const request = await fetch(`${etherscanApiUrl}?${formattedParams}`);
const request = await fetch(`${explorer.API_URL}?${formattedParams}`);
const { result }: any = await request.json();
return Boolean(result);
};

/*
Etherscan needs time to process the deployment, depending of the network load could take more or less time.
*/
export const waitTillVisible = async (
deploymentAddress: string,
explorerUrl: string,
etherscanApiKey?: string,
): Promise<void> => {
export const waitTillVisible = async (deploymentAddress: string, explorer: ExplorerConfig): Promise<void> => {
let visible = false;
let logged = false;

while (!visible) {
visible = await checkIfVisible(deploymentAddress, explorerUrl, etherscanApiKey);
visible = await checkIfVisible(deploymentAddress, explorer);
if (!visible) {
if (!logged) {
console.log("Waiting for on-chain settlement...");
Expand All @@ -89,14 +85,13 @@ export const waitTillVisible = async (
*/
export const checkVerificationStatus = async (
GUID: string,
explorerUrl: string,
apiKey?: string,
explorer: ExplorerConfig,
): Promise<{
status: number;
message: string;
}> => {
const params = {
apikey: apiKey || "",
apikey: explorer.API_KEY || "",
guid: GUID,
module: "contract",
action: "checkverifystatus",
Expand All @@ -105,7 +100,7 @@ export const checkVerificationStatus = async (
const formattedParams = new URLSearchParams(params).toString();

try {
const request = await fetch(`${explorerUrl}?${formattedParams}`);
const request = await fetch(`${explorer.API_URL}?${formattedParams}`);

const { status, result }: any = await request.json();
if (result === "Pending in queue") {
Expand Down
7 changes: 7 additions & 0 deletions src/utils/misc.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ExplorerConfig } from "../config";

Check failure on line 1 in src/utils/misc.ts

View workflow job for this annotation

GitHub Actions / Lint

All these imports are only used as types.

export function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
Expand All @@ -11,3 +13,8 @@ export function isHex(str: string) {

return false;
}

export function renderExplorerUrl(address: string, explorer: ExplorerConfig) {
if (!explorer.SITE_URL) return address;
return `${explorer.SITE_URL}/address/${address}`;
}

0 comments on commit 597f1eb

Please sign in to comment.