diff options
-rw-r--r-- | packages/contracts/deploy/src/compiler.ts | 153 | ||||
-rw-r--r-- | packages/contracts/package.json | 2 | ||||
-rw-r--r-- | packages/contracts/test/ts/multi_sig_with_time_lock_except_remove_auth_addr.ts | 4 | ||||
-rw-r--r-- | packages/contracts/util/multi_sig_wrapper.ts | 22 |
4 files changed, 92 insertions, 89 deletions
diff --git a/packages/contracts/deploy/src/compiler.ts b/packages/contracts/deploy/src/compiler.ts index 5909bdda1..70b88b514 100644 --- a/packages/contracts/deploy/src/compiler.ts +++ b/packages/contracts/deploy/src/compiler.ts @@ -20,77 +20,6 @@ import {utils} from './utils/utils'; const SOLIDITY_FILE_EXTENSION = '.sol'; -/** - * Recursively retrieves Solidity source code from directory. - * @param dirPath Directory to search. - * @return Mapping of contract name to contract source. - */ -async function 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 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. - */ -function 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. - */ -function 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; -} - export class Compiler { private contractsDir: string; private networkId: number; @@ -98,7 +27,81 @@ export class Compiler { 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; @@ -111,7 +114,7 @@ export class Compiler { */ public async compileAllAsync(): Promise<void> { await this.createArtifactsDirIfDoesNotExistAsync(); - this.contractSourcesIfExists = await getContractSourcesAsync(this.contractsDir); + this.contractSourcesIfExists = await Compiler.getContractSourcesAsync(this.contractsDir); const contractBaseNames = _.keys(this.contractSourcesIfExists); const compiledContractPromises = _.map(contractBaseNames, async (contractBaseName: string): Promise<void> => { @@ -163,7 +166,7 @@ export class Compiler { const input = { [contractBaseName]: source, }; - const solcVersion = parseSolidityVersion(source); + const solcVersion = Compiler.parseSolidityVersion(source); const fullSolcVersion = binPaths[solcVersion]; const solcBinPath = `./../solc/solc_bin/${fullSolcVersion}`; const solcBin = require(solcBinPath); @@ -179,7 +182,7 @@ export class Compiler { if (!_.isUndefined(compiled.errors)) { _.each(compiled.errors, errMsg => { - const normalizedErrMsg = getNormalizedErrMsg(errMsg); + const normalizedErrMsg = Compiler.getNormalizedErrMsg(errMsg); this.solcErrors.add(normalizedErrMsg); }); } diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 346add2ae..0bbf39eef 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -14,7 +14,7 @@ "migrate:truffle": "npm run build; truffle migrate", "migrate": "npm run build; node lib/deploy/cli.js migrate", "lint": "tslint --project . 'migrations/*.ts' 'test/**/*.ts' 'util/*.ts' 'deploy/**/*.ts'", - "mocha": "npm run build; mocha lib/deploy/test/*_test.js" + "test:deployer": "npm run build; mocha lib/deploy/test/*_test.js" }, "repository": { "type": "git", diff --git a/packages/contracts/test/ts/multi_sig_with_time_lock_except_remove_auth_addr.ts b/packages/contracts/test/ts/multi_sig_with_time_lock_except_remove_auth_addr.ts index ed0a6c3dd..97ccac2bd 100644 --- a/packages/contracts/test/ts/multi_sig_with_time_lock_except_remove_auth_addr.ts +++ b/packages/contracts/test/ts/multi_sig_with_time_lock_except_remove_auth_addr.ts @@ -42,13 +42,13 @@ contract('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', (accounts: s describe('isFunctionRemoveAuthorizedAddress', () => { it('should throw if data is not for removeAuthorizedAddress', async () => { - const data = multiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]); + const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]); return expect(multiSig.isFunctionRemoveAuthorizedAddress.call(data)) .to.be.rejectedWith(constants.INVALID_OPCODE); }); it('should return true if data is for removeAuthorizedAddress', async () => { - const data = multiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]); + const data = MultiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]); const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress.call(data); expect(isFunctionRemoveAuthorizedAddress).to.be.true(); }); diff --git a/packages/contracts/util/multi_sig_wrapper.ts b/packages/contracts/util/multi_sig_wrapper.ts index 3adaab592..4ad970ac9 100644 --- a/packages/contracts/util/multi_sig_wrapper.ts +++ b/packages/contracts/util/multi_sig_wrapper.ts @@ -7,17 +7,7 @@ import {ContractInstance, TransactionDataParams} from './types'; export class MultiSigWrapper { private multiSig: ContractInstance; - constructor(multiSigContractInstance: ContractInstance) { - this.multiSig = multiSigContractInstance; - } - public async submitTransactionAsync(destination: string, from: string, - dataParams: TransactionDataParams, - value: number = 0) { - const {name, abi, args = []} = dataParams; - const encoded = this.encodeFnArgs(name, abi, args); - return this.multiSig.submitTransaction(destination, value, encoded, {from}); - } - public encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) { + public static encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) { const abiEntity = _.find(abi, {name}) as Web3.MethodAbi; if (_.isUndefined(abiEntity)) { throw new Error(`Did not find abi entry for name: ${name}`); @@ -31,4 +21,14 @@ export class MultiSigWrapper { }); return funcSig + argsData.join(''); } + constructor(multiSigContractInstance: ContractInstance) { + this.multiSig = multiSigContractInstance; + } + public async submitTransactionAsync(destination: string, from: string, + dataParams: TransactionDataParams, + value: number = 0) { + const {name, abi, args = []} = dataParams; + const encoded = MultiSigWrapper.encodeFnArgs(name, abi, args); + return this.multiSig.submitTransaction(destination, value, encoded, {from}); + } } |