aboutsummaryrefslogtreecommitdiffstats
path: root/packages/deployer/src
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2018-01-30 20:26:46 +0800
committerFabio Berger <me@fabioberger.com>2018-01-30 20:26:46 +0800
commitc6dece6bd1e5f5afa56b290557eb7a6245c76cb6 (patch)
treead7a33ffe5d80c0eb41ae10fbc8314f193e52383 /packages/deployer/src
parent93a5b3f457c1211676296840c285759007a55500 (diff)
downloaddexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar
dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar.gz
dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar.bz2
dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar.lz
dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar.xz
dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.tar.zst
dexon-sol-tools-c6dece6bd1e5f5afa56b290557eb7a6245c76cb6.zip
Add config file specifically in prettier command and fix files
Diffstat (limited to 'packages/deployer/src')
-rw-r--r--packages/deployer/src/cli.ts218
-rw-r--r--packages/deployer/src/commands.ts24
-rw-r--r--packages/deployer/src/compiler.ts450
-rw-r--r--packages/deployer/src/deployer.ts326
-rw-r--r--packages/deployer/src/globals.d.ts6
-rw-r--r--packages/deployer/src/migrations/config/multisig_sample.ts10
-rw-r--r--packages/deployer/src/migrations/config/token_info.ts70
-rw-r--r--packages/deployer/src/migrations/migrate.ts154
-rw-r--r--packages/deployer/src/solc/bin_paths.ts20
-rw-r--r--packages/deployer/src/types.ts24
-rw-r--r--packages/deployer/src/utils/constants.ts2
-rw-r--r--packages/deployer/src/utils/contract.ts144
-rw-r--r--packages/deployer/src/utils/encoder.ts24
-rw-r--r--packages/deployer/src/utils/fs_wrapper.ts12
-rw-r--r--packages/deployer/src/utils/types.ts110
-rw-r--r--packages/deployer/src/utils/utils.ts22
16 files changed, 808 insertions, 808 deletions
diff --git a/packages/deployer/src/cli.ts b/packages/deployer/src/cli.ts
index f4241b1cc..decb37fdc 100644
--- a/packages/deployer/src/cli.ts
+++ b/packages/deployer/src/cli.ts
@@ -20,13 +20,13 @@ const DEFAULT_GAS_PRICE = (10 ** 9 * 2).toString();
* @param argv Instance of process.argv provided by yargs.
*/
async function onCompileCommand(argv: CliOptions): Promise<void> {
- const opts: CompilerOptions = {
- contractsDir: argv.contractsDir,
- networkId: argv.networkId,
- optimizerEnabled: argv.shouldOptimize ? 1 : 0,
- artifactsDir: argv.artifactsDir,
- };
- await commands.compileAsync(opts);
+ const opts: CompilerOptions = {
+ contractsDir: argv.contractsDir,
+ networkId: argv.networkId,
+ optimizerEnabled: argv.shouldOptimize ? 1 : 0,
+ artifactsDir: argv.artifactsDir,
+ };
+ await commands.compileAsync(opts);
}
/**
* Compiles all contracts and runs migration script with options passed in through CLI.
@@ -34,123 +34,123 @@ async function onCompileCommand(argv: CliOptions): Promise<void> {
* @param argv Instance of process.argv provided by yargs.
*/
async function onMigrateCommand(argv: CliOptions): Promise<void> {
- const url = `http://localhost:${argv.jsonrpcPort}`;
- const web3Provider = new Web3.providers.HttpProvider(url);
- const web3Wrapper = new Web3Wrapper(web3Provider);
- const networkId = await web3Wrapper.getNetworkIdAsync();
- const compilerOpts: CompilerOptions = {
- contractsDir: argv.contractsDir,
- networkId,
- optimizerEnabled: argv.shouldOptimize ? 1 : 0,
- artifactsDir: argv.artifactsDir,
- };
- await commands.compileAsync(compilerOpts);
+ const url = `http://localhost:${argv.jsonrpcPort}`;
+ const web3Provider = new Web3.providers.HttpProvider(url);
+ const web3Wrapper = new Web3Wrapper(web3Provider);
+ const networkId = await web3Wrapper.getNetworkIdAsync();
+ const compilerOpts: CompilerOptions = {
+ contractsDir: argv.contractsDir,
+ networkId,
+ optimizerEnabled: argv.shouldOptimize ? 1 : 0,
+ artifactsDir: argv.artifactsDir,
+ };
+ await commands.compileAsync(compilerOpts);
- const defaults = {
- gasPrice: new BigNumber(argv.gasPrice),
- from: argv.account,
- };
- const deployerOpts = {
- artifactsDir: argv.artifactsDir,
- jsonrpcPort: argv.jsonrpcPort,
- networkId,
- defaults,
- };
- await commands.migrateAsync(deployerOpts);
+ const defaults = {
+ gasPrice: new BigNumber(argv.gasPrice),
+ from: argv.account,
+ };
+ const deployerOpts = {
+ artifactsDir: argv.artifactsDir,
+ jsonrpcPort: argv.jsonrpcPort,
+ networkId,
+ defaults,
+ };
+ await commands.migrateAsync(deployerOpts);
}
/**
* Deploys a single contract with provided name and args.
* @param argv Instance of process.argv provided by yargs.
*/
async function onDeployCommand(argv: CliOptions): Promise<void> {
- const url = `http://localhost:${argv.jsonrpcPort}`;
- const web3Provider = new Web3.providers.HttpProvider(url);
- const web3Wrapper = new Web3Wrapper(web3Provider);
- const networkId = await web3Wrapper.getNetworkIdAsync();
- const compilerOpts: CompilerOptions = {
- contractsDir: argv.contractsDir,
- networkId,
- optimizerEnabled: argv.shouldOptimize ? 1 : 0,
- artifactsDir: argv.artifactsDir,
- };
- await commands.compileAsync(compilerOpts);
+ const url = `http://localhost:${argv.jsonrpcPort}`;
+ const web3Provider = new Web3.providers.HttpProvider(url);
+ const web3Wrapper = new Web3Wrapper(web3Provider);
+ const networkId = await web3Wrapper.getNetworkIdAsync();
+ const compilerOpts: CompilerOptions = {
+ contractsDir: argv.contractsDir,
+ networkId,
+ optimizerEnabled: argv.shouldOptimize ? 1 : 0,
+ artifactsDir: argv.artifactsDir,
+ };
+ await commands.compileAsync(compilerOpts);
- const defaults = {
- gasPrice: new BigNumber(argv.gasPrice),
- from: argv.account,
- };
- const deployerOpts: DeployerOptions = {
- artifactsDir: argv.artifactsDir,
- jsonrpcPort: argv.jsonrpcPort,
- networkId,
- defaults,
- };
- const deployerArgsString = argv.args;
- const deployerArgs = deployerArgsString.split(',');
- await commands.deployAsync(argv.contract, deployerArgs, deployerOpts);
+ const defaults = {
+ gasPrice: new BigNumber(argv.gasPrice),
+ from: argv.account,
+ };
+ const deployerOpts: DeployerOptions = {
+ artifactsDir: argv.artifactsDir,
+ jsonrpcPort: argv.jsonrpcPort,
+ networkId,
+ defaults,
+ };
+ const deployerArgsString = argv.args;
+ const deployerArgs = deployerArgsString.split(',');
+ await commands.deployAsync(argv.contract, deployerArgs, deployerOpts);
}
/**
* Provides extra required options for deploy command.
* @param yargsInstance yargs instance provided in builder function callback.
*/
function deployCommandBuilder(yargsInstance: any) {
- return yargsInstance
- .option('contract', {
- type: 'string',
- description: 'name of contract to deploy, exluding .sol extension',
- })
- .option('args', {
- type: 'string',
- description: 'comma separated list of constructor args to deploy contract with',
- })
- .demandOption(['contract', 'args'])
- .help().argv;
+ return yargsInstance
+ .option('contract', {
+ type: 'string',
+ description: 'name of contract to deploy, exluding .sol extension',
+ })
+ .option('args', {
+ type: 'string',
+ description: 'comma separated list of constructor args to deploy contract with',
+ })
+ .demandOption(['contract', 'args'])
+ .help().argv;
}
(() => {
- const identityCommandBuilder = _.identity;
- return yargs
- .option('contracts-dir', {
- type: 'string',
- default: DEFAULT_CONTRACTS_DIR,
- description: 'path of contracts directory to compile',
- })
- .option('network-id', {
- type: 'number',
- default: DEFAULT_NETWORK_ID,
- description: 'mainnet=1, kovan=42, testrpc=50',
- })
- .option('should-optimize', {
- type: 'boolean',
- default: DEFAULT_OPTIMIZER_ENABLED,
- description: 'enable optimizer',
- })
- .option('artifacts-dir', {
- type: 'string',
- default: DEFAULT_ARTIFACTS_DIR,
- description: 'path to write contracts artifacts to',
- })
- .option('jsonrpc-port', {
- type: 'number',
- default: DEFAULT_JSONRPC_PORT,
- description: 'port connected to JSON RPC',
- })
- .option('gas-price', {
- type: 'string',
- default: DEFAULT_GAS_PRICE,
- description: 'gasPrice to be used for transactions',
- })
- .option('account', {
- type: 'string',
- description: 'account to use for deploying contracts',
- })
- .command('compile', 'compile contracts', identityCommandBuilder, onCompileCommand)
- .command(
- 'migrate',
- 'compile and deploy contracts using migration scripts',
- identityCommandBuilder,
- onMigrateCommand,
- )
- .command('deploy', 'deploy a single contract with provided arguments', deployCommandBuilder, onDeployCommand)
- .help().argv;
+ const identityCommandBuilder = _.identity;
+ return yargs
+ .option('contracts-dir', {
+ type: 'string',
+ default: DEFAULT_CONTRACTS_DIR,
+ description: 'path of contracts directory to compile',
+ })
+ .option('network-id', {
+ type: 'number',
+ default: DEFAULT_NETWORK_ID,
+ description: 'mainnet=1, kovan=42, testrpc=50',
+ })
+ .option('should-optimize', {
+ type: 'boolean',
+ default: DEFAULT_OPTIMIZER_ENABLED,
+ description: 'enable optimizer',
+ })
+ .option('artifacts-dir', {
+ type: 'string',
+ default: DEFAULT_ARTIFACTS_DIR,
+ description: 'path to write contracts artifacts to',
+ })
+ .option('jsonrpc-port', {
+ type: 'number',
+ default: DEFAULT_JSONRPC_PORT,
+ description: 'port connected to JSON RPC',
+ })
+ .option('gas-price', {
+ type: 'string',
+ default: DEFAULT_GAS_PRICE,
+ description: 'gasPrice to be used for transactions',
+ })
+ .option('account', {
+ type: 'string',
+ description: 'account to use for deploying contracts',
+ })
+ .command('compile', 'compile contracts', identityCommandBuilder, onCompileCommand)
+ .command(
+ 'migrate',
+ 'compile and deploy contracts using migration scripts',
+ identityCommandBuilder,
+ onMigrateCommand,
+ )
+ .command('deploy', 'deploy a single contract with provided arguments', deployCommandBuilder, onDeployCommand)
+ .help().argv;
})();
diff --git a/packages/deployer/src/commands.ts b/packages/deployer/src/commands.ts
index 63e75685e..2acef8e8f 100644
--- a/packages/deployer/src/commands.ts
+++ b/packages/deployer/src/commands.ts
@@ -4,16 +4,16 @@ import { Deployer } from './deployer';
import { CompilerOptions, DeployerOptions } from './utils/types';
export const commands = {
- async compileAsync(opts: CompilerOptions): Promise<void> {
- const compiler = new Compiler(opts);
- await compiler.compileAllAsync();
- },
- async migrateAsync(opts: DeployerOptions): Promise<void> {
- const deployer = new Deployer(opts);
- await migrator.runMigrationsAsync(deployer);
- },
- async deployAsync(contractName: string, args: any[], opts: DeployerOptions): Promise<void> {
- const deployer = new Deployer(opts);
- await deployer.deployAndSaveAsync(contractName, args);
- },
+ async compileAsync(opts: CompilerOptions): Promise<void> {
+ const compiler = new Compiler(opts);
+ await compiler.compileAllAsync();
+ },
+ async migrateAsync(opts: DeployerOptions): Promise<void> {
+ const deployer = new Deployer(opts);
+ await migrator.runMigrationsAsync(deployer);
+ },
+ async deployAsync(contractName: string, args: any[], opts: DeployerOptions): Promise<void> {
+ const deployer = new Deployer(opts);
+ await deployer.deployAndSaveAsync(contractName, args);
+ },
};
diff --git a/packages/deployer/src/compiler.ts b/packages/deployer/src/compiler.ts
index bc003149c..63db6c865 100644
--- a/packages/deployer/src/compiler.ts
+++ b/packages/deployer/src/compiler.ts
@@ -7,245 +7,245 @@ import * as Web3 from 'web3';
import { binPaths } from './solc/bin_paths';
import { fsWrapper } from './utils/fs_wrapper';
import {
- CompilerOptions,
- ContractArtifact,
- ContractData,
- ContractNetworks,
- ContractSources,
- ImportContents,
+ CompilerOptions,
+ ContractArtifact,
+ ContractData,
+ ContractNetworks,
+ ContractSources,
+ ImportContents,
} from './utils/types';
import { utils } from './utils/utils';
const SOLIDITY_FILE_EXTENSION = '.sol';
export class Compiler {
- private _contractsDir: string;
- private _networkId: number;
- private _optimizerEnabled: number;
- private _artifactsDir: string;
- private _contractSourcesIfExists?: ContractSources;
- private _solcErrors: Set<string>;
- /**
- * Recursively retrieves Solidity source code from directory.
- * @param dirPath Directory to search.
- * @return Mapping of contract name to contract source.
- */
- private static async _getContractSourcesAsync(dirPath: string): Promise<ContractSources> {
- let dirContents: string[] = [];
- try {
- dirContents = await fsWrapper.readdirAsync(dirPath);
- } catch (err) {
- throw new Error(`No directory found at ${dirPath}`);
- }
- let sources: ContractSources = {};
- for (const name of dirContents) {
- const contentPath = `${dirPath}/${name}`;
- if (path.extname(name) === SOLIDITY_FILE_EXTENSION) {
- try {
- const opts = {
- encoding: 'utf8',
- };
- sources[name] = await fsWrapper.readFileAsync(contentPath, opts);
- utils.consoleLog(`Reading ${name} source...`);
- } catch (err) {
- utils.consoleLog(`Could not find file at ${contentPath}`);
- }
- } else {
- try {
- const nestedSources = await Compiler._getContractSourcesAsync(contentPath);
- sources = {
- ...sources,
- ...nestedSources,
- };
- } catch (err) {
- utils.consoleLog(`${contentPath} is not a directory or ${SOLIDITY_FILE_EXTENSION} file`);
- }
- }
- }
- return sources;
- }
- /**
- * Searches Solidity source code for compiler version.
- * @param source Source code of contract.
- * @return Solc compiler version.
- */
- private static _parseSolidityVersion(source: string): string {
- const solcVersionMatch = source.match(/(?:solidity\s\^?)([0-9]{1,2}[.][0-9]{1,2}[.][0-9]{1,2})/);
- if (_.isNull(solcVersionMatch)) {
- throw new Error('Could not find Solidity version in source');
- }
- const solcVersion = solcVersionMatch[1];
- return solcVersion;
- }
- /**
- * Normalizes the path found in the error message.
- * Example: converts 'base/Token.sol:6:46: Warning: Unused local variable'
- * to 'Token.sol:6:46: Warning: Unused local variable'
- * This is used to prevent logging the same error multiple times.
- * @param errMsg An error message from the compiled output.
- * @return The error message with directories truncated from the contract path.
- */
- private static _getNormalizedErrMsg(errMsg: string): string {
- const errPathMatch = errMsg.match(/(.*\.sol)/);
- if (_.isNull(errPathMatch)) {
- throw new Error('Could not find a path in error message');
- }
- const errPath = errPathMatch[0];
- const baseContract = path.basename(errPath);
- const normalizedErrMsg = errMsg.replace(errPath, baseContract);
- return normalizedErrMsg;
- }
- /**
- * 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._solcErrors = new Set();
- }
- /**
- * Compiles all Solidity files found in contractsDir and writes JSON artifacts to artifactsDir.
- */
- public async compileAllAsync(): Promise<void> {
- await this._createArtifactsDirIfDoesNotExistAsync();
- this._contractSourcesIfExists = await Compiler._getContractSourcesAsync(this._contractsDir);
- const contractBaseNames = _.keys(this._contractSourcesIfExists);
- const compiledContractPromises = _.map(contractBaseNames, async (contractBaseName: string): Promise<void> => {
- return this._compileContractAsync(contractBaseName);
- });
- await Promise.all(compiledContractPromises);
+ private _contractsDir: string;
+ private _networkId: number;
+ private _optimizerEnabled: number;
+ private _artifactsDir: string;
+ private _contractSourcesIfExists?: ContractSources;
+ private _solcErrors: Set<string>;
+ /**
+ * Recursively retrieves Solidity source code from directory.
+ * @param dirPath Directory to search.
+ * @return Mapping of contract name to contract source.
+ */
+ private static async _getContractSourcesAsync(dirPath: string): Promise<ContractSources> {
+ let dirContents: string[] = [];
+ try {
+ dirContents = await fsWrapper.readdirAsync(dirPath);
+ } catch (err) {
+ throw new Error(`No directory found at ${dirPath}`);
+ }
+ let sources: ContractSources = {};
+ for (const name of dirContents) {
+ const contentPath = `${dirPath}/${name}`;
+ if (path.extname(name) === SOLIDITY_FILE_EXTENSION) {
+ try {
+ const opts = {
+ encoding: 'utf8',
+ };
+ sources[name] = await fsWrapper.readFileAsync(contentPath, opts);
+ utils.consoleLog(`Reading ${name} source...`);
+ } catch (err) {
+ utils.consoleLog(`Could not find file at ${contentPath}`);
+ }
+ } else {
+ try {
+ const nestedSources = await Compiler._getContractSourcesAsync(contentPath);
+ sources = {
+ ...sources,
+ ...nestedSources,
+ };
+ } catch (err) {
+ utils.consoleLog(`${contentPath} is not a directory or ${SOLIDITY_FILE_EXTENSION} file`);
+ }
+ }
+ }
+ return sources;
+ }
+ /**
+ * Searches Solidity source code for compiler version.
+ * @param source Source code of contract.
+ * @return Solc compiler version.
+ */
+ private static _parseSolidityVersion(source: string): string {
+ const solcVersionMatch = source.match(/(?:solidity\s\^?)([0-9]{1,2}[.][0-9]{1,2}[.][0-9]{1,2})/);
+ if (_.isNull(solcVersionMatch)) {
+ throw new Error('Could not find Solidity version in source');
+ }
+ const solcVersion = solcVersionMatch[1];
+ return solcVersion;
+ }
+ /**
+ * Normalizes the path found in the error message.
+ * Example: converts 'base/Token.sol:6:46: Warning: Unused local variable'
+ * to 'Token.sol:6:46: Warning: Unused local variable'
+ * This is used to prevent logging the same error multiple times.
+ * @param errMsg An error message from the compiled output.
+ * @return The error message with directories truncated from the contract path.
+ */
+ private static _getNormalizedErrMsg(errMsg: string): string {
+ const errPathMatch = errMsg.match(/(.*\.sol)/);
+ if (_.isNull(errPathMatch)) {
+ throw new Error('Could not find a path in error message');
+ }
+ const errPath = errPathMatch[0];
+ const baseContract = path.basename(errPath);
+ const normalizedErrMsg = errMsg.replace(errPath, baseContract);
+ return normalizedErrMsg;
+ }
+ /**
+ * 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._solcErrors = new Set();
+ }
+ /**
+ * Compiles all Solidity files found in contractsDir and writes JSON artifacts to artifactsDir.
+ */
+ public async compileAllAsync(): Promise<void> {
+ await this._createArtifactsDirIfDoesNotExistAsync();
+ this._contractSourcesIfExists = await Compiler._getContractSourcesAsync(this._contractsDir);
+ const contractBaseNames = _.keys(this._contractSourcesIfExists);
+ const compiledContractPromises = _.map(contractBaseNames, async (contractBaseName: string): Promise<void> => {
+ return this._compileContractAsync(contractBaseName);
+ });
+ await Promise.all(compiledContractPromises);
- this._solcErrors.forEach(errMsg => {
- utils.consoleLog(errMsg);
- });
- }
- /**
- * Compiles contract and saves artifact to artifactsDir.
- * @param contractBaseName Name of contract with '.sol' extension.
- */
- private async _compileContractAsync(contractBaseName: string): Promise<void> {
- if (_.isUndefined(this._contractSourcesIfExists)) {
- throw new Error('Contract sources not yet initialized');
- }
+ this._solcErrors.forEach(errMsg => {
+ utils.consoleLog(errMsg);
+ });
+ }
+ /**
+ * Compiles contract and saves artifact to artifactsDir.
+ * @param contractBaseName Name of contract with '.sol' extension.
+ */
+ private async _compileContractAsync(contractBaseName: string): Promise<void> {
+ if (_.isUndefined(this._contractSourcesIfExists)) {
+ throw new Error('Contract sources not yet initialized');
+ }
- const source = this._contractSourcesIfExists[contractBaseName];
- const contractName = path.basename(contractBaseName, SOLIDITY_FILE_EXTENSION);
- const currentArtifactPath = `${this._artifactsDir}/${contractName}.json`;
- const sourceHash = `0x${ethUtil.sha3(source).toString('hex')}`;
+ const source = this._contractSourcesIfExists[contractBaseName];
+ const contractName = path.basename(contractBaseName, SOLIDITY_FILE_EXTENSION);
+ const currentArtifactPath = `${this._artifactsDir}/${contractName}.json`;
+ const sourceHash = `0x${ethUtil.sha3(source).toString('hex')}`;
- let currentArtifactString: string;
- let currentArtifact: ContractArtifact;
- let oldNetworks: ContractNetworks;
- let shouldCompile: boolean;
- try {
- const opts = {
- encoding: 'utf8',
- };
- currentArtifactString = await fsWrapper.readFileAsync(currentArtifactPath, opts);
- currentArtifact = JSON.parse(currentArtifactString);
- oldNetworks = currentArtifact.networks;
- const oldNetwork: ContractData = oldNetworks[this._networkId];
- shouldCompile =
- _.isUndefined(oldNetwork) ||
- oldNetwork.keccak256 !== sourceHash ||
- oldNetwork.optimizer_enabled !== this._optimizerEnabled;
- } catch (err) {
- shouldCompile = true;
- }
+ let currentArtifactString: string;
+ let currentArtifact: ContractArtifact;
+ let oldNetworks: ContractNetworks;
+ let shouldCompile: boolean;
+ try {
+ const opts = {
+ encoding: 'utf8',
+ };
+ currentArtifactString = await fsWrapper.readFileAsync(currentArtifactPath, opts);
+ currentArtifact = JSON.parse(currentArtifactString);
+ oldNetworks = currentArtifact.networks;
+ const oldNetwork: ContractData = oldNetworks[this._networkId];
+ shouldCompile =
+ _.isUndefined(oldNetwork) ||
+ oldNetwork.keccak256 !== sourceHash ||
+ oldNetwork.optimizer_enabled !== this._optimizerEnabled;
+ } catch (err) {
+ shouldCompile = true;
+ }
- if (!shouldCompile) {
- return;
- }
+ if (!shouldCompile) {
+ return;
+ }
- const input = {
- [contractBaseName]: source,
- };
- const solcVersion = Compiler._parseSolidityVersion(source);
- const fullSolcVersion = binPaths[solcVersion];
- const solcBinPath = `./solc/solc_bin/${fullSolcVersion}`;
- const solcBin = require(solcBinPath);
- const solcInstance = solc.setupMethods(solcBin);
+ const input = {
+ [contractBaseName]: source,
+ };
+ const solcVersion = Compiler._parseSolidityVersion(source);
+ const fullSolcVersion = binPaths[solcVersion];
+ const solcBinPath = `./solc/solc_bin/${fullSolcVersion}`;
+ const solcBin = require(solcBinPath);
+ const solcInstance = solc.setupMethods(solcBin);
- utils.consoleLog(`Compiling ${contractBaseName}...`);
- const sourcesToCompile = {
- sources: input,
- };
- const compiled = solcInstance.compile(
- sourcesToCompile,
- this._optimizerEnabled,
- this._findImportsIfSourcesExist.bind(this),
- );
+ utils.consoleLog(`Compiling ${contractBaseName}...`);
+ const sourcesToCompile = {
+ sources: input,
+ };
+ const compiled = solcInstance.compile(
+ sourcesToCompile,
+ this._optimizerEnabled,
+ this._findImportsIfSourcesExist.bind(this),
+ );
- if (!_.isUndefined(compiled.errors)) {
- _.each(compiled.errors, errMsg => {
- const normalizedErrMsg = Compiler._getNormalizedErrMsg(errMsg);
- this._solcErrors.add(normalizedErrMsg);
- });
- }
+ if (!_.isUndefined(compiled.errors)) {
+ _.each(compiled.errors, errMsg => {
+ const normalizedErrMsg = Compiler._getNormalizedErrMsg(errMsg);
+ this._solcErrors.add(normalizedErrMsg);
+ });
+ }
- const contractIdentifier = `${contractBaseName}:${contractName}`;
- const abi: Web3.ContractAbi = JSON.parse(compiled.contracts[contractIdentifier].interface);
- const unlinked_binary = `0x${compiled.contracts[contractIdentifier].bytecode}`;
- const updated_at = Date.now();
- const contractData: ContractData = {
- solc_version: solcVersion,
- keccak256: sourceHash,
- optimizer_enabled: this._optimizerEnabled,
- abi,
- unlinked_binary,
- updated_at,
- };
+ const contractIdentifier = `${contractBaseName}:${contractName}`;
+ const abi: Web3.ContractAbi = JSON.parse(compiled.contracts[contractIdentifier].interface);
+ const unlinked_binary = `0x${compiled.contracts[contractIdentifier].bytecode}`;
+ const updated_at = Date.now();
+ const contractData: ContractData = {
+ solc_version: solcVersion,
+ keccak256: sourceHash,
+ optimizer_enabled: this._optimizerEnabled,
+ abi,
+ unlinked_binary,
+ updated_at,
+ };
- let newArtifact: ContractArtifact;
- if (!_.isUndefined(currentArtifactString)) {
- newArtifact = {
- ...currentArtifact,
- networks: {
- ...oldNetworks,
- [this._networkId]: contractData,
- },
- };
- } else {
- newArtifact = {
- contract_name: contractName,
- networks: {
- [this._networkId]: contractData,
- },
- };
- }
+ let newArtifact: ContractArtifact;
+ if (!_.isUndefined(currentArtifactString)) {
+ newArtifact = {
+ ...currentArtifact,
+ networks: {
+ ...oldNetworks,
+ [this._networkId]: contractData,
+ },
+ };
+ } else {
+ newArtifact = {
+ contract_name: contractName,
+ networks: {
+ [this._networkId]: contractData,
+ },
+ };
+ }
- const artifactString = utils.stringifyWithFormatting(newArtifact);
- await fsWrapper.writeFileAsync(currentArtifactPath, artifactString);
- utils.consoleLog(`${contractBaseName} artifact saved!`);
- }
- /**
- * Callback to resolve dependencies with `solc.compile`.
- * Throws error if contractSources not yet initialized.
- * @param importPath Path to an imported dependency.
- * @return Import contents object containing source code of dependency.
- */
- private _findImportsIfSourcesExist(importPath: string): ImportContents {
- if (_.isUndefined(this._contractSourcesIfExists)) {
- throw new Error('Contract sources not yet initialized');
- }
- const contractBaseName = path.basename(importPath);
- const source = this._contractSourcesIfExists[contractBaseName];
- const importContents: ImportContents = {
- contents: source,
- };
- return importContents;
- }
- /**
- * Creates the artifacts directory if it does not already exist.
- */
- private async _createArtifactsDirIfDoesNotExistAsync(): Promise<void> {
- if (!fsWrapper.doesPathExistSync(this._artifactsDir)) {
- utils.consoleLog('Creating artifacts directory...');
- await fsWrapper.mkdirAsync(this._artifactsDir);
- }
- }
+ const artifactString = utils.stringifyWithFormatting(newArtifact);
+ await fsWrapper.writeFileAsync(currentArtifactPath, artifactString);
+ utils.consoleLog(`${contractBaseName} artifact saved!`);
+ }
+ /**
+ * Callback to resolve dependencies with `solc.compile`.
+ * Throws error if contractSources not yet initialized.
+ * @param importPath Path to an imported dependency.
+ * @return Import contents object containing source code of dependency.
+ */
+ private _findImportsIfSourcesExist(importPath: string): ImportContents {
+ if (_.isUndefined(this._contractSourcesIfExists)) {
+ throw new Error('Contract sources not yet initialized');
+ }
+ const contractBaseName = path.basename(importPath);
+ const source = this._contractSourcesIfExists[contractBaseName];
+ const importContents: ImportContents = {
+ contents: source,
+ };
+ return importContents;
+ }
+ /**
+ * Creates the artifacts directory if it does not already exist.
+ */
+ private async _createArtifactsDirIfDoesNotExistAsync(): Promise<void> {
+ if (!fsWrapper.doesPathExistSync(this._artifactsDir)) {
+ utils.consoleLog('Creating artifacts directory...');
+ await fsWrapper.mkdirAsync(this._artifactsDir);
+ }
+ }
}
diff --git a/packages/deployer/src/deployer.ts b/packages/deployer/src/deployer.ts
index 34e20a197..6f03581e8 100644
--- a/packages/deployer/src/deployer.ts
+++ b/packages/deployer/src/deployer.ts
@@ -13,168 +13,168 @@ import { utils } from './utils/utils';
const EXTRA_GAS = 200000;
export class Deployer {
- public web3Wrapper: Web3Wrapper;
- private _artifactsDir: string;
- private _jsonrpcPort: number;
- private _networkId: number;
- private _defaults: Partial<TxData>;
+ public web3Wrapper: Web3Wrapper;
+ private _artifactsDir: string;
+ private _jsonrpcPort: number;
+ private _networkId: number;
+ private _defaults: Partial<TxData>;
- constructor(opts: DeployerOptions) {
- this._artifactsDir = opts.artifactsDir;
- this._jsonrpcPort = opts.jsonrpcPort;
- this._networkId = opts.networkId;
- const jsonrpcUrl = `http://localhost:${this._jsonrpcPort}`;
- const web3Provider = new Web3.providers.HttpProvider(jsonrpcUrl);
- this._defaults = opts.defaults;
- this.web3Wrapper = new Web3Wrapper(web3Provider, this._defaults);
- }
- /**
- * Loads contract artifact and deploys contract with given arguments.
- * @param contractName Name of the contract to deploy. Must match name of an artifact in artifacts directory.
- * @param args Array of contract constructor arguments.
- * @return Deployed contract instance.
- */
- public async deployAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> {
- const contractArtifact: ContractArtifact = this._loadContractArtifactIfExists(contractName);
- const contractData: ContractData = this._getContractDataFromArtifactIfExists(contractArtifact);
- const data = contractData.unlinked_binary;
- const from = await this._getFromAddressAsync();
- const gas = await this._getAllowableGasEstimateAsync(data);
- const txData = {
- gasPrice: this._defaults.gasPrice,
- from,
- data,
- gas,
- };
- const abi = contractData.abi;
- const web3ContractInstance = await this._deployFromAbiAsync(abi, args, txData);
- utils.consoleLog(`${contractName}.sol successfully deployed at ${web3ContractInstance.address}`);
- const contractInstance = new Contract(web3ContractInstance, this._defaults);
- return contractInstance;
- }
- /**
- * Loads contract artifact, deploys with given arguments, and saves updated data to artifact.
- * @param contractName Name of the contract to deploy. Must match name of an artifact in artifacts directory.
- * @param args Array of contract constructor arguments.
- * @return Deployed contract instance.
- */
- public async deployAndSaveAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> {
- const contractInstance = await this.deployAsync(contractName, args);
- await this._saveContractDataToArtifactAsync(contractName, contractInstance.address, args);
- return contractInstance;
- }
- /**
- * Deploys a contract given its ABI, arguments, and transaction data.
- * @param abi ABI of contract to deploy.
- * @param args Constructor arguments to use in deployment.
- * @param txData Tx options used for deployment.
- * @return Promise that resolves to a web3 contract instance.
- */
- private async _deployFromAbiAsync(abi: Web3.ContractAbi, args: any[], txData: Web3.TxData): Promise<any> {
- const contract: Web3.Contract<Web3.ContractInstance> = this.web3Wrapper.getContractFromAbi(abi);
- const deployPromise = new Promise((resolve, reject) => {
- /**
- * Contract is inferred as 'any' because TypeScript
- * is not able to read 'new' from the Contract interface
- */
- (contract as any).new(...args, txData, (err: Error, res: any): any => {
- if (err) {
- reject(err);
- } else if (_.isUndefined(res.address) && !_.isUndefined(res.transactionHash)) {
- utils.consoleLog(`transactionHash: ${res.transactionHash}`);
- } else {
- resolve(res);
- }
- });
- });
- return deployPromise;
- }
- /**
- * Updates a contract artifact's address and encoded constructor arguments.
- * @param contractName Name of contract. Must match an existing artifact.
- * @param contractAddress Contract address to save to artifact.
- * @param args Contract constructor arguments that will be encoded and saved to artifact.
- */
- private async _saveContractDataToArtifactAsync(
- contractName: string,
- contractAddress: string,
- args: any[],
- ): Promise<void> {
- const contractArtifact: ContractArtifact = this._loadContractArtifactIfExists(contractName);
- const contractData: ContractData = this._getContractDataFromArtifactIfExists(contractArtifact);
- const abi = contractData.abi;
- const encodedConstructorArgs = encoder.encodeConstructorArgsFromAbi(args, abi);
- const newContractData = {
- ...contractData,
- address: contractAddress,
- constructor_args: encodedConstructorArgs,
- };
- const newArtifact = {
- ...contractArtifact,
- networks: {
- ...contractArtifact.networks,
- [this._networkId]: newContractData,
- },
- };
- const artifactString = utils.stringifyWithFormatting(newArtifact);
- const artifactPath = `${this._artifactsDir}/${contractName}.json`;
- await fsWrapper.writeFileAsync(artifactPath, artifactString);
- }
- /**
- * Loads a contract artifact, if it exists.
- * @param contractName Name of the contract, without the extension.
- * @return The contract artifact.
- */
- private _loadContractArtifactIfExists(contractName: string): ContractArtifact {
- const artifactPath = `${this._artifactsDir}/${contractName}.json`;
- try {
- const contractArtifact: ContractArtifact = require(artifactPath);
- return contractArtifact;
- } catch (err) {
- throw new Error(`Artifact not found for contract: ${contractName}`);
- }
- }
- /**
- * Gets data for current networkId stored in artifact.
- * @param contractArtifact The contract artifact.
- * @return Network specific contract data.
- */
- private _getContractDataFromArtifactIfExists(contractArtifact: ContractArtifact): ContractData {
- const contractData = contractArtifact.networks[this._networkId];
- if (_.isUndefined(contractData)) {
- throw new Error(`Data not found in artifact for contract: ${contractArtifact.contract_name}`);
- }
- return contractData;
- }
- /**
- * Gets the address to use for sending a transaction.
- * @return The default from address. If not specified, returns the first address accessible by web3.
- */
- private async _getFromAddressAsync(): Promise<string> {
- let from: string;
- if (_.isUndefined(this._defaults.from)) {
- const accounts = await this.web3Wrapper.getAvailableAddressesAsync();
- from = accounts[0];
- } else {
- from = this._defaults.from;
- }
- return from;
- }
- /**
- * Estimates the gas required for a transaction.
- * If gas would be over the block gas limit, the max allowable gas is returned instead.
- * @param data Bytecode to estimate gas for.
- * @return Gas estimate for transaction data.
- */
- private async _getAllowableGasEstimateAsync(data: string): Promise<number> {
- const block = await this.web3Wrapper.getBlockAsync('latest');
- let gas: number;
- try {
- const gasEstimate: number = await this.web3Wrapper.estimateGasAsync(data);
- gas = Math.min(gasEstimate + EXTRA_GAS, block.gasLimit);
- } catch (err) {
- gas = block.gasLimit;
- }
- return gas;
- }
+ constructor(opts: DeployerOptions) {
+ this._artifactsDir = opts.artifactsDir;
+ this._jsonrpcPort = opts.jsonrpcPort;
+ this._networkId = opts.networkId;
+ const jsonrpcUrl = `http://localhost:${this._jsonrpcPort}`;
+ const web3Provider = new Web3.providers.HttpProvider(jsonrpcUrl);
+ this._defaults = opts.defaults;
+ this.web3Wrapper = new Web3Wrapper(web3Provider, this._defaults);
+ }
+ /**
+ * Loads contract artifact and deploys contract with given arguments.
+ * @param contractName Name of the contract to deploy. Must match name of an artifact in artifacts directory.
+ * @param args Array of contract constructor arguments.
+ * @return Deployed contract instance.
+ */
+ public async deployAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> {
+ const contractArtifact: ContractArtifact = this._loadContractArtifactIfExists(contractName);
+ const contractData: ContractData = this._getContractDataFromArtifactIfExists(contractArtifact);
+ const data = contractData.unlinked_binary;
+ const from = await this._getFromAddressAsync();
+ const gas = await this._getAllowableGasEstimateAsync(data);
+ const txData = {
+ gasPrice: this._defaults.gasPrice,
+ from,
+ data,
+ gas,
+ };
+ const abi = contractData.abi;
+ const web3ContractInstance = await this._deployFromAbiAsync(abi, args, txData);
+ utils.consoleLog(`${contractName}.sol successfully deployed at ${web3ContractInstance.address}`);
+ const contractInstance = new Contract(web3ContractInstance, this._defaults);
+ return contractInstance;
+ }
+ /**
+ * Loads contract artifact, deploys with given arguments, and saves updated data to artifact.
+ * @param contractName Name of the contract to deploy. Must match name of an artifact in artifacts directory.
+ * @param args Array of contract constructor arguments.
+ * @return Deployed contract instance.
+ */
+ public async deployAndSaveAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> {
+ const contractInstance = await this.deployAsync(contractName, args);
+ await this._saveContractDataToArtifactAsync(contractName, contractInstance.address, args);
+ return contractInstance;
+ }
+ /**
+ * Deploys a contract given its ABI, arguments, and transaction data.
+ * @param abi ABI of contract to deploy.
+ * @param args Constructor arguments to use in deployment.
+ * @param txData Tx options used for deployment.
+ * @return Promise that resolves to a web3 contract instance.
+ */
+ private async _deployFromAbiAsync(abi: Web3.ContractAbi, args: any[], txData: Web3.TxData): Promise<any> {
+ const contract: Web3.Contract<Web3.ContractInstance> = this.web3Wrapper.getContractFromAbi(abi);
+ const deployPromise = new Promise((resolve, reject) => {
+ /**
+ * Contract is inferred as 'any' because TypeScript
+ * is not able to read 'new' from the Contract interface
+ */
+ (contract as any).new(...args, txData, (err: Error, res: any): any => {
+ if (err) {
+ reject(err);
+ } else if (_.isUndefined(res.address) && !_.isUndefined(res.transactionHash)) {
+ utils.consoleLog(`transactionHash: ${res.transactionHash}`);
+ } else {
+ resolve(res);
+ }
+ });
+ });
+ return deployPromise;
+ }
+ /**
+ * Updates a contract artifact's address and encoded constructor arguments.
+ * @param contractName Name of contract. Must match an existing artifact.
+ * @param contractAddress Contract address to save to artifact.
+ * @param args Contract constructor arguments that will be encoded and saved to artifact.
+ */
+ private async _saveContractDataToArtifactAsync(
+ contractName: string,
+ contractAddress: string,
+ args: any[],
+ ): Promise<void> {
+ const contractArtifact: ContractArtifact = this._loadContractArtifactIfExists(contractName);
+ const contractData: ContractData = this._getContractDataFromArtifactIfExists(contractArtifact);
+ const abi = contractData.abi;
+ const encodedConstructorArgs = encoder.encodeConstructorArgsFromAbi(args, abi);
+ const newContractData = {
+ ...contractData,
+ address: contractAddress,
+ constructor_args: encodedConstructorArgs,
+ };
+ const newArtifact = {
+ ...contractArtifact,
+ networks: {
+ ...contractArtifact.networks,
+ [this._networkId]: newContractData,
+ },
+ };
+ const artifactString = utils.stringifyWithFormatting(newArtifact);
+ const artifactPath = `${this._artifactsDir}/${contractName}.json`;
+ await fsWrapper.writeFileAsync(artifactPath, artifactString);
+ }
+ /**
+ * Loads a contract artifact, if it exists.
+ * @param contractName Name of the contract, without the extension.
+ * @return The contract artifact.
+ */
+ private _loadContractArtifactIfExists(contractName: string): ContractArtifact {
+ const artifactPath = `${this._artifactsDir}/${contractName}.json`;
+ try {
+ const contractArtifact: ContractArtifact = require(artifactPath);
+ return contractArtifact;
+ } catch (err) {
+ throw new Error(`Artifact not found for contract: ${contractName}`);
+ }
+ }
+ /**
+ * Gets data for current networkId stored in artifact.
+ * @param contractArtifact The contract artifact.
+ * @return Network specific contract data.
+ */
+ private _getContractDataFromArtifactIfExists(contractArtifact: ContractArtifact): ContractData {
+ const contractData = contractArtifact.networks[this._networkId];
+ if (_.isUndefined(contractData)) {
+ throw new Error(`Data not found in artifact for contract: ${contractArtifact.contract_name}`);
+ }
+ return contractData;
+ }
+ /**
+ * Gets the address to use for sending a transaction.
+ * @return The default from address. If not specified, returns the first address accessible by web3.
+ */
+ private async _getFromAddressAsync(): Promise<string> {
+ let from: string;
+ if (_.isUndefined(this._defaults.from)) {
+ const accounts = await this.web3Wrapper.getAvailableAddressesAsync();
+ from = accounts[0];
+ } else {
+ from = this._defaults.from;
+ }
+ return from;
+ }
+ /**
+ * Estimates the gas required for a transaction.
+ * If gas would be over the block gas limit, the max allowable gas is returned instead.
+ * @param data Bytecode to estimate gas for.
+ * @return Gas estimate for transaction data.
+ */
+ private async _getAllowableGasEstimateAsync(data: string): Promise<number> {
+ const block = await this.web3Wrapper.getBlockAsync('latest');
+ let gas: number;
+ try {
+ const gasEstimate: number = await this.web3Wrapper.estimateGasAsync(data);
+ gas = Math.min(gasEstimate + EXTRA_GAS, block.gasLimit);
+ } catch (err) {
+ gas = block.gasLimit;
+ }
+ return gas;
+ }
}
diff --git a/packages/deployer/src/globals.d.ts b/packages/deployer/src/globals.d.ts
index d61f54870..0a35002da 100644
--- a/packages/deployer/src/globals.d.ts
+++ b/packages/deployer/src/globals.d.ts
@@ -1,8 +1,8 @@
declare module 'solc' {
- export function compile(sources: any, optimizerEnabled: number, findImports: (importPath: string) => any): any;
- export function setupMethods(solcBin: any): any;
+ export function compile(sources: any, optimizerEnabled: number, findImports: (importPath: string) => any): any;
+ export function setupMethods(solcBin: any): any;
}
declare module 'web3-eth-abi' {
- export function encodeParameters(typesArray: string[], parameters: any[]): string;
+ export function encodeParameters(typesArray: string[], parameters: any[]): string;
}
diff --git a/packages/deployer/src/migrations/config/multisig_sample.ts b/packages/deployer/src/migrations/config/multisig_sample.ts
index d65ab06d2..dabeb7a4f 100644
--- a/packages/deployer/src/migrations/config/multisig_sample.ts
+++ b/packages/deployer/src/migrations/config/multisig_sample.ts
@@ -2,9 +2,9 @@ import { MultiSigConfigByNetwork } from '../../types';
// Make a copy of this file named `multisig.js` and input custom params as needed
export const multiSig: MultiSigConfigByNetwork = {
- kovan: {
- owners: [],
- confirmationsRequired: 0,
- secondsRequired: 0,
- },
+ kovan: {
+ owners: [],
+ confirmationsRequired: 0,
+ secondsRequired: 0,
+ },
};
diff --git a/packages/deployer/src/migrations/config/token_info.ts b/packages/deployer/src/migrations/config/token_info.ts
index ebcd3f796..7e822fc3b 100644
--- a/packages/deployer/src/migrations/config/token_info.ts
+++ b/packages/deployer/src/migrations/config/token_info.ts
@@ -2,39 +2,39 @@ import { constants } from '../../utils/constants';
import { Token } from '../../types';
export const tokenInfo: Token[] = [
- {
- name: 'Augur Reputation Token',
- symbol: 'REP',
- decimals: 18,
- ipfsHash: constants.NULL_BYTES,
- swarmHash: constants.NULL_BYTES,
- },
- {
- name: 'Digix DAO Token',
- symbol: 'DGD',
- decimals: 18,
- ipfsHash: constants.NULL_BYTES,
- swarmHash: constants.NULL_BYTES,
- },
- {
- name: 'Golem Network Token',
- symbol: 'GNT',
- decimals: 18,
- ipfsHash: constants.NULL_BYTES,
- swarmHash: constants.NULL_BYTES,
- },
- {
- name: 'MakerDAO',
- symbol: 'MKR',
- decimals: 18,
- ipfsHash: constants.NULL_BYTES,
- swarmHash: constants.NULL_BYTES,
- },
- {
- name: 'Melon Token',
- symbol: 'MLN',
- decimals: 18,
- ipfsHash: constants.NULL_BYTES,
- swarmHash: constants.NULL_BYTES,
- },
+ {
+ name: 'Augur Reputation Token',
+ symbol: 'REP',
+ decimals: 18,
+ ipfsHash: constants.NULL_BYTES,
+ swarmHash: constants.NULL_BYTES,
+ },
+ {
+ name: 'Digix DAO Token',
+ symbol: 'DGD',
+ decimals: 18,
+ ipfsHash: constants.NULL_BYTES,
+ swarmHash: constants.NULL_BYTES,
+ },
+ {
+ name: 'Golem Network Token',
+ symbol: 'GNT',
+ decimals: 18,
+ ipfsHash: constants.NULL_BYTES,
+ swarmHash: constants.NULL_BYTES,
+ },
+ {
+ name: 'MakerDAO',
+ symbol: 'MKR',
+ decimals: 18,
+ ipfsHash: constants.NULL_BYTES,
+ swarmHash: constants.NULL_BYTES,
+ },
+ {
+ name: 'Melon Token',
+ symbol: 'MLN',
+ decimals: 18,
+ ipfsHash: constants.NULL_BYTES,
+ swarmHash: constants.NULL_BYTES,
+ },
];
diff --git a/packages/deployer/src/migrations/migrate.ts b/packages/deployer/src/migrations/migrate.ts
index 48cf93000..393806b45 100644
--- a/packages/deployer/src/migrations/migrate.ts
+++ b/packages/deployer/src/migrations/migrate.ts
@@ -7,84 +7,84 @@ import { constants } from '../utils/constants';
import { tokenInfo } from './config/token_info';
export const migrator = {
- /**
- * Custom migrations should be defined in this function. This will be called with the CLI 'migrate' command.
- * Some operations might be completed in parallel, but we don't do that on purpose.
- * That way the addresses are deterministic.
- * @param deployer Deployer instance.
- */
- async runMigrationsAsync(deployer: Deployer): Promise<void> {
- const web3Wrapper: Web3Wrapper = deployer.web3Wrapper;
- const accounts: string[] = await web3Wrapper.getAvailableAddressesAsync();
+ /**
+ * Custom migrations should be defined in this function. This will be called with the CLI 'migrate' command.
+ * Some operations might be completed in parallel, but we don't do that on purpose.
+ * That way the addresses are deterministic.
+ * @param deployer Deployer instance.
+ */
+ async runMigrationsAsync(deployer: Deployer): Promise<void> {
+ const web3Wrapper: Web3Wrapper = deployer.web3Wrapper;
+ const accounts: string[] = await web3Wrapper.getAvailableAddressesAsync();
- const tokenTransferProxy = await deployer.deployAndSaveAsync('TokenTransferProxy');
- const zrxToken = await deployer.deployAndSaveAsync('ZRXToken');
- const etherToken = await deployer.deployAndSaveAsync('WETH9');
- const tokenReg = await deployer.deployAndSaveAsync('TokenRegistry');
+ const tokenTransferProxy = await deployer.deployAndSaveAsync('TokenTransferProxy');
+ const zrxToken = await deployer.deployAndSaveAsync('ZRXToken');
+ const etherToken = await deployer.deployAndSaveAsync('WETH9');
+ const tokenReg = await deployer.deployAndSaveAsync('TokenRegistry');
- const exchangeArgs = [zrxToken.address, tokenTransferProxy.address];
- const owners = [accounts[0], accounts[1]];
- const confirmationsRequired = new BigNumber(2);
- const secondsRequired = new BigNumber(0);
- const multiSigArgs = [owners, confirmationsRequired, secondsRequired, tokenTransferProxy.address];
- const exchange = await deployer.deployAndSaveAsync('Exchange', exchangeArgs);
- const multiSig = await deployer.deployAndSaveAsync(
- 'MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress',
- multiSigArgs,
- );
+ const exchangeArgs = [zrxToken.address, tokenTransferProxy.address];
+ const owners = [accounts[0], accounts[1]];
+ const confirmationsRequired = new BigNumber(2);
+ const secondsRequired = new BigNumber(0);
+ const multiSigArgs = [owners, confirmationsRequired, secondsRequired, tokenTransferProxy.address];
+ const exchange = await deployer.deployAndSaveAsync('Exchange', exchangeArgs);
+ const multiSig = await deployer.deployAndSaveAsync(
+ 'MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress',
+ multiSigArgs,
+ );
- const owner = accounts[0];
- await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner });
- await tokenTransferProxy.transferOwnership.sendTransactionAsync(multiSig.address, { from: owner });
- const addTokenGasEstimate = await tokenReg.addToken.estimateGasAsync(
- zrxToken.address,
- tokenInfo[0].name,
- tokenInfo[0].symbol,
- tokenInfo[0].decimals,
- tokenInfo[0].ipfsHash,
- tokenInfo[0].swarmHash,
- { from: owner },
- );
- await tokenReg.addToken.sendTransactionAsync(
- zrxToken.address,
- '0x Protocol Token',
- 'ZRX',
- 18,
- constants.NULL_BYTES,
- constants.NULL_BYTES,
- {
- from: owner,
- gas: addTokenGasEstimate,
- },
- );
- await tokenReg.addToken.sendTransactionAsync(
- etherToken.address,
- 'Ether Token',
- 'WETH',
- 18,
- constants.NULL_BYTES,
- constants.NULL_BYTES,
- {
- from: owner,
- gas: addTokenGasEstimate,
- },
- );
- for (const token of tokenInfo) {
- const totalSupply = new BigNumber(0);
- const args = [token.name, token.symbol, token.decimals, totalSupply];
- const dummyToken = await deployer.deployAsync('DummyToken', args);
- await tokenReg.addToken.sendTransactionAsync(
- dummyToken.address,
- token.name,
- token.symbol,
- token.decimals,
- token.ipfsHash,
- token.swarmHash,
- {
- from: owner,
- gas: addTokenGasEstimate,
- },
- );
- }
- },
+ const owner = accounts[0];
+ await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner });
+ await tokenTransferProxy.transferOwnership.sendTransactionAsync(multiSig.address, { from: owner });
+ const addTokenGasEstimate = await tokenReg.addToken.estimateGasAsync(
+ zrxToken.address,
+ tokenInfo[0].name,
+ tokenInfo[0].symbol,
+ tokenInfo[0].decimals,
+ tokenInfo[0].ipfsHash,
+ tokenInfo[0].swarmHash,
+ { from: owner },
+ );
+ await tokenReg.addToken.sendTransactionAsync(
+ zrxToken.address,
+ '0x Protocol Token',
+ 'ZRX',
+ 18,
+ constants.NULL_BYTES,
+ constants.NULL_BYTES,
+ {
+ from: owner,
+ gas: addTokenGasEstimate,
+ },
+ );
+ await tokenReg.addToken.sendTransactionAsync(
+ etherToken.address,
+ 'Ether Token',
+ 'WETH',
+ 18,
+ constants.NULL_BYTES,
+ constants.NULL_BYTES,
+ {
+ from: owner,
+ gas: addTokenGasEstimate,
+ },
+ );
+ for (const token of tokenInfo) {
+ const totalSupply = new BigNumber(0);
+ const args = [token.name, token.symbol, token.decimals, totalSupply];
+ const dummyToken = await deployer.deployAsync('DummyToken', args);
+ await tokenReg.addToken.sendTransactionAsync(
+ dummyToken.address,
+ token.name,
+ token.symbol,
+ token.decimals,
+ token.ipfsHash,
+ token.swarmHash,
+ {
+ from: owner,
+ gas: addTokenGasEstimate,
+ },
+ );
+ }
+ },
};
diff --git a/packages/deployer/src/solc/bin_paths.ts b/packages/deployer/src/solc/bin_paths.ts
index 7a22f911a..e5b107101 100644
--- a/packages/deployer/src/solc/bin_paths.ts
+++ b/packages/deployer/src/solc/bin_paths.ts
@@ -1,15 +1,15 @@
export interface BinaryPaths {
- [key: string]: string;
+ [key: string]: string;
}
export const binPaths: BinaryPaths = {
- '0.4.10': 'soljson-v0.4.10+commit.f0d539ae.js',
- '0.4.11': 'soljson-v0.4.11+commit.68ef5810.js',
- '0.4.12': 'soljson-v0.4.12+commit.194ff033.js',
- '0.4.13': 'soljson-v0.4.13+commit.fb4cb1a.js',
- '0.4.14': 'soljson-v0.4.14+commit.c2215d46.js',
- '0.4.15': 'soljson-v0.4.15+commit.bbb8e64f.js',
- '0.4.16': 'soljson-v0.4.16+commit.d7661dd9.js',
- '0.4.17': 'soljson-v0.4.17+commit.bdeb9e52.js',
- '0.4.18': 'soljson-v0.4.18+commit.9cf6e910.js',
+ '0.4.10': 'soljson-v0.4.10+commit.f0d539ae.js',
+ '0.4.11': 'soljson-v0.4.11+commit.68ef5810.js',
+ '0.4.12': 'soljson-v0.4.12+commit.194ff033.js',
+ '0.4.13': 'soljson-v0.4.13+commit.fb4cb1a.js',
+ '0.4.14': 'soljson-v0.4.14+commit.c2215d46.js',
+ '0.4.15': 'soljson-v0.4.15+commit.bbb8e64f.js',
+ '0.4.16': 'soljson-v0.4.16+commit.d7661dd9.js',
+ '0.4.17': 'soljson-v0.4.17+commit.bdeb9e52.js',
+ '0.4.18': 'soljson-v0.4.18+commit.9cf6e910.js',
};
diff --git a/packages/deployer/src/types.ts b/packages/deployer/src/types.ts
index aeff39d46..58d1e5b4f 100644
--- a/packages/deployer/src/types.ts
+++ b/packages/deployer/src/types.ts
@@ -1,23 +1,23 @@
export interface MultiSigConfig {
- owners: string[];
- confirmationsRequired: number;
- secondsRequired: number;
+ owners: string[];
+ confirmationsRequired: number;
+ secondsRequired: number;
}
export interface MultiSigConfigByNetwork {
- [networkName: string]: MultiSigConfig;
+ [networkName: string]: MultiSigConfig;
}
export interface Token {
- address?: string;
- name: string;
- symbol: string;
- decimals: number;
- ipfsHash: string;
- swarmHash: string;
+ address?: string;
+ name: string;
+ symbol: string;
+ decimals: number;
+ ipfsHash: string;
+ swarmHash: string;
}
export interface TokenInfoByNetwork {
- development: Token[];
- live: Token[];
+ development: Token[];
+ live: Token[];
}
diff --git a/packages/deployer/src/utils/constants.ts b/packages/deployer/src/utils/constants.ts
index 9f22114e7..8871a470d 100644
--- a/packages/deployer/src/utils/constants.ts
+++ b/packages/deployer/src/utils/constants.ts
@@ -1,3 +1,3 @@
export const constants = {
- NULL_BYTES: '0x',
+ NULL_BYTES: '0x',
};
diff --git a/packages/deployer/src/utils/contract.ts b/packages/deployer/src/utils/contract.ts
index 473ca95c8..546e82dfb 100644
--- a/packages/deployer/src/utils/contract.ts
+++ b/packages/deployer/src/utils/contract.ts
@@ -6,76 +6,76 @@ import * as Web3 from 'web3';
import { AbiType } from './types';
export class Contract implements Web3.ContractInstance {
- public address: string;
- public abi: Web3.ContractAbi;
- private _contract: Web3.ContractInstance;
- private _defaults: Partial<Web3.TxData>;
- private _validator: SchemaValidator;
- // This class instance is going to be populated with functions and events depending on the ABI
- // and we don't know their types in advance
- [name: string]: any;
- constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<Web3.TxData>) {
- this._contract = web3ContractInstance;
- this.address = web3ContractInstance.address;
- this.abi = web3ContractInstance.abi;
- this._defaults = defaults;
- this._populateEvents();
- this._populateFunctions();
- this._validator = new SchemaValidator();
- }
- private _populateFunctions(): void {
- const functionsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Function) as Web3.FunctionAbi[];
- _.forEach(functionsAbi, (functionAbi: Web3.MethodAbi) => {
- if (functionAbi.constant) {
- const cbStyleCallFunction = this._contract[functionAbi.name].call;
- this[functionAbi.name] = {
- callAsync: promisify(cbStyleCallFunction, this._contract),
- };
- } else {
- const cbStyleFunction = this._contract[functionAbi.name];
- const cbStyleEstimateGasFunction = this._contract[functionAbi.name].estimateGas;
- this[functionAbi.name] = {
- estimateGasAsync: promisify(cbStyleEstimateGasFunction, this._contract),
- sendTransactionAsync: this._promisifyWithDefaultParams(cbStyleFunction),
- };
- }
- });
- }
- private _populateEvents(): void {
- const eventsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Event) as Web3.EventAbi[];
- _.forEach(eventsAbi, (eventAbi: Web3.EventAbi) => {
- this[eventAbi.name] = this._contract[eventAbi.name];
- });
- }
- private _promisifyWithDefaultParams(fn: (...args: any[]) => void): (...args: any[]) => Promise<any> {
- const promisifiedWithDefaultParams = async (...args: any[]) => {
- const promise = new Promise((resolve, reject) => {
- const lastArg = args[args.length - 1];
- let txData: Partial<Web3.TxData> = {};
- if (this._isTxData(lastArg)) {
- txData = args.pop();
- }
- txData = {
- ...this._defaults,
- ...txData,
- };
- const callback = (err: Error, data: any) => {
- if (_.isNull(err)) {
- resolve(data);
- } else {
- reject(err);
- }
- };
- args.push(txData);
- args.push(callback);
- fn.apply(this._contract, args);
- });
- return promise;
- };
- return promisifiedWithDefaultParams;
- }
- private _isTxData(lastArg: any): boolean {
- const isValid = this._validator.isValid(lastArg, schemas.txDataSchema);
- return isValid;
- }
+ public address: string;
+ public abi: Web3.ContractAbi;
+ private _contract: Web3.ContractInstance;
+ private _defaults: Partial<Web3.TxData>;
+ private _validator: SchemaValidator;
+ // This class instance is going to be populated with functions and events depending on the ABI
+ // and we don't know their types in advance
+ [name: string]: any;
+ constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<Web3.TxData>) {
+ this._contract = web3ContractInstance;
+ this.address = web3ContractInstance.address;
+ this.abi = web3ContractInstance.abi;
+ this._defaults = defaults;
+ this._populateEvents();
+ this._populateFunctions();
+ this._validator = new SchemaValidator();
+ }
+ private _populateFunctions(): void {
+ const functionsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Function) as Web3.FunctionAbi[];
+ _.forEach(functionsAbi, (functionAbi: Web3.MethodAbi) => {
+ if (functionAbi.constant) {
+ const cbStyleCallFunction = this._contract[functionAbi.name].call;
+ this[functionAbi.name] = {
+ callAsync: promisify(cbStyleCallFunction, this._contract),
+ };
+ } else {
+ const cbStyleFunction = this._contract[functionAbi.name];
+ const cbStyleEstimateGasFunction = this._contract[functionAbi.name].estimateGas;
+ this[functionAbi.name] = {
+ estimateGasAsync: promisify(cbStyleEstimateGasFunction, this._contract),
+ sendTransactionAsync: this._promisifyWithDefaultParams(cbStyleFunction),
+ };
+ }
+ });
+ }
+ private _populateEvents(): void {
+ const eventsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Event) as Web3.EventAbi[];
+ _.forEach(eventsAbi, (eventAbi: Web3.EventAbi) => {
+ this[eventAbi.name] = this._contract[eventAbi.name];
+ });
+ }
+ private _promisifyWithDefaultParams(fn: (...args: any[]) => void): (...args: any[]) => Promise<any> {
+ const promisifiedWithDefaultParams = async (...args: any[]) => {
+ const promise = new Promise((resolve, reject) => {
+ const lastArg = args[args.length - 1];
+ let txData: Partial<Web3.TxData> = {};
+ if (this._isTxData(lastArg)) {
+ txData = args.pop();
+ }
+ txData = {
+ ...this._defaults,
+ ...txData,
+ };
+ const callback = (err: Error, data: any) => {
+ if (_.isNull(err)) {
+ resolve(data);
+ } else {
+ reject(err);
+ }
+ };
+ args.push(txData);
+ args.push(callback);
+ fn.apply(this._contract, args);
+ });
+ return promise;
+ };
+ return promisifiedWithDefaultParams;
+ }
+ private _isTxData(lastArg: any): boolean {
+ const isValid = this._validator.isValid(lastArg, schemas.txDataSchema);
+ return isValid;
+ }
}
diff --git a/packages/deployer/src/utils/encoder.ts b/packages/deployer/src/utils/encoder.ts
index 30772b4bc..d5f807774 100644
--- a/packages/deployer/src/utils/encoder.ts
+++ b/packages/deployer/src/utils/encoder.ts
@@ -5,16 +5,16 @@ import * as web3Abi from 'web3-eth-abi';
import { AbiType } from './types';
export const encoder = {
- encodeConstructorArgsFromAbi(args: any[], abi: Web3.ContractAbi): string {
- const constructorTypes: string[] = [];
- _.each(abi, (element: Web3.AbiDefinition) => {
- if (element.type === AbiType.Constructor) {
- _.each(element.inputs, (input: Web3.FunctionParameter) => {
- constructorTypes.push(input.type);
- });
- }
- });
- const encodedParameters = web3Abi.encodeParameters(constructorTypes, args);
- return encodedParameters;
- },
+ encodeConstructorArgsFromAbi(args: any[], abi: Web3.ContractAbi): string {
+ const constructorTypes: string[] = [];
+ _.each(abi, (element: Web3.AbiDefinition) => {
+ if (element.type === AbiType.Constructor) {
+ _.each(element.inputs, (input: Web3.FunctionParameter) => {
+ constructorTypes.push(input.type);
+ });
+ }
+ });
+ const encodedParameters = web3Abi.encodeParameters(constructorTypes, args);
+ return encodedParameters;
+ },
};
diff --git a/packages/deployer/src/utils/fs_wrapper.ts b/packages/deployer/src/utils/fs_wrapper.ts
index 42bdc9969..34c7caa0e 100644
--- a/packages/deployer/src/utils/fs_wrapper.ts
+++ b/packages/deployer/src/utils/fs_wrapper.ts
@@ -2,10 +2,10 @@ import { promisify } from '@0xproject/utils';
import * as fs from 'fs';
export const fsWrapper = {
- readdirAsync: promisify<string[]>(fs.readdir),
- readFileAsync: promisify<string>(fs.readFile),
- writeFileAsync: promisify<undefined>(fs.writeFile),
- mkdirAsync: promisify<undefined>(fs.mkdir),
- doesPathExistSync: fs.existsSync,
- removeFileAsync: promisify<undefined>(fs.unlink),
+ readdirAsync: promisify<string[]>(fs.readdir),
+ readFileAsync: promisify<string>(fs.readFile),
+ writeFileAsync: promisify<undefined>(fs.writeFile),
+ mkdirAsync: promisify<undefined>(fs.mkdir),
+ doesPathExistSync: fs.existsSync,
+ removeFileAsync: promisify<undefined>(fs.unlink),
};
diff --git a/packages/deployer/src/utils/types.ts b/packages/deployer/src/utils/types.ts
index 9e1378e24..e054b9cc2 100644
--- a/packages/deployer/src/utils/types.ts
+++ b/packages/deployer/src/utils/types.ts
@@ -3,95 +3,95 @@ import * as Web3 from 'web3';
import * as yargs from 'yargs';
export enum AbiType {
- Function = 'function',
- Constructor = 'constructor',
- Event = 'event',
- Fallback = 'fallback',
+ Function = 'function',
+ Constructor = 'constructor',
+ Event = 'event',
+ Fallback = 'fallback',
}
export interface ContractArtifact {
- contract_name: string;
- networks: ContractNetworks;
+ contract_name: string;
+ networks: ContractNetworks;
}
export interface ContractNetworks {
- [key: number]: ContractData;
+ [key: number]: ContractData;
}
export interface ContractData {
- solc_version: string;
- optimizer_enabled: number;
- keccak256: string;
- abi: Web3.ContractAbi;
- unlinked_binary: string;
- address?: string;
- constructor_args?: string;
- updated_at: number;
+ solc_version: string;
+ optimizer_enabled: number;
+ keccak256: string;
+ abi: Web3.ContractAbi;
+ unlinked_binary: string;
+ address?: string;
+ constructor_args?: string;
+ updated_at: number;
}
export interface SolcErrors {
- [key: string]: boolean;
+ [key: string]: boolean;
}
export interface CliOptions extends yargs.Arguments {
- artifactsDir: string;
- contractsDir: string;
- jsonrpcPort: number;
- networkId: number;
- shouldOptimize: boolean;
- gasPrice: string;
- account?: string;
- contract?: string;
- args?: string;
+ artifactsDir: string;
+ contractsDir: string;
+ jsonrpcPort: number;
+ networkId: number;
+ shouldOptimize: boolean;
+ gasPrice: string;
+ account?: string;
+ contract?: string;
+ args?: string;
}
export interface CompilerOptions {
- contractsDir: string;
- networkId: number;
- optimizerEnabled: number;
- artifactsDir: string;
+ contractsDir: string;
+ networkId: number;
+ optimizerEnabled: number;
+ artifactsDir: string;
}
export interface DeployerOptions {
- artifactsDir: string;
- jsonrpcPort: number;
- networkId: number;
- defaults: Partial<TxData>;
+ artifactsDir: string;
+ jsonrpcPort: number;
+ networkId: number;
+ defaults: Partial<TxData>;
}
export interface ContractSources {
- [key: string]: string;
+ [key: string]: string;
}
export interface ImportContents {
- contents: string;
+ contents: string;
}
// TODO: Consolidate with 0x.js definitions once types are moved into a separate package.
export enum ZeroExError {
- ContractDoesNotExist = 'CONTRACT_DOES_NOT_EXIST',
- ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
- UnhandledError = 'UNHANDLED_ERROR',
- UserHasNoAssociatedAddress = 'USER_HAS_NO_ASSOCIATED_ADDRESSES',
- InvalidSignature = 'INVALID_SIGNATURE',
- ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
- InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
- InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
- InsufficientEthBalanceForDeposit = 'INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT',
- InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL',
- InvalidJump = 'INVALID_JUMP',
- OutOfGas = 'OUT_OF_GAS',
- NoNetworkId = 'NO_NETWORK_ID',
- SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
+ ContractDoesNotExist = 'CONTRACT_DOES_NOT_EXIST',
+ ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
+ UnhandledError = 'UNHANDLED_ERROR',
+ UserHasNoAssociatedAddress = 'USER_HAS_NO_ASSOCIATED_ADDRESSES',
+ InvalidSignature = 'INVALID_SIGNATURE',
+ ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
+ InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
+ InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
+ InsufficientEthBalanceForDeposit = 'INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT',
+ InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL',
+ InvalidJump = 'INVALID_JUMP',
+ OutOfGas = 'OUT_OF_GAS',
+ NoNetworkId = 'NO_NETWORK_ID',
+ SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
}
export interface Token {
- address?: string;
- name: string;
- symbol: string;
- decimals: number;
- ipfsHash: string;
- swarmHash: string;
+ address?: string;
+ name: string;
+ symbol: string;
+ decimals: number;
+ ipfsHash: string;
+ swarmHash: string;
}
export type DoneCallback = (err?: Error) => void;
diff --git a/packages/deployer/src/utils/utils.ts b/packages/deployer/src/utils/utils.ts
index 931ad6f73..4390d8813 100644
--- a/packages/deployer/src/utils/utils.ts
+++ b/packages/deployer/src/utils/utils.ts
@@ -1,13 +1,13 @@
export const utils = {
- consoleLog(message: string): void {
- /* tslint:disable */
- console.log(message);
- /* tslint:enable */
- },
- stringifyWithFormatting(obj: any): string {
- const jsonReplacer: null = null;
- const numberOfJsonSpaces = 4;
- const stringifiedObj = JSON.stringify(obj, jsonReplacer, numberOfJsonSpaces);
- return stringifiedObj;
- },
+ consoleLog(message: string): void {
+ /* tslint:disable */
+ console.log(message);
+ /* tslint:enable */
+ },
+ stringifyWithFormatting(obj: any): string {
+ const jsonReplacer: null = null;
+ const numberOfJsonSpaces = 4;
+ const stringifiedObj = JSON.stringify(obj, jsonReplacer, numberOfJsonSpaces);
+ return stringifiedObj;
+ },
};