customError.js 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. const { expect } = require('chai');
  2. /** Revert handler that supports custom errors. */
  3. async function expectRevertCustomError(promise, expectedErrorName, args) {
  4. try {
  5. await promise;
  6. expect.fail("Expected promise to throw but it didn't");
  7. } catch (revert) {
  8. if (!Array.isArray(args)) {
  9. expect.fail('Expected 3rd array parameter for error arguments');
  10. }
  11. // The revert message for custom errors looks like:
  12. // VM Exception while processing transaction:
  13. // reverted with custom error 'InvalidAccountNonce("0x70997970C51812dc3A010C7d01b50e0d17dc79C8", 0)'
  14. // We trim out anything inside the single quotes as comma-separated values
  15. const [, error] = revert.message.match(/'(.*)'/);
  16. // Attempt to parse as an error
  17. const match = error.match(/(?<name>\w+)\((?<args>.*)\)/);
  18. if (!match) {
  19. expect.fail(`Couldn't parse "${error}" as a custom error`);
  20. }
  21. // Extract the error name and parameters
  22. const errorName = match.groups.name;
  23. const argMatches = [...match.groups.args.matchAll(/-?\w+/g)];
  24. // Assert error name
  25. expect(errorName).to.be.equal(
  26. expectedErrorName,
  27. `Unexpected custom error name (with found args: [${argMatches.map(([a]) => a)}])`,
  28. );
  29. // Coerce to string for comparison since `arg` can be either a number or hex.
  30. const sanitizedExpected = args.map(arg => arg.toString().toLowerCase());
  31. const sanitizedActual = argMatches.map(([arg]) => arg.toString().toLowerCase());
  32. // Assert argument equality
  33. expect(sanitizedActual).to.have.members(sanitizedExpected, `Unexpected ${errorName} arguments`);
  34. }
  35. }
  36. module.exports = {
  37. expectRevertCustomError,
  38. };