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
```