UNPKG

5.63 kBPlain TextView Raw
1import async from 'async'
2import { execution } from 'remix-lib'
3import Web3 from 'web3'
4import { compilationInterface } from 'types'
5
6/**
7 * @dev Deploy all contracts from compilation result
8 * @param compileResult compilation result
9 * @param web3 web3 object
10 * @param withDoubleGas If true, try deployment with gas double of estimation (used for Out-of-gas error only)
11 * @param callback Callback
12 */
13
14export function deployAll(compileResult: compilationInterface, web3: Web3, withDoubleGas: boolean, callback) {
15 let compiledObject = {}
16 let contracts = {}
17 let accounts: string[] = []
18
19 async.waterfall([
20 function getAccountList(next: Function) {
21 web3.eth.getAccounts((_err, _accounts) => {
22 accounts = _accounts
23 next()
24 })
25 },
26 function getContractData(next: Function) {
27 for (let contractFile in compileResult) {
28 for (let contractName in compileResult[contractFile]) {
29 let contract = compileResult[contractFile][contractName]
30
31 const className = contractName
32 const filename = contractFile
33
34 let abi = contract.abi
35 let code = contract.evm.bytecode.object
36
37 compiledObject[className] = {}
38 compiledObject[className].abi = abi
39 compiledObject[className].code = code
40 compiledObject[className].filename = filename
41 compiledObject[className].className = className
42 compiledObject[className].raw = contract
43
44 if (contractFile.endsWith('_test.sol')) {
45 compiledObject[className].isTest = true
46 }
47 }
48 }
49 next()
50 },
51 function determineContractsToDeploy(next: Function) {
52 let contractsToDeploy: string[] = ['Assert']
53 let allContracts = Object.keys(compiledObject)
54
55 for (let contractName of allContracts) {
56 if (contractName === 'Assert') {
57 continue
58 }
59 if (compiledObject[contractName].isTest) {
60 contractsToDeploy.push(contractName)
61 }
62 }
63 next(null, contractsToDeploy)
64 },
65 function deployContracts(contractsToDeploy: string[], next: Function) {
66 const deployRunner = (deployObject, contractObject, contractName, filename, callback) => {
67 deployObject.estimateGas().then((gasValue) => {
68 const gasBase = Math.ceil(gasValue * 1.2)
69 const gas = withDoubleGas ? gasBase * 2 : gasBase
70 deployObject.send({
71 from: accounts[0],
72 gas: gas
73 }).on('receipt', function (receipt) {
74 contractObject.options.address = receipt.contractAddress
75 contractObject.options.from = accounts[0]
76 contractObject.options.gas = 5000 * 1000
77 compiledObject[contractName].deployedAddress = receipt.contractAddress
78
79 contracts[contractName] = contractObject
80 contracts[contractName].filename = filename
81
82 callback(null, { result: { createdAddress: receipt.contractAddress } }) // TODO this will only work with JavaScriptV VM
83 }).on('error', function (err) {
84 console.error(err)
85 callback(err)
86 })
87 })
88 }
89
90 async.eachOfLimit(contractsToDeploy, 1, function (contractName, index, nextEach) {
91 let contract = compiledObject[contractName]
92 let encodeDataFinalCallback = (error, contractDeployData) => {
93 if (error) return nextEach(error)
94 try {
95 let contractObject = new web3.eth.Contract(contract.abi)
96 let deployObject = contractObject.deploy({arguments: [], data: '0x' + contractDeployData.dataHex})
97 deployRunner(deployObject, contractObject, contractName, contract.filename, (error) => { nextEach(error) })
98 } catch (e) {
99 throw e
100 }
101 }
102
103 let encodeDataStepCallback = (msg) => { console.dir(msg) }
104
105 let encodeDataDeployLibraryCallback = (libData, callback) => {
106 let abi = compiledObject[libData.data.contractName].abi
107 let code = compiledObject[libData.data.contractName].code
108 let libraryObject = new web3.eth.Contract(abi)
109 let deployObject = libraryObject.deploy({arguments: [], data: '0x' + code})
110 deployRunner(deployObject, libraryObject, libData.data.contractName, contract.filename, callback)
111 }
112
113 let funAbi = null // no need to set the abi for encoding the constructor
114 let params = '' // we suppose that the test contract does not have any param in the constructor
115 execution.txFormat.encodeConstructorCallAndDeployLibraries(contractName, contract.raw, compileResult, params, funAbi, encodeDataFinalCallback, encodeDataStepCallback, encodeDataDeployLibraryCallback)
116 }, function (err) {
117 if(err) next(err)
118 next(null, contracts)
119 })
120 }
121 ], callback)
122}