* deploy a contract using our deterministic deployer. * The deployer is deployed (unless it is already deployed) * NOTE: this transaction will fail if already deployed. use getDeployedAddress to check it first. * @param initCode deployment code. can be a hex string or factory.getDeploymentT
(initCode: string | TransactionRequest, salt: BigNumberish = 0, gasLimit?: BigNumberish | 'estimate')
| 28 | * @param gasLimit gas limit or 'estimate' to use estimateGas. by default, calculate gas based on data size. |
| 29 | */ |
| 30 | async deploy (initCode: string | TransactionRequest, salt: BigNumberish = 0, gasLimit?: BigNumberish | 'estimate'): Promise<string> { |
| 31 | await this.deployFactory() |
| 32 | if (typeof initCode !== 'string') { |
| 33 | // eslint-disable-next-line @typescript-eslint/no-base-to-string |
| 34 | initCode = (initCode as TransactionRequest).data!.toString() |
| 35 | } |
| 36 | |
| 37 | const addr = Create2Factory.getDeployedAddress(initCode, salt) |
| 38 | if (await this.provider.getCode(addr).then(code => code.length) > 2) { |
| 39 | return addr |
| 40 | } |
| 41 | |
| 42 | const deployTx = { |
| 43 | to: Create2Factory.contractAddress, |
| 44 | data: this.getDeployTransactionCallData(initCode, salt) |
| 45 | } |
| 46 | if (gasLimit === 'estimate') { |
| 47 | gasLimit = await this.signer.estimateGas(deployTx) |
| 48 | } |
| 49 | |
| 50 | // manual estimation (its bit larger: we don't know actual deployed code size) |
| 51 | if (gasLimit === undefined) { |
| 52 | gasLimit = arrayify(initCode) |
| 53 | .map(x => x === 0 ? 4 : 16) |
| 54 | .reduce((sum, x) => sum + x) + |
| 55 | 200 * initCode.length / 2 + // actual is usually somewhat smaller (only deposited code, not entire constructor) |
| 56 | 6 * Math.ceil(initCode.length / 64) + // hash price. very minor compared to deposit costs |
| 57 | 32000 + |
| 58 | 21000 |
| 59 | |
| 60 | // deployer requires some extra gas |
| 61 | gasLimit = Math.floor(gasLimit * 64 / 63) |
| 62 | } |
| 63 | |
| 64 | await this.signer.sendTransaction({ ...deployTx, gasLimit }).then(async tx => tx.wait()) |
| 65 | |
| 66 | if (await this.provider.getCode(addr).then(code => code.length) === 2) { |
| 67 | throw new Error('failed to deploy') |
| 68 | } |
| 69 | return addr |
| 70 | } |
| 71 | |
| 72 | getDeployTransactionCallData (initCode: string, salt: BigNumberish = 0): string { |
| 73 | const saltBytes32 = hexZeroPad(hexlify(salt), 32) |
no test coverage detected