erc4337.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. const { ethers } = require('hardhat');
  2. const SIG_VALIDATION_SUCCESS = '0x0000000000000000000000000000000000000000';
  3. const SIG_VALIDATION_FAILURE = '0x0000000000000000000000000000000000000001';
  4. function getAddress(account) {
  5. return account.target ?? account.address ?? account;
  6. }
  7. function pack(left, right) {
  8. return ethers.solidityPacked(['uint128', 'uint128'], [left, right]);
  9. }
  10. function packValidationData(validAfter, validUntil, authorizer) {
  11. return ethers.solidityPacked(
  12. ['uint48', 'uint48', 'address'],
  13. [
  14. validAfter,
  15. validUntil,
  16. typeof authorizer == 'boolean'
  17. ? authorizer
  18. ? SIG_VALIDATION_SUCCESS
  19. : SIG_VALIDATION_FAILURE
  20. : getAddress(authorizer),
  21. ],
  22. );
  23. }
  24. function packInitCode(factory, factoryData) {
  25. return ethers.solidityPacked(['address', 'bytes'], [getAddress(factory), factoryData]);
  26. }
  27. function packPaymasterAndData(paymaster, paymasterVerificationGasLimit, paymasterPostOpGasLimit, paymasterData) {
  28. return ethers.solidityPacked(
  29. ['address', 'uint128', 'uint128', 'bytes'],
  30. [getAddress(paymaster), paymasterVerificationGasLimit, paymasterPostOpGasLimit, paymasterData],
  31. );
  32. }
  33. /// Represent one user operation
  34. class UserOperation {
  35. constructor(params) {
  36. this.sender = getAddress(params.sender);
  37. this.nonce = params.nonce;
  38. this.factory = params.factory ?? undefined;
  39. this.factoryData = params.factoryData ?? '0x';
  40. this.callData = params.callData ?? '0x';
  41. this.verificationGas = params.verificationGas ?? 10_000_000n;
  42. this.callGas = params.callGas ?? 100_000n;
  43. this.preVerificationGas = params.preVerificationGas ?? 100_000n;
  44. this.maxPriorityFee = params.maxPriorityFee ?? 100_000n;
  45. this.maxFeePerGas = params.maxFeePerGas ?? 100_000n;
  46. this.paymaster = params.paymaster ?? undefined;
  47. this.paymasterVerificationGasLimit = params.paymasterVerificationGasLimit ?? 0n;
  48. this.paymasterPostOpGasLimit = params.paymasterPostOpGasLimit ?? 0n;
  49. this.paymasterData = params.paymasterData ?? '0x';
  50. this.signature = params.signature ?? '0x';
  51. }
  52. get packed() {
  53. return {
  54. sender: this.sender,
  55. nonce: this.nonce,
  56. initCode: this.factory ? packInitCode(this.factory, this.factoryData) : '0x',
  57. callData: this.callData,
  58. accountGasLimits: pack(this.verificationGas, this.callGas),
  59. preVerificationGas: this.preVerificationGas,
  60. gasFees: pack(this.maxPriorityFee, this.maxFeePerGas),
  61. paymasterAndData: this.paymaster
  62. ? packPaymasterAndData(
  63. this.paymaster,
  64. this.paymasterVerificationGasLimit,
  65. this.paymasterPostOpGasLimit,
  66. this.paymasterData,
  67. )
  68. : '0x',
  69. signature: this.signature,
  70. };
  71. }
  72. hash(entrypoint) {
  73. return entrypoint.getUserOpHash(this.packed);
  74. }
  75. }
  76. module.exports = {
  77. SIG_VALIDATION_SUCCESS,
  78. SIG_VALIDATION_FAILURE,
  79. packValidationData,
  80. packInitCode,
  81. packPaymasterAndData,
  82. UserOperation,
  83. };