or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

contract-deployment.mdcontract-management.mdencoding-utilities.mdevent-handling.mdindex.mdmethod-execution.md

contract-deployment.mddocs/

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

```