or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

account-operations.mdblockchain-state.mdcryptographic-operations.mdevent-monitoring.mdgas-fee-management.mdindex.mdnetwork-information.mdsmart-contract-interaction.mdtransaction-management.mdtransaction-utilities.md

smart-contract-interaction.mddocs/

0

# Smart Contract Interaction

1

2

The smart contract interaction functionality provides methods to execute contract calls, estimate gas consumption, create access lists, and interact with smart contracts without state changes.

3

4

## Contract Calls

5

6

### call

7

8

Executes a read-only call to a smart contract method without creating a transaction on the blockchain.

9

10

```typescript { .api }

11

call(transaction?: TransactionCall, blockNumber?: BlockNumberOrTag, returnFormat?: DataFormat): Promise<Bytes>;

12

```

13

14

**Parameters:**

15

- `transaction`: Transaction call object with contract address, method data, and parameters

16

- `blockNumber`: Block number or tag to execute call against (defaults to "latest")

17

- `returnFormat`: Output format configuration

18

19

**Usage Example:**

20

```typescript

21

// Simple contract call - get total supply of an ERC20 token

22

const totalSupplyCall = {

23

to: "0x1234567890123456789012345678901234567890", // token contract address

24

data: "0x18160ddd" // totalSupply() method selector

25

};

26

27

const result = await eth.call(totalSupplyCall);

28

console.log("Total supply (raw):", result);

29

30

// Contract call with parameters - get balance of specific address

31

import { encodeFunctionCall } from "web3-eth-abi";

32

33

const balanceOfCall = {

34

to: "0x1234567890123456789012345678901234567890",

35

data: encodeFunctionCall({

36

name: "balanceOf",

37

type: "function",

38

inputs: [{ name: "owner", type: "address" }]

39

}, ["0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E"])

40

};

41

42

const balance = await eth.call(balanceOfCall);

43

console.log("Token balance:", balance);

44

45

// Historical state query

46

const historicalBalance = await eth.call(balanceOfCall, 15000000);

47

```

48

49

## Gas Estimation

50

51

### estimateGas

52

53

Estimates the amount of gas required to execute a transaction or contract call.

54

55

```typescript { .api }

56

estimateGas(transaction?: TransactionCall, blockNumber?: BlockNumberOrTag, returnFormat?: DataFormat): Promise<Numbers>;

57

```

58

59

**Usage Example:**

60

```typescript

61

// Estimate gas for token transfer

62

const transferGasEstimate = await eth.estimateGas({

63

from: "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E",

64

to: "0x1234567890123456789012345678901234567890", // token contract

65

data: encodeFunctionCall({

66

name: "transfer",

67

type: "function",

68

inputs: [

69

{ name: "to", type: "address" },

70

{ name: "amount", type: "uint256" }

71

]

72

}, [

73

"0x8ba1f109551bD432803012645Hac136c1c1b6c5E", // recipient

74

"1000000000000000000" // 1 token (assuming 18 decimals)

75

])

76

});

77

78

console.log(`Estimated gas for transfer: ${transferGasEstimate}`);

79

80

// Estimate gas for contract deployment

81

const deploymentGasEstimate = await eth.estimateGas({

82

from: "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E",

83

data: "0x608060405234801561001057600080fd5b50..." // contract bytecode

84

});

85

86

console.log(`Estimated gas for deployment: ${deploymentGasEstimate}`);

87

88

// Add buffer to gas estimate (common practice)

89

const gasWithBuffer = Math.floor(Number(transferGasEstimate) * 1.2); // 20% buffer

90

```

91

92

## EIP-2930 Access Lists

93

94

### createAccessList

95

96

Generates an access list for EIP-2930 transactions to reduce gas costs by pre-declaring storage access.

97

98

```typescript { .api }

99

createAccessList(transaction?: TransactionForAccessList, blockNumber?: BlockNumberOrTag, returnFormat?: DataFormat): Promise<AccessListResult>;

100

```

101

102

**Usage Example:**

103

```typescript

104

// Create access list for token transfer

105

const accessListResult = await eth.createAccessList({

106

from: "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E",

107

to: "0x1234567890123456789012345678901234567890",

108

data: encodeFunctionCall({

109

name: "transfer",

110

type: "function",

111

inputs: [

112

{ name: "to", type: "address" },

113

{ name: "amount", type: "uint256" }

114

]

115

}, [

116

"0x8ba1f109551bD432803012645Hac136c1c1b6c5E",

117

"1000000000000000000"

118

])

119

});

120

121

console.log("Access list:", accessListResult.accessList);

122

console.log("Gas used with access list:", accessListResult.gasUsed);

123

124

// Use access list in transaction to save gas

125

const receipt = await eth.sendTransaction({

126

from: "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E",

127

to: "0x1234567890123456789012345678901234567890",

128

data: encodeFunctionCall(/* ... */),

129

accessList: accessListResult.accessList,

130

type: 1 // EIP-2930 transaction type

131

});

132

```

133

134

## Contract Interaction Patterns

135

136

### ERC20 Token Interactions

137

138

```typescript

139

// Common ERC20 interactions

140

class ERC20Helper {

141

constructor(private eth: Web3Eth, private tokenAddress: Address) {}

142

143

async totalSupply(): Promise<string> {

144

const result = await this.eth.call({

145

to: this.tokenAddress,

146

data: "0x18160ddd" // totalSupply()

147

});

148

return result;

149

}

150

151

async balanceOf(owner: Address): Promise<string> {

152

const result = await this.eth.call({

153

to: this.tokenAddress,

154

data: encodeFunctionCall({

155

name: "balanceOf",

156

type: "function",

157

inputs: [{ name: "owner", type: "address" }]

158

}, [owner])

159

});

160

return result;

161

}

162

163

async estimateTransfer(from: Address, to: Address, amount: string): Promise<number> {

164

const gasEstimate = await this.eth.estimateGas({

165

from,

166

to: this.tokenAddress,

167

data: encodeFunctionCall({

168

name: "transfer",

169

type: "function",

170

inputs: [

171

{ name: "to", type: "address" },

172

{ name: "amount", type: "uint256" }

173

]

174

}, [to, amount])

175

});

176

return Number(gasEstimate);

177

}

178

}

179

```

180

181

### Contract State Queries

182

183

```typescript

184

// Query multiple contract states efficiently

185

async function getContractStates(contractAddress: Address) {

186

// Prepare multiple calls

187

const calls = [

188

{ to: contractAddress, data: "0x18160ddd" }, // totalSupply()

189

{ to: contractAddress, data: "0x313ce567" }, // decimals()

190

{ to: contractAddress, data: "0x95d89b41" }, // symbol()

191

{ to: contractAddress, data: "0x06fdde03" } // name()

192

];

193

194

// Execute all calls in parallel

195

const results = await Promise.all(

196

calls.map(call => eth.call(call))

197

);

198

199

return {

200

totalSupply: results[0],

201

decimals: results[1],

202

symbol: results[2],

203

name: results[3]

204

};

205

}

206

```

207

208

### View Function Helpers

209

210

```typescript

211

// Helper for common view function patterns

212

async function callViewFunction(

213

contractAddress: Address,

214

functionAbi: any,

215

params: any[] = [],

216

blockNumber?: BlockNumberOrTag

217

) {

218

const data = encodeFunctionCall(functionAbi, params);

219

220

return await eth.call({

221

to: contractAddress,

222

data

223

}, blockNumber);

224

}

225

226

// Usage example

227

const ownerResult = await callViewFunction(

228

"0x1234567890123456789012345678901234567890",

229

{

230

name: "owner",

231

type: "function",

232

inputs: [],

233

outputs: [{ name: "", type: "address" }]

234

}

235

);

236

```

237

238

## Error Handling

239

240

```typescript

241

// Handle contract call errors

242

async function safeContractCall(transaction: TransactionCall) {

243

try {

244

const result = await eth.call(transaction);

245

return { success: true, data: result };

246

} catch (error) {

247

// Check if it's a revert with reason

248

if (error.message.includes("execution reverted")) {

249

return {

250

success: false,

251

error: "Contract execution reverted",

252

details: error.message

253

};

254

}

255

256

// Other errors (invalid address, network issues, etc.)

257

return {

258

success: false,

259

error: "Call failed",

260

details: error.message

261

};

262

}

263

}

264

```

265

266

## Core Types

267

268

```typescript { .api }

269

interface TransactionCall {

270

from?: Address;

271

to: Address;

272

gas?: Numbers;

273

gasPrice?: Numbers;

274

maxFeePerGas?: Numbers;

275

maxPriorityFeePerGas?: Numbers;

276

value?: Numbers;

277

data?: Bytes;

278

type?: Numbers;

279

accessList?: AccessList;

280

}

281

282

interface TransactionForAccessList {

283

from?: Address;

284

to?: Address;

285

gas?: Numbers;

286

gasPrice?: Numbers;

287

maxFeePerGas?: Numbers;

288

maxPriorityFeePerGas?: Numbers;

289

value?: Numbers;

290

data?: Bytes;

291

}

292

293

interface AccessList {

294

address: Address;

295

storageKeys: HexString32Bytes[];

296

}

297

298

interface AccessListResult {

299

accessList: AccessList[];

300

gasUsed: HexString;

301

}

302

303

type Address = HexString20Bytes;

304

type Numbers = HexString | number | bigint;

305

type Bytes = HexString;

306

type BlockNumberOrTag = Numbers | "latest" | "earliest" | "pending" | "safe" | "finalized";

307

308

interface DataFormat {

309

number: NumberFormat;

310

bytes: BytesFormat;

311

}

312

```