0
# Account Management
1
2
Manage test accounts, balances, and nonces without requiring private keys. Essential for testing scenarios involving specific addresses, high-value accounts, or complex multi-account interactions.
3
4
## Capabilities
5
6
### Impersonate Account
7
8
Allows the test environment to sign transactions as any address without needing the private key.
9
10
```typescript { .api }
11
/**
12
* Allows Hardhat Network to sign transactions as the given address
13
* @param address The address to impersonate (can be any valid Ethereum address)
14
* @returns Promise that resolves once the account is impersonated
15
*/
16
impersonateAccount(address: string): Promise<void>;
17
```
18
19
**Usage Example:**
20
21
```typescript
22
import { network } from "hardhat";
23
24
const { networkHelpers } = await network.connect();
25
26
// Impersonate a whale address or specific account
27
const whaleAddress = "0x742d35Cc6635C0532925a3b8D23CAaF803C5C1b7";
28
await networkHelpers.impersonateAccount(whaleAddress);
29
30
// Now can send transactions as this address
31
const whale = await ethers.getSigner(whaleAddress);
32
const tx = await whale.sendTransaction({
33
to: "0x123...",
34
value: ethers.parseEther("100")
35
});
36
```
37
38
### Stop Impersonating Account
39
40
Disables transaction signing for a previously impersonated address.
41
42
```typescript { .api }
43
/**
44
* Stops Hardhat Network from impersonating the given address
45
* @param address The address to stop impersonating
46
* @returns Promise that resolves once impersonation is stopped
47
*/
48
stopImpersonatingAccount(address: string): Promise<void>;
49
```
50
51
**Usage Example:**
52
53
```typescript
54
const { networkHelpers } = await network.connect();
55
56
const address = "0x742d35Cc6635C0532925a3b8D23CAaF803C5C1b7";
57
58
// Start impersonation
59
await networkHelpers.impersonateAccount(address);
60
61
// Use the account...
62
const signer = await ethers.getSigner(address);
63
await signer.sendTransaction({ /* ... */ });
64
65
// Stop impersonation when done
66
await networkHelpers.stopImpersonatingAccount(address);
67
```
68
69
### Set Balance
70
71
Sets the ETH balance for any address, useful for funding test accounts or simulating specific balance conditions.
72
73
```typescript { .api }
74
/**
75
* Sets the balance for the given address
76
* @param address The address whose balance will be updated
77
* @param balance The new balance to set in wei (can be number, bigint, or string)
78
* @returns Promise that resolves once the balance has been set
79
*/
80
setBalance(address: string, balance: NumberLike): Promise<void>;
81
```
82
83
**Usage Examples:**
84
85
```typescript
86
const { networkHelpers } = await network.connect();
87
88
// Set balance to 1000 ETH
89
await networkHelpers.setBalance(
90
"0x123...",
91
ethers.parseEther("1000")
92
);
93
94
// Set balance using bigint
95
await networkHelpers.setBalance(
96
"0x456...",
97
1000000000000000000n // 1 ETH in wei
98
);
99
100
// Set balance to zero
101
await networkHelpers.setBalance("0x789...", 0);
102
```
103
104
### Set Nonce
105
106
Modifies an account's nonce, useful for testing transaction ordering or simulating specific account states.
107
108
```typescript { .api }
109
/**
110
* Modifies an account's nonce by overwriting it
111
* @param address The address whose nonce is to be changed
112
* @param nonce The new nonce value
113
* @returns Promise that resolves once the nonce is set
114
*/
115
setNonce(address: string, nonce: NumberLike): Promise<void>;
116
```
117
118
**Usage Examples:**
119
120
```typescript
121
const { networkHelpers } = await network.connect();
122
123
// Set nonce to specific value
124
await networkHelpers.setNonce("0x123...", 42);
125
126
// Reset nonce to zero
127
await networkHelpers.setNonce("0x456...", 0);
128
129
// Set high nonce for testing
130
await networkHelpers.setNonce("0x789...", 1000000);
131
```
132
133
## Account Management Patterns
134
135
### Whale Testing
136
137
```typescript
138
it("should work with whale account", async () => {
139
const { networkHelpers } = await network.connect();
140
141
// Use a known whale address
142
const whaleAddress = "0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503";
143
144
// Give the whale some ETH and impersonate
145
await networkHelpers.setBalance(whaleAddress, ethers.parseEther("1000"));
146
await networkHelpers.impersonateAccount(whaleAddress);
147
148
const whale = await ethers.getSigner(whaleAddress);
149
150
// Whale can now interact with contracts
151
const contract = await ethers.getContractAt("MyContract", contractAddress);
152
await contract.connect(whale).largeTransaction({ value: ethers.parseEther("100") });
153
154
// Clean up
155
await networkHelpers.stopImpersonatingAccount(whaleAddress);
156
});
157
```
158
159
### Multi-Account Testing
160
161
```typescript
162
it("should handle multiple impersonated accounts", async () => {
163
const { networkHelpers } = await network.connect();
164
165
const accounts = [
166
"0x742d35Cc6635C0532925a3b8D23CAaF803C5C1b7",
167
"0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503",
168
"0x8ba1f109551bD432803012645Hac136c4D6eF81E"
169
];
170
171
// Set up all accounts
172
for (const account of accounts) {
173
await networkHelpers.setBalance(account, ethers.parseEther("100"));
174
await networkHelpers.impersonateAccount(account);
175
}
176
177
// Get signers for all accounts
178
const signers = await Promise.all(
179
accounts.map(addr => ethers.getSigner(addr))
180
);
181
182
// Use accounts for multi-sig or voting scenarios
183
const multiSig = await ethers.getContractAt("MultiSig", multiSigAddress);
184
185
for (const signer of signers) {
186
await multiSig.connect(signer).vote(1, true);
187
}
188
189
// Execute multi-sig transaction
190
await multiSig.connect(signers[0]).execute(1);
191
});
192
```
193
194
### Nonce Management for Transaction Ordering
195
196
```typescript
197
it("should control transaction ordering with nonces", async () => {
198
const { networkHelpers } = await network.connect();
199
200
const address = "0x123...";
201
await networkHelpers.setBalance(address, ethers.parseEther("10"));
202
await networkHelpers.impersonateAccount(address);
203
204
// Reset nonce to ensure predictable ordering
205
await networkHelpers.setNonce(address, 0);
206
207
const signer = await ethers.getSigner(address);
208
209
// Send transactions in specific order
210
const tx1 = await signer.sendTransaction({
211
to: "0x456...",
212
value: ethers.parseEther("1"),
213
nonce: 0
214
});
215
216
const tx2 = await signer.sendTransaction({
217
to: "0x789...",
218
value: ethers.parseEther("1"),
219
nonce: 1
220
});
221
222
// Both transactions will be mined in order
223
await Promise.all([tx1.wait(), tx2.wait()]);
224
});
225
```
226
227
### Contract Owner Simulation
228
229
```typescript
230
it("should test as contract owner", async () => {
231
const { networkHelpers } = await network.connect();
232
233
// Deploy contract
234
const contract = await ethers.deployContract("OwnableContract");
235
const originalOwner = await contract.owner();
236
237
// Impersonate the original owner
238
await networkHelpers.impersonateAccount(originalOwner);
239
await networkHelpers.setBalance(originalOwner, ethers.parseEther("1"));
240
241
const ownerSigner = await ethers.getSigner(originalOwner);
242
243
// Execute owner-only functions
244
await contract.connect(ownerSigner).setNewParameter(42);
245
await contract.connect(ownerSigner).transferOwnership("0x123...");
246
247
// Verify changes
248
expect(await contract.getParameter()).to.equal(42);
249
expect(await contract.owner()).to.equal("0x123...");
250
});
251
```
252
253
### Balance Manipulation for Edge Cases
254
255
```typescript
256
it("should handle insufficient balance scenarios", async () => {
257
const { networkHelpers } = await network.connect();
258
259
const poorAddress = "0x123...";
260
await networkHelpers.impersonateAccount(poorAddress);
261
262
// Set very low balance
263
await networkHelpers.setBalance(poorAddress, 1000); // 1000 wei
264
265
const poorSigner = await ethers.getSigner(poorAddress);
266
267
// Transaction should fail due to insufficient balance
268
await expect(
269
poorSigner.sendTransaction({
270
to: "0x456...",
271
value: ethers.parseEther("1") // Much more than available
272
})
273
).to.be.revertedWith("insufficient funds");
274
275
// Add more balance and retry
276
await networkHelpers.setBalance(poorAddress, ethers.parseEther("2"));
277
278
// Now should succeed
279
await expect(
280
poorSigner.sendTransaction({
281
to: "0x456...",
282
value: ethers.parseEther("1")
283
})
284
).to.not.be.reverted;
285
});
286
```