Skip to content

Commit 2f70faf

Browse files
committed
fix: throw when TestClient.revert is given an invalid snapshot
evm_revert returns false for missing or already-consumed snapshot IDs instead of a JSON-RPC error. Check that boolean and throw so failed reverts are observable. Closes #5064
1 parent 3db6cdf commit 2f70faf

7 files changed

Lines changed: 51 additions & 5 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"viem": patch
3+
---
4+
5+
Fixed `TestClient.revert` swallowing invalid snapshot IDs.

site/pages/docs/actions/test/revert.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ description: Revert the state of the blockchain at the current block.
66

77
Revert the state of the blockchain at the current block.
88

9+
Throws if the snapshot ID does not exist or has already been consumed.
10+
911
## Usage
1012

1113
:::code-group
@@ -43,4 +45,4 @@ The snapshot ID.
4345
await testClient.revert({
4446
id: '0x...' // [!code focus]
4547
})
46-
```
48+
```

src/actions/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ export {
414414
export {
415415
type RevertErrorType,
416416
type RevertParameters,
417+
type SnapshotRevertErrorType,
417418
revert,
418419
} from './test/revert.js'
419420
export {

src/actions/test/revert.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,22 @@ test('reverts', async () => {
4040
}),
4141
).toBe(balance)
4242
})
43+
44+
test('throws on an invalid snapshot id', async () => {
45+
await expect(
46+
revert(client, { id: '0xffffffffffffffff' }),
47+
).rejects.toMatchInlineSnapshot(`
48+
[SnapshotRevertError: Failed to revert to snapshot "0xffffffffffffffff".
49+
50+
Docs: https://viem.sh/docs/actions/test/revert
51+
Version: viem@x.y.z]
52+
`)
53+
})
54+
55+
test('throws when the snapshot has already been consumed', async () => {
56+
const id = await snapshot(client)
57+
await revert(client, { id })
58+
await expect(revert(client, { id })).rejects.toThrowError(
59+
`Failed to revert to snapshot "${id}"`,
60+
)
61+
})

src/actions/test/revert.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {
33
TestClientMode,
44
} from '../../clients/createTestClient.js'
55
import type { Transport } from '../../clients/transports/createTransport.js'
6+
import { BaseError } from '../../errors/base.js'
67
import type { ErrorType } from '../../errors/utils.js'
78
import type { Account } from '../../types/account.js'
89
import type { Chain } from '../../types/chain.js'
@@ -14,7 +15,22 @@ export type RevertParameters = {
1415
id: Quantity
1516
}
1617

17-
export type RevertErrorType = RequestErrorType | ErrorType
18+
export type SnapshotRevertErrorType = SnapshotRevertError & {
19+
name: 'SnapshotRevertError'
20+
}
21+
export class SnapshotRevertError extends BaseError {
22+
constructor({ id }: { id: Quantity }) {
23+
super(`Failed to revert to snapshot "${id}".`, {
24+
name: 'SnapshotRevertError',
25+
docsPath: '/docs/actions/test/revert',
26+
})
27+
}
28+
}
29+
30+
export type RevertErrorType =
31+
| SnapshotRevertErrorType
32+
| RequestErrorType
33+
| ErrorType
1834

1935
/**
2036
* Revert the state of the blockchain at the current block.
@@ -43,8 +59,9 @@ export async function revert<
4359
client: TestClient<TestClientMode, Transport, chain, account, false>,
4460
{ id }: RevertParameters,
4561
) {
46-
await client.request({
62+
const reverted = await client.request({
4763
method: 'evm_revert',
4864
params: [id],
4965
})
66+
if (reverted === false) throw new SnapshotRevertError({ id })
5067
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ export type { ResetErrorType, ResetParameters } from './actions/test/reset.js'
406406
export type {
407407
RevertErrorType,
408408
RevertParameters,
409+
SnapshotRevertErrorType,
409410
} from './actions/test/revert.js'
410411
export type {
411412
SendUnsignedTransactionErrorType,

src/types/eip1193.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,12 +1595,13 @@ export type TestRpcSchema<mode extends string> = [
15951595
ReturnType: Quantity
15961596
},
15971597
/**
1598-
* @description Revert the state of the blockchain to a previous snapshot. Takes a single parameter, which is the snapshot id to revert to.
1598+
* @description Revert the state of the blockchain to a previous snapshot. Takes a single parameter, which is the snapshot id to revert to. Returns `true` if the snapshot existed, `false` otherwise.
1599+
* @link https://hardhat.org/hardhat-network/docs/reference#evm_revert
15991600
*/
16001601
{
16011602
Method: 'evm_revert'
16021603
Parameters?: [id: Quantity] | undefined
1603-
ReturnType: void
1604+
ReturnType: boolean
16041605
},
16051606
/**
16061607
* @description Enables the automatic mining of new blocks with each new transaction submitted to the network.

0 commit comments

Comments
 (0)