Socket
Socket
Sign inDemoInstall

@nomiclabs/hardhat-etherscan

Package Overview
Dependencies
Maintainers
3
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nomiclabs/hardhat-etherscan - npm Package Compare versions

Comparing version 2.1.1 to 2.1.8

CHANGELOG.md

46

dist/src/index.js

@@ -59,2 +59,3 @@ "use strict";

const verifySubtask = async ({ address, constructorArguments, contract: contractFQN, libraries }, { config, network, run }) => {
var _a;
const { etherscan } = config;

@@ -88,21 +89,16 @@ if (etherscan.apiKey === undefined || etherscan.apiKey.trim() === "") {

});
if (matchingCompilerVersions.length === 0) {
const detailedContext = [];
if (isVersionRange(inferredSolcVersion)) {
detailedContext.push(`The expected version range is ${inferredSolcVersion}.`);
}
else {
detailedContext.push(`The expected version is ${inferredSolcVersion}.`);
}
// There is always at least one configured version.
if (matchingCompilerVersions.length === 0 &&
// don't error if the bytecode appears to be OVM bytecode, because we can't infer a specific OVM solc version from the bytecode
!deployedBytecode.isOvmInferred()) {
let configuredCompilersFragment;
if (compilerVersions.length > 1) {
detailedContext.push(`The selected compiler versions are: ${compilerVersions.join(", ")}`);
configuredCompilersFragment = `your configured compiler versions are: ${compilerVersions.join(", ")}`;
}
else {
detailedContext.push(`The selected compiler version is: ${compilerVersions[0]}`);
configuredCompilersFragment = `your configured compiler version is: ${compilerVersions[0]}`;
}
const message = `The bytecode retrieved could not have been generated by any of the selected compilers.
${detailedContext.join("\n")}
const message = `The contract you want to verify was compiled with solidity ${inferredSolcVersion}, but ${configuredCompilersFragment}.
Possible causes are:
- You are not in the same commit that was used to deploy the contract.
- Wrong compiler version selected in hardhat config.

@@ -121,4 +117,23 @@ - The given address is wrong.

});
// Override solc version based on hardhat config if verifying for the OVM. This is used instead of fetching the
// full version name from a solc bin JSON file (as is done for EVM solc in src/solc/version.ts) because it's
// simpler and avoids a network request we don't need. This is ok because the solc version specified in the OVM
// config always equals the full solc version
if (deployedBytecode.isOvmInferred()) {
// We cast to this custom type here instead of using `extendConfig` to avoid always mutating the HardhatConfig
// type. We don't want that type to always contain the `ovm` field, because users only using hardhat-etherscan
// without the Optimism plugin should not have that field in their type definitions
const configCopy = Object.assign({}, config);
const ovmSolcVersion = (_a = configCopy.ovm) === null || _a === void 0 ? void 0 : _a.solcVersion;
if (ovmSolcVersion === undefined) {
const message = `It looks like you are verifying an OVM contract, but do not have an OVM solcVersion specified in the hardhat config.`;
throw new plugins_1.NomicLabsHardhatPluginError(constants_1.pluginName, message);
}
contractInformation.solcVersion = `v${ovmSolcVersion}`; // Etherscan requires the leading `v` before the version string
}
const deployArgumentsEncoded = await ABIEncoder_1.encodeArguments(contractInformation.contract.abi, contractInformation.sourceName, contractInformation.contractName, constructorArguments);
const solcFullVersion = await version_1.getLongVersion(contractInformation.solcVersion);
// If OVM, the full version string was already read from the hardhat config. If solc, get the full version string
const solcFullVersion = deployedBytecode.isOvmInferred()
? contractInformation.solcVersion
: await version_1.getLongVersion(contractInformation.solcVersion);
const minimumBuild = await run(constants_1.TASK_VERIFY_GET_MINIMUM_BUILD, {

@@ -339,3 +354,4 @@ sourceName: contractInformation.sourceName,

}
if (!matchingCompilerVersions.includes(buildInfo.solcVersion)) {
if (!matchingCompilerVersions.includes(buildInfo.solcVersion) &&
!deployedBytecode.isOvmInferred()) {
const inferredSolcVersion = deployedBytecode.getInferredSolcVersion();

@@ -342,0 +358,0 @@ let versionDetails;

@@ -17,2 +17,23 @@ "use strict";

NetworkID[NetworkID["BSC_TESTNET"] = 97] = "BSC_TESTNET";
// Huobi ECO Chain
NetworkID[NetworkID["HECO"] = 128] = "HECO";
NetworkID[NetworkID["HECO_TESTNET"] = 256] = "HECO_TESTNET";
// Fantom mainnet
NetworkID[NetworkID["OPERA"] = 250] = "OPERA";
NetworkID[NetworkID["FTM_TESTNET"] = 4002] = "FTM_TESTNET";
// Optimistim
NetworkID[NetworkID["OPTIMISTIC_ETHEREUM"] = 10] = "OPTIMISTIC_ETHEREUM";
NetworkID[NetworkID["OPTIMISTIC_KOVAN"] = 69] = "OPTIMISTIC_KOVAN";
// Polygon
NetworkID[NetworkID["POLYGON"] = 137] = "POLYGON";
NetworkID[NetworkID["POLYGON_MUMBAI"] = 80001] = "POLYGON_MUMBAI";
// Arbitrum
NetworkID[NetworkID["ARBITRUM_ONE"] = 42161] = "ARBITRUM_ONE";
NetworkID[NetworkID["ARBITRUM_TESTNET"] = 421611] = "ARBITRUM_TESTNET";
// Avalanche
NetworkID[NetworkID["AVALANCHE"] = 43114] = "AVALANCHE";
NetworkID[NetworkID["AVALANCHE_FUJI_TESTNET"] = 43113] = "AVALANCHE_FUJI_TESTNET";
// Moonriver
NetworkID[NetworkID["MOONRIVER"] = 1285] = "MOONRIVER";
NetworkID[NetworkID["MOONBASE_ALPHA"] = 1287] = "MOONBASE_ALPHA";
})(NetworkID || (NetworkID = {}));

@@ -22,3 +43,3 @@ const networkIDtoEndpoints = {

apiURL: "https://api.etherscan.io/api",
browserURL: "https://etherscan.io/",
browserURL: "https://etherscan.io",
},

@@ -49,2 +70,58 @@ [NetworkID.ROPSTEN]: {

},
[NetworkID.HECO]: {
apiURL: "https://api.hecoinfo.com/api",
browserURL: "https://hecoinfo.com",
},
[NetworkID.HECO_TESTNET]: {
apiURL: "https://api-testnet.hecoinfo.com/api",
browserURL: "https://testnet.hecoinfo.com",
},
[NetworkID.OPERA]: {
apiURL: "https://api.ftmscan.com/api",
browserURL: "https://ftmscan.com",
},
[NetworkID.FTM_TESTNET]: {
apiURL: "https://api-testnet.ftmscan.com/api",
browserURL: "https://testnet.ftmscan.com",
},
[NetworkID.OPTIMISTIC_ETHEREUM]: {
apiURL: "https://api-optimistic.etherscan.io/api",
browserURL: "https://optimistic.etherscan.io/",
},
[NetworkID.OPTIMISTIC_KOVAN]: {
apiURL: "https://api-kovan-optimistic.etherscan.io/api",
browserURL: "https://kovan-optimistic.etherscan.io/",
},
[NetworkID.POLYGON]: {
apiURL: "https://api.polygonscan.com/api",
browserURL: "https://polygonscan.com",
},
[NetworkID.POLYGON_MUMBAI]: {
apiURL: "https://api-testnet.polygonscan.com/api",
browserURL: "https://mumbai.polygonscan.com/",
},
[NetworkID.ARBITRUM_ONE]: {
apiURL: "https://api.arbiscan.io/api",
browserURL: "https://arbiscan.io/",
},
[NetworkID.ARBITRUM_TESTNET]: {
apiURL: "https://api-testnet.arbiscan.io/api",
browserURL: "https://testnet.arbiscan.io/",
},
[NetworkID.AVALANCHE]: {
apiURL: "https://api.snowtrace.io/api",
browserURL: "https://snowtrace.io/",
},
[NetworkID.AVALANCHE_FUJI_TESTNET]: {
apiURL: "https://api-testnet.snowtrace.io/api",
browserURL: "https://testnet.snowtrace.io/",
},
[NetworkID.MOONRIVER]: {
apiURL: "https://api-moonriver.moonscan.io/api",
browserURL: "https://moonscan.io",
},
[NetworkID.MOONBASE_ALPHA]: {
apiURL: "https://api-moonbase.moonscan.io/api",
browserURL: "https://moonbase.moonscan.io/",
},
};

@@ -51,0 +128,0 @@ async function getEtherscanEndpoints(provider, networkName) {

@@ -28,2 +28,3 @@ import { Artifacts, BuildInfo, CompilerInput, CompilerOutput, CompilerOutputBytecode } from "hardhat/types";

private _version;
private _isOvm;
private _executableSection;

@@ -33,2 +34,3 @@ private _metadataSection;

getInferredSolcVersion(): string;
isOvmInferred(): boolean;
getExecutableSection(): string;

@@ -35,0 +37,0 @@ hasMetadata(): boolean;

@@ -6,2 +6,11 @@ "use strict";

const metadata_1 = require("./metadata");
// If the compiler output bytecode is OVM bytecode, we need to make a fix to account for a bug in some versions of
// the OVM compiler. The artifact’s deployedBytecode is incorrect, but because its bytecode (initcode) is correct, when we
// actually deploy contracts, the code that ends up getting stored on chain is also correct. During verification,
// Etherscan will compile the source code, pull out the artifact’s deployedBytecode, and then perform the
// below find and replace, then check that resulting output against the code retrieved on chain from eth_getCode.
// We define the strings for that find and replace here, and use them later so we can know if the bytecode matches
// before it gets to Etherscan. Source: https://github.com/ethereum-optimism/optimism/blob/8d67991aba584c1703692ea46273ea8a1ef45f56/packages/contracts/src/contract-dumps.ts#L195-L204
const ovmFindOpcodes = "336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52";
const ovmReplaceOpcodes = "336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b";
class Bytecode {

@@ -20,2 +29,14 @@ constructor(bytecode) {

};
// Check if this is OVM bytecode by looking for the concatenation of the two opcodes defined here:
// https://github.com/ethereum-optimism/optimism/blob/33cb9025f5e463525d6abe67c8457f81a87c5a24/packages/contracts/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyChecker.sol#L143
// - This check would only fail if the EVM solidity compiler didn't use any of the following opcodes: https://github.com/ethereum-optimism/optimism/blob/c42fc0df2790a5319027393cb8fa34e4f7bb520f/packages/contracts/contracts/optimistic-ethereum/iOVM/execution/iOVM_ExecutionManager.sol#L94-L175
// This is the list of opcodes that calls the OVM execution manager. But the current solidity
// compiler seems to add REVERT in all cases, meaning it currently won't happen and this check
// will always be correct.
// - It is possible, though very unlikely, that this string appears in the bytecode of an EVM
// contract. As a result result, this _isOvm flag should only be used after trying to infer
// the solc version
// - We need this check because OVM bytecode has no metadata, so when verifying
// OVM bytecode the check in `inferSolcVersion` will always return `METADATA_ABSENT_VERSION_RANGE`.
this._isOvm = bytecode.includes(ovmReplaceOpcodes);
}

@@ -25,2 +46,5 @@ getInferredSolcVersion() {

}
isOvmInferred() {
return this._isOvm;
}
getExecutableSection() {

@@ -43,3 +67,5 @@ const { start, length } = this._executableSection;

}
if (!matchingCompilerVersions.includes(buildInfo.solcVersion)) {
if (!matchingCompilerVersions.includes(buildInfo.solcVersion) &&
// if OVM, we will not have matching compiler versions because we can't infer a specific OVM solc version from the bytecode
!deployedBytecode.isOvmInferred()) {
continue;

@@ -60,2 +86,8 @@ }

const { deployedBytecode: runtimeBytecodeSymbols } = contract.evm;
// If this is OVM bytecode, do the required find and replace (see above comments for more info)
if (deployedBytecode.isOvmInferred()) {
runtimeBytecodeSymbols.object = runtimeBytecodeSymbols.object
.split(ovmFindOpcodes)
.join(ovmReplaceOpcodes);
}
const analyzedBytecode = await compareBytecode(deployedBytecode, runtimeBytecodeSymbols);

@@ -74,7 +106,10 @@ if (analyzedBytecode !== null) {

const runtimeBytecodeExecutableSectionLength = metadata_1.measureExecutableSectionLength(runtimeBytecodeSymbols.object);
if (deployedExecutableSection.length !== runtimeBytecodeExecutableSectionLength) {
if (deployedExecutableSection.length !==
runtimeBytecodeExecutableSectionLength &&
// OVM bytecode has no metadata so we ignore this comparison if operating on OVM bytecode
!deployedBytecode.isOvmInferred()) {
return null;
}
// Normalize deployed bytecode according to this contract.
const { immutableValues, libraryLinks, normalizedBytecode, } = await normalizeBytecode(deployedExecutableSection, runtimeBytecodeSymbols);
const { immutableValues, libraryLinks, normalizedBytecode } = await normalizeBytecode(deployedExecutableSection, runtimeBytecodeSymbols);
// Library hash placeholders are embedded into the bytes where the library addresses are linked.

@@ -81,0 +116,0 @@ // We need to zero them out to compare them.

@@ -131,3 +131,4 @@ "use strict";

}
normalizedLibraries[neededLibrary.sourceName][neededLibrary.libName] = linkedLibraryAddress;
normalizedLibraries[neededLibrary.sourceName][neededLibrary.libName] =
linkedLibraryAddress;
}

@@ -134,0 +135,0 @@ return normalizedLibraries;

@@ -45,3 +45,3 @@ "use strict";

}
return response.json();
return await response.json();
}

@@ -48,0 +48,0 @@ catch (error) {

{
"name": "@nomiclabs/hardhat-etherscan",
"version": "2.1.1",
"version": "2.1.8",
"description": "Hardhat plugin for verifying contracts on etherscan",

@@ -23,7 +23,9 @@ "repository": "github:nomiclabs/hardhat",

"scripts": {
"lint:fix": "node ../../node_modules/prettier/bin-prettier.js --write \"src/**/*.{js,ts}\" \"test/**/*.{js,ts}\" && yarn lint --fix",
"lint": "node ../../node_modules/tslint/bin/tslint --config tslint.json --project ./tsconfig.json",
"test": "node ../../node_modules/mocha/bin/mocha --recursive \"test/**/*.ts\" --exit",
"build": "node ../../node_modules/typescript/bin/tsc --build .",
"clean": "node ../../node_modules/rimraf/bin.js dist"
"lint": "yarn prettier --check && yarn eslint",
"lint:fix": "yarn prettier --write && yarn eslint --fix",
"eslint": "eslint 'src/**/*.ts' 'test/**/*.ts'",
"prettier": "prettier \"**/*.{js,md,json}\"",
"test": "mocha --recursive \"test/**/*.ts\" --exit",
"build": "tsc --build .",
"clean": "rimraf dist"
},

@@ -37,3 +39,3 @@ "files": [

"dependencies": {
"@ethersproject/abi": "^5.0.2",
"@ethersproject/abi": "^5.1.2",
"@ethersproject/address": "^5.0.2",

@@ -51,8 +53,21 @@ "cbor": "^5.0.2",

"@types/fs-extra": "^5.1.0",
"@types/mocha": "^5.2.6",
"@types/node-fetch": "^2.3.7",
"@types/node": "^10.17.24",
"@types/semver": "^6.0.2",
"@typescript-eslint/eslint-plugin": "4.29.2",
"@typescript-eslint/parser": "4.29.2",
"chai": "^4.2.0",
"eslint": "^7.29.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-import": "2.24.1",
"eslint-plugin-prettier": "3.4.0",
"ethers": "^5.0.8",
"hardhat": "^2.0.4",
"nock": "^13.0.5"
"mocha": "^7.1.2",
"nock": "^13.0.5",
"prettier": "2.3.2",
"rimraf": "^3.0.2",
"ts-node": "^8.1.0",
"typescript": "~4.0.3"
},

@@ -59,0 +74,0 @@ "peerDependencies": {

@@ -1,3 +0,2 @@

[![npm](https://img.shields.io/npm/v/@nomiclabs/hardhat-etherscan.svg)](https://www.npmjs.com/package/@nomiclabs/hardhat-etherscan)
[![hardhat](https://hardhat.org/buidler-plugin-badge.svg?1)](https://hardhat.org)
[![npm](https://img.shields.io/npm/v/@nomiclabs/hardhat-etherscan.svg)](https://www.npmjs.com/package/@nomiclabs/hardhat-etherscan) [![hardhat](https://hardhat.org/buidler-plugin-badge.svg?1)](https://hardhat.org)

@@ -13,2 +12,3 @@ # hardhat-etherscan

It's smart and it tries to do as much as possible to facilitate the process:
- Just provide the deployment address and constructor arguments, and the plugin will detect locally which contract to verify.

@@ -70,3 +70,3 @@ - If your contract uses Solidity libraries, the plugin will detect them and deal with them automatically. You don't need to do anything about them.

When the constructor has a complex argument list, it might be easier to write a javascript module that exports the argument list. The expected format is the same as a constructor list for an [ethers contract](https://docs.ethers.io/v5/api/contract/). For example, if you have a contract like this:
When the constructor has a complex argument list, you'll need to write a javascript module that exports the argument list. The expected format is the same as a constructor list for an [ethers contract](https://docs.ethers.io/v5/api/contract/). For example, if you have a contract like this:

@@ -122,3 +122,3 @@ ```solidity

SomeLibrary: "0x...",
}
};
```

@@ -130,3 +130,2 @@

```js

@@ -144,3 +143,3 @@ await hre.run("verify:verify", {

],
})
});
```

@@ -147,0 +146,0 @@

@@ -137,3 +137,3 @@ import { NomicLabsHardhatPluginError } from "hardhat/plugins";

public constructor(response: any) {
constructor(response: any) {
this.status = parseInt(response.status, 10);

@@ -140,0 +140,0 @@ this.message = response.result;

@@ -210,25 +210,19 @@ import {

});
if (matchingCompilerVersions.length === 0) {
const detailedContext = [];
if (isVersionRange(inferredSolcVersion)) {
detailedContext.push(
`The expected version range is ${inferredSolcVersion}.`
);
} else {
detailedContext.push(`The expected version is ${inferredSolcVersion}.`);
}
// There is always at least one configured version.
if (
matchingCompilerVersions.length === 0 &&
// don't error if the bytecode appears to be OVM bytecode, because we can't infer a specific OVM solc version from the bytecode
!deployedBytecode.isOvmInferred()
) {
let configuredCompilersFragment;
if (compilerVersions.length > 1) {
detailedContext.push(
`The selected compiler versions are: ${compilerVersions.join(", ")}`
);
configuredCompilersFragment = `your configured compiler versions are: ${compilerVersions.join(
", "
)}`;
} else {
detailedContext.push(
`The selected compiler version is: ${compilerVersions[0]}`
);
configuredCompilersFragment = `your configured compiler version is: ${compilerVersions[0]}`;
}
const message = `The bytecode retrieved could not have been generated by any of the selected compilers.
${detailedContext.join("\n")}
const message = `The contract you want to verify was compiled with solidity ${inferredSolcVersion}, but ${configuredCompilersFragment}.
Possible causes are:
- You are not in the same commit that was used to deploy the contract.
- Wrong compiler version selected in hardhat config.

@@ -253,2 +247,21 @@ - The given address is wrong.

// Override solc version based on hardhat config if verifying for the OVM. This is used instead of fetching the
// full version name from a solc bin JSON file (as is done for EVM solc in src/solc/version.ts) because it's
// simpler and avoids a network request we don't need. This is ok because the solc version specified in the OVM
// config always equals the full solc version
if (deployedBytecode.isOvmInferred()) {
// We cast to this custom type here instead of using `extendConfig` to avoid always mutating the HardhatConfig
// type. We don't want that type to always contain the `ovm` field, because users only using hardhat-etherscan
// without the Optimism plugin should not have that field in their type definitions
const configCopy = { ...config } as unknown as {
ovm?: { solcVersion?: string };
};
const ovmSolcVersion = configCopy.ovm?.solcVersion;
if (ovmSolcVersion === undefined) {
const message = `It looks like you are verifying an OVM contract, but do not have an OVM solcVersion specified in the hardhat config.`;
throw new NomicLabsHardhatPluginError(pluginName, message);
}
contractInformation.solcVersion = `v${ovmSolcVersion}`; // Etherscan requires the leading `v` before the version string
}
const deployArgumentsEncoded = await encodeArguments(

@@ -261,3 +274,6 @@ contractInformation.contract.abi,

const solcFullVersion = await getLongVersion(contractInformation.solcVersion);
// If OVM, the full version string was already read from the hardhat config. If solc, get the full version string
const solcFullVersion = deployedBytecode.isOvmInferred()
? contractInformation.solcVersion
: await getLongVersion(contractInformation.solcVersion);

@@ -629,3 +645,6 @@ const minimumBuild: Build = await run(TASK_VERIFY_GET_MINIMUM_BUILD, {

if (!matchingCompilerVersions.includes(buildInfo.solcVersion)) {
if (
!matchingCompilerVersions.includes(buildInfo.solcVersion) &&
!deployedBytecode.isOvmInferred()
) {
const inferredSolcVersion = deployedBytecode.getInferredSolcVersion();

@@ -651,5 +670,4 @@ let versionDetails;

const { sourceName, contractName } = parseFullyQualifiedName(
contractFQN
);
const { sourceName, contractName } =
parseFullyQualifiedName(contractFQN);
contractInformation = await extractMatchingContractInformation(

@@ -656,0 +674,0 @@ sourceName,

@@ -28,2 +28,23 @@ import {

BSC_TESTNET = 97,
// Huobi ECO Chain
HECO = 128,
HECO_TESTNET = 256,
// Fantom mainnet
OPERA = 250,
FTM_TESTNET = 4002,
// Optimistim
OPTIMISTIC_ETHEREUM = 10,
OPTIMISTIC_KOVAN = 69,
// Polygon
POLYGON = 137,
POLYGON_MUMBAI = 80001,
// Arbitrum
ARBITRUM_ONE = 42161,
ARBITRUM_TESTNET = 421611,
// Avalanche
AVALANCHE = 43114,
AVALANCHE_FUJI_TESTNET = 43113,
// Moonriver
MOONRIVER = 1285,
MOONBASE_ALPHA = 1287,
}

@@ -34,3 +55,3 @@

apiURL: "https://api.etherscan.io/api",
browserURL: "https://etherscan.io/",
browserURL: "https://etherscan.io",
},

@@ -61,2 +82,58 @@ [NetworkID.ROPSTEN]: {

},
[NetworkID.HECO]: {
apiURL: "https://api.hecoinfo.com/api",
browserURL: "https://hecoinfo.com",
},
[NetworkID.HECO_TESTNET]: {
apiURL: "https://api-testnet.hecoinfo.com/api",
browserURL: "https://testnet.hecoinfo.com",
},
[NetworkID.OPERA]: {
apiURL: "https://api.ftmscan.com/api",
browserURL: "https://ftmscan.com",
},
[NetworkID.FTM_TESTNET]: {
apiURL: "https://api-testnet.ftmscan.com/api",
browserURL: "https://testnet.ftmscan.com",
},
[NetworkID.OPTIMISTIC_ETHEREUM]: {
apiURL: "https://api-optimistic.etherscan.io/api",
browserURL: "https://optimistic.etherscan.io/",
},
[NetworkID.OPTIMISTIC_KOVAN]: {
apiURL: "https://api-kovan-optimistic.etherscan.io/api",
browserURL: "https://kovan-optimistic.etherscan.io/",
},
[NetworkID.POLYGON]: {
apiURL: "https://api.polygonscan.com/api",
browserURL: "https://polygonscan.com",
},
[NetworkID.POLYGON_MUMBAI]: {
apiURL: "https://api-testnet.polygonscan.com/api",
browserURL: "https://mumbai.polygonscan.com/",
},
[NetworkID.ARBITRUM_ONE]: {
apiURL: "https://api.arbiscan.io/api",
browserURL: "https://arbiscan.io/",
},
[NetworkID.ARBITRUM_TESTNET]: {
apiURL: "https://api-testnet.arbiscan.io/api",
browserURL: "https://testnet.arbiscan.io/",
},
[NetworkID.AVALANCHE]: {
apiURL: "https://api.snowtrace.io/api",
browserURL: "https://snowtrace.io/",
},
[NetworkID.AVALANCHE_FUJI_TESTNET]: {
apiURL: "https://api-testnet.snowtrace.io/api",
browserURL: "https://testnet.snowtrace.io/",
},
[NetworkID.MOONRIVER]: {
apiURL: "https://api-moonriver.moonscan.io/api",
browserURL: "https://moonscan.io",
},
[NetworkID.MOONBASE_ALPHA]: {
apiURL: "https://api-moonbase.moonscan.io/api",
browserURL: "https://moonbase.moonscan.io/",
},
};

@@ -63,0 +140,0 @@

@@ -10,8 +10,3 @@ import {

import { LibraryNames } from "./libraries";
import {
inferSolcVersion,
measureExecutableSectionLength,
METADATA_ABSENT_VERSION_RANGE,
} from "./metadata";
import { inferSolcVersion, measureExecutableSectionLength } from "./metadata";

@@ -56,5 +51,18 @@ interface BytecodeExtractedData {

// If the compiler output bytecode is OVM bytecode, we need to make a fix to account for a bug in some versions of
// the OVM compiler. The artifact’s deployedBytecode is incorrect, but because its bytecode (initcode) is correct, when we
// actually deploy contracts, the code that ends up getting stored on chain is also correct. During verification,
// Etherscan will compile the source code, pull out the artifact’s deployedBytecode, and then perform the
// below find and replace, then check that resulting output against the code retrieved on chain from eth_getCode.
// We define the strings for that find and replace here, and use them later so we can know if the bytecode matches
// before it gets to Etherscan. Source: https://github.com/ethereum-optimism/optimism/blob/8d67991aba584c1703692ea46273ea8a1ef45f56/packages/contracts/src/contract-dumps.ts#L195-L204
const ovmFindOpcodes =
"336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52";
const ovmReplaceOpcodes =
"336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b";
export class Bytecode {
private _bytecode: string;
private _version: string;
private _isOvm: boolean;

@@ -78,2 +86,15 @@ private _executableSection: BytecodeSlice;

};
// Check if this is OVM bytecode by looking for the concatenation of the two opcodes defined here:
// https://github.com/ethereum-optimism/optimism/blob/33cb9025f5e463525d6abe67c8457f81a87c5a24/packages/contracts/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyChecker.sol#L143
// - This check would only fail if the EVM solidity compiler didn't use any of the following opcodes: https://github.com/ethereum-optimism/optimism/blob/c42fc0df2790a5319027393cb8fa34e4f7bb520f/packages/contracts/contracts/optimistic-ethereum/iOVM/execution/iOVM_ExecutionManager.sol#L94-L175
// This is the list of opcodes that calls the OVM execution manager. But the current solidity
// compiler seems to add REVERT in all cases, meaning it currently won't happen and this check
// will always be correct.
// - It is possible, though very unlikely, that this string appears in the bytecode of an EVM
// contract. As a result result, this _isOvm flag should only be used after trying to infer
// the solc version
// - We need this check because OVM bytecode has no metadata, so when verifying
// OVM bytecode the check in `inferSolcVersion` will always return `METADATA_ABSENT_VERSION_RANGE`.
this._isOvm = bytecode.includes(ovmReplaceOpcodes);
}

@@ -85,2 +106,6 @@

public isOvmInferred(): boolean {
return this._isOvm;
}
public getExecutableSection(): string {

@@ -111,3 +136,7 @@ const { start, length } = this._executableSection;

if (!matchingCompilerVersions.includes(buildInfo.solcVersion)) {
if (
!matchingCompilerVersions.includes(buildInfo.solcVersion) &&
// if OVM, we will not have matching compiler versions because we can't infer a specific OVM solc version from the bytecode
!deployedBytecode.isOvmInferred()
) {
continue;

@@ -142,2 +171,9 @@ }

// If this is OVM bytecode, do the required find and replace (see above comments for more info)
if (deployedBytecode.isOvmInferred()) {
runtimeBytecodeSymbols.object = runtimeBytecodeSymbols.object
.split(ovmFindOpcodes)
.join(ovmReplaceOpcodes);
}
const analyzedBytecode = await compareBytecode(

@@ -174,3 +210,6 @@ deployedBytecode,

if (
deployedExecutableSection.length !== runtimeBytecodeExecutableSectionLength
deployedExecutableSection.length !==
runtimeBytecodeExecutableSectionLength &&
// OVM bytecode has no metadata so we ignore this comparison if operating on OVM bytecode
!deployedBytecode.isOvmInferred()
) {

@@ -181,10 +220,4 @@ return null;

// Normalize deployed bytecode according to this contract.
const {
immutableValues,
libraryLinks,
normalizedBytecode,
} = await normalizeBytecode(
deployedExecutableSection,
runtimeBytecodeSymbols
);
const { immutableValues, libraryLinks, normalizedBytecode } =
await normalizeBytecode(deployedExecutableSection, runtimeBytecodeSymbols);

@@ -191,0 +224,0 @@ // Library hash placeholders are embedded into the bytes where the library addresses are linked.

@@ -199,5 +199,4 @@ import { NomicLabsHardhatPluginError } from "hardhat/plugins";

}
normalizedLibraries[neededLibrary.sourceName][
neededLibrary.libName
] = linkedLibraryAddress;
normalizedLibraries[neededLibrary.sourceName][neededLibrary.libName] =
linkedLibraryAddress;
}

@@ -204,0 +203,0 @@ return normalizedLibraries;

@@ -5,4 +5,2 @@ import type cbor from "cbor";

import { pluginName } from "../constants";
interface MetadataDescription {

@@ -128,7 +126,6 @@ solcVersion: string;

const runtimeMetadataSectionLength = getSolcMetadataSectionLength(
metadataLengthSlice
);
const runtimeMetadataSectionLength =
getSolcMetadataSectionLength(metadataLengthSlice);
return bytecode.length - runtimeMetadataSectionLength * 2;
}

@@ -44,3 +44,3 @@ import { NomicLabsHardhatPluginError } from "hardhat/plugins";

return response.json();
return await response.json();
} catch (error) {

@@ -47,0 +47,0 @@ throw new NomicLabsHardhatPluginError(

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc