or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

contract-deployment.mdcontract-factories.mdcontract-interaction.mdindex.mdsigner-management.md

signer-management.mddocs/

0

# Signer Management

1

2

Enhanced signer functionality with SignerWithAddress class and helper functions for managing test accounts and impersonation. Provides streamlined access to signers in the Hardhat environment.

3

4

## Capabilities

5

6

### Get All Signers

7

8

Retrieves all available signers as SignerWithAddress instances, typically configured accounts in your Hardhat network.

9

10

```typescript { .api }

11

/**

12

* Gets all available signers as SignerWithAddress instances

13

* @returns Promise resolving to array of SignerWithAddress instances

14

*/

15

function getSigners(): Promise<SignerWithAddress[]>;

16

```

17

18

**Usage Examples:**

19

20

```typescript

21

import { ethers } from "hardhat";

22

23

// Get all signers

24

const signers = await ethers.getSigners();

25

const [deployer, user1, user2, ...others] = signers;

26

27

console.log("Available signers:", signers.length);

28

console.log("Deployer address:", deployer.address);

29

console.log("User1 address:", user1.address);

30

31

// Use signers for different roles

32

const contract = await ethers.deployContract("MyContract", [], deployer);

33

const contractAsUser1 = contract.connect(user1);

34

```

35

36

### Get Specific Signer

37

38

Retrieves a specific signer by address as a SignerWithAddress instance.

39

40

```typescript { .api }

41

/**

42

* Gets a specific signer by address as SignerWithAddress instance

43

* @param address - Ethereum address of the signer

44

* @returns Promise resolving to SignerWithAddress instance

45

*/

46

function getSigner(address: string): Promise<SignerWithAddress>;

47

```

48

49

**Usage Examples:**

50

51

```typescript

52

import { ethers } from "hardhat";

53

54

// Get signer by known address

55

const signerAddress = "0x1234567890123456789012345678901234567890";

56

const signer = await ethers.getSigner(signerAddress);

57

58

console.log("Signer address:", signer.address);

59

60

// Use specific signer

61

const contract = await ethers.getContractAt("MyContract", contractAddress, signer);

62

const tx = await contract.someFunction();

63

await tx.wait();

64

```

65

66

### Get Impersonated Signer

67

68

Creates an impersonated signer for testing purposes, allowing you to send transactions as any address.

69

70

```typescript { .api }

71

/**

72

* Creates an impersonated signer for testing (enables hardhat_impersonateAccount)

73

* @param address - Ethereum address to impersonate

74

* @returns Promise resolving to SignerWithAddress instance for the impersonated account

75

*/

76

function getImpersonatedSigner(address: string): Promise<SignerWithAddress>;

77

```

78

79

**Usage Examples:**

80

81

```typescript

82

import { ethers } from "hardhat";

83

84

// Impersonate a specific address (useful for testing)

85

const whaleAddress = "0x8ba1f109551bD432803012645Hac136c6348B618";

86

const whaleSigner = await ethers.getImpersonatedSigner(whaleAddress);

87

88

// Now you can send transactions as the whale

89

const token = await ethers.getContractAt("IERC20", tokenAddress, whaleSigner);

90

const balance = await token.balanceOf(whaleAddress);

91

console.log("Whale balance:", ethers.utils.formatEther(balance));

92

93

// Transfer tokens as the whale

94

const tx = await token.transfer(recipientAddress, ethers.utils.parseEther("100"));

95

await tx.wait();

96

```

97

98

## SignerWithAddress Class

99

100

Enhanced signer class that extends ethers.Signer with additional functionality and properties.

101

102

```typescript { .api }

103

/**

104

* Enhanced signer class that includes the address property

105

*/

106

class SignerWithAddress extends ethers.Signer {

107

/** The address of this signer (readonly) */

108

readonly address: string;

109

110

/**

111

* Creates a SignerWithAddress instance from a JsonRpcSigner

112

* @param signer - JsonRpcSigner to wrap

113

* @returns Promise resolving to SignerWithAddress instance

114

*/

115

static create(signer: ethers.providers.JsonRpcSigner): Promise<SignerWithAddress>;

116

117

/**

118

* Gets the address of this signer

119

* @returns Promise resolving to the signer's address

120

*/

121

getAddress(): Promise<string>;

122

123

/**

124

* Signs a message

125

* @param message - Message to sign

126

* @returns Promise resolving to signature string

127

*/

128

signMessage(message: string | ethers.utils.Bytes): Promise<string>;

129

130

/**

131

* Signs a transaction

132

* @param transaction - Transaction to sign

133

* @returns Promise resolving to signed transaction string

134

*/

135

signTransaction(

136

transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>

137

): Promise<string>;

138

139

/**

140

* Sends a transaction

141

* @param transaction - Transaction to send

142

* @returns Promise resolving to transaction response

143

*/

144

sendTransaction(

145

transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>

146

): Promise<ethers.providers.TransactionResponse>;

147

148

/**

149

* Connects this signer to a different provider

150

* @param provider - Provider to connect to

151

* @returns New SignerWithAddress instance connected to the provider

152

*/

153

connect(provider: ethers.providers.Provider): SignerWithAddress;

154

155

/**

156

* Signs typed data (EIP-712)

157

* @param params - Typed data parameters

158

* @returns Promise resolving to signature string

159

*/

160

_signTypedData(

161

...params: Parameters<ethers.providers.JsonRpcSigner["_signTypedData"]>

162

): Promise<string>;

163

164

/**

165

* Returns JSON representation of the signer

166

* @returns String representation including address

167

*/

168

toJSON(): string;

169

}

170

```

171

172

### SignerWithAddress Usage Examples

173

174

```typescript

175

import { ethers } from "hardhat";

176

177

// Get signers

178

const [deployer, user] = await ethers.getSigners();

179

180

// Access address directly (main advantage over regular ethers.Signer)

181

console.log("Deployer address:", deployer.address);

182

console.log("User address:", user.address);

183

184

// Sign messages

185

const message = "Hello, Ethereum!";

186

const signature = await user.signMessage(message);

187

console.log("Signature:", signature);

188

189

// Send transactions

190

const tx = await user.sendTransaction({

191

to: "0x1234567890123456789012345678901234567890",

192

value: ethers.utils.parseEther("1.0")

193

});

194

await tx.wait();

195

196

// Connect to different provider

197

const mainnetProvider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/...");

198

const userOnMainnet = user.connect(mainnetProvider);

199

```

200

201

## Common Signer Patterns

202

203

### Multi-Signer Contract Interactions

204

205

```typescript

206

import { ethers } from "hardhat";

207

208

async function multiSignerExample() {

209

const [owner, admin, user1, user2] = await ethers.getSigners();

210

211

// Deploy with owner

212

const contract = await ethers.deployContract("MultiSigWallet", [

213

[owner.address, admin.address],

214

2 // require 2 signatures

215

], owner);

216

217

// Different roles interact with contract

218

const contractAsAdmin = contract.connect(admin);

219

const contractAsUser1 = contract.connect(user1);

220

221

// Owner submits transaction

222

await contract.submitTransaction(user1.address, ethers.utils.parseEther("1"), "0x");

223

224

// Admin confirms transaction

225

await contractAsAdmin.confirmTransaction(0);

226

}

227

```

228

229

### Impersonation for Testing

230

231

```typescript

232

import { ethers, network } from "hardhat";

233

234

async function testWithImpersonation() {

235

// Impersonate a whale account

236

const whaleAddress = "0x8ba1f109551bD432803012645Hac136c6348B618";

237

238

// Fund the whale with some ETH for gas

239

await network.provider.send("hardhat_setBalance", [

240

whaleAddress,

241

"0x1000000000000000000", // 1 ETH

242

]);

243

244

const whale = await ethers.getImpersonatedSigner(whaleAddress);

245

246

// Use whale to interact with contracts

247

const token = await ethers.getContractAt("IERC20", tokenAddress, whale);

248

const balance = await token.balanceOf(whale.address);

249

250

if (balance.gt(0)) {

251

await token.transfer(testUserAddress, ethers.utils.parseEther("1000"));

252

}

253

}

254

```

255

256

### Signer Validation

257

258

```typescript

259

import { ethers } from "hardhat";

260

261

async function validateSigners() {

262

const signers = await ethers.getSigners();

263

264

if (signers.length === 0) {

265

throw new Error("No signers available");

266

}

267

268

// Check signer balances

269

for (let i = 0; i < signers.length; i++) {

270

const balance = await signers[i].getBalance();

271

console.log(`Signer ${i} (${signers[i].address}): ${ethers.utils.formatEther(balance)} ETH`);

272

273

if (balance.eq(0)) {

274

console.warn(`Signer ${i} has zero balance`);

275

}

276

}

277

278

return signers;

279

}

280

```

281

282

## Network Compatibility

283

284

### Local Development Networks

285

286

On Hardhat Network and other local networks, `getSigners()` returns the configured accounts:

287

288

```typescript

289

// hardhat.config.js

290

module.exports = {

291

networks: {

292

hardhat: {

293

accounts: {

294

count: 20,

295

accountsBalance: "10000000000000000000000" // 10000 ETH

296

}

297

}

298

}

299

};

300

```

301

302

### Live Networks

303

304

On live networks, signers are typically loaded from:

305

- Private keys in environment variables

306

- Hardware wallets

307

- Mnemonic phrases

308

309

```typescript

310

// Example configuration for live networks

311

const signers = await ethers.getSigners();

312

console.log("Available signers on mainnet:", signers.length);

313

314

// Always check you have the expected signer

315

if (signers.length === 0) {

316

throw new Error("No signers configured for this network");

317

}

318

```

319

320

## Error Handling

321

322

Signer functions can throw errors in the following cases:

323

324

- **No signers available**: When `getSigners()` returns an empty array

325

- **Invalid address**: When `getSigner()` or `getImpersonatedSigner()` receives an invalid address

326

- **Account not found**: When `getSigner()` is called with an address not in the available accounts

327

- **Impersonation failure**: When `getImpersonatedSigner()` fails to enable impersonation (network doesn't support it)

328

- **Insufficient balance**: When signers don't have enough ETH for gas

329

- **Network connection issues**: When unable to connect to the blockchain network