aboutsummaryrefslogtreecommitdiffstats
path: root/packages/deployer/src/compiler.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/deployer/src/compiler.ts')
-rw-r--r--packages/deployer/src/compiler.ts130
1 files changed, 64 insertions, 66 deletions
diff --git a/packages/deployer/src/compiler.ts b/packages/deployer/src/compiler.ts
index a3c8004ec..e81df3c0a 100644
--- a/packages/deployer/src/compiler.ts
+++ b/packages/deployer/src/compiler.ts
@@ -6,6 +6,7 @@ import {
FSResolver,
NameResolver,
NPMResolver,
+ RelativeFSResolver,
Resolver,
URLResolver,
} from '@0xproject/sol-resolver';
@@ -38,11 +39,30 @@ import {
ContractNetworks,
ContractSourceData,
ContractSpecificSourceData,
+ ContractVersionData,
} from './utils/types';
import { utils } from './utils/utils';
+type TYPE_ALL_FILES_IDENTIFIER = '*';
const ALL_CONTRACTS_IDENTIFIER = '*';
+const ALL_FILES_IDENTIFIER = '*';
const SOLC_BIN_DIR = path.join(__dirname, '..', '..', 'solc_bin');
+const DEFAULT_CONTRACTS_DIR = path.resolve('contracts');
+const DEFAULT_ARTIFACTS_DIR = path.resolve('artifacts');
+// 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'],
+ },
+ },
+};
+const CONFIG_FILE = 'compiler.json';
/**
* The Compiler facilitates compiling Solidity smart contracts and saves the results
@@ -52,26 +72,28 @@ export class Compiler {
private _resolver: Resolver;
private _nameResolver: NameResolver;
private _contractsDir: string;
- private _networkId: number;
- private _optimizerEnabled: boolean;
+ private _compilerSettings: solc.CompilerSettings;
private _artifactsDir: string;
- private _specifiedContracts: Set<string> = new Set();
+ private _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER;
/**
* Instantiates a new instance of the Compiler class.
- * @param opts Options specifying directories, network, and optimization settings.
* @return An instance of the Compiler class.
*/
constructor(opts: CompilerOptions) {
- this._contractsDir = opts.contractsDir;
- this._networkId = opts.networkId;
- this._optimizerEnabled = opts.optimizerEnabled;
- this._artifactsDir = opts.artifactsDir;
- this._specifiedContracts = opts.specifiedContracts;
+ // 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())
+ : {};
+ this._contractsDir = opts.contractsDir || config.contractsDir || DEFAULT_CONTRACTS_DIR;
+ this._compilerSettings = opts.compilerSettings || config.compilerSettings || DEFAULT_COMPILER_SETTINGS;
+ this._artifactsDir = opts.artifactsDir || config.artifactsDir || DEFAULT_ARTIFACTS_DIR;
+ this._specifiedContracts = opts.contracts || config.contracts || ALL_CONTRACTS_IDENTIFIER;
this._nameResolver = new NameResolver(path.resolve(this._contractsDir));
const resolver = new FallthroughResolver();
resolver.appendResolver(new URLResolver());
const packagePath = path.resolve('');
resolver.appendResolver(new NPMResolver(packagePath));
+ resolver.appendResolver(new RelativeFSResolver(this._contractsDir));
resolver.appendResolver(new FSResolver());
resolver.appendResolver(this._nameResolver);
this._resolver = resolver;
@@ -83,13 +105,13 @@ export class Compiler {
await createDirIfDoesNotExistAsync(this._artifactsDir);
await createDirIfDoesNotExistAsync(SOLC_BIN_DIR);
let contractNamesToCompile: string[] = [];
- if (this._specifiedContracts.has(ALL_CONTRACTS_IDENTIFIER)) {
+ if (this._specifiedContracts === ALL_CONTRACTS_IDENTIFIER) {
const allContracts = this._nameResolver.getAll();
contractNamesToCompile = _.map(allContracts, contractSource =>
path.basename(contractSource.path, constants.SOLIDITY_FILE_EXTENSION),
);
} else {
- contractNamesToCompile = Array.from(this._specifiedContracts.values());
+ contractNamesToCompile = this._specifiedContracts;
}
for (const contractNameToCompile of contractNamesToCompile) {
await this._compileContractAsync(contractNameToCompile);
@@ -101,17 +123,18 @@ export class Compiler {
*/
private async _compileContractAsync(contractName: string): Promise<void> {
const contractSource = this._resolver.resolve(contractName);
+ const absoluteContractPath = path.join(this._contractsDir, contractSource.path);
const currentArtifactIfExists = await getContractArtifactIfExistsAsync(this._artifactsDir, contractName);
- const sourceTreeHashHex = `0x${this._getSourceTreeHash(contractSource.path).toString('hex')}`;
-
+ const sourceTreeHashHex = `0x${this._getSourceTreeHash(absoluteContractPath).toString('hex')}`;
let shouldCompile = false;
if (_.isUndefined(currentArtifactIfExists)) {
shouldCompile = true;
} else {
const currentArtifact = currentArtifactIfExists as ContractArtifact;
- shouldCompile =
- currentArtifact.networks[this._networkId].optimizer_enabled !== this._optimizerEnabled ||
- currentArtifact.networks[this._networkId].source_tree_hash !== sourceTreeHashHex;
+ const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION;
+ const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings);
+ const didSourceChange = currentArtifact.sourceTreeHashHex !== sourceTreeHashHex;
+ shouldCompile = isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange;
}
if (!shouldCompile) {
return;
@@ -139,30 +162,14 @@ export class Compiler {
logUtils.log(`Compiling ${contractName} with Solidity v${solcVersion}...`);
const source = contractSource.source;
- const absoluteFilePath = contractSource.path;
const standardInput: solc.StandardInput = {
language: 'Solidity',
sources: {
- [absoluteFilePath]: {
- urls: [`file://${absoluteFilePath}`],
- },
- },
- settings: {
- optimizer: {
- enabled: this._optimizerEnabled,
- },
- outputSelection: {
- '*': {
- '*': [
- 'abi',
- 'evm.bytecode.object',
- 'evm.bytecode.sourceMap',
- 'evm.deployedBytecode.object',
- 'evm.deployedBytecode.sourceMap',
- ],
- },
+ [contractSource.path]: {
+ content: contractSource.source,
},
},
+ settings: this._compilerSettings,
};
const compiled: solc.StandardOutput = JSON.parse(
solcInstance.compileStandardWrapper(JSON.stringify(standardInput), importPath => {
@@ -188,34 +195,28 @@ export class Compiler {
});
}
}
- const compiledData = compiled.contracts[absoluteFilePath][contractName];
+ const compiledData = compiled.contracts[contractSource.path][contractName];
if (_.isUndefined(compiledData)) {
throw new Error(
- `Contract ${contractName} not found in ${absoluteFilePath}. Please make sure your contract has the same name as it's file name`,
+ `Contract ${contractName} not found in ${
+ contractSource.path
+ }. Please make sure your contract has the same name as it's file name`,
);
}
- const abi: ContractAbi = compiledData.abi;
- const bytecode = `0x${compiledData.evm.bytecode.object}`;
- const runtimeBytecode = `0x${compiledData.evm.deployedBytecode.object}`;
- const sourceMap = compiledData.evm.bytecode.sourceMap;
- const sourceMapRuntime = compiledData.evm.deployedBytecode.sourceMap;
- const unresolvedSourcePaths = _.keys(compiled.sources);
- const sources = _.map(
- unresolvedSourcePaths,
- unresolvedSourcePath => this._resolver.resolve(unresolvedSourcePath).path,
+ const sourceCodes = _.mapValues(
+ compiled.sources,
+ (_1, sourceFilePath) => this._resolver.resolve(sourceFilePath).source,
);
- const updated_at = Date.now();
- const contractNetworkData: ContractNetworkData = {
- solc_version: solcVersion,
- source_tree_hash: sourceTreeHashHex,
- optimizer_enabled: this._optimizerEnabled,
- abi,
- bytecode,
- runtime_bytecode: runtimeBytecode,
- updated_at,
- source_map: sourceMap,
- source_map_runtime: sourceMapRuntime,
- sources,
+ const contractVersion: ContractVersionData = {
+ compilerOutput: compiledData,
+ sources: compiled.sources,
+ sourceCodes,
+ sourceTreeHashHex,
+ compiler: {
+ name: 'solc',
+ version: solcVersion,
+ settings: this._compilerSettings,
+ },
};
let newArtifact: ContractArtifact;
@@ -223,17 +224,14 @@ export class Compiler {
const currentArtifact = currentArtifactIfExists as ContractArtifact;
newArtifact = {
...currentArtifact,
- networks: {
- ...currentArtifact.networks,
- [this._networkId]: contractNetworkData,
- },
+ ...contractVersion,
};
} else {
newArtifact = {
- contract_name: contractName,
- networks: {
- [this._networkId]: contractNetworkData,
- },
+ schemaVersion: constants.LATEST_ARTIFACT_VERSION,
+ contractName,
+ ...contractVersion,
+ networks: {},
};
}