diff options
Diffstat (limited to 'packages/deployer/src')
-rw-r--r-- | packages/deployer/src/cli.ts | 218 | ||||
-rw-r--r-- | packages/deployer/src/commands.ts | 24 | ||||
-rw-r--r-- | packages/deployer/src/compiler.ts | 450 | ||||
-rw-r--r-- | packages/deployer/src/deployer.ts | 326 | ||||
-rw-r--r-- | packages/deployer/src/globals.d.ts | 6 | ||||
-rw-r--r-- | packages/deployer/src/migrations/config/multisig_sample.ts | 10 | ||||
-rw-r--r-- | packages/deployer/src/migrations/config/token_info.ts | 70 | ||||
-rw-r--r-- | packages/deployer/src/migrations/migrate.ts | 154 | ||||
-rw-r--r-- | packages/deployer/src/solc/bin_paths.ts | 20 | ||||
-rw-r--r-- | packages/deployer/src/types.ts | 24 | ||||
-rw-r--r-- | packages/deployer/src/utils/constants.ts | 2 | ||||
-rw-r--r-- | packages/deployer/src/utils/contract.ts | 144 | ||||
-rw-r--r-- | packages/deployer/src/utils/encoder.ts | 24 | ||||
-rw-r--r-- | packages/deployer/src/utils/fs_wrapper.ts | 12 | ||||
-rw-r--r-- | packages/deployer/src/utils/types.ts | 110 | ||||
-rw-r--r-- | packages/deployer/src/utils/utils.ts | 22 |
16 files changed, 808 insertions, 808 deletions
diff --git a/packages/deployer/src/cli.ts b/packages/deployer/src/cli.ts index decb37fdc..f4241b1cc 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 2acef8e8f..63e75685e 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 63db6c865..bc003149c 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 6f03581e8..34e20a197 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 0a35002da..d61f54870 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 dabeb7a4f..d65ab06d2 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 7e822fc3b..ebcd3f796 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 393806b45..48cf93000 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 e5b107101..7a22f911a 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 58d1e5b4f..aeff39d46 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 8871a470d..9f22114e7 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 546e82dfb..473ca95c8 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 d5f807774..30772b4bc 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 34c7caa0e..42bdc9969 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 e054b9cc2..9e1378e24 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 4390d8813..931ad6f73 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; + }, }; |