or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

argument-utilities.mdbalance-matchers.mdbignumber-support.mdevent-matchers.mdindex.mdpanic-codes.mdrevert-matchers.mdvalidation-matchers.md

argument-utilities.mddocs/

0

# Argument Matching Utilities

1

2

Helper functions for flexible argument matching in event and error testing scenarios, allowing partial validation of complex arguments.

3

4

## Import

5

6

```typescript

7

import { anyValue, anyUint } from "@nomicfoundation/hardhat-chai-matchers/withArgs";

8

```

9

10

## Capabilities

11

12

### Any Value Matcher

13

14

A predicate function that accepts any value as a positive match, useful when you want to ignore specific arguments in event or error validation.

15

16

```typescript { .api }

17

/**

18

* Predicate that matches any argument value

19

* @returns boolean - always returns true for any input

20

*/

21

function anyValue(): boolean;

22

```

23

24

**Usage Examples:**

25

26

```typescript

27

import { expect } from "chai";

28

import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs";

29

30

// Test event emission ignoring specific arguments

31

await expect(contract.mint(user, 1000, metadata))

32

.to.emit(contract, "Mint")

33

.withArgs(user.address, 1000, anyValue); // Ignore metadata argument

34

35

// Test custom error with partial argument matching

36

await expect(contract.complexOperation(data))

37

.to.be.revertedWithCustomError(contract, "OperationFailed")

38

.withArgs(anyValue, 404, "Invalid data"); // Ignore first argument

39

40

// Multiple anyValue uses

41

await expect(contract.multiParamEvent())

42

.to.emit(contract, "ComplexEvent")

43

.withArgs(anyValue, anyValue, "important", anyValue); // Only validate 3rd argument

44

45

// Mixed with specific values

46

await expect(token.transfer(recipient, amount))

47

.to.emit(token, "Transfer")

48

.withArgs(anyValue, recipient.address, anyValue); // Only care about recipient

49

```

50

51

### Any Unsigned Integer Matcher

52

53

A predicate function that validates the argument is a valid unsigned integer (positive number or zero), while accepting any specific value within that constraint.

54

55

```typescript { .api }

56

/**

57

* Predicate that matches any unsigned integer value

58

* @param i - The value to validate as unsigned integer

59

* @returns boolean - true if value is valid unsigned integer

60

* @throws AssertionError if value is negative or not a number

61

*/

62

function anyUint(i: any): boolean;

63

```

64

65

**Usage Examples:**

66

67

```typescript

68

import { anyUint } from "@nomicfoundation/hardhat-chai-matchers/withArgs";

69

70

// Test event with any positive amount

71

await expect(contract.deposit({ value: ethers.parseEther("1") }))

72

.to.emit(contract, "Deposit")

73

.withArgs(user.address, anyUint); // Any positive deposit amount

74

75

// Test token transfer with amount validation

76

await expect(token.mint(recipient, 1000))

77

.to.emit(token, "Mint")

78

.withArgs(recipient.address, anyUint); // Validates amount is positive

79

80

// Combined with other matchers

81

await expect(contract.updateBalance(user, newBalance))

82

.to.emit(contract, "BalanceUpdated")

83

.withArgs(user.address, anyUint, anyValue); // Balance positive, timestamp ignored

84

85

// Works with BigInt values

86

const largeAmount = ethers.parseEther("1000000");

87

await expect(contract.largeTransfer(recipient, largeAmount))

88

.to.emit(contract, "Transfer")

89

.withArgs(anyValue, recipient.address, anyUint); // Validates BigInt amount

90

```

91

92

### Type Validation Behavior

93

94

```typescript

95

// anyUint accepts regular numbers (>= 0)

96

anyUint(0); // ✅ true

97

anyUint(42); // ✅ true

98

anyUint(1000); // ✅ true

99

100

// anyUint accepts BigInt values (>= 0n)

101

anyUint(0n); // ✅ true

102

anyUint(42n); // ✅ true

103

anyUint(ethers.parseEther("1")); // ✅ true

104

105

// anyUint rejects negative values

106

anyUint(-1); // ❌ throws AssertionError

107

anyUint(-42n); // ❌ throws AssertionError

108

109

// anyUint rejects non-numeric values

110

anyUint("123"); // ❌ throws AssertionError

111

anyUint(null); // ❌ throws AssertionError

112

anyUint({}); // ❌ throws AssertionError

113

```

114

115

## Advanced Usage Patterns

116

117

### Complex Event Validation

118

119

```typescript

120

// Validate multi-parameter events with mixed requirements

121

await expect(dex.swap(tokenA, tokenB, amountIn))

122

.to.emit(dex, "Swap")

123

.withArgs(

124

user.address, // Specific user

125

tokenA.address, // Specific input token

126

tokenB.address, // Specific output token

127

anyUint, // Any valid input amount

128

anyUint, // Any valid output amount

129

anyValue // Ignore price/slippage data

130

);

131

132

// Validate fee distribution events

133

await expect(protocol.distributeFees())

134

.to.emit(protocol, "FeesDistributed")

135

.withArgs(

136

anyUint, // Treasury fee (any positive amount)

137

anyUint, // Dev fee (any positive amount)

138

anyUint, // Staking rewards (any positive amount)

139

anyValue // Ignore timestamp

140

);

141

```

142

143

### Error Argument Validation

144

145

```typescript

146

// Test custom errors with flexible argument matching

147

await expect(lending.borrow(amount, collateral))

148

.to.be.revertedWithCustomError(lending, "InsufficientCollateral")

149

.withArgs(

150

user.address, // Specific borrower

151

anyUint, // Any requested amount

152

anyUint, // Any collateral value

153

anyValue // Ignore collateral ratio calculation

154

);

155

156

// Validate access control errors

157

await expect(contract.adminFunction())

158

.to.be.revertedWithCustomError(contract, "AccessDenied")

159

.withArgs(user.address, "ADMIN_ROLE", anyValue); // Ignore additional context

160

```

161

162

### Combining Multiple Utilities

163

164

```typescript

165

// Complex validation combining both utilities

166

await expect(marketplace.createListing(nft, price, duration))

167

.to.emit(marketplace, "ListingCreated")

168

.withArgs(

169

anyUint, // Listing ID (any positive ID)

170

user.address, // Specific seller

171

nft.address, // Specific NFT contract

172

anyUint, // Token ID (any valid token)

173

anyUint, // Price (any positive price)

174

anyValue // Ignore expiration timestamp

175

);

176

177

// Batch operation validation

178

await expect(contract.batchProcess(items))

179

.to.emit(contract, "BatchProcessed")

180

.withArgs(

181

anyUint, // Batch ID

182

anyUint, // Items processed count

183

anyUint, // Success count

184

anyValue, // Ignore failure details

185

anyValue // Ignore processing metadata

186

);

187

```

188

189

## Error Messages

190

191

The utilities provide clear error messages when validation fails:

192

193

```typescript

194

// anyUint with negative number:

195

// "anyUint expected its argument to be an unsigned integer, but it was negative, with value -42"

196

197

// anyUint with non-numeric type:

198

// "anyUint expected its argument to be an integer, but its type was 'string'"

199

200

// anyUint with negative BigInt:

201

// "anyUint expected its argument to be an unsigned integer, but it was negative, with value -42n"

202

```

203

204

## Integration with Other Matchers

205

206

### Event Emission

207

208

```typescript

209

// Use with event emission testing

210

await expect(contract.complexFunction())

211

.to.emit(contract, "Event1")

212

.withArgs(specificValue, anyValue, anyUint)

213

.and.to.emit(contract, "Event2")

214

.withArgs(anyValue, anyUint, specificValue);

215

```

216

217

### Custom Error Testing

218

219

```typescript

220

// Use with custom error validation

221

await expect(contract.restrictedFunction())

222

.to.be.revertedWithCustomError(contract, "ValidationError")

223

.withArgs(anyValue, anyUint, "Required field missing");

224

```

225

226

## Best Practices

227

228

### When to Use anyValue

229

230

- Ignore timestamp arguments that change between test runs

231

- Skip complex computed values that are tested elsewhere

232

- Focus tests on specific arguments of interest

233

- Ignore metadata or auxiliary information

234

235

### When to Use anyUint

236

237

- Validate amounts are positive without caring about exact values

238

- Test fee calculations where any positive fee is acceptable

239

- Verify ID generation produces valid positive identifiers

240

- Ensure counters increment correctly

241

242

### Combining with Specific Values

243

244

```typescript

245

// Good: Mix specific requirements with flexible matching

246

await expect(contract.operation())

247

.to.emit(contract, "Operation")

248

.withArgs(

249

user.address, // Specific - who performed operation

250

"CREATE", // Specific - what operation type

251

anyUint, // Flexible - any valid item ID

252

anyValue // Flexible - ignore metadata

253

);

254

255

// Avoid: Using anyValue for everything (not very useful)

256

await expect(contract.operation())

257

.to.emit(contract, "Operation")

258

.withArgs(anyValue, anyValue, anyValue, anyValue); // Too permissive

259

```