AccountWebAuthn.test.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. const { ethers, entrypoint } = require('hardhat');
  2. const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
  3. const { getDomain } = require('../helpers/eip712');
  4. const { ERC4337Helper } = require('../helpers/erc4337');
  5. const { NonNativeSigner, P256SigningKey, WebAuthnSigningKey } = require('../helpers/signers');
  6. const { PackedUserOperation } = require('../helpers/eip712-types');
  7. const { shouldBehaveLikeAccountCore, shouldBehaveLikeAccountHolder } = require('./Account.behavior');
  8. const { shouldBehaveLikeERC1271 } = require('../utils/cryptography/ERC1271.behavior');
  9. const { shouldBehaveLikeERC7821 } = require('./extensions/ERC7821.behavior');
  10. const webAuthnSigner = new NonNativeSigner(WebAuthnSigningKey.random());
  11. const p256Signer = new NonNativeSigner(P256SigningKey.random());
  12. async function fixture() {
  13. // EOAs and environment
  14. const [beneficiary, other] = await ethers.getSigners();
  15. const target = await ethers.deployContract('CallReceiverMock');
  16. // ERC-4337 account
  17. const helper = new ERC4337Helper();
  18. const webAuthnMock = await helper.newAccount('$AccountWebAuthnMock', [
  19. webAuthnSigner.signingKey.publicKey.qx,
  20. webAuthnSigner.signingKey.publicKey.qy,
  21. 'AccountWebAuthn',
  22. '1',
  23. ]);
  24. const p256Mock = await helper.newAccount('$AccountWebAuthnMock', [
  25. p256Signer.signingKey.publicKey.qx,
  26. p256Signer.signingKey.publicKey.qy,
  27. 'AccountWebAuthn',
  28. '1',
  29. ]);
  30. // ERC-4337 Entrypoint domain
  31. const entrypointDomain = await getDomain(entrypoint.v08);
  32. // domain cannot be fetched using getDomain(mock) before the mock is deployed
  33. const domain = {
  34. name: 'AccountWebAuthn',
  35. version: '1',
  36. chainId: entrypointDomain.chainId,
  37. };
  38. // Sign userOp with the active signer
  39. const signUserOp = function (userOp) {
  40. return this.signer
  41. .signTypedData(entrypointDomain, { PackedUserOperation }, userOp.packed)
  42. .then(signature => Object.assign(userOp, { signature }));
  43. };
  44. return { helper, domain, webAuthnMock, p256Mock, target, beneficiary, other, signUserOp };
  45. }
  46. describe('AccountWebAuthn', function () {
  47. beforeEach(async function () {
  48. Object.assign(this, await loadFixture(fixture));
  49. });
  50. describe('WebAuthn Assertions', function () {
  51. beforeEach(async function () {
  52. this.signer = webAuthnSigner;
  53. this.mock = this.webAuthnMock;
  54. this.domain.verifyingContract = this.mock.address;
  55. });
  56. shouldBehaveLikeAccountCore();
  57. shouldBehaveLikeAccountHolder();
  58. shouldBehaveLikeERC1271({ erc7739: true });
  59. shouldBehaveLikeERC7821();
  60. });
  61. describe('as regular P256 validator', function () {
  62. beforeEach(async function () {
  63. this.signer = p256Signer;
  64. this.mock = this.p256Mock;
  65. this.domain.verifyingContract = this.mock.address;
  66. });
  67. shouldBehaveLikeAccountCore();
  68. shouldBehaveLikeAccountHolder();
  69. shouldBehaveLikeERC1271({ erc7739: true });
  70. shouldBehaveLikeERC7821();
  71. });
  72. });