From e19dae9b282f8d9c3eab53895211b3dcdad19bbe Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Fri, 27 Mar 2020 15:44:02 -0400 Subject: [PATCH 1/6] `@0x/typescript-typings`: Add `version()` to `SolcInstance` --- packages/typescript-typings/CHANGELOG.json | 9 +++++++++ packages/typescript-typings/types/solc/index.d.ts | 1 + 2 files changed, 10 insertions(+) diff --git a/packages/typescript-typings/CHANGELOG.json b/packages/typescript-typings/CHANGELOG.json index bd9a3997f6..0320b1e080 100644 --- a/packages/typescript-typings/CHANGELOG.json +++ b/packages/typescript-typings/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "5.1.0", + "changes": [ + { + "note": "Add `version()` to `SolcInstance`", + "pr": 2532 + } + ] + }, { "timestamp": 1581204851, "version": "5.0.2", diff --git a/packages/typescript-typings/types/solc/index.d.ts b/packages/typescript-typings/types/solc/index.d.ts index 09370467b5..3b993d9e1c 100644 --- a/packages/typescript-typings/types/solc/index.d.ts +++ b/packages/typescript-typings/types/solc/index.d.ts @@ -105,6 +105,7 @@ declare module 'solc' { findImports: (importPath: string) => ImportContents, ): CompilationResult; compileStandardWrapper(input: string, findImports?: (importPath: string) => ImportContents): string; + version(): string; } export function loadRemoteVersion( versionName: string, From dc437aacf1cfb07b693f29d91aad45c583d48626 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Thu, 26 Mar 2020 18:19:59 -0400 Subject: [PATCH 2/6] @0x/sol-compiler`: Refactor + add solidity 0.6 support --- packages/sol-compiler/CHANGELOG.json | 9 + packages/sol-compiler/src/cli.ts | 17 +- packages/sol-compiler/src/compiler.ts | 370 +++++++++--------- packages/sol-compiler/src/solc_wrapper.ts | 35 ++ packages/sol-compiler/src/solc_wrapper_v04.ts | 9 + packages/sol-compiler/src/solc_wrapper_v05.ts | 108 +++++ packages/sol-compiler/src/solc_wrapper_v06.ts | 25 ++ packages/sol-compiler/src/utils/compiler.ts | 210 ++++++---- 8 files changed, 527 insertions(+), 256 deletions(-) create mode 100644 packages/sol-compiler/src/solc_wrapper.ts create mode 100644 packages/sol-compiler/src/solc_wrapper_v04.ts create mode 100644 packages/sol-compiler/src/solc_wrapper_v05.ts create mode 100644 packages/sol-compiler/src/solc_wrapper_v06.ts diff --git a/packages/sol-compiler/CHANGELOG.json b/packages/sol-compiler/CHANGELOG.json index 78ab952329..469e9b554b 100644 --- a/packages/sol-compiler/CHANGELOG.json +++ b/packages/sol-compiler/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "4.1.0", + "changes": [ + { + "note": "Refactor + add solidity 0.6 support", + "pr": 2532 + } + ] + }, { "timestamp": 1582623685, "version": "4.0.8", diff --git a/packages/sol-compiler/src/cli.ts b/packages/sol-compiler/src/cli.ts index e53a680af2..c76a083396 100644 --- a/packages/sol-compiler/src/cli.ts +++ b/packages/sol-compiler/src/cli.ts @@ -36,13 +36,16 @@ const SEPARATOR = ','; : argv.contracts === DEFAULT_CONTRACTS_LIST ? DEFAULT_CONTRACTS_LIST : argv.contracts.split(SEPARATOR); - const opts = { - contractsDir: argv.contractsDir, - artifactsDir: argv.artifactsDir, - contracts, - isOfflineMode: process.env.SOLC_OFFLINE ? true : undefined, - }; - const compiler = new Compiler(opts); + const opts = _.omitBy( + { + contractsDir: argv.contractsDir, + artifactsDir: argv.artifactsDir, + contracts, + isOfflineMode: process.env.SOLC_OFFLINE ? true : undefined, + }, + v => v === undefined, + ); + const compiler = new Compiler(await Compiler.getCompilerOptionsAsync(opts)); if (argv.watch) { await compiler.watchAsync(); } else { diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index cb7a5f2a27..335cafe55d 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -1,5 +1,6 @@ import { assert } from '@0x/assert'; import { + ContractSource, FallthroughResolver, FSResolver, NameResolver, @@ -10,7 +11,6 @@ import { URLResolver, } from '@0x/sol-resolver'; import { logUtils } from '@0x/utils'; -import { execSync } from 'child_process'; import * as chokidar from 'chokidar'; import { CompilerOptions, ContractArtifact, ContractVersionData, StandardOutput } from 'ethereum-types'; import * as fs from 'fs'; @@ -18,59 +18,45 @@ import * as _ from 'lodash'; import * as path from 'path'; import * as pluralize from 'pluralize'; import * as semver from 'semver'; -import solc = require('solc'); +import { StandardInput } from 'solc'; import { compilerOptionsSchema } from './schemas/compiler_options_schema'; import { - addHexPrefixToContractBytecode, - compileDockerAsync, - compileSolcJSAsync, + CompiledSources, createDirIfDoesNotExistAsync, getContractArtifactIfExistsAsync, getDependencyNameToPackagePath, - getSolcJSAsync, - getSolcJSFromPath, getSolcJSReleasesAsync, getSolcJSVersionFromPath, getSourcesWithDependencies, getSourceTreeHash, - makeContractPathsRelative, + normalizeSolcVersion, parseSolidityVersionRange, - printCompilationErrorsAndWarnings, } from './utils/compiler'; import { constants } from './utils/constants'; import { fsWrapper } from './utils/fs_wrapper'; import { utils } from './utils/utils'; -type TYPE_ALL_FILES_IDENTIFIER = '*'; -const ALL_CONTRACTS_IDENTIFIER = '*'; -const ALL_FILES_IDENTIFIER = '*'; -const DEFAULT_CONTRACTS_DIR = path.resolve('contracts'); -const DEFAULT_ARTIFACTS_DIR = path.resolve('artifacts'); -const DEFAULT_USE_DOCKERISED_SOLC = false; -const DEFAULT_IS_OFFLINE_MODE = false; -const DEFAULT_SHOULD_SAVE_STANDARD_INPUT = false; +import { ContractContentsByPath, ImportPrefixRemappings, SolcWrapper } from './solc_wrapper'; +import { SolcWrapperV04 } from './solc_wrapper_v04'; +import { SolcWrapperV05 } from './solc_wrapper_v05'; +import { SolcWrapperV06 } from './solc_wrapper_v06'; -// Solc compiler settings cannot be configured from the commandline. -// If you need this configured, please create a `compiler.json` config file -// with your desired configurations. -const DEFAULT_COMPILER_SETTINGS: solc.CompilerSettings = { - optimizer: { - enabled: false, - }, - outputSelection: { - [ALL_FILES_IDENTIFIER]: { - [ALL_CONTRACTS_IDENTIFIER]: ['abi', 'evm.bytecode.object'], - }, - }, +export type TYPE_ALL_FILES_IDENTIFIER = '*'; +export const ALL_CONTRACTS_IDENTIFIER = '*'; +export const ALL_FILES_IDENTIFIER = '*'; + +const DEFAULT_COMPILER_OPTS: CompilerOptions = { + contractsDir: path.resolve('contracts'), + artifactsDir: path.resolve('artifacts'), + contracts: ALL_CONTRACTS_IDENTIFIER as TYPE_ALL_FILES_IDENTIFIER, + useDockerisedSolc: false, + isOfflineMode: false, + shouldSaveStandardInput: false, }; -const CONFIG_FILE = 'compiler.json'; -interface VersionToInputs { - [solcVersion: string]: { - standardInput: solc.StandardInput; - contractsToCompile: string[]; - }; +interface ContractsByVersion { + [solcVersion: string]: ContractContentsByPath; } interface ContractPathToData { @@ -83,60 +69,75 @@ interface ContractData { contractName: string; } +// tslint:disable no-non-null-assertion /** * The Compiler facilitates compiling Solidity smart contracts and saves the results * to artifact files. */ export class Compiler { + private readonly _opts: CompilerOptions; private readonly _resolver: Resolver; private readonly _nameResolver: NameResolver; private readonly _contractsDir: string; - private readonly _compilerSettings: solc.CompilerSettings; private readonly _artifactsDir: string; private readonly _solcVersionIfExists: string | undefined; private readonly _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; - private readonly _useDockerisedSolc: boolean; private readonly _isOfflineMode: boolean; private readonly _shouldSaveStandardInput: boolean; + private readonly _solcWrappersByVersion: { [version: string]: SolcWrapper } = {}; + + public static async getCompilerOptionsAsync( + overrides: Partial = {}, + file: string = 'compiler.json', + ): Promise { + // TODO: Look for config file in parent directories if not found in current directory + const fileConfig: CompilerOptions = (await fs.promises.stat(file)).isFile + ? JSON.parse((await fs.promises.readFile(file, 'utf8')).toString()) + : {}; + assert.doesConformToSchema('compiler.json', fileConfig, compilerOptionsSchema); + return { + ...fileConfig, + ...overrides, + }; + } + + private static _createDefaultResolver( + contractsDir: string, + // tslint:disable-next-line: trailing-comma + ...appendedResolvers: Resolver[] + ): Resolver { + const resolver = new FallthroughResolver(); + resolver.appendResolver(new URLResolver()); + resolver.appendResolver(new NPMResolver(contractsDir)); + resolver.appendResolver(new RelativeFSResolver(contractsDir)); + resolver.appendResolver(new FSResolver()); + for (const appendedResolver of appendedResolvers) { + resolver.appendResolver(appendedResolver); + } + return resolver; + } + /** * Instantiates a new instance of the Compiler class. * @param opts Optional compiler options * @return An instance of the Compiler class. */ - constructor(opts?: CompilerOptions) { - const passedOpts = opts || {}; - assert.doesConformToSchema('opts', passedOpts, compilerOptionsSchema); - // TODO: Look for config file in parent directories if not found in current directory - const config: CompilerOptions = fs.existsSync(CONFIG_FILE) - ? JSON.parse(fs.readFileSync(CONFIG_FILE).toString()) - : {}; - assert.doesConformToSchema('compiler.json', config, compilerOptionsSchema); - this._contractsDir = path.resolve(passedOpts.contractsDir || config.contractsDir || DEFAULT_CONTRACTS_DIR); + constructor(opts: CompilerOptions = {}) { + this._opts = { ...DEFAULT_COMPILER_OPTS, ...opts }; + assert.doesConformToSchema('opts', this._opts, compilerOptionsSchema); + this._contractsDir = path.resolve(this._opts.contractsDir!); this._solcVersionIfExists = process.env.SOLCJS_PATH !== undefined ? getSolcJSVersionFromPath(process.env.SOLCJS_PATH) - : passedOpts.solcVersion || config.solcVersion; - this._compilerSettings = { - ...DEFAULT_COMPILER_SETTINGS, - ...config.compilerSettings, - ...passedOpts.compilerSettings, - }; - this._artifactsDir = passedOpts.artifactsDir || config.artifactsDir || DEFAULT_ARTIFACTS_DIR; - this._specifiedContracts = passedOpts.contracts || config.contracts || ALL_CONTRACTS_IDENTIFIER; - this._useDockerisedSolc = - passedOpts.useDockerisedSolc || config.useDockerisedSolc || DEFAULT_USE_DOCKERISED_SOLC; - this._isOfflineMode = passedOpts.isOfflineMode || config.isOfflineMode || DEFAULT_IS_OFFLINE_MODE; - this._shouldSaveStandardInput = - passedOpts.shouldSaveStandardInput || config.shouldSaveStandardInput || DEFAULT_SHOULD_SAVE_STANDARD_INPUT; + : this._opts.solcVersion; + this._artifactsDir = this._opts.artifactsDir!; + this._specifiedContracts = this._opts.contracts!; + this._isOfflineMode = this._opts.isOfflineMode!; + this._shouldSaveStandardInput = this._opts.shouldSaveStandardInput!; this._nameResolver = new NameResolver(this._contractsDir); - const resolver = new FallthroughResolver(); - resolver.appendResolver(new URLResolver()); - resolver.appendResolver(new NPMResolver(this._contractsDir)); - resolver.appendResolver(new RelativeFSResolver(this._contractsDir)); - resolver.appendResolver(new FSResolver()); - resolver.appendResolver(this._nameResolver); - this._resolver = resolver; + this._resolver = Compiler._createDefaultResolver(this._contractsDir, this._nameResolver); } + /** * Compiles selected Solidity files found in `contractsDir` and writes JSON artifacts to `artifactsDir`. */ @@ -145,6 +146,7 @@ export class Compiler { await createDirIfDoesNotExistAsync(constants.SOLC_BIN_DIR); await this._compileContractsAsync(this.getContractNamesToCompile(), true); } + /** * Compiles Solidity files specified during instantiation, and returns the * compiler output given by solc. Return value is an array of outputs: @@ -157,6 +159,10 @@ export class Compiler { const promisedOutputs = this._compileContractsAsync(this.getContractNamesToCompile(), false); return promisedOutputs; } + + /** + * Watch contracts in the current project directory and recompile on changes. + */ public async watchAsync(): Promise { console.clear(); // tslint:disable-line:no-console logUtils.logWithTime('Starting compilation in watch mode...'); @@ -183,7 +189,7 @@ export class Compiler { watcher.add(pathsToWatch); }; await onFileChangedAsync(); - watcher.on('change', (changedFilePath: string) => { + watcher.on('change', () => { console.clear(); // tslint:disable-line:no-console logUtils.logWithTime('File change detected. Starting incremental compilation...'); // NOTE: We can't await it here because that's a callback. @@ -191,6 +197,7 @@ export class Compiler { onFileChangedAsync(); // tslint:disable-line no-floating-promises }); } + /** * Gets a list of contracts to compile. */ @@ -206,6 +213,7 @@ export class Compiler { } return contractNamesToCompile; } + private _getPathsToWatch(): string[] { const contractNames = this.getContractNamesToCompile(); const spyResolver = new SpyResolver(this._resolver); @@ -220,6 +228,7 @@ export class Compiler { const pathsToWatch = _.uniq(spyResolver.resolvedContractSources.map(cs => cs.absolutePath)); return pathsToWatch; } + /** * Compiles contracts, and, if `shouldPersist` is true, saves artifacts to artifactsDir. * @param fileName Name of contract with '.sol' extension. @@ -227,13 +236,12 @@ export class Compiler { */ private async _compileContractsAsync(contractNames: string[], shouldPersist: boolean): Promise { // batch input contracts together based on the version of the compiler that they require. - const versionToInputs: VersionToInputs = {}; - + const contractsByVersion: ContractsByVersion = {}; // map contract paths to data about them for later verification and persistence const contractPathToData: ContractPathToData = {}; const solcJSReleases = await getSolcJSReleasesAsync(this._isOfflineMode); - const resolvedContractSources = []; + const resolvedContractSources: ContractSource[] = []; for (const contractName of contractNames) { const spyResolver = new SpyResolver(this._resolver); const contractSource = spyResolver.resolve(contractName); @@ -246,161 +254,155 @@ export class Compiler { if (!this._shouldCompile(contractData)) { continue; } - contractPathToData[contractSource.path] = contractData; - const solcVersion = - this._solcVersionIfExists === undefined - ? semver.maxSatisfying(_.keys(solcJSReleases), parseSolidityVersionRange(contractSource.source)) - : this._solcVersionIfExists; - if (solcVersion === null) { + contractPathToData[contractSource.absolutePath] = contractData; + let solcVersion: string | undefined; + if (this._solcVersionIfExists) { + solcVersion = this._solcVersionIfExists; + } else { + const solidityVersion = semver.maxSatisfying( + _.keys(solcJSReleases), + parseSolidityVersionRange(contractSource.source), + ); + if (solidityVersion) { + solcVersion = normalizeSolcVersion(solcJSReleases[solidityVersion]); + } + } + if (solcVersion === undefined) { throw new Error( `Couldn't find any solidity version satisfying the constraint ${parseSolidityVersionRange( contractSource.source, )}`, ); } - const isFirstContractWithThisVersion = versionToInputs[solcVersion] === undefined; - if (isFirstContractWithThisVersion) { - versionToInputs[solcVersion] = { - standardInput: { - language: 'Solidity', - sources: {}, - settings: this._compilerSettings, - }, - contractsToCompile: [], - }; - } // add input to the right version batch for (const resolvedContractSource of spyResolver.resolvedContractSources) { - versionToInputs[solcVersion].standardInput.sources[resolvedContractSource.absolutePath] = { - content: resolvedContractSource.source, - }; + contractsByVersion[solcVersion] = contractsByVersion[solcVersion] || {}; + contractsByVersion[solcVersion][resolvedContractSource.absolutePath] = resolvedContractSource.source; + resolvedContractSources.push(resolvedContractSource); } - resolvedContractSources.push(...spyResolver.resolvedContractSources); - versionToInputs[solcVersion].contractsToCompile.push(contractSource.path); } - const dependencyNameToPath = getDependencyNameToPackagePath(resolvedContractSources); + const importRemappings = getDependencyNameToPackagePath(resolvedContractSources); + const versions = Object.keys(contractsByVersion); - const compilerOutputs: StandardOutput[] = []; - for (const solcVersion of _.keys(versionToInputs)) { - const input = versionToInputs[solcVersion]; - logUtils.warn( - `Compiling ${input.contractsToCompile.length} contracts (${ - input.contractsToCompile - }) with Solidity v${solcVersion}...`, - ); - let compilerOutput; - let fullSolcVersion; - input.standardInput.settings.remappings = _.map( - dependencyNameToPath, - (dependencyPackagePath: string, dependencyName: string) => `${dependencyName}=${dependencyPackagePath}`, - ); - if (this._useDockerisedSolc) { - const dockerCommand = `docker run ethereum/solc:${solcVersion} --version`; - const versionCommandOutput = execSync(dockerCommand).toString(); - const versionCommandOutputParts = versionCommandOutput.split(' '); - fullSolcVersion = versionCommandOutputParts[versionCommandOutputParts.length - 1].trim(); - compilerOutput = await compileDockerAsync(solcVersion, input.standardInput); - } else { - fullSolcVersion = solcJSReleases[solcVersion]; - const solcInstance = - process.env.SOLCJS_PATH !== undefined - ? getSolcJSFromPath(process.env.SOLCJS_PATH) - : await getSolcJSAsync(solcVersion, this._isOfflineMode); - compilerOutput = await compileSolcJSAsync(solcInstance, input.standardInput); - } - if (compilerOutput.errors !== undefined) { - printCompilationErrorsAndWarnings(compilerOutput.errors); - } - compilerOutput.sources = makeContractPathsRelative( - compilerOutput.sources, - this._contractsDir, - dependencyNameToPath, - ); - compilerOutput.contracts = makeContractPathsRelative( - compilerOutput.contracts, - this._contractsDir, - dependencyNameToPath, - ); + const compilationResults = await Promise.all( + versions.map(async solcVersion => { + const contracts = contractsByVersion[solcVersion]; + logUtils.warn( + `Compiling ${Object.keys(contracts).length} contracts (${Object.keys(contracts).map(p => + path.basename(p), + )}) with Solidity ${solcVersion}...`, + ); + return this._getSolcWrapperForVersion(solcVersion).compileAsync(contracts, importRemappings); + }), + ); - for (const contractPath of input.contractsToCompile) { - const contractName = contractPathToData[contractPath].contractName; - if (compilerOutput.contracts[contractPath] !== undefined) { - const compiledContract = compilerOutput.contracts[contractPath][contractName]; - if (compiledContract === undefined) { - throw new Error( - `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, - ); - } - if (this._shouldSaveStandardInput) { - await fsWrapper.writeFileAsync( - `${this._artifactsDir}/${contractName}.input.json`, - utils.stringifyWithFormatting(input.standardInput), - ); - } - addHexPrefixToContractBytecode(compiledContract); - } - - if (shouldPersist) { - await this._persistCompiledContractAsync( - contractPath, - contractPathToData[contractPath].currentArtifactIfExists, - contractPathToData[contractPath].sourceTreeHashHex, - contractName, - fullSolcVersion, - compilerOutput, + if (shouldPersist) { + await Promise.all( + versions.map(async (solcVersion, i) => { + const compilationResult = compilationResults[i]; + const contracts = contractsByVersion[solcVersion]; + // tslint:disable-next-line: forin + await Promise.all( + Object.keys(contracts).map(async contractPath => { + const contractData = contractPathToData[contractPath]; + if (contractData === undefined) { + return; + } + const { contractName } = contractData; + const compiledContract = compilationResult.output.contracts[contractPath][contractName]; + if (compiledContract === undefined) { + throw new Error( + `Contract ${contractName} not found in ${contractPath}. Please make sure your contract has the same name as it's file name`, + ); + } + await this._persistCompiledContractAsync( + contractPath, + contractPathToData[contractPath].currentArtifactIfExists, + contractPathToData[contractPath].sourceTreeHashHex, + contractName, + solcVersion, + contracts, + compilationResult.input, + compilationResult.output, + importRemappings, + ); + }), ); - } - } - - compilerOutputs.push(compilerOutput); + }), + ); } - - return compilerOutputs; + return compilationResults.map(r => r.output); } + private _shouldCompile(contractData: ContractData): boolean { if (contractData.currentArtifactIfExists === undefined) { return true; } else { const currentArtifact = contractData.currentArtifactIfExists as ContractArtifact; + const solc = this._getSolcWrapperForVersion(currentArtifact.compiler.version); const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; - const didCompilerSettingsChange = !_.isEqual( - _.omit(currentArtifact.compiler.settings, 'remappings'), - _.omit(this._compilerSettings, 'remappings'), - ); + const didCompilerSettingsChange = solc.areCompilerSettingsDifferent(currentArtifact.compiler.settings); const didSourceChange = currentArtifact.sourceTreeHashHex !== contractData.sourceTreeHashHex; return !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; } } + + private _getSolcWrapperForVersion(solcVersion: string): SolcWrapper { + const normalizedVersion = normalizeSolcVersion(solcVersion); + return ( + this._solcWrappersByVersion[normalizedVersion] || + (this._solcWrappersByVersion[normalizedVersion] = this._createSolcInstance(normalizedVersion)) + ); + } + + private _createSolcInstance(solcVersion: string): SolcWrapper { + if (solcVersion.startsWith('0.4.')) { + return new SolcWrapperV04(solcVersion, this._opts); + } + if (solcVersion.startsWith('0.5.')) { + return new SolcWrapperV05(solcVersion, this._opts); + } + if (solcVersion.startsWith('0.6')) { + return new SolcWrapperV06(solcVersion, this._opts); + } + throw new Error(`Missing Solc wrapper implementation for version ${solcVersion}`); + } + private async _persistCompiledContractAsync( contractPath: string, currentArtifactIfExists: ContractArtifact | void, sourceTreeHashHex: string, contractName: string, fullSolcVersion: string, - compilerOutput: solc.StandardOutput, + sourcesByPath: ContractContentsByPath, + compilerInput: StandardInput, + compilerOutput: StandardOutput, + importRemappings: ImportPrefixRemappings, ): Promise { const compiledContract = compilerOutput.contracts[contractPath][contractName]; - // need to gather sourceCodes for this artifact, but compilerOutput.sources (the list of contract modules) // contains listings for every contract compiled during the compiler invocation that compiled the contract // to be persisted, which could include many that are irrelevant to the contract at hand. So, gather up only // the relevant sources: - const { sourceCodes, sources } = getSourcesWithDependencies( - this._resolver, - contractPath, - compilerOutput.sources, - ); + const allSources: CompiledSources = {}; + // tslint:disable-next-line: forin + for (const sourceContractPath in sourcesByPath) { + const content = sourcesByPath[sourceContractPath]; + const { id } = compilerOutput.sources[sourceContractPath]; + allSources[sourceContractPath] = { id, content }; + } + const usedSources = getSourcesWithDependencies(contractPath, allSources, importRemappings); const contractVersion: ContractVersionData = { compilerOutput: compiledContract, - sources, - sourceCodes, sourceTreeHashHex, + sources: _.mapValues(usedSources, ({ id }) => ({ id })), + sourceCodes: _.mapValues(usedSources, ({ content }) => content), compiler: { name: 'solc', version: fullSolcVersion, - settings: this._compilerSettings, + settings: compilerInput.settings, }, }; @@ -424,5 +426,13 @@ export class Compiler { const currentArtifactPath = `${this._artifactsDir}/${contractName}.json`; await fsWrapper.writeFileAsync(currentArtifactPath, artifactString); logUtils.warn(`${contractName} artifact saved!`); + + if (this._shouldSaveStandardInput) { + await fsWrapper.writeFileAsync( + `${this._artifactsDir}/${contractName}.input.json`, + utils.stringifyWithFormatting(compilerInput), + ); + logUtils.warn(`${contractName} input artifact saved!`); + } } } diff --git a/packages/sol-compiler/src/solc_wrapper.ts b/packages/sol-compiler/src/solc_wrapper.ts new file mode 100644 index 0000000000..4ad2a337df --- /dev/null +++ b/packages/sol-compiler/src/solc_wrapper.ts @@ -0,0 +1,35 @@ +import { StandardOutput } from 'ethereum-types'; +import { StandardInput } from 'solc'; + +export interface ContractContentsByPath { + [path: string]: string; +} + +export interface ImportPrefixRemappings { + [prefix: string]: string; +} + +export interface CompilationResult { + input: StandardInput; + output: StandardOutput; +} + +export abstract class SolcWrapper { + /** + * Get the solc version. + */ + public abstract get version(): string; + + /** + * Check if the configured compiler settings is different from another. + */ + public abstract areCompilerSettingsDifferent(settings: any): boolean; + + /** + * Compile contracts, returning standard input and output. + */ + public abstract compileAsync( + contractsByPath: ContractContentsByPath, + dependencies: ImportPrefixRemappings, + ): Promise; +} diff --git a/packages/sol-compiler/src/solc_wrapper_v04.ts b/packages/sol-compiler/src/solc_wrapper_v04.ts new file mode 100644 index 0000000000..5d0b675850 --- /dev/null +++ b/packages/sol-compiler/src/solc_wrapper_v04.ts @@ -0,0 +1,9 @@ +import { CompilerOptions } from 'ethereum-types'; + +import { SolcWrapperV05 } from './solc_wrapper_v05'; + +export class SolcWrapperV04 extends SolcWrapperV05 { + constructor(solcVersion: string, opts: CompilerOptions) { + super(solcVersion, opts); + } +} diff --git a/packages/sol-compiler/src/solc_wrapper_v05.ts b/packages/sol-compiler/src/solc_wrapper_v05.ts new file mode 100644 index 0000000000..24bf05a610 --- /dev/null +++ b/packages/sol-compiler/src/solc_wrapper_v05.ts @@ -0,0 +1,108 @@ +import { CompilerOptions, StandardOutput } from 'ethereum-types'; +import * as _ from 'lodash'; +import solc = require('solc'); + +import { + addHexPrefixToContractBytecode, + compileDockerAsync, + compileSolcJSAsync, + getSolcJSAsync, + getSolidityVersionFromSolcVersion, + printCompilationErrorsAndWarnings, +} from './utils/compiler'; + +import { CompilationResult, ContractContentsByPath, ImportPrefixRemappings, SolcWrapper } from './solc_wrapper'; + +// Solc compiler settings cannot be configured from the commandline. +// If you need this configured, please create a `compiler.json` config file +// with your desired configurations. +export const DEFAULT_COMPILER_SETTINGS: solc.CompilerSettings = { + optimizer: { + enabled: false, + }, + outputSelection: { + '*': { + '*': ['abi', 'evm.bytecode.object'], + }, + }, +}; + +// tslint:disable no-non-null-assertion + +export class SolcWrapperV05 extends SolcWrapper { + protected readonly _compilerSettings: solc.CompilerSettings; + + public static normalizeOutput( + output: StandardOutput, + importRemappings: ImportPrefixRemappings, + opts: CompilerOptions, + ): StandardOutput { + const _output = _.cloneDeep(output); + // _output.sources = makeContractPathsRelative(_output.sources, opts.contractsDir!, importRemappings); + // _output.contracts = makeContractPathsRelative(_output.contracts, opts.contractsDir!, importRemappings); + // tslint:disable-next-line forin + for (const contractPath in _output.contracts) { + // tslint:disable-next-line forin + for (const contract of Object.values(_output.contracts[contractPath])) { + addHexPrefixToContractBytecode(contract); + } + } + return _output; + } + + constructor(protected readonly _solcVersion: string, protected readonly _opts: CompilerOptions) { + super(); + this._compilerSettings = { + ...DEFAULT_COMPILER_SETTINGS, + ..._opts.compilerSettings, + }; + } + + public get version(): string { + return this._solcVersion; + } + + public get solidityVersion(): string { + return getSolidityVersionFromSolcVersion(this._solcVersion); + } + + public areCompilerSettingsDifferent(settings: any): boolean { + return !_.isEqual(_.omit(settings, 'remappings'), _.omit(this._compilerSettings, 'remappings')); + } + + public async compileAsync( + contractsByPath: ContractContentsByPath, + importRemappings: ImportPrefixRemappings, + ): Promise { + const input: solc.StandardInput = { + language: 'Solidity', + sources: {}, + settings: { + remappings: [], + ...this._compilerSettings, + }, + }; + for (const [contractPath, contractContent] of Object.entries(contractsByPath)) { + input.sources[contractPath] = { content: contractContent }; + } + for (const [prefix, _path] of Object.entries(importRemappings)) { + input.settings.remappings!.push(`${prefix}=${_path}`); + } + const output = await this._compileInputAsync(input); + if (output.errors !== undefined) { + printCompilationErrorsAndWarnings(output.errors); + } + return { + input, + output: SolcWrapperV05.normalizeOutput(output, importRemappings, this._opts), + }; + } + + protected async _compileInputAsync(input: solc.StandardInput): Promise { + if (this._opts.useDockerisedSolc) { + return compileDockerAsync(this.solidityVersion, input); + } + const solcInstance = await getSolcJSAsync(this.solidityVersion, !!this._opts.isOfflineMode); + return compileSolcJSAsync(solcInstance, input); + } +} diff --git a/packages/sol-compiler/src/solc_wrapper_v06.ts b/packages/sol-compiler/src/solc_wrapper_v06.ts new file mode 100644 index 0000000000..f69b77e5b6 --- /dev/null +++ b/packages/sol-compiler/src/solc_wrapper_v06.ts @@ -0,0 +1,25 @@ +import { CompilerOptions, StandardOutput } from 'ethereum-types'; +import solc = require('solc'); + +import { compileSolcJSAsync, getSolcJSAsync } from './utils/compiler'; + +import { SolcWrapperV05 } from './solc_wrapper_v05'; + +// 0.6.x has a `compile()` function in lieu of `compileStandardWrapper`. +type SolcV06 = solc.SolcInstance & { compile(input: string): string }; + +export class SolcWrapperV06 extends SolcWrapperV05 { + constructor(solcVersion: string, opts: CompilerOptions) { + super(solcVersion, opts); + } + + protected async _compileInputAsync(input: solc.StandardInput): Promise { + if (this._opts.useDockerisedSolc) { + return super._compileInputAsync(input); + } + // Shim the old `compileStandardWrapper` function. + const solcInstance = (await getSolcJSAsync(this.solidityVersion, !!this._opts.isOfflineMode)) as SolcV06; + solcInstance.compileStandardWrapper = solcInstance.compile; + return compileSolcJSAsync(solcInstance, input); + } +} diff --git a/packages/sol-compiler/src/utils/compiler.ts b/packages/sol-compiler/src/utils/compiler.ts index 19d2fffb8e..622a0bd01d 100644 --- a/packages/sol-compiler/src/utils/compiler.ts +++ b/packages/sol-compiler/src/utils/compiler.ts @@ -1,13 +1,14 @@ import { ContractSource, Resolver } from '@0x/sol-resolver'; import { fetchAsync, logUtils } from '@0x/utils'; import chalk from 'chalk'; -import { execSync } from 'child_process'; +import { exec, spawn } from 'child_process'; import { ContractArtifact } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; import * as path from 'path'; import * as requireFromString from 'require-from-string'; import * as solc from 'solc'; +import { promisify } from 'util'; import { constants } from './constants'; import { fsWrapper } from './fs_wrapper'; @@ -152,18 +153,42 @@ export async function compileSolcJSAsync( /** * Compiles the contracts and prints errors/warnings - * @param solcVersion Version of a solc compiler + * @param solidityVersion Solidity version * @param standardInput Solidity standard JSON input */ export async function compileDockerAsync( - solcVersion: string, + solidityVersion: string, standardInput: solc.StandardInput, ): Promise { const standardInputStr = JSON.stringify(standardInput, null, 2); - const dockerCommand = `docker run -i -a stdin -a stdout -a stderr ethereum/solc:${solcVersion} solc --standard-json`; - const standardOutputStr = execSync(dockerCommand, { input: standardInputStr }).toString(); - const compiled: solc.StandardOutput = JSON.parse(standardOutputStr); - return compiled; + const dockerArgs = [ + 'run', + '-i', + '-a', + 'stdin', + '-a', + 'stdout', + '-a', + 'stderr', + `ethereum/solc:${solidityVersion}`, + 'solc', + '--standard-json', + ]; + return new Promise((accept, reject) => { + const p = spawn('docker', dockerArgs, { shell: true, stdio: ['pipe', 'inherit', 'inherit'] }); + p.stdin.write(standardInputStr); + p.stdin.end(); + let fullOutput = ''; + p.stdout.on('data', (chunk: string) => { + fullOutput += chunk; + }); + p.on('close', code => { + if (code !== 0) { + reject('Compilation failed'); + } + accept(JSON.parse(fullOutput)); + }); + }); } /** @@ -250,43 +275,57 @@ export function getSourceTreeHash(resolver: Resolver, importPath: string): Buffe } /** - * For the given @param contractPath, populates JSON objects to be used in the ContractVersionData interface's - * properties `sources` (source code file names mapped to ID numbers) and `sourceCodes` (source code content of - * contracts) for that contract. The source code pointed to by contractPath is read and parsed directly (via - * `resolver.resolve().source`), as are its imports, recursively. The ID numbers for @return `sources` are - * taken from the corresponding ID's in @param fullSources, and the content for @return sourceCodes is read from - * disk (via the aforementioned `resolver.source`). + * Mapping of absolute contract path to compilation ID and source code. + */ +export interface CompiledSources { + [sourcePath: string]: { id: number; content: string }; +} + +/** + * Contract sources by import path. + */ +export interface CompiledImports { + [importPath: string]: { id: number; content: string }; +} + +/** + * Recursively parses imports from sources starting from `contractPath`. + * @return Sources required by imports. */ export function getSourcesWithDependencies( - resolver: Resolver, contractPath: string, - fullSources: { [sourceName: string]: { id: number } }, -): { sourceCodes: { [sourceName: string]: string }; sources: { [sourceName: string]: { id: number } } } { - const sources = { [contractPath]: fullSources[contractPath] }; - const sourceCodes = { [contractPath]: resolver.resolve(contractPath).source }; + sourcesByAbsolutePath: CompiledSources, + importRemappings: { [prefix: string]: string }, +): CompiledImports { + const compiledImports = { [`./${path.basename(contractPath)}`]: sourcesByAbsolutePath[contractPath] }; recursivelyGatherDependencySources( - resolver, contractPath, - sourceCodes[contractPath], - fullSources, - sources, - sourceCodes, + path.dirname(contractPath), + sourcesByAbsolutePath, + importRemappings, + compiledImports, ); - return { sourceCodes, sources }; + return compiledImports; } function recursivelyGatherDependencySources( - resolver: Resolver, contractPath: string, - contractSource: string, - fullSources: { [sourceName: string]: { id: number } }, - sourcesToAppendTo: { [sourceName: string]: { id: number } }, - sourceCodesToAppendTo: { [sourceName: string]: string }, + rootDir: string, + sourcesByAbsolutePath: CompiledSources, + importRemappings: { [prefix: string]: string }, + compiledImports: CompiledImports, + visitedAbsolutePaths: { [absPath: string]: boolean } = {}, ): void { + if (visitedAbsolutePaths[contractPath]) { + return; + } + const contractSource = sourcesByAbsolutePath[contractPath].content; const importStatementMatches = contractSource.match(/\nimport[^;]*;/g); if (importStatementMatches === null) { return; } + const lastPathSeparatorPos = contractPath.lastIndexOf('/'); + const contractFolder = lastPathSeparatorPos === -1 ? '' : contractPath.slice(0, lastPathSeparatorPos + 1); for (const importStatementMatch of importStatementMatches) { const importPathMatches = importStatementMatch.match(/\"([^\"]*)\"/); if (importPathMatches === null || importPathMatches.length === 0) { @@ -294,59 +333,48 @@ function recursivelyGatherDependencySources( } let importPath = importPathMatches[1]; - // HACK(albrow): We have, e.g.: - // - // importPath = "../../utils/LibBytes/LibBytes.sol" - // contractPath = "2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol" - // - // Resolver doesn't understand "../" so we want to pass - // "2.0.0/utils/LibBytes/LibBytes.sol" to resolver. - // - // This hack involves using path.resolve. But path.resolve returns - // absolute directories by default. We trick it into thinking that - // contractPath is a root directory by prepending a '/' and then - // removing the '/' the end. - // - // path.resolve("/a/b/c", ""../../d/e") === "/a/d/e" - // - const lastPathSeparatorPos = contractPath.lastIndexOf('/'); - const contractFolder = lastPathSeparatorPos === -1 ? '' : contractPath.slice(0, lastPathSeparatorPos + 1); + let absPath = importPath; if (importPath.startsWith('.')) { - /** - * Some imports path are relative ("../Token.sol", "./Wallet.sol") - * while others are absolute ("Token.sol", "@0x/contracts/Wallet.sol") - * And we need to append the base path for relative imports. - */ - importPath = path.resolve(`/${contractFolder}`, importPath).replace('/', ''); + absPath = path.join(contractFolder, importPath); + // Express relative imports paths as paths from the root directory. + importPath = path.relative(rootDir, absPath); + if (!importPath.startsWith('.')) { + importPath = `./${importPath}`; + } + } else { + for (const [prefix, replacement] of Object.entries(importRemappings)) { + if (importPath.startsWith(prefix)) { + absPath = `${replacement}${importPath.substr(prefix.length)}`; + break; + } + } } - if (sourcesToAppendTo[importPath] === undefined) { - sourcesToAppendTo[importPath] = { id: fullSources[importPath].id }; - sourceCodesToAppendTo[importPath] = resolver.resolve(importPath).source; + compiledImports[importPath] = sourcesByAbsolutePath[absPath]; + visitedAbsolutePaths[absPath] = true; - recursivelyGatherDependencySources( - resolver, - importPath, - resolver.resolve(importPath).source, - fullSources, - sourcesToAppendTo, - sourceCodesToAppendTo, - ); - } + recursivelyGatherDependencySources( + absPath, + rootDir, + sourcesByAbsolutePath, + importRemappings, + compiledImports, + visitedAbsolutePaths, + ); } } /** * Gets the solidity compiler instance. If the compiler is already cached - gets it from FS, * otherwise - fetches it and caches it. - * @param solcVersion The compiler version. e.g. 0.5.0 + * @param solidityVersion The solidity version. e.g. 0.5.0 * @param isOfflineMode Offline mode flag */ -export async function getSolcJSAsync(solcVersion: string, isOfflineMode: boolean): Promise { +export async function getSolcJSAsync(solidityVersion: string, isOfflineMode: boolean): Promise { const solcJSReleases = await getSolcJSReleasesAsync(isOfflineMode); - const fullSolcVersion = solcJSReleases[solcVersion]; + const fullSolcVersion = solcJSReleases[solidityVersion]; if (fullSolcVersion === undefined) { - throw new Error(`${solcVersion} is not a known compiler version`); + throw new Error(`${solidityVersion} is not a known compiler version`); } const compilerBinFilename = path.join(constants.SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; @@ -383,7 +411,7 @@ export function getSolcJSFromPath(modulePath: string): solc.SolcInstance { * @param path The path to the solc module. */ export function getSolcJSVersionFromPath(modulePath: string): string { - return require(modulePath).version(); + return normalizeSolcVersion(require(modulePath).version()); } /** @@ -437,3 +465,47 @@ export function getDependencyNameToPackagePath( }); return dependencyNameToPath; } + +/** + * Extract the solidity version (e.g., '0.5.9') from a solc version (e.g., `0.5.9+commit.34d3134f`). + */ +export function getSolidityVersionFromSolcVersion(solcVersion: string): string { + const m = /(\d+\.\d+\.\d+)\+commit\.[a-f0-9]{8}/.exec(solcVersion); + if (!m) { + throw new Error(`Unable to parse solc version string "${solcVersion}"`); + } + return m[1]; +} + +/** + * Strips any extra characters before and after the version + commit hash of a solc version string. + */ +export function normalizeSolcVersion(fullSolcVersion: string): string { + const m = /\d+\.\d+\.\d+\+commit\.[a-f0-9]{8}/.exec(fullSolcVersion); + if (!m) { + throw new Error(`Unable to parse solc version string "${fullSolcVersion}"`); + } + return m[0]; +} + +/** + * Gets the full version string of a dockerized solc. + */ +export async function getDockerFullSolcVersionAsync(solidityVersion: string): Promise { + const dockerCommand = `docker run ethereum/solc:${solidityVersion} --version`; + const versionCommandOutput = (await promisify(exec)(dockerCommand)).stdout.toString(); + const versionCommandOutputParts = versionCommandOutput.split(' '); + return normalizeSolcVersion(versionCommandOutputParts[versionCommandOutputParts.length - 1].trim()); +} + +/** + * Gets the full version string of a JS module solc. + */ +export async function getJSFullSolcVersionAsync( + solidityVersion: string, + isOfflineMode: boolean = false, +): Promise { + return normalizeSolcVersion((await getSolcJSAsync(solidityVersion, isOfflineMode)).version()); +} + +// tslint:disable-next-line: max-file-line-count From b36373ab8117b2cfea22c6787ed10cbb0b706b78 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Mon, 30 Mar 2020 13:51:24 -0400 Subject: [PATCH 3/6] `@0x/sol-compiler`: Insert compiler version in input artifacts. --- packages/sol-compiler/src/compiler.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 335cafe55d..940b260879 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -374,7 +374,7 @@ export class Compiler { currentArtifactIfExists: ContractArtifact | void, sourceTreeHashHex: string, contractName: string, - fullSolcVersion: string, + solcVersion: string, sourcesByPath: ContractContentsByPath, compilerInput: StandardInput, compilerOutput: StandardOutput, @@ -401,7 +401,7 @@ export class Compiler { sourceCodes: _.mapValues(usedSources, ({ content }) => content), compiler: { name: 'solc', - version: fullSolcVersion, + version: solcVersion, settings: compilerInput.settings, }, }; @@ -430,7 +430,14 @@ export class Compiler { if (this._shouldSaveStandardInput) { await fsWrapper.writeFileAsync( `${this._artifactsDir}/${contractName}.input.json`, - utils.stringifyWithFormatting(compilerInput), + utils.stringifyWithFormatting({ + ...compilerInput, + // Insert solcVersion into input. + settings: { + ...compilerInput.settings, + version: solcVersion, + }, + }), ); logUtils.warn(`${contractName} input artifact saved!`); } From 6e29c8bea98197588e55e601d13c221d88e570db Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Mon, 30 Mar 2020 15:54:27 -0400 Subject: [PATCH 4/6] `@0x/sol-compiler`: Make source paths in output artifacts nicer if they're within modules. `@0x/sol-compiler`: Makea Add v0.6 solidity test. --- packages/sol-compiler/src/utils/compiler.ts | 23 ++++++++---- packages/sol-compiler/test/compiler_test.ts | 20 +++++++++- .../test/fixtures/contracts/V6Contract.sol | 37 +++++++++++++++++++ 3 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 packages/sol-compiler/test/fixtures/contracts/V6Contract.sol diff --git a/packages/sol-compiler/src/utils/compiler.ts b/packages/sol-compiler/src/utils/compiler.ts index 622a0bd01d..7c5805283f 100644 --- a/packages/sol-compiler/src/utils/compiler.ts +++ b/packages/sol-compiler/src/utils/compiler.ts @@ -315,9 +315,12 @@ function recursivelyGatherDependencySources( importRemappings: { [prefix: string]: string }, compiledImports: CompiledImports, visitedAbsolutePaths: { [absPath: string]: boolean } = {}, + importRootDir?: string, ): void { if (visitedAbsolutePaths[contractPath]) { return; + } else { + visitedAbsolutePaths[contractPath] = true; } const contractSource = sourcesByAbsolutePath[contractPath].content; const importStatementMatches = contractSource.match(/\nimport[^;]*;/g); @@ -334,25 +337,30 @@ function recursivelyGatherDependencySources( let importPath = importPathMatches[1]; let absPath = importPath; + let _importRootDir = importRootDir; if (importPath.startsWith('.')) { absPath = path.join(contractFolder, importPath); - // Express relative imports paths as paths from the root directory. - importPath = path.relative(rootDir, absPath); - if (!importPath.startsWith('.')) { - importPath = `./${importPath}`; + if (_importRootDir) { + // If there's an `_importRootDir`, we're in a package, so express + // the import path as within the package. + importPath = path.join(_importRootDir, importPath); + } else { + // Express relative imports paths as paths from the root directory. + importPath = path.relative(rootDir, absPath); + if (!importPath.startsWith('.')) { + importPath = `./${importPath}`; + } } } else { for (const [prefix, replacement] of Object.entries(importRemappings)) { if (importPath.startsWith(prefix)) { absPath = `${replacement}${importPath.substr(prefix.length)}`; + _importRootDir = path.dirname(importPath); break; } } } - compiledImports[importPath] = sourcesByAbsolutePath[absPath]; - visitedAbsolutePaths[absPath] = true; - recursivelyGatherDependencySources( absPath, rootDir, @@ -360,6 +368,7 @@ function recursivelyGatherDependencySources( importRemappings, compiledImports, visitedAbsolutePaths, + _importRootDir, ); } } diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index cae6bce053..7dcecd2cbf 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -26,7 +26,7 @@ describe('#Compiler', function(): void { it('should create a Compiler with empty opts', async () => { const _compiler = new Compiler(); // tslint:disable-line no-unused-variable }); - it('should create an Exchange artifact with the correct unlinked binary', async () => { + it.only('should create an Exchange artifact with the correct unlinked binary', async () => { compilerOpts.contracts = ['Exchange']; const exchangeArtifactPath = `${artifactsDir}/Exchange.json`; @@ -114,4 +114,22 @@ describe('#Compiler', function(): void { expect(artifact).to.equal('EmptyContract.json'); } }); + it('should compile a V0.6 contract', async () => { + compilerOpts.contracts = ['V6Contract']; + + const artifactPath = `${artifactsDir}/V6Contract.json`; + if (fsWrapper.doesPathExistSync(artifactPath)) { + await fsWrapper.removeFileAsync(artifactPath); + } + + await new Compiler(compilerOpts).compileAsync(); + + const opts = { + encoding: 'utf8', + }; + const exchangeArtifactString = await fsWrapper.readFileAsync(artifactPath, opts); + const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString); + const bin = exchangeArtifact.compilerOutput.evm.bytecode.object; + expect(bin.slice(2)).to.length.to.be.gt(0); + }); }); diff --git a/packages/sol-compiler/test/fixtures/contracts/V6Contract.sol b/packages/sol-compiler/test/fixtures/contracts/V6Contract.sol new file mode 100644 index 0000000000..de9f038a59 --- /dev/null +++ b/packages/sol-compiler/test/fixtures/contracts/V6Contract.sol @@ -0,0 +1,37 @@ +/* + + Copyright 2020 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.6.4; + + +contract V6Contract { + + uint256 private _privateNumber; + + constructor(uint256 privateNumber) public { + _privateNumber = privateNumber; + } + + fallback() external { + revert('nope'); + } + + receive() payable external { + // no-op + } +} From 74647f0e8872ae7756adf3f35a90135f5e8cab6e Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Mon, 30 Mar 2020 16:11:19 -0400 Subject: [PATCH 5/6] `@0x/sol-compiler`: remove `fs.promises` usage --- packages/sol-compiler/src/compiler.ts | 5 +++-- packages/sol-compiler/test/compiler_test.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 940b260879..3d6f348a48 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -19,6 +19,7 @@ import * as path from 'path'; import * as pluralize from 'pluralize'; import * as semver from 'semver'; import { StandardInput } from 'solc'; +import { promisify } from 'util'; import { compilerOptionsSchema } from './schemas/compiler_options_schema'; import { @@ -91,8 +92,8 @@ export class Compiler { file: string = 'compiler.json', ): Promise { // TODO: Look for config file in parent directories if not found in current directory - const fileConfig: CompilerOptions = (await fs.promises.stat(file)).isFile - ? JSON.parse((await fs.promises.readFile(file, 'utf8')).toString()) + const fileConfig: CompilerOptions = (await promisify(fs.stat)(file)).isFile + ? JSON.parse((await promisify(fs.readFile)(file, 'utf8')).toString()) : {}; assert.doesConformToSchema('compiler.json', fileConfig, compilerOptionsSchema); return { diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index 7dcecd2cbf..3c31d36bdd 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -26,7 +26,7 @@ describe('#Compiler', function(): void { it('should create a Compiler with empty opts', async () => { const _compiler = new Compiler(); // tslint:disable-line no-unused-variable }); - it.only('should create an Exchange artifact with the correct unlinked binary', async () => { + it('should create an Exchange artifact with the correct unlinked binary', async () => { compilerOpts.contracts = ['Exchange']; const exchangeArtifactPath = `${artifactsDir}/Exchange.json`; From b9a68c0b8edc396edf5a668e0873e3589439fd23 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Wed, 1 Apr 2020 13:42:45 -0400 Subject: [PATCH 6/6] `@0x/sol-compiler`: Address review feedback. --- packages/sol-compiler/src/compiler.ts | 1 - packages/sol-compiler/src/solc_wrapper_v04.ts | 8 +----- packages/sol-compiler/src/solc_wrapper_v05.ts | 10 ++----- packages/sol-compiler/src/utils/compiler.ts | 17 +++++------ packages/sol-compiler/test/compiler_test.ts | 28 +++++++++++-------- .../test/fixtures/contracts/V6Contract.sol | 2 +- .../test/fixtures/exchange_bin.ts | 2 +- .../test/fixtures/v6_contract_bin.ts | 2 ++ 8 files changed, 31 insertions(+), 39 deletions(-) create mode 100644 packages/sol-compiler/test/fixtures/v6_contract_bin.ts diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 3d6f348a48..20dc38b182 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -91,7 +91,6 @@ export class Compiler { overrides: Partial = {}, file: string = 'compiler.json', ): Promise { - // TODO: Look for config file in parent directories if not found in current directory const fileConfig: CompilerOptions = (await promisify(fs.stat)(file)).isFile ? JSON.parse((await promisify(fs.readFile)(file, 'utf8')).toString()) : {}; diff --git a/packages/sol-compiler/src/solc_wrapper_v04.ts b/packages/sol-compiler/src/solc_wrapper_v04.ts index 5d0b675850..f0ad4b0538 100644 --- a/packages/sol-compiler/src/solc_wrapper_v04.ts +++ b/packages/sol-compiler/src/solc_wrapper_v04.ts @@ -1,9 +1,3 @@ -import { CompilerOptions } from 'ethereum-types'; - import { SolcWrapperV05 } from './solc_wrapper_v05'; -export class SolcWrapperV04 extends SolcWrapperV05 { - constructor(solcVersion: string, opts: CompilerOptions) { - super(solcVersion, opts); - } -} +export const SolcWrapperV04 = SolcWrapperV05; diff --git a/packages/sol-compiler/src/solc_wrapper_v05.ts b/packages/sol-compiler/src/solc_wrapper_v05.ts index 24bf05a610..17184dbec0 100644 --- a/packages/sol-compiler/src/solc_wrapper_v05.ts +++ b/packages/sol-compiler/src/solc_wrapper_v05.ts @@ -32,14 +32,8 @@ export const DEFAULT_COMPILER_SETTINGS: solc.CompilerSettings = { export class SolcWrapperV05 extends SolcWrapper { protected readonly _compilerSettings: solc.CompilerSettings; - public static normalizeOutput( - output: StandardOutput, - importRemappings: ImportPrefixRemappings, - opts: CompilerOptions, - ): StandardOutput { + public static normalizeOutput(output: StandardOutput): StandardOutput { const _output = _.cloneDeep(output); - // _output.sources = makeContractPathsRelative(_output.sources, opts.contractsDir!, importRemappings); - // _output.contracts = makeContractPathsRelative(_output.contracts, opts.contractsDir!, importRemappings); // tslint:disable-next-line forin for (const contractPath in _output.contracts) { // tslint:disable-next-line forin @@ -94,7 +88,7 @@ export class SolcWrapperV05 extends SolcWrapper { } return { input, - output: SolcWrapperV05.normalizeOutput(output, importRemappings, this._opts), + output: SolcWrapperV05.normalizeOutput(output), }; } diff --git a/packages/sol-compiler/src/utils/compiler.ts b/packages/sol-compiler/src/utils/compiler.ts index 7c5805283f..7040427c8f 100644 --- a/packages/sol-compiler/src/utils/compiler.ts +++ b/packages/sol-compiler/src/utils/compiler.ts @@ -161,18 +161,15 @@ export async function compileDockerAsync( standardInput: solc.StandardInput, ): Promise { const standardInputStr = JSON.stringify(standardInput, null, 2); + // prettier-ignore const dockerArgs = [ 'run', '-i', - '-a', - 'stdin', - '-a', - 'stdout', - '-a', - 'stderr', + '-a', 'stdin', + '-a', 'stdout', + '-a', 'stderr', `ethereum/solc:${solidityVersion}`, - 'solc', - '--standard-json', + 'solc', '--standard-json', ]; return new Promise((accept, reject) => { const p = spawn('docker', dockerArgs, { shell: true, stdio: ['pipe', 'inherit', 'inherit'] }); @@ -479,7 +476,7 @@ export function getDependencyNameToPackagePath( * Extract the solidity version (e.g., '0.5.9') from a solc version (e.g., `0.5.9+commit.34d3134f`). */ export function getSolidityVersionFromSolcVersion(solcVersion: string): string { - const m = /(\d+\.\d+\.\d+)\+commit\.[a-f0-9]{8}/.exec(solcVersion); + const m = /(\d+\.\d+\.\d+)\+commit\.[a-fA-F0-9]{8}/.exec(solcVersion); if (!m) { throw new Error(`Unable to parse solc version string "${solcVersion}"`); } @@ -490,7 +487,7 @@ export function getSolidityVersionFromSolcVersion(solcVersion: string): string { * Strips any extra characters before and after the version + commit hash of a solc version string. */ export function normalizeSolcVersion(fullSolcVersion: string): string { - const m = /\d+\.\d+\.\d+\+commit\.[a-f0-9]{8}/.exec(fullSolcVersion); + const m = /\d+\.\d+\.\d+\+commit\.[a-fA-F0-9]{8}/.exec(fullSolcVersion); if (!m) { throw new Error(`Unable to parse solc version string "${fullSolcVersion}"`); } diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index 3c31d36bdd..83fd3ad4c9 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -1,19 +1,22 @@ -import { join } from 'path'; - +import { hexUtils } from '@0x/utils'; import * as chai from 'chai'; import { CompilerOptions, ContractArtifact } from 'ethereum-types'; import 'mocha'; +import { join } from 'path'; import { Compiler } from '../src/compiler'; import { fsWrapper } from '../src/utils/fs_wrapper'; import { exchange_binary } from './fixtures/exchange_bin'; +import { v6_contract_binary } from './fixtures/v6_contract_bin'; import { chaiSetup } from './util/chai_setup'; import { constants } from './util/constants'; chaiSetup.configure(); const expect = chai.expect; +const METADATA_SIZE = 43; + describe('#Compiler', function(): void { this.timeout(constants.timeoutMs); // tslint:disable-line:no-invalid-this const artifactsDir = `${__dirname}/fixtures/artifacts`; @@ -41,14 +44,12 @@ describe('#Compiler', function(): void { }; const exchangeArtifactString = await fsWrapper.readFileAsync(exchangeArtifactPath, opts); const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString); - // The last 43 bytes of the binaries are metadata which may not be equivalent - const metadataByteLength = 43; - const metadataHexLength = metadataByteLength * 2; - const unlinkedBinaryWithoutMetadata = exchangeArtifact.compilerOutput.evm.bytecode.object.slice( - 2, - -metadataHexLength, + const unlinkedBinaryWithoutMetadata = hexUtils.slice( + exchangeArtifact.compilerOutput.evm.bytecode.object, + 0, + -METADATA_SIZE, ); - const exchangeBinaryWithoutMetadata = exchange_binary.slice(0, -metadataHexLength); + const exchangeBinaryWithoutMetadata = hexUtils.slice(exchange_binary, 0, -METADATA_SIZE); expect(unlinkedBinaryWithoutMetadata).to.equal(exchangeBinaryWithoutMetadata); }); it("should throw when Whatever.sol doesn't contain a Whatever contract", async () => { @@ -129,7 +130,12 @@ describe('#Compiler', function(): void { }; const exchangeArtifactString = await fsWrapper.readFileAsync(artifactPath, opts); const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString); - const bin = exchangeArtifact.compilerOutput.evm.bytecode.object; - expect(bin.slice(2)).to.length.to.be.gt(0); + const actualBinaryWithoutMetadata = hexUtils.slice( + exchangeArtifact.compilerOutput.evm.bytecode.object, + 0, + -METADATA_SIZE, + ); + const expectedBinaryWithoutMetadata = hexUtils.slice(v6_contract_binary, 0, -METADATA_SIZE); + expect(actualBinaryWithoutMetadata).to.eq(expectedBinaryWithoutMetadata); }); }); diff --git a/packages/sol-compiler/test/fixtures/contracts/V6Contract.sol b/packages/sol-compiler/test/fixtures/contracts/V6Contract.sol index de9f038a59..6180d53a34 100644 --- a/packages/sol-compiler/test/fixtures/contracts/V6Contract.sol +++ b/packages/sol-compiler/test/fixtures/contracts/V6Contract.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.6.4; +pragma solidity 0.6.4; contract V6Contract { diff --git a/packages/sol-compiler/test/fixtures/exchange_bin.ts b/packages/sol-compiler/test/fixtures/exchange_bin.ts index 914e76bf59..9fbf9bf957 100644 --- a/packages/sol-compiler/test/fixtures/exchange_bin.ts +++ b/packages/sol-compiler/test/fixtures/exchange_bin.ts @@ -1,4 +1,4 @@ export const constructor_args = '0x000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f4980000000000000000000000008da0d80f5007ef1e431dd2127178d224e32c2ef4'; export const exchange_binary = - '608060405234801561001057600080fd5b50604051604080612d998339810180604052810190808051906020019092919080519060200190929190505050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050612cca806100cf6000396000f3006080604052600436106100fc576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806314df96ee14610101578063288cdc911461015a5780632ac126221461019f578063363349be146101e4578063394c21e7146103f85780633b30ba59146104975780634f150787146104ee578063741bcc931461071b5780637e9abb50146107cf5780638163681e1461081457806398024a8b146108a6578063add1cbc5146108fb578063b7b2c7d614610952578063baa0181d14610b8b578063bc61394a14610cef578063cfc4d0ec14610dc3578063f06bbf7514610e60578063ffa1ad7414610e93575b600080fd5b34801561010d57600080fd5b50610140600480360381019080803590602001909291908035906020019092919080359060200190929190505050610f23565b604051808215151515815260200191505060405180910390f35b34801561016657600080fd5b506101896004803603810190808035600019169060200190929190505050610f7b565b6040518082815260200191505060405180910390f35b3480156101ab57600080fd5b506101ce6004803603810190808035600019169060200190929190505050610f93565b6040518082815260200191505060405180910390f35b3480156101f057600080fd5b506103e260048036038101908080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b8282101561027257848483905060a00201600580602002604051908101604052809291908260056020028082843782019150505050508152602001906001019061022d565b5050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156102f157848483905060c0020160068060200260405190810160405280929190826006602002808284378201915050505050815260200190600101906102ac565b5050505050919291929080359060200190929190803515159060200190929190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050610fab565b6040518082815260200191505060405180910390f35b34801561040457600080fd5b506104816004803603810190808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091929192908060c0019060068060200260405190810160405280929190826006602002808284378201915050505050919291929080359060200190929190505050611110565b6040518082815260200191505060405180910390f35b3480156104a357600080fd5b506104ac6115f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156104fa57600080fd5b5061071960048036038101908080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b8282101561057c57848483905060a002016005806020026040519081016040528092919082600560200280828437820191505050505081526020019060010190610537565b5050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156105fb57848483905060c0020160068060200260405190810160405280929190826006602002808284378201915050505050815260200190600101906105b6565b505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929050505061161d565b005b34801561072757600080fd5b506107cd6004803603810190808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091929192908060c0019060068060200260405190810160405280929190826006602002808284378201915050505050919291929080359060200190929190803560ff169060200190929190803560001916906020019092919080356000191690602001909291905050506116da565b005b3480156107db57600080fd5b506107fe60048036038101908080356000191690602001909291905050506116ff565b6040518082815260200191505060405180910390f35b34801561082057600080fd5b5061088c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035600019169060200190929190803560ff16906020019092919080356000191690602001909291908035600019169060200190929190505050611748565b604051808215151515815260200191505060405180910390f35b3480156108b257600080fd5b506108e5600480360381019080803590602001909291908035906020019092919080359060200190929190505050611849565b6040518082815260200191505060405180910390f35b34801561090757600080fd5b50610910611867565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561095e57600080fd5b50610b8960048036038101908080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156109e057848483905060a00201600580602002604051908101604052809291908260056020028082843782019150505050508152602001906001019061099b565b5050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b82821015610a5f57848483905060c002016006806020026040519081016040528092919082600660200280828437820191505050505081526020019060010190610a1a565b505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080351515906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929050505061188d565b005b348015610b9757600080fd5b50610ced60048036038101908080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b82821015610c1957848483905060a002016005806020026040519081016040528092919082600560200280828437820191505050505081526020019060010190610bd4565b5050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b82821015610c9857848483905060c002016006806020026040519081016040528092919082600660200280828437820191505050505081526020019060010190610c53565b505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929050505061194d565b005b348015610cfb57600080fd5b50610dad6004803603810190808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091929192908060c0019060068060200260405190810160405280929190826006602002808284378201915050505050919291929080359060200190929190803515159060200190929190803560ff169060200190929190803560001916906020019092919080356000191690602001909291905050506119c0565b6040518082815260200191505060405180910390f35b348015610dcf57600080fd5b50610e426004803603810190808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091929192908060c00190600680602002604051908101604052809291908260066020028082843782019150505050509192919290505050612160565b60405180826000191660001916815260200191505060405180910390f35b348015610e6c57600080fd5b50610e7561240b565b604051808261ffff1661ffff16815260200191505060405180910390f35b348015610e9f57600080fd5b50610ea8612411565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610ee8578082015181840152602081019050610ecd565b50505050905090810190601f168015610f155780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600080600084801515610f3257fe5b86850991506000821415610f495760009250610f72565b610f68610f5983620f424061244a565b610f63888761244a565b61247d565b90506103e8811192505b50509392505050565b60026020528060005260406000206000915090505481565b60036020528060005260406000206000915090505481565b6000806000809150600090505b895181101561110057896000815181101515610fd057fe5b906020019060200201516003600581101515610fe857fe5b602002015173ffffffffffffffffffffffffffffffffffffffff168a8281518110151561101157fe5b90602001906020020151600360058110151561102957fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1614151561105057600080fd5b6110e4826110df8c8481518110151561106557fe5b906020019060200201518c8581518110151561107d57fe5b906020019060200201516110918d88612498565b8c8c888151811015156110a057fe5b906020019060200201518c898151811015156110b857fe5b906020019060200201518c8a8151811015156110d057fe5b906020019060200201516119c0565b6124b1565b9150878214156110f357611100565b8080600101915050610fb8565b8192505050979650505050505050565b600061111a612bd2565b6000806101606040519081016040528088600060058110151561113957fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200188600160058110151561116857fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200188600260058110151561119757fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018860036005811015156111c657fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018860046005811015156111f557fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200187600060068110151561122457fe5b6020020151815260200187600160068110151561123d57fe5b6020020151815260200187600260068110151561125657fe5b6020020151815260200187600360068110151561126f57fe5b6020020151815260200187600460068110151561128857fe5b6020020151815260200161129c8989612160565b6000191681525092503373ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff161415156112e357600080fd5b60008360a001511180156112fb575060008360c00151115b80156113075750600085115b151561131257600080fd5b8261012001514210151561136f57826101400151600019166000600381111561133757fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a3600093506115ee565b61138a8360c001516113858561014001516116ff565b612498565b915061139685836124cf565b905060008114156113f05782610140015160001916600160038111156113b857fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a3600093506115ee565b61141a600360008561014001516000191660001916815260200190815260200160002054826124b1565b60036000856101400151600019166000191681526020019081526020016000208190555082604001518360600151604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140192505050604051809103902060001916836080015173ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff167f67d66f160bc93d925d05dae1794c90d2d6d6688b29b84ff069398a9b0458713186604001518760600151611552878a60c001518b60a00151611849565b878a6101400151604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200183815260200182600019166000191681526020019550505050505060405180910390a48093505b5050509392505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008090505b86518110156116d1576116c4878281518110151561163d57fe5b90602001906020020151878381518110151561165557fe5b90602001906020020151878481518110151561166d57fe5b90602001906020020151878581518110151561168557fe5b90602001906020020151878681518110151561169d57fe5b9060200190602002015187878151811015156116b557fe5b906020019060200201516116da565b8080600101915050611623565b50505050505050565b836116eb87878760008888886119c0565b1415156116f757600080fd5b505050505050565b600061174160026000846000191660001916815260200190815260200160002054600360008560001916600019168152602001908152602001600020546124b1565b9050919050565b600060018560405180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040518091039020858585604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1158015611806573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614905095945050505050565b600061185e611858858461244a565b8461247d565b90509392505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008090505b87518110156119435761193588828151811015156118ad57fe5b9060200190602002015188838151811015156118c557fe5b9060200190602002015188848151811015156118dd57fe5b906020019060200201518888868151811015156118f657fe5b90602001906020020151888781518110151561190e57fe5b90602001906020020151888881518110151561192657fe5b906020019060200201516119c0565b508080600101915050611893565b5050505050505050565b60008090505b83518110156119ba576119ac848281518110151561196d57fe5b90602001906020020151848381518110151561198557fe5b90602001906020020151848481518110151561199d57fe5b90602001906020020151611110565b508080600101915050611953565b50505050565b60006119ca612bd2565b600080600080610160604051908101604052808e60006005811015156119ec57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e6001600581101515611a1b57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e6002600581101515611a4a57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e6003600581101515611a7957fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e6004600581101515611aa857fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018d6000600681101515611ad757fe5b602002015181526020018d6001600681101515611af057fe5b602002015181526020018d6002600681101515611b0957fe5b602002015181526020018d6003600681101515611b2257fe5b602002015181526020018d6004600681101515611b3b57fe5b60200201518152602001611b4f8f8f612160565b600019168152509450600073ffffffffffffffffffffffffffffffffffffffff16856020015173ffffffffffffffffffffffffffffffffffffffff161480611bc657503373ffffffffffffffffffffffffffffffffffffffff16856020015173ffffffffffffffffffffffffffffffffffffffff16145b1515611bd157600080fd5b60008560a00151118015611be9575060008560c00151115b8015611bf5575060008b115b1515611c0057600080fd5b611c1685600001518661014001518b8b8b611748565b1515611c2157600080fd5b84610120015142101515611c7e578461014001516000191660006003811115611c4657fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612150565b611c998560c00151611c948761014001516116ff565b612498565b9350611ca58b856124cf565b95506000861415611cff578461014001516000191660016003811115611cc757fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612150565b611d12868660c001518760a00151610f23565b15611d66578461014001516000191660026003811115611d2e57fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612150565b89158015611d7b5750611d7985876124e8565b155b15611dce5784610140015160001916600380811115611d9657fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612150565b611de1868660c001518760a00151611849565b9250611e0d600260008761014001516000191660001916815260200190815260200160002054876124b1565b600260008761014001516000191660001916815260200190815260200160002081905550611e45856040015186600001513386612838565b1515611e5057600080fd5b611e64856060015133876000015189612838565b1515611e6f57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff16856080015173ffffffffffffffffffffffffffffffffffffffff16141515611f6e5760008560e001511115611f0c57611ec9868660c001518760e00151611849565b9150611f006000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168660000151876080015185612838565b1515611f0b57600080fd5b5b60008561010001511115611f6d57611f2e868660c00151876101000151611849565b9050611f616000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633876080015184612838565b1515611f6c57600080fd5b5b5b84604001518560600151604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140192505050604051809103902060001916856080015173ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb33389604001518a60600151898d8a8a8f6101400151604051808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186815260200185815260200184815260200183815260200182600019166000191681526020019850505050505050505060405180910390a48595505b5050505050979650505050505050565b60003083600060058110151561217257fe5b602002015184600160058110151561218657fe5b602002015185600260058110151561219a57fe5b60200201518660036005811015156121ae57fe5b60200201518760046005811015156121c257fe5b60200201518760006006811015156121d657fe5b60200201518860016006811015156121ea57fe5b60200201518960026006811015156121fe57fe5b60200201518a600360068110151561221257fe5b60200201518b600460068110151561222657fe5b60200201518c600560068110151561223a57fe5b6020020151604051808d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018781526020018681526020018581526020018481526020018381526020018281526020019c505050505050505050505050506040518091039020905092915050565b61138781565b6040805190810160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6000808284029050600084148061246b575082848281151561246857fe5b04145b151561247357fe5b8091505092915050565b600080828481151561248b57fe5b0490508091505092915050565b60008282111515156124a657fe5b818303905092915050565b60008082840190508381101515156124c557fe5b8091505092915050565b60008183106124de57816124e0565b825b905092915050565b600080600080600080600080600033975061250c8a8c60c001518d60a00151611849565b9650600073ffffffffffffffffffffffffffffffffffffffff168b6080015173ffffffffffffffffffffffffffffffffffffffff161415156127b9576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168b6040015173ffffffffffffffffffffffffffffffffffffffff161495506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168b6060015173ffffffffffffffffffffffffffffffffffffffff161494506126078a8c60c001518d60e00151611849565b935061261d8a8c60c001518d6101000151611849565b92508561262a5783612635565b61263487856124b1565b5b915084612642578261264d565b61264c8a846124b1565b5b90508161267f6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d600001516129ac565b10806126b85750816126b66000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d60000151612a94565b105b806126ec5750806126ea6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a6129ac565b105b8061272057508061271e6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a612a94565b105b1561272e576000985061282a565b8515801561276757508661274a8c604001518d600001516129ac565b10806127665750866127648c604001518d60000151612a94565b105b5b15612775576000985061282a565b841580156127a657508961278d8c606001518a6129ac565b10806127a55750896127a38c606001518a612a94565b105b5b156127b4576000985061282a565b612825565b866127cc8c604001518d600001516129ac565b10806127e85750866127e68c604001518d60000151612a94565b105b806127ff5750896127fd8c606001518a6129ac565b105b806128165750896128148c606001518a612a94565b105b15612824576000985061282a565b5b600198505b505050505050505092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166315dacbea868686866040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001945050505050602060405180830381600087803b15801561296757600080fd5b505af115801561297b573d6000803e3d6000fd5b505050506040513d602081101561299157600080fd5b81019080805190602001909291905050509050949350505050565b60008273ffffffffffffffffffffffffffffffffffffffff166370a0823161138761ffff16846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600088803b158015612a5057600080fd5b5087f1158015612a64573d6000803e3d6000fd5b50505050506040513d6020811015612a7b57600080fd5b8101908080519060200190929190505050905092915050565b60008273ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e61138761ffff1684600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600088803b158015612b8e57600080fd5b5087f1158015612ba2573d6000803e3d6000fd5b50505050506040513d6020811015612bb957600080fd5b8101908080519060200190929190505050905092915050565b61016060405190810160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081526020016000801916815250905600a165627a7a72305820f91599ebd80f85632ef190bb5e1a738e7288d68a2cf9dcc6b579d76b892dcf6f0029'; + '0x608060405234801561001057600080fd5b50604051604080612d998339810180604052810190808051906020019092919080519060200190929190505050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050612cca806100cf6000396000f3006080604052600436106100fc576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806314df96ee14610101578063288cdc911461015a5780632ac126221461019f578063363349be146101e4578063394c21e7146103f85780633b30ba59146104975780634f150787146104ee578063741bcc931461071b5780637e9abb50146107cf5780638163681e1461081457806398024a8b146108a6578063add1cbc5146108fb578063b7b2c7d614610952578063baa0181d14610b8b578063bc61394a14610cef578063cfc4d0ec14610dc3578063f06bbf7514610e60578063ffa1ad7414610e93575b600080fd5b34801561010d57600080fd5b50610140600480360381019080803590602001909291908035906020019092919080359060200190929190505050610f23565b604051808215151515815260200191505060405180910390f35b34801561016657600080fd5b506101896004803603810190808035600019169060200190929190505050610f7b565b6040518082815260200191505060405180910390f35b3480156101ab57600080fd5b506101ce6004803603810190808035600019169060200190929190505050610f93565b6040518082815260200191505060405180910390f35b3480156101f057600080fd5b506103e260048036038101908080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b8282101561027257848483905060a00201600580602002604051908101604052809291908260056020028082843782019150505050508152602001906001019061022d565b5050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156102f157848483905060c0020160068060200260405190810160405280929190826006602002808284378201915050505050815260200190600101906102ac565b5050505050919291929080359060200190929190803515159060200190929190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050610fab565b6040518082815260200191505060405180910390f35b34801561040457600080fd5b506104816004803603810190808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091929192908060c0019060068060200260405190810160405280929190826006602002808284378201915050505050919291929080359060200190929190505050611110565b6040518082815260200191505060405180910390f35b3480156104a357600080fd5b506104ac6115f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156104fa57600080fd5b5061071960048036038101908080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b8282101561057c57848483905060a002016005806020026040519081016040528092919082600560200280828437820191505050505081526020019060010190610537565b5050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156105fb57848483905060c0020160068060200260405190810160405280929190826006602002808284378201915050505050815260200190600101906105b6565b505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929050505061161d565b005b34801561072757600080fd5b506107cd6004803603810190808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091929192908060c0019060068060200260405190810160405280929190826006602002808284378201915050505050919291929080359060200190929190803560ff169060200190929190803560001916906020019092919080356000191690602001909291905050506116da565b005b3480156107db57600080fd5b506107fe60048036038101908080356000191690602001909291905050506116ff565b6040518082815260200191505060405180910390f35b34801561082057600080fd5b5061088c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035600019169060200190929190803560ff16906020019092919080356000191690602001909291908035600019169060200190929190505050611748565b604051808215151515815260200191505060405180910390f35b3480156108b257600080fd5b506108e5600480360381019080803590602001909291908035906020019092919080359060200190929190505050611849565b6040518082815260200191505060405180910390f35b34801561090757600080fd5b50610910611867565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561095e57600080fd5b50610b8960048036038101908080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156109e057848483905060a00201600580602002604051908101604052809291908260056020028082843782019150505050508152602001906001019061099b565b5050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b82821015610a5f57848483905060c002016006806020026040519081016040528092919082600660200280828437820191505050505081526020019060010190610a1a565b505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080351515906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929050505061188d565b005b348015610b9757600080fd5b50610ced60048036038101908080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b82821015610c1957848483905060a002016005806020026040519081016040528092919082600560200280828437820191505050505081526020019060010190610bd4565b5050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b82821015610c9857848483905060c002016006806020026040519081016040528092919082600660200280828437820191505050505081526020019060010190610c53565b505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929050505061194d565b005b348015610cfb57600080fd5b50610dad6004803603810190808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091929192908060c0019060068060200260405190810160405280929190826006602002808284378201915050505050919291929080359060200190929190803515159060200190929190803560ff169060200190929190803560001916906020019092919080356000191690602001909291905050506119c0565b6040518082815260200191505060405180910390f35b348015610dcf57600080fd5b50610e426004803603810190808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091929192908060c00190600680602002604051908101604052809291908260066020028082843782019150505050509192919290505050612160565b60405180826000191660001916815260200191505060405180910390f35b348015610e6c57600080fd5b50610e7561240b565b604051808261ffff1661ffff16815260200191505060405180910390f35b348015610e9f57600080fd5b50610ea8612411565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610ee8578082015181840152602081019050610ecd565b50505050905090810190601f168015610f155780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600080600084801515610f3257fe5b86850991506000821415610f495760009250610f72565b610f68610f5983620f424061244a565b610f63888761244a565b61247d565b90506103e8811192505b50509392505050565b60026020528060005260406000206000915090505481565b60036020528060005260406000206000915090505481565b6000806000809150600090505b895181101561110057896000815181101515610fd057fe5b906020019060200201516003600581101515610fe857fe5b602002015173ffffffffffffffffffffffffffffffffffffffff168a8281518110151561101157fe5b90602001906020020151600360058110151561102957fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1614151561105057600080fd5b6110e4826110df8c8481518110151561106557fe5b906020019060200201518c8581518110151561107d57fe5b906020019060200201516110918d88612498565b8c8c888151811015156110a057fe5b906020019060200201518c898151811015156110b857fe5b906020019060200201518c8a8151811015156110d057fe5b906020019060200201516119c0565b6124b1565b9150878214156110f357611100565b8080600101915050610fb8565b8192505050979650505050505050565b600061111a612bd2565b6000806101606040519081016040528088600060058110151561113957fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200188600160058110151561116857fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200188600260058110151561119757fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018860036005811015156111c657fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018860046005811015156111f557fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200187600060068110151561122457fe5b6020020151815260200187600160068110151561123d57fe5b6020020151815260200187600260068110151561125657fe5b6020020151815260200187600360068110151561126f57fe5b6020020151815260200187600460068110151561128857fe5b6020020151815260200161129c8989612160565b6000191681525092503373ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff161415156112e357600080fd5b60008360a001511180156112fb575060008360c00151115b80156113075750600085115b151561131257600080fd5b8261012001514210151561136f57826101400151600019166000600381111561133757fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a3600093506115ee565b61138a8360c001516113858561014001516116ff565b612498565b915061139685836124cf565b905060008114156113f05782610140015160001916600160038111156113b857fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a3600093506115ee565b61141a600360008561014001516000191660001916815260200190815260200160002054826124b1565b60036000856101400151600019166000191681526020019081526020016000208190555082604001518360600151604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140192505050604051809103902060001916836080015173ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff167f67d66f160bc93d925d05dae1794c90d2d6d6688b29b84ff069398a9b0458713186604001518760600151611552878a60c001518b60a00151611849565b878a6101400151604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200183815260200182600019166000191681526020019550505050505060405180910390a48093505b5050509392505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008090505b86518110156116d1576116c4878281518110151561163d57fe5b90602001906020020151878381518110151561165557fe5b90602001906020020151878481518110151561166d57fe5b90602001906020020151878581518110151561168557fe5b90602001906020020151878681518110151561169d57fe5b9060200190602002015187878151811015156116b557fe5b906020019060200201516116da565b8080600101915050611623565b50505050505050565b836116eb87878760008888886119c0565b1415156116f757600080fd5b505050505050565b600061174160026000846000191660001916815260200190815260200160002054600360008560001916600019168152602001908152602001600020546124b1565b9050919050565b600060018560405180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040518091039020858585604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1158015611806573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614905095945050505050565b600061185e611858858461244a565b8461247d565b90509392505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008090505b87518110156119435761193588828151811015156118ad57fe5b9060200190602002015188838151811015156118c557fe5b9060200190602002015188848151811015156118dd57fe5b906020019060200201518888868151811015156118f657fe5b90602001906020020151888781518110151561190e57fe5b90602001906020020151888881518110151561192657fe5b906020019060200201516119c0565b508080600101915050611893565b5050505050505050565b60008090505b83518110156119ba576119ac848281518110151561196d57fe5b90602001906020020151848381518110151561198557fe5b90602001906020020151848481518110151561199d57fe5b90602001906020020151611110565b508080600101915050611953565b50505050565b60006119ca612bd2565b600080600080610160604051908101604052808e60006005811015156119ec57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e6001600581101515611a1b57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e6002600581101515611a4a57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e6003600581101515611a7957fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e6004600581101515611aa857fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018d6000600681101515611ad757fe5b602002015181526020018d6001600681101515611af057fe5b602002015181526020018d6002600681101515611b0957fe5b602002015181526020018d6003600681101515611b2257fe5b602002015181526020018d6004600681101515611b3b57fe5b60200201518152602001611b4f8f8f612160565b600019168152509450600073ffffffffffffffffffffffffffffffffffffffff16856020015173ffffffffffffffffffffffffffffffffffffffff161480611bc657503373ffffffffffffffffffffffffffffffffffffffff16856020015173ffffffffffffffffffffffffffffffffffffffff16145b1515611bd157600080fd5b60008560a00151118015611be9575060008560c00151115b8015611bf5575060008b115b1515611c0057600080fd5b611c1685600001518661014001518b8b8b611748565b1515611c2157600080fd5b84610120015142101515611c7e578461014001516000191660006003811115611c4657fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612150565b611c998560c00151611c948761014001516116ff565b612498565b9350611ca58b856124cf565b95506000861415611cff578461014001516000191660016003811115611cc757fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612150565b611d12868660c001518760a00151610f23565b15611d66578461014001516000191660026003811115611d2e57fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612150565b89158015611d7b5750611d7985876124e8565b155b15611dce5784610140015160001916600380811115611d9657fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612150565b611de1868660c001518760a00151611849565b9250611e0d600260008761014001516000191660001916815260200190815260200160002054876124b1565b600260008761014001516000191660001916815260200190815260200160002081905550611e45856040015186600001513386612838565b1515611e5057600080fd5b611e64856060015133876000015189612838565b1515611e6f57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff16856080015173ffffffffffffffffffffffffffffffffffffffff16141515611f6e5760008560e001511115611f0c57611ec9868660c001518760e00151611849565b9150611f006000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168660000151876080015185612838565b1515611f0b57600080fd5b5b60008561010001511115611f6d57611f2e868660c00151876101000151611849565b9050611f616000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633876080015184612838565b1515611f6c57600080fd5b5b5b84604001518560600151604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140192505050604051809103902060001916856080015173ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb33389604001518a60600151898d8a8a8f6101400151604051808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186815260200185815260200184815260200183815260200182600019166000191681526020019850505050505050505060405180910390a48595505b5050505050979650505050505050565b60003083600060058110151561217257fe5b602002015184600160058110151561218657fe5b602002015185600260058110151561219a57fe5b60200201518660036005811015156121ae57fe5b60200201518760046005811015156121c257fe5b60200201518760006006811015156121d657fe5b60200201518860016006811015156121ea57fe5b60200201518960026006811015156121fe57fe5b60200201518a600360068110151561221257fe5b60200201518b600460068110151561222657fe5b60200201518c600560068110151561223a57fe5b6020020151604051808d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018781526020018681526020018581526020018481526020018381526020018281526020019c505050505050505050505050506040518091039020905092915050565b61138781565b6040805190810160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6000808284029050600084148061246b575082848281151561246857fe5b04145b151561247357fe5b8091505092915050565b600080828481151561248b57fe5b0490508091505092915050565b60008282111515156124a657fe5b818303905092915050565b60008082840190508381101515156124c557fe5b8091505092915050565b60008183106124de57816124e0565b825b905092915050565b600080600080600080600080600033975061250c8a8c60c001518d60a00151611849565b9650600073ffffffffffffffffffffffffffffffffffffffff168b6080015173ffffffffffffffffffffffffffffffffffffffff161415156127b9576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168b6040015173ffffffffffffffffffffffffffffffffffffffff161495506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168b6060015173ffffffffffffffffffffffffffffffffffffffff161494506126078a8c60c001518d60e00151611849565b935061261d8a8c60c001518d6101000151611849565b92508561262a5783612635565b61263487856124b1565b5b915084612642578261264d565b61264c8a846124b1565b5b90508161267f6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d600001516129ac565b10806126b85750816126b66000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d60000151612a94565b105b806126ec5750806126ea6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a6129ac565b105b8061272057508061271e6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a612a94565b105b1561272e576000985061282a565b8515801561276757508661274a8c604001518d600001516129ac565b10806127665750866127648c604001518d60000151612a94565b105b5b15612775576000985061282a565b841580156127a657508961278d8c606001518a6129ac565b10806127a55750896127a38c606001518a612a94565b105b5b156127b4576000985061282a565b612825565b866127cc8c604001518d600001516129ac565b10806127e85750866127e68c604001518d60000151612a94565b105b806127ff5750896127fd8c606001518a6129ac565b105b806128165750896128148c606001518a612a94565b105b15612824576000985061282a565b5b600198505b505050505050505092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166315dacbea868686866040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001945050505050602060405180830381600087803b15801561296757600080fd5b505af115801561297b573d6000803e3d6000fd5b505050506040513d602081101561299157600080fd5b81019080805190602001909291905050509050949350505050565b60008273ffffffffffffffffffffffffffffffffffffffff166370a0823161138761ffff16846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600088803b158015612a5057600080fd5b5087f1158015612a64573d6000803e3d6000fd5b50505050506040513d6020811015612a7b57600080fd5b8101908080519060200190929190505050905092915050565b60008273ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e61138761ffff1684600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600088803b158015612b8e57600080fd5b5087f1158015612ba2573d6000803e3d6000fd5b50505050506040513d6020811015612bb957600080fd5b8101908080519060200190929190505050905092915050565b61016060405190810160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081526020016000801916815250905600a165627a7a72305820f91599ebd80f85632ef190bb5e1a738e7288d68a2cf9dcc6b579d76b892dcf6f0029'; diff --git a/packages/sol-compiler/test/fixtures/v6_contract_bin.ts b/packages/sol-compiler/test/fixtures/v6_contract_bin.ts new file mode 100644 index 0000000000..04cfbcc143 --- /dev/null +++ b/packages/sol-compiler/test/fixtures/v6_contract_bin.ts @@ -0,0 +1,2 @@ +export const v6_contract_binary = + '0x6080604052348015600f57600080fd5b5060405161011238038061011283398181016040526020811015603157600080fd5b8101908080519060200190929190505050806000819055505060ba806100586000396000f3fe608060405236600a57005b348015601557600080fd5b506040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260048152602001807f6e6f70650000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fdfea26469706673582212208084a572151fb41e40aa4d1197e387cba7b4f0cbd982e34682974038667b564764736f6c63430006040033';