0
# Contract Deployment
1
2
Deploy new smart contracts with constructor arguments and deployment options using the DeployerMethodClass.
3
4
## Capabilities
5
6
### DeployerMethodClass
7
8
Handles contract deployment operations with type-safe constructor argument handling.
9
10
```typescript { .api }
11
/**
12
* Class for deploying contracts with constructor arguments
13
*/
14
class DeployerMethodClass<FullContractAbi extends ContractAbi> {
15
constructor(
16
parentContext: Web3Context<EthExecutionAPI>,
17
parentOptions: ContractOptions & { address: undefined },
18
contractAbi: FullContractAbi
19
);
20
21
/**
22
* Deploy a new contract instance
23
* @param options - Deployment options including bytecode and constructor arguments
24
* @returns Deployment method object with send, estimateGas, and createAccessList
25
*/
26
deploy(options: {
27
/** Contract bytecode (hex string) */
28
data: Bytes;
29
/** Constructor arguments (if contract has constructor) */
30
arguments?: ContractConstructorArgs<FullContractAbi>;
31
}): {
32
/** Deploy the contract and return a PromiEvent resolving to Contract instance */
33
send(options?: PayableTxOptions): ContractDeploySend<FullContractAbi>;
34
/** Estimate gas required for deployment */
35
estimateGas(options?: PayableTxOptions): Promise<number>;
36
/** Create access list for deployment transaction */
37
createAccessList(options?: PayableTxOptions): Promise<AccessListResult>;
38
};
39
}
40
```
41
42
### Contract Deploy Method
43
44
Access deployment functionality through the contract's `deploy` method.
45
46
```typescript { .api }
47
class Contract<Abi extends ContractAbi> {
48
/**
49
* Deploy the contract to the blockchain
50
* @param deployOptions - Deployment options including bytecode and constructor arguments
51
* @returns DeployerMethodClass instance for deployment operations
52
*/
53
deploy(deployOptions?: {
54
/** Contract bytecode */
55
data?: HexString;
56
/** Alternative to data */
57
input?: HexString;
58
/** Constructor arguments */
59
arguments?: ContractConstructorArgs<Abi>;
60
}): DeployerMethodClass<Abi>;
61
}
62
```
63
64
### Deployment Return Types
65
66
```typescript { .api }
67
/**
68
* PromiEvent for contract deployment that resolves to deployed Contract instance
69
*/
70
type ContractDeploySend<Abi extends ContractAbi> = Web3PromiEvent<
71
Contract<Abi>,
72
SendTransactionEvents<DataFormat>
73
>;
74
75
/**
76
* Constructor arguments type based on contract ABI
77
*/
78
type ContractConstructorArgs<Abi extends ContractAbi> =
79
Abi extends readonly [infer A, ...any[]]
80
? A extends AbiConstructorFragment
81
? ContractMethodInputParameters<A['inputs']>
82
: never
83
: never;
84
```
85
86
## Usage Examples
87
88
### Basic Contract Deployment
89
90
```typescript
91
import { Contract } from "web3-eth-contract";
92
93
// Contract ABI with constructor
94
const abi = [
95
{
96
inputs: [
97
{ name: "_initialValue", type: "uint256" },
98
{ name: "_name", type: "string" }
99
],
100
stateMutability: "nonpayable",
101
type: "constructor"
102
},
103
{
104
inputs: [],
105
name: "getValue",
106
outputs: [{ name: "", type: "uint256" }],
107
stateMutability: "view",
108
type: "function"
109
}
110
] as const;
111
112
// Contract bytecode (normally from compilation)
113
const bytecode = "0x608060405234801561001057600080fd5b506040516101a03803806101a0833981810160405281019061003291906100b7565b81600081905550806001908051906020019061004f9291906100fe565b50505061027a565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61007e8161006b565b811461008957600080fd5b50565b60008151905061009b81610075565b92915050565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6100fd826100b4565b810181811067ffffffffffffffff8211171561011c5761011b6100c5565b5b80604052505050565b600061012f610056565b905061013b82826100f4565b919050565b600067ffffffffffffffff82111561015b5761015a6100c5565b5b610164826100b4565b9050602081019050919050565b60005b8381101561018f578082015181840152602081019050610174565b8381111561019e576000848401525b50505050565b60006101b76101b284610140565b610125565b9050828152602081018484840111156101d3576101d26100af565b5b6101de848285610171565b509392505050565b600082601f8301126101fb576101fa6100aa565b5b815161020b8482602086016101a4565b91505092915050565b60008060408385031215610227576102266100fe565b5b600061023585828601610089565b925050602083015167ffffffffffffffff8111156102565761025561010b565b5b610262858286016101e6565b9150509250929050565b610108806102796000396000f3fe";
114
115
// Create contract instance (no address yet)
116
const contract = new Contract(abi);
117
118
// Deploy with constructor arguments
119
const deployedContract = await contract.deploy({
120
data: bytecode,
121
arguments: [42, "MyContract"] // _initialValue: 42, _name: "MyContract"
122
}).send({
123
from: "0x1234567890123456789012345678901234567890",
124
gas: 1000000,
125
gasPrice: "20000000000"
126
});
127
128
console.log("Contract deployed at:", deployedContract.options.address);
129
130
// Use the deployed contract
131
const value = await deployedContract.methods.getValue().call();
132
console.log("Initial value:", value); // Should be 42
133
```
134
135
### Deployment with Event Monitoring
136
137
```typescript
138
// Monitor deployment progress
139
const deploymentPromiEvent = contract.deploy({
140
data: bytecode,
141
arguments: [100, "TestContract"]
142
}).send({
143
from: "0x1234567890123456789012345678901234567890",
144
gas: 1500000
145
});
146
147
deploymentPromiEvent
148
.on('transactionHash', (hash) => {
149
console.log('Deployment transaction sent:', hash);
150
})
151
.on('receipt', (receipt) => {
152
console.log('Deployment confirmed in block:', receipt.blockNumber);
153
console.log('Gas used:', receipt.gasUsed);
154
})
155
.on('confirmation', (confirmationNumber, receipt) => {
156
console.log('Confirmation', confirmationNumber, 'received');
157
})
158
.on('error', (error) => {
159
console.error('Deployment failed:', error);
160
});
161
162
try {
163
const deployedContract = await deploymentPromiEvent;
164
console.log('Deployment successful!');
165
console.log('Contract address:', deployedContract.options.address);
166
} catch (error) {
167
console.error('Deployment error:', error);
168
}
169
```
170
171
### Gas Estimation for Deployment
172
173
```typescript
174
// Estimate gas before deployment
175
const gasEstimate = await contract.deploy({
176
data: bytecode,
177
arguments: [42, "MyContract"]
178
}).estimateGas({
179
from: "0x1234567890123456789012345678901234567890"
180
});
181
182
console.log('Estimated gas for deployment:', gasEstimate);
183
184
// Deploy with estimated gas plus buffer
185
const deployedContract = await contract.deploy({
186
data: bytecode,
187
arguments: [42, "MyContract"]
188
}).send({
189
from: "0x1234567890123456789012345678901234567890",
190
gas: Math.floor(gasEstimate * 1.2) // Add 20% buffer
191
});
192
```
193
194
### Access List for Deployment
195
196
```typescript
197
// Create access list for deployment (EIP-2930)
198
const accessList = await contract.deploy({
199
data: bytecode,
200
arguments: [42, "MyContract"]
201
}).createAccessList({
202
from: "0x1234567890123456789012345678901234567890"
203
});
204
205
console.log('Access list:', accessList.accessList);
206
console.log('Gas with access list:', accessList.gasUsed);
207
208
// Deploy with access list
209
const deployedContract = await contract.deploy({
210
data: bytecode,
211
arguments: [42, "MyContract"]
212
}).send({
213
from: "0x1234567890123456789012345678901234567890",
214
accessList: accessList.accessList,
215
type: '0x1' // EIP-2930 transaction type
216
});
217
```
218
219
### Constructor Without Arguments
220
221
```typescript
222
// Contract with no constructor arguments
223
const simpleAbi = [
224
{
225
inputs: [],
226
stateMutability: "nonpayable",
227
type: "constructor"
228
},
229
{
230
inputs: [],
231
name: "getValue",
232
outputs: [{ name: "", type: "uint256" }],
233
stateMutability: "view",
234
type: "function"
235
}
236
] as const;
237
238
const simpleContract = new Contract(simpleAbi);
239
240
// Deploy without arguments
241
const deployedSimpleContract = await simpleContract.deploy({
242
data: simpleBytecode
243
// No arguments needed
244
}).send({
245
from: "0x1234567890123456789012345678901234567890",
246
gas: 500000
247
});
248
```
249
250
### Complex Constructor Arguments
251
252
```typescript
253
// Contract with complex constructor
254
const complexAbi = [
255
{
256
inputs: [
257
{ name: "_addresses", type: "address[]" },
258
{ name: "_amounts", type: "uint256[]" },
259
{ name: "_config", type: "tuple",
260
components: [
261
{ name: "enabled", type: "bool" },
262
{ name: "threshold", type: "uint256" }
263
]
264
}
265
],
266
stateMutability: "nonpayable",
267
type: "constructor"
268
}
269
] as const;
270
271
const complexContract = new Contract(complexAbi);
272
273
// Deploy with complex arguments
274
const deployedComplexContract = await complexContract.deploy({
275
data: complexBytecode,
276
arguments: [
277
["0x1111...", "0x2222...", "0x3333..."], // address array
278
[100, 200, 300], // uint256 array
279
{ enabled: true, threshold: 50 } // tuple/struct
280
]
281
}).send({
282
from: "0x1234567890123456789012345678901234567890",
283
gas: 2000000
284
});
285
```
286
287
### Error Handling
288
289
```typescript
290
async function deployWithErrorHandling() {
291
try {
292
// Validate inputs before deployment
293
if (!bytecode || !bytecode.startsWith('0x')) {
294
throw new Error('Invalid bytecode format');
295
}
296
297
// Estimate gas first
298
const gasEstimate = await contract.deploy({
299
data: bytecode,
300
arguments: [42, "TestContract"]
301
}).estimateGas({
302
from: deployer
303
});
304
305
// Deploy with proper error handling
306
const deployedContract = await contract.deploy({
307
data: bytecode,
308
arguments: [42, "TestContract"]
309
}).send({
310
from: deployer,
311
gas: Math.floor(gasEstimate * 1.3),
312
gasPrice: await web3.eth.getGasPrice()
313
});
314
315
console.log('Deployment successful:', deployedContract.options.address);
316
return deployedContract;
317
318
} catch (error) {
319
if (error.message.includes('revert')) {
320
console.error('Contract deployment reverted:', error.message);
321
} else if (error.message.includes('out of gas')) {
322
console.error('Deployment failed due to insufficient gas');
323
} else {
324
console.error('Deployment failed:', error.message);
325
}
326
throw error;
327
}
328
}
329
```
330
331
### Deployment with Custom Options
332
333
```typescript
334
// Deploy with custom transaction options
335
const deployedContract = await contract.deploy({
336
data: bytecode,
337
arguments: [42, "MyContract"]
338
}).send({
339
from: "0x1234567890123456789012345678901234567890",
340
gas: 1000000,
341
gasPrice: "30000000000", // 30 gwei
342
value: "0", // No ether sent (unless constructor is payable)
343
nonce: await web3.eth.getTransactionCount(deployer),
344
// EIP-1559 options (alternative to gasPrice)
345
// maxFeePerGas: "40000000000",
346
// maxPriorityFeePerGas: "2000000000"
347
});
348
```
349
350
### Contract Factory Pattern
351
352
```typescript
353
class ContractFactory {
354
private contract: Contract<typeof abi>;
355
private bytecode: string;
356
357
constructor(abi: typeof abi, bytecode: string) {
358
this.contract = new Contract(abi);
359
this.bytecode = bytecode;
360
}
361
362
async deploy(
363
constructorArgs: any[],
364
options: PayableTxOptions
365
): Promise<Contract<typeof abi>> {
366
return await this.contract.deploy({
367
data: this.bytecode,
368
arguments: constructorArgs
369
}).send(options);
370
}
371
372
async estimateDeploymentGas(
373
constructorArgs: any[],
374
from: string
375
): Promise<number> {
376
return await this.contract.deploy({
377
data: this.bytecode,
378
arguments: constructorArgs
379
}).estimateGas({ from });
380
}
381
}
382
383
// Usage
384
const factory = new ContractFactory(abi, bytecode);
385
const deployedContract = await factory.deploy(
386
[42, "MyContract"],
387
{ from: deployer, gas: 1000000 }
388
);
389
```