diff --git a/packages/buidler-etherscan/package.json b/packages/buidler-etherscan/package.json index 2ae29e2765..a10cb00d06 100644 --- a/packages/buidler-etherscan/package.json +++ b/packages/buidler-etherscan/package.json @@ -39,7 +39,7 @@ "@ethersproject/abi": "^5.0.2", "@ethersproject/address": "^5.0.2", "cbor": "^5.0.2", - "ethereumjs-abi": "^0.6.8", + "fs-extra": "^7.0.1", "node-fetch": "^2.6.0", "semver": "^6.3.0" }, @@ -47,6 +47,7 @@ "@nomiclabs/hardhat-ethers": "^2.0.0", "@types/cbor": "^5.0.1", "@types/chai": "^4.2.0", + "@types/fs-extra": "^5.1.0", "@types/nock": "^9.3.1", "@types/node-fetch": "^2.3.7", "@types/semver": "^6.0.2", diff --git a/packages/buidler-etherscan/src/ABIEncoder.ts b/packages/buidler-etherscan/src/ABIEncoder.ts index b189fbd722..3e91e7e15a 100644 --- a/packages/buidler-etherscan/src/ABIEncoder.ts +++ b/packages/buidler-etherscan/src/ABIEncoder.ts @@ -4,7 +4,7 @@ import { pluginName } from "./pluginContext"; export async function encodeArguments( abi: any, - contractFilename: string, + sourceName: string, contractName: string, constructorArguments: any[] ) { @@ -24,7 +24,7 @@ export async function encodeArguments( } = await import("./ABITypes"); if (isABIArgumentLengthError(error)) { // TODO: add a list of types and constructor arguments to the error message? - const message = `The constructor for ${contractFilename}:${contractName} has ${error.count.types} parameters + const message = `The constructor for ${sourceName}:${contractName} has ${error.count.types} parameters but ${error.count.values} arguments were provided instead.`; throw new NomicLabsHardhatPluginError(pluginName, message, error); } diff --git a/packages/buidler-etherscan/src/etherscan/EtherscanVerifyContractRequest.ts b/packages/buidler-etherscan/src/etherscan/EtherscanVerifyContractRequest.ts index 44ed43c9f1..7bbf1560d1 100644 --- a/packages/buidler-etherscan/src/etherscan/EtherscanVerifyContractRequest.ts +++ b/packages/buidler-etherscan/src/etherscan/EtherscanVerifyContractRequest.ts @@ -25,7 +25,7 @@ export function toVerifyRequest(params: { apiKey: string; contractAddress: string; sourceCode: string; - contractFilename: string; + sourceName: string; contractName: string; compilerVersion: string; constructorArguments: string; @@ -37,7 +37,7 @@ export function toVerifyRequest(params: { contractaddress: params.contractAddress, sourceCode: params.sourceCode, codeformat: "solidity-standard-json-input", - contractname: `${params.contractFilename}:${params.contractName}`, + contractname: `${params.sourceName}:${params.contractName}`, compilerversion: params.compilerVersion, constructorArguements: params.constructorArguments, }; diff --git a/packages/buidler-etherscan/src/index.ts b/packages/buidler-etherscan/src/index.ts index 4b19cd2643..c726a59ff8 100644 --- a/packages/buidler-etherscan/src/index.ts +++ b/packages/buidler-etherscan/src/index.ts @@ -60,12 +60,16 @@ See https://etherscan.io/apis` // TODO: perhaps querying and scraping this list would be a better approach? // This list should be validated - it links to https://github.com/ethereum/solc-bin/blob/gh-pages/bin/list.txt // which has many old compilers included in the list too. - // TODO-HH: handle multiple compilers + const configuredVersions = config.solidity.compilers.map((c) => c.version); + if (config.solidity.overrides !== undefined) { + for (const { version } of Object.values(config.solidity.overrides)) { + configuredVersions.push(version); + } + } if ( - !semver.satisfies( - config.solidity.compilers[0].version, - supportedSolcVersionRange - ) + configuredVersions.some((version) => { + return !semver.satisfies(version, supportedSolcVersionRange); + }) ) { throw new NomicLabsHardhatPluginError( pluginName, @@ -143,38 +147,45 @@ The selected network is ${network.name}.` const bytecodeBuffer = Buffer.from(deployedContractBytecode, "hex"); const inferredSolcVersion = await inferSolcVersion(bytecodeBuffer); - // TODO-HH: handle multiple compilers - if ( - !semver.satisfies( - config.solidity.compilers[0].version, - inferredSolcVersion.range - ) - ) { - let detailedContext; + const matchingVersions = configuredVersions.filter((version) => { + return semver.satisfies(version, inferredSolcVersion.range); + }); + if (matchingVersions.length === 0) { + const detailedContext = []; if (inferredSolcVersion.inferralType === InferralType.EXACT) { - detailedContext = `The expected version is ${inferredSolcVersion.range}.`; + detailedContext.push( + `The expected version is ${inferredSolcVersion.range}.` + ); } else { - detailedContext = `The expected version range is ${inferredSolcVersion.range}.`; + detailedContext.push( + `The expected version range is ${inferredSolcVersion.range}.` + ); } - // TODO-HH: handle multiple compilers - const message = `The bytecode retrieved could not have been generated by the selected compiler. -The selected compiler version is v${config.solidity.compilers[0].version}. -${detailedContext} + // There is always at least one configured version. + if (configuredVersions.length > 1) { + detailedContext.push( + `The selected compiler versions are: ${configuredVersions.join(", ")}` + ); + } else { + detailedContext.push( + `The selected compiler version is: ${configuredVersions[0]}` + ); + } + const message = `The bytecode retrieved could not have been generated by any of the selected compilers. +${detailedContext.join("\n")} Possible causes are: - - Wrong compiler version in hardhat config. + - Wrong compiler version selected in hardhat config. - The given address is wrong. - The selected network (${network.name}) is wrong.`; throw new NomicLabsHardhatPluginError(pluginName, message); } const { lookupMatchingBytecode, compile } = await import("./solc/bytecode"); - // TODO: this gives us the input for all contracts. - // This could be restricted to relevant contracts in a future iteration of the compiler tasks. - const { compilerInput, compilerOutput } = await compile(run); + const builds = await compile(run, matchingVersions, config.paths.artifacts); const contractMatches = await lookupMatchingBytecode( - compilerOutput.contracts, + builds, deployedContractBytecode, inferredSolcVersion.inferralType ); @@ -192,7 +203,7 @@ Possible causes are: if (contractMatches.length > 1) { const nameList = contractMatches .map((contract) => { - return `${contract.contractFilename}:${contract.contractName}`; + return `${contract.sourceName}:${contract.contractName}`; }) .join(", "); const message = `More than one contract was found to match the deployed bytecode. @@ -202,22 +213,34 @@ ${nameList}`; } const [contractInformation] = contractMatches; + const libraryLinks = contractInformation.libraryLinks; + const deployLibraryReferences = + contractInformation.contract.evm.bytecode.linkReferences; + if ( + Object.keys(libraryLinks).length < + Object.keys(deployLibraryReferences).length + ) { + throw new NomicLabsHardhatPluginError( + pluginName, + `The contract ${contractInformation.sourceName}:${contractInformation.contractName} has one or more library references that cannot be detected from deployed bytecode. +This can occur if the library is only called in the contract constructor.` + ); + } + const { encodeArguments } = await import("./ABIEncoder"); const deployArgumentsEncoded = await encodeArguments( contractInformation.contract.abi, - contractInformation.contractFilename, + contractInformation.sourceName, contractInformation.contractName, constructorArguments ); // Ensure the linking information is present in the compiler input; - compilerInput.settings.libraries = contractInformation.libraryLinks; - const compilerInputJSON = JSON.stringify(compilerInput); + contractInformation.compilerInput.settings.libraries = + contractInformation.libraryLinks; + const compilerInputJSON = JSON.stringify(contractInformation.compilerInput); - // TODO-HH: handle multiple compilers - const solcFullVersion = await getLongVersion( - config.solidity.compilers[0].version - ); + const solcFullVersion = await getLongVersion(contractInformation.solcVersion); const { toVerifyRequest, toCheckStatusRequest } = await import( "./etherscan/EtherscanVerifyContractRequest" @@ -226,7 +249,7 @@ ${nameList}`; apiKey: etherscan.apiKey, contractAddress: address, sourceCode: compilerInputJSON, - contractFilename: contractInformation.contractFilename, + sourceName: contractInformation.sourceName, contractName: contractInformation.contractName, compilerVersion: solcFullVersion, constructorArguments: deployArgumentsEncoded, @@ -239,7 +262,7 @@ ${nameList}`; console.log( `Successfully submitted source code for contract -${contractInformation.contractFilename}:${contractInformation.contractName} at ${address} +${contractInformation.sourceName}:${contractInformation.contractName} at ${address} for verification on etherscan. Waiting for verification result...` ); diff --git a/packages/buidler-etherscan/src/solc/bytecode.ts b/packages/buidler-etherscan/src/solc/bytecode.ts index 95f6bf7575..7288162662 100644 --- a/packages/buidler-etherscan/src/solc/bytecode.ts +++ b/packages/buidler-etherscan/src/solc/bytecode.ts @@ -1,59 +1,150 @@ +import fs from "fs-extra"; +import { Artifacts } from "hardhat/plugins"; import { RunTaskFunction } from "hardhat/types"; +import path from "path"; import { METADATA_LENGTH_SIZE, readSolcMetadataLength } from "./metadata"; import { InferralType } from "./version"; +type BytecodeComparison = + | { match: false } + | { match: true; contractInformation: BytecodeExtractedData }; + +interface BytecodeExtractedData { + immutableValues: ImmutableValues; + libraryLinks: ResolvedLinks; + normalizedBytecode: string; +} + +interface ResolvedLinks { + [sourceName: string]: { + [libraryName: string]: string; + }; +} + +interface ImmutableValues { + [key: string]: string; +} + +interface BytecodeSlice { + start: number; + length: number; +} + +type LinkReferences = CompilerOutputBytecode["linkReferences"][string][string]; +type NestedSliceReferences = BytecodeSlice[][]; + +/* Taken from stack trace hardhat network internals + * This is not an exhaustive interface for compiler input nor output. + */ + +interface CompilerInput { + language: "Solidity"; + sources: { [sourceName: string]: { content: string } }; + settings: { + optimizer: { runs: number; enabled: boolean }; + evmVersion?: string; + libraries?: ResolvedLinks; + }; +} + +interface CompilerOutput { + sources: CompilerOutputSources; + contracts: { + [sourceName: string]: { + [contractName: string]: { + abi: any; + evm: { + bytecode: CompilerOutputBytecode; + deployedBytecode: CompilerOutputBytecode; + methodIdentifiers: { + [methodSignature: string]: string; + }; + }; + }; + }; + }; +} + +interface CompilerOutputSource { + id: number; + ast: any; +} + +interface CompilerOutputSources { + [sourceName: string]: CompilerOutputSource; +} + +interface CompilerOutputBytecode { + object: string; + opcodes: string; + sourceMap: string; + linkReferences: { + [sourceName: string]: { + [libraryName: string]: Array<{ start: 0; length: 20 }>; + }; + }; + immutableReferences?: { + [key: string]: Array<{ start: number; length: number }>; + }; +} + +interface BuildInfo { + input: CompilerInput; + output: CompilerOutput; + solcVersion: string; +} + +interface ContractBuildInfo { + contractName: string; + sourceName: string; + buildInfo: BuildInfo; +} + +/**/ + export async function lookupMatchingBytecode( - contractFiles: CompilerOutput["contracts"], + contractBuilds: ContractBuildInfo[], deployedBytecode: string, inferralType: InferralType ) { const contractMatches = []; - for (const [contractFilename, contracts] of Object.entries(contractFiles)) { - for (const [contractName, contract] of Object.entries(contracts)) { - // Normalize deployed bytecode according to this contract. - const { deployedBytecode: runtimeBytecodeSymbols } = contract.evm; - - const comparison = await compareBytecode( - deployedBytecode, - runtimeBytecodeSymbols, - inferralType - ); - - if (comparison.match) { - const { - contractInformation: { - immutableValues, - libraryLinks, - normalizedBytecode, - }, - } = comparison; - // The bytecode matches - contractMatches.push({ + for (const { contractName, sourceName, buildInfo } of contractBuilds) { + const contract = buildInfo.output.contracts[sourceName][contractName]; + // Normalize deployed bytecode according to this contract. + const { deployedBytecode: runtimeBytecodeSymbols } = contract.evm; + + const comparison = await compareBytecode( + deployedBytecode, + runtimeBytecodeSymbols, + inferralType + ); + + if (comparison.match) { + const { + contractInformation: { immutableValues, libraryLinks, normalizedBytecode, - contractFilename, - contractName, - contract, - }); - } + }, + } = comparison; + // The bytecode matches + contractMatches.push({ + compilerInput: buildInfo.input, + solcVersion: buildInfo.solcVersion, + immutableValues, + libraryLinks, + normalizedBytecode, + sourceName, + contractName, + contract, + }); } } return contractMatches; } -type BytecodeComparison = - | { match: false } - | { match: true; contractInformation: BytecodeExtractedData }; - -interface BytecodeExtractedData { - immutableValues: ImmutableValues; - libraryLinks: ResolvedLinks; - normalizedBytecode: string; -} - export async function compareBytecode( deployedBytecode: string, runtimeBytecodeSymbols: CompilerOutputBytecode, @@ -125,31 +216,15 @@ export async function compareBytecode( return { match: false }; } -interface ResolvedLinks { - [sourceName: string]: { - [libraryName: string]: string; - }; -} - -interface ImmutableValues { - [key: string]: string; -} - -interface BytecodeSlice { - start: number; - length: number; -} - -type LinkReferences = CompilerOutputBytecode["linkReferences"][string][string]; -type NestedSliceReferences = BytecodeSlice[][]; - export async function normalizeBytecode( bytecode: string, symbols: CompilerOutputBytecode ) { const nestedSliceReferences: NestedSliceReferences = []; const libraryLinks: ResolvedLinks = {}; - for (const [filename, libraries] of Object.entries(symbols.linkReferences)) { + for (const [sourceName, libraries] of Object.entries( + symbols.linkReferences + )) { for (const [libraryName, linkReferences] of Object.entries(libraries)) { // Is this even a possibility? if (linkReferences.length === 0) { @@ -157,11 +232,11 @@ export async function normalizeBytecode( } const { start, length } = linkReferences[0]; - if (libraryLinks[filename] === undefined) { - libraryLinks[filename] = {}; + if (libraryLinks[sourceName] === undefined) { + libraryLinks[sourceName] = {}; } // We have the bytecode encoded as a hex string - libraryLinks[filename][libraryName] = `0x${bytecode.slice( + libraryLinks[sourceName][libraryName] = `0x${bytecode.slice( start * 2, (start + length) * 2 )}`; @@ -224,61 +299,45 @@ export function zeroOutSlices( return code; } -/* Taken from stack trace hardhat internals - * This is not an exhaustive interface for compiler input nor output. - */ - -export interface CompilerInput { - language: "Solidity"; - sources: { [sourceName: string]: { content: string } }; - settings: { - optimizer: { runs: number; enabled: boolean }; - evmVersion?: string; - libraries?: ResolvedLinks; - }; -} - -export interface CompilerOutput { - contracts: { - [sourceName: string]: { - [contractName: string]: { - abi: any; - evm: { - bytecode: CompilerOutputBytecode; - deployedBytecode: CompilerOutputBytecode; - }; - }; - }; - }; -} - -export interface CompilerOutputBytecode { - object: string; - linkReferences: { - [sourceName: string]: { - [libraryName: string]: Array<{ start: number; length: 20 }>; - }; - }; - immutableReferences?: { - [key: string]: Array<{ start: number; length: number }>; - }; -} +export async function compile( + taskRun: RunTaskFunction, + matchingVersions: string[], + artifactsPath: string +): Promise { + const { TASK_COMPILE } = await import("hardhat/builtin-tasks/task-names"); + + await taskRun(TASK_COMPILE); + + const artifacts = new Artifacts(artifactsPath); + const buildInfoFiles = await artifacts.getBuildInfoFiles(); + + // TODO: Here would be an ideal place to separate builds into several compilation jobs + // to address https://github.com/nomiclabs/buidler/issues/804 if possible. + const builds: { [buildHash: string]: BuildInfo } = {}; + for (const buildInfoFile of buildInfoFiles) { + const buildInfo: BuildInfo = await fs.readJSON(buildInfoFile); + if (matchingVersions.includes(buildInfo.solcVersion)) { + builds[path.basename(buildInfoFile)] = buildInfo; + } + } -/**/ + const contracts = []; + const artifactFiles = await artifacts.getArtifacts(); + for (const artifactFile of artifactFiles) { + const contractName = path.basename(artifactFile.replace(".json", "")); + const sourceName = path.relative(artifactsPath, path.dirname(artifactFile)); + const dbgFile = path.join( + artifactsPath, + sourceName, + `${contractName}.dbg.json` + ); + const dbgInfo: { buildInfo: string } = await fs.readJSON(dbgFile); + contracts.push({ + contractName, + sourceName, + buildInfo: builds[path.basename(dbgInfo.buildInfo)], + }); + } -// TODO: This is extremely ugly and should be replaced with better build primitives when possible. -// Ideally, we would access the input and output through some sort of artifact. -export async function compile(taskRun: RunTaskFunction) { - const { - TASK_COMPILE_SOLIDITY_COMPILE, - TASK_COMPILE_SOLIDITY_GET_COMPILER_INPUT, - } = await import("hardhat/builtin-tasks/task-names"); - - const compilerInput = (await taskRun( - TASK_COMPILE_SOLIDITY_GET_COMPILER_INPUT - )) as CompilerInput; - const compilerOutput = (await taskRun( - TASK_COMPILE_SOLIDITY_COMPILE - )) as CompilerOutput; - return { compilerInput, compilerOutput }; + return contracts; } diff --git a/packages/buidler-etherscan/test/hardhat-project-defined-config/hardhat.config.js b/packages/buidler-etherscan/test/hardhat-project-defined-config/hardhat.config.js index a35c698209..64b11905b6 100644 --- a/packages/buidler-etherscan/test/hardhat-project-defined-config/hardhat.config.js +++ b/packages/buidler-etherscan/test/hardhat-project-defined-config/hardhat.config.js @@ -6,7 +6,7 @@ module.exports = { etherscan: { apiKey: "testtoken", }, - solc: { + solidity: { version: "0.5.15", }, }; diff --git a/packages/buidler-etherscan/test/hardhat-project-undefined-config/hardhat.config.js b/packages/buidler-etherscan/test/hardhat-project-undefined-config/hardhat.config.js index 0b9c1c1a06..e1160d8e39 100644 --- a/packages/buidler-etherscan/test/hardhat-project-undefined-config/hardhat.config.js +++ b/packages/buidler-etherscan/test/hardhat-project-undefined-config/hardhat.config.js @@ -3,7 +3,7 @@ const { loadPluginFile } = require("hardhat/plugins-testing"); loadPluginFile(__dirname + "/../../src/index"); module.exports = { - solc: { + solidity: { version: "0.5.15", }, }; diff --git a/packages/buidler-etherscan/test/hardhat-project/hardhat.config.js b/packages/buidler-etherscan/test/hardhat-project/hardhat.config.js index 12a3df5644..5247c680cc 100644 --- a/packages/buidler-etherscan/test/hardhat-project/hardhat.config.js +++ b/packages/buidler-etherscan/test/hardhat-project/hardhat.config.js @@ -8,7 +8,7 @@ module.exports = { etherscan: { apiKey: process.env.ETHERSCAN_API_KEY, }, - solc: { + solidity: { version: "0.5.15", }, networks: { diff --git a/packages/buidler-etherscan/test/integration/PluginTests.ts b/packages/buidler-etherscan/test/integration/PluginTests.ts index 36e414b505..9b7d92b04a 100644 --- a/packages/buidler-etherscan/test/integration/PluginTests.ts +++ b/packages/buidler-etherscan/test/integration/PluginTests.ts @@ -165,6 +165,6 @@ async function deployContract( const factory = await ethers.getContractFactory(contractName, wallet); const contract = await factory.deploy(...constructorArguments); - await contract.deployTransaction.wait(3); + await contract.deployTransaction.wait(4); return contract.address; } diff --git a/packages/buidler-etherscan/test/unit/ABIEncoder.ts b/packages/buidler-etherscan/test/unit/ABIEncoder.ts index b85576d4a8..9aa17b24ea 100644 --- a/packages/buidler-etherscan/test/unit/ABIEncoder.ts +++ b/packages/buidler-etherscan/test/unit/ABIEncoder.ts @@ -4,7 +4,7 @@ import { NomicLabsHardhatPluginError } from "hardhat/plugins"; import { encodeArguments } from "../../src/ABIEncoder"; describe("constructor argument validation tests", () => { - const contractFilename = "TheContract.sol"; + const sourceName = "TheContract.sol"; const contractName = "TheContract"; it("should validate empty argument list", async () => { @@ -18,7 +18,7 @@ describe("constructor argument validation tests", () => { const constructorArguments: any[] = []; const encodedArguments = await encodeArguments( abi, - contractFilename, + sourceName, contractName, constructorArguments ); @@ -41,7 +41,7 @@ describe("constructor argument validation tests", () => { const constructorArguments: any[] = [50]; const encodedArguments = await encodeArguments( abi, - contractFilename, + sourceName, contractName, constructorArguments ); @@ -71,7 +71,7 @@ describe("constructor argument validation tests", () => { const encodedArguments = await encodeArguments( abi, - contractFilename, + sourceName, contractName, constructorArguments ).catch((reason) => { @@ -99,7 +99,7 @@ describe("constructor argument validation tests", () => { const constructorArguments: any[] = [50]; return encodeArguments( abi, - contractFilename, + sourceName, contractName, constructorArguments ).catch((reason) => { @@ -123,7 +123,7 @@ describe("constructor argument validation tests", () => { const constructorArguments: any[] = [50, 100]; return encodeArguments( abi, - contractFilename, + sourceName, contractName, constructorArguments ).catch((reason) => { @@ -159,7 +159,7 @@ describe("constructor argument validation tests", () => { ]; const encodedArguments = await encodeArguments( abi, - contractFilename, + sourceName, contractName, constructorArguments ); @@ -201,7 +201,7 @@ describe("constructor argument validation tests", () => { ]; return encodeArguments( abi, - contractFilename, + sourceName, contractName, constructorArguments ).catch((reason) => { @@ -258,7 +258,7 @@ describe("constructor argument validation tests", () => { ]; const encodedArguments = await encodeArguments( abi, - contractFilename, + sourceName, contractName, constructorArguments ); diff --git a/packages/buidler-etherscan/test/unit/solc/bytecode.ts b/packages/buidler-etherscan/test/unit/solc/bytecode.ts index cc9b2f1da4..6cab2f6586 100644 --- a/packages/buidler-etherscan/test/unit/solc/bytecode.ts +++ b/packages/buidler-etherscan/test/unit/solc/bytecode.ts @@ -24,6 +24,8 @@ describe("Compiler bytecode and deployed bytecode matching", () => { const contractSymbols = { object: contract.runtimeBytecode.slice(2), linkReferences: contract.linkReferences, + opcodes: "", + sourceMap: "", // immutableReferences: contract.immutableReferences, }; const deployedBytecode = contract.deployedBytecode.slice(2); @@ -50,6 +52,8 @@ describe("Compiler bytecode and deployed bytecode matching", () => { const contractSymbols = { object: contract.runtimeBytecode.slice(2), linkReferences: contract.linkReferences, + opcodes: "", + sourceMap: "", immutableReferences: contract.immutableReferences, }; const deployedBytecode = contract.deployedBytecode.slice(2); @@ -101,6 +105,8 @@ describe("Compiler bytecode and deployed bytecode matching", () => { const contractSymbols = { object: bytecodeWithNewMetadata, linkReferences: contract.linkReferences, + opcodes: "", + sourceMap: "", immutableReferences: contract.immutableReferences, }; @@ -128,6 +134,8 @@ describe("Compiler bytecode and deployed bytecode matching", () => { const contractSymbols = { object: contract.runtimeBytecode.slice(2), linkReferences: contract.linkReferences, + opcodes: "", + sourceMap: "", immutableReferences: contract.immutableReferences, }; const deployedBytecode = contract.deployedBytecode.slice(2); @@ -159,6 +167,8 @@ describe("Compiler bytecode and deployed bytecode matching", () => { const contractSymbols = { object: contract.runtimeBytecode.slice(2), linkReferences: contract.linkReferences, + opcodes: "", + sourceMap: "", // immutableReferences: contract.immutableReferences, }; const deployedBytecode = contract.deployedBytecode.slice(2); @@ -188,6 +198,8 @@ describe("Compiler bytecode and deployed bytecode matching", () => { const contractSymbols = { object: contract.runtimeBytecode.slice(2), linkReferences: contract.linkReferences, + opcodes: "", + sourceMap: "", // immutableReferences: contract.immutableReferences, }; const deployedBytecode = contract.deployedBytecode.slice(2); @@ -218,6 +230,8 @@ describe("Compiler bytecode and deployed bytecode matching", () => { const contractSymbols = { object: contract.runtimeBytecode.slice(2), linkReferences: contract.linkReferences, + opcodes: "", + sourceMap: "", immutableReferences: contract.immutableReferences, }; const deployedBytecode = contract.deployedBytecode.slice(2); @@ -246,6 +260,8 @@ describe("Compiler bytecode and deployed bytecode matching", () => { const contractSymbols = { object: contract.runtimeBytecode.slice(2), linkReferences: contract.linkReferences, + opcodes: "", + sourceMap: "", immutableReferences: contract.immutableReferences, }; const deployedBytecode = contract.deployedBytecode.slice(2); @@ -272,6 +288,8 @@ describe("Compiler bytecode and deployed bytecode matching", () => { const contractSymbols = { object: contract.runtimeBytecode.slice(2), linkReferences: contract.linkReferences, + opcodes: "", + sourceMap: "", immutableReferences: contract.immutableReferences, }; const deployedBytecode = contract.deployedBytecode.slice(2); @@ -300,6 +318,8 @@ describe("Compiler bytecode and deployed bytecode matching", () => { const contractSymbols = { object: contract.runtimeBytecode.slice(2), linkReferences: contract.linkReferences, + opcodes: "", + sourceMap: "", immutableReferences: contract.immutableReferences, }; const deployedBytecode = contract.deployedBytecode.slice(2);