diff --git a/.changeset/calm-shoes-approve.md b/.changeset/calm-shoes-approve.md new file mode 100644 index 00000000..d6bfb2b6 --- /dev/null +++ b/.changeset/calm-shoes-approve.md @@ -0,0 +1,5 @@ +--- +"permissionless": patch +--- + +Added prepareUserOperationErc20ForPaymaster under pimlico/experimental diff --git a/bun.lockb b/bun.lockb index 19098027..8f89f8b2 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index be1cc134..102ca2d6 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "get-port": "^7.0.0", "tsc-alias": "^1.8.8", "vitest": "^1.2.0", - "viem": "^2.20.0", + "viem": "^2.21.2", "wagmi": "^2.12.8", "@permissionless/wagmi": "workspace:packages/wagmi", "@types/react": "^18.3.1", diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/abi.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/abi.ts index 79d58e5e..79f4b41f 100644 --- a/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/abi.ts +++ b/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/abi.ts @@ -1,4 +1,38 @@ -export const VERIFYING_PAYMASTER_V07_ABI = [ +export const SINGLETON_PAYMASTER_V07_ABI = [ + { + type: "constructor", + inputs: [ + { + name: "_entryPoint", + type: "address", + internalType: "address" + }, + { + name: "_owner", + type: "address", + internalType: "address" + }, + { + name: "_signers", + type: "address[]", + internalType: "address[]" + } + ], + stateMutability: "nonpayable" + }, + { + type: "function", + name: "addSigner", + inputs: [ + { + name: "_signer", + type: "address", + internalType: "address" + } + ], + outputs: [], + stateMutability: "nonpayable" + }, { type: "function", name: "addStake", @@ -21,10 +55,75 @@ export const VERIFYING_PAYMASTER_V07_ABI = [ }, { type: "function", - name: "validatePaymasterUserOp", + name: "entryPoint", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "contract IEntryPoint" + } + ], + stateMutability: "view" + }, + { + type: "function", + name: "getCostInToken", inputs: [ { - name: "userOp", + name: "_actualGasCost", + type: "uint256", + internalType: "uint256" + }, + { + name: "_postOpGas", + type: "uint256", + internalType: "uint256" + }, + { + name: "_actualUserOpFeePerGas", + type: "uint256", + internalType: "uint256" + }, + { + name: "_exchangeRate", + type: "uint256", + internalType: "uint256" + } + ], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256" + } + ], + stateMutability: "pure" + }, + { + type: "function", + name: "getDeposit", + inputs: [], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256" + } + ], + stateMutability: "view" + }, + { + type: "function", + name: "getHash", + inputs: [ + { + name: "_mode", + type: "uint8", + internalType: "uint8" + }, + { + name: "_userOp", type: "tuple", internalType: "struct PackedUserOperation", components: [ @@ -74,35 +173,146 @@ export const VERIFYING_PAYMASTER_V07_ABI = [ internalType: "bytes" } ] - }, + } + ], + outputs: [ { - name: "userOpHash", + name: "", type: "bytes32", internalType: "bytes32" - }, - { - name: "maxCost", - type: "uint256", - internalType: "uint256" } ], + stateMutability: "view" + }, + { + type: "function", + name: "owner", + inputs: [], outputs: [ + { + name: "", + type: "address", + internalType: "address" + } + ], + stateMutability: "view" + }, + { + type: "function", + name: "postOp", + inputs: [ + { + name: "mode", + type: "uint8", + internalType: "enum PostOpMode" + }, { name: "context", type: "bytes", internalType: "bytes" }, { - name: "validationData", + name: "actualGasCost", + type: "uint256", + internalType: "uint256" + }, + { + name: "actualUserOpFeePerGas", type: "uint256", internalType: "uint256" } ], + outputs: [], stateMutability: "nonpayable" }, { type: "function", - name: "getHash", + name: "removeSigner", + inputs: [ + { + name: "_signer", + type: "address", + internalType: "address" + } + ], + outputs: [], + stateMutability: "nonpayable" + }, + { + type: "function", + name: "renounceOwnership", + inputs: [], + outputs: [], + stateMutability: "nonpayable" + }, + { + type: "function", + name: "setTreasury", + inputs: [ + { + name: "_treasury", + type: "address", + internalType: "address" + } + ], + outputs: [], + stateMutability: "nonpayable" + }, + { + type: "function", + name: "signers", + inputs: [ + { + name: "account", + type: "address", + internalType: "address" + } + ], + outputs: [ + { + name: "isValidSigner", + type: "bool", + internalType: "bool" + } + ], + stateMutability: "view" + }, + { + type: "function", + name: "transferOwnership", + inputs: [ + { + name: "newOwner", + type: "address", + internalType: "address" + } + ], + outputs: [], + stateMutability: "nonpayable" + }, + { + type: "function", + name: "treasury", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "address" + } + ], + stateMutability: "view" + }, + { + type: "function", + name: "unlockStake", + inputs: [], + outputs: [], + stateMutability: "nonpayable" + }, + { + type: "function", + name: "validatePaymasterUserOp", inputs: [ { name: "userOp", @@ -157,70 +367,419 @@ export const VERIFYING_PAYMASTER_V07_ABI = [ ] }, { - name: "validUntil", - type: "uint48", - internalType: "uint48" + name: "userOpHash", + type: "bytes32", + internalType: "bytes32" + }, + { + name: "maxCost", + type: "uint256", + internalType: "uint256" + } + ], + outputs: [ + { + name: "context", + type: "bytes", + internalType: "bytes" + }, + { + name: "validationData", + type: "uint256", + internalType: "uint256" + } + ], + stateMutability: "nonpayable" + }, + { + type: "function", + name: "withdrawStake", + inputs: [ + { + name: "withdrawAddress", + type: "address", + internalType: "address payable" + } + ], + outputs: [], + stateMutability: "nonpayable" + }, + { + type: "function", + name: "withdrawTo", + inputs: [ + { + name: "withdrawAddress", + type: "address", + internalType: "address payable" + }, + { + name: "amount", + type: "uint256", + internalType: "uint256" + } + ], + outputs: [], + stateMutability: "nonpayable" + }, + { + type: "event", + name: "OwnershipTransferred", + inputs: [ + { + name: "previousOwner", + type: "address", + indexed: true, + internalType: "address" + }, + { + name: "newOwner", + type: "address", + indexed: true, + internalType: "address" + } + ], + anonymous: false + }, + { + type: "event", + name: "SignerAdded", + inputs: [ + { + name: "signer", + type: "address", + indexed: false, + internalType: "address" + } + ], + anonymous: false + }, + { + type: "event", + name: "SignerRemoved", + inputs: [ + { + name: "signer", + type: "address", + indexed: false, + internalType: "address" + } + ], + anonymous: false + }, + { + type: "event", + name: "TreasuryUpdated", + inputs: [ + { + name: "oldTreasury", + type: "address", + indexed: false, + internalType: "address" + }, + { + name: "newTreasury", + type: "address", + indexed: false, + internalType: "address" + } + ], + anonymous: false + }, + { + type: "event", + name: "UserOperationSponsored", + inputs: [ + { + name: "userOpHash", + type: "bytes32", + indexed: true, + internalType: "bytes32" + }, + { + name: "user", + type: "address", + indexed: true, + internalType: "address" + }, + { + name: "paymasterMode", + type: "uint8", + indexed: false, + internalType: "uint8" + }, + { + name: "token", + type: "address", + indexed: false, + internalType: "address" + }, + { + name: "tokenAmountPaid", + type: "uint256", + indexed: false, + internalType: "uint256" + }, + { + name: "exchangeRate", + type: "uint256", + indexed: false, + internalType: "uint256" + } + ], + anonymous: false + }, + { + type: "error", + name: "ECDSAInvalidSignature", + inputs: [] + }, + { + type: "error", + name: "ECDSAInvalidSignatureLength", + inputs: [ + { + name: "length", + type: "uint256", + internalType: "uint256" + } + ] + }, + { + type: "error", + name: "ECDSAInvalidSignatureS", + inputs: [ + { + name: "s", + type: "bytes32", + internalType: "bytes32" + } + ] + }, + { + type: "error", + name: "ExchangeRateInvalid", + inputs: [] + }, + { + type: "error", + name: "OwnableInvalidOwner", + inputs: [ + { + name: "owner", + type: "address", + internalType: "address" + } + ] + }, + { + type: "error", + name: "OwnableUnauthorizedAccount", + inputs: [ + { + name: "account", + type: "address", + internalType: "address" + } + ] + }, + { + type: "error", + name: "PaymasterAndDataLengthInvalid", + inputs: [] + }, + { + type: "error", + name: "PaymasterConfigLengthInvalid", + inputs: [] + }, + { + type: "error", + name: "PaymasterModeInvalid", + inputs: [] + }, + { + type: "error", + name: "PaymasterSignatureLengthInvalid", + inputs: [] + }, + { + type: "error", + name: "PostOpTransferFromFailed", + inputs: [ + { + name: "msg", + type: "string", + internalType: "string" + } + ] + }, + { + type: "error", + name: "TokenAddressInvalid", + inputs: [] + } +] as const + +export const SINGLETON_PAYMASTER_V06_ABI = [ + { + inputs: [ + { internalType: "address", name: "_entryPoint", type: "address" }, + { internalType: "address", name: "_owner", type: "address" }, + { internalType: "address[]", name: "_signers", type: "address[]" } + ], + stateMutability: "nonpayable", + type: "constructor" + }, + { inputs: [], name: "ECDSAInvalidSignature", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "length", type: "uint256" }], + name: "ECDSAInvalidSignatureLength", + type: "error" + }, + { + inputs: [{ internalType: "bytes32", name: "s", type: "bytes32" }], + name: "ECDSAInvalidSignatureS", + type: "error" + }, + { inputs: [], name: "ExchangeRateInvalid", type: "error" }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "OwnableInvalidOwner", + type: "error" + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "OwnableUnauthorizedAccount", + type: "error" + }, + { inputs: [], name: "PaymasterAndDataLengthInvalid", type: "error" }, + { inputs: [], name: "PaymasterConfigLengthInvalid", type: "error" }, + { inputs: [], name: "PaymasterModeInvalid", type: "error" }, + { inputs: [], name: "PaymasterSignatureLengthInvalid", type: "error" }, + { + inputs: [{ internalType: "string", name: "msg", type: "string" }], + name: "PostOpTransferFromFailed", + type: "error" + }, + { inputs: [], name: "TokenAddressInvalid", type: "error" }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address" }, { - name: "validAfter", - type: "uint48", - internalType: "uint48" + indexed: true, + internalType: "address", + name: "newOwner", + type: "address" } ], - outputs: [ + name: "OwnershipTransferred", + type: "event" + }, + { + anonymous: false, + inputs: [ { - name: "", - type: "bytes32", - internalType: "bytes32" + indexed: false, + internalType: "address", + name: "signer", + type: "address" } ], - stateMutability: "view" - } -] as const - -export const VERIFYING_PAYMASTER_V06_ABI = [ + name: "SignerAdded", + type: "event" + }, { + anonymous: false, inputs: [ { - internalType: "contract IEntryPoint", - name: "_entryPoint", + indexed: false, + internalType: "address", + name: "signer", + type: "address" + } + ], + name: "SignerRemoved", + type: "event" + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldTreasury", type: "address" }, { + indexed: false, internalType: "address", - name: "_verifyingSigner", + name: "newTreasury", type: "address" } ], - stateMutability: "nonpayable", - type: "constructor" + name: "TreasuryUpdated", + type: "event" }, { anonymous: false, inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "userOpHash", + type: "bytes32" + }, { indexed: true, internalType: "address", - name: "previousOwner", + name: "user", type: "address" }, { - indexed: true, + indexed: false, + internalType: "uint8", + name: "paymasterMode", + type: "uint8" + }, + { + indexed: false, internalType: "address", - name: "newOwner", + name: "token", type: "address" + }, + { + indexed: false, + internalType: "uint256", + name: "tokenAmountPaid", + type: "uint256" + }, + { + indexed: false, + internalType: "uint256", + name: "exchangeRate", + type: "uint256" } ], - name: "OwnershipTransferred", + name: "UserOperationSponsored", type: "event" }, + { + inputs: [{ internalType: "address", name: "_signer", type: "address" }], + name: "addSigner", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, { inputs: [ - { - internalType: "uint32", - name: "unstakeDelaySec", - type: "uint32" - } + { internalType: "uint32", name: "unstakeDelaySec", type: "uint32" } ], name: "addStake", outputs: [], @@ -238,30 +797,41 @@ export const VERIFYING_PAYMASTER_V06_ABI = [ inputs: [], name: "entryPoint", outputs: [ - { - internalType: "contract IEntryPoint", - name: "", - type: "address" - } + { internalType: "contract IEntryPoint", name: "", type: "address" } ], stateMutability: "view", type: "function" }, { - inputs: [], - name: "getDeposit", - outputs: [ + inputs: [ { internalType: "uint256", - name: "", + name: "_actualGasCost", type: "uint256" - } + }, + { internalType: "uint256", name: "_postOpGas", type: "uint256" }, + { + internalType: "uint256", + name: "_actualUserOpFeePerGas", + type: "uint256" + }, + { internalType: "uint256", name: "_exchangeRate", type: "uint256" } ], + name: "getCostInToken", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function" + }, + { + inputs: [], + name: "getDeposit", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function" }, { inputs: [ + { internalType: "uint8", name: "_mode", type: "uint8" }, { components: [ { @@ -269,21 +839,9 @@ export const VERIFYING_PAYMASTER_V06_ABI = [ name: "sender", type: "address" }, - { - internalType: "uint256", - name: "nonce", - type: "uint256" - }, - { - internalType: "bytes", - name: "initCode", - type: "bytes" - }, - { - internalType: "bytes", - name: "callData", - type: "bytes" - }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "bytes", name: "initCode", type: "bytes" }, + { internalType: "bytes", name: "callData", type: "bytes" }, { internalType: "uint256", name: "callGasLimit", @@ -314,99 +872,39 @@ export const VERIFYING_PAYMASTER_V06_ABI = [ name: "paymasterAndData", type: "bytes" }, - { - internalType: "bytes", - name: "signature", - type: "bytes" - } + { internalType: "bytes", name: "signature", type: "bytes" } ], internalType: "struct UserOperation", - name: "userOp", + name: "_userOp", type: "tuple" - }, - { - internalType: "uint48", - name: "validUntil", - type: "uint48" - }, - { - internalType: "uint48", - name: "validAfter", - type: "uint48" } ], name: "getHash", - outputs: [ - { - internalType: "bytes32", - name: "", - type: "bytes32" - } - ], + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], stateMutability: "view", type: "function" }, { inputs: [], name: "owner", - outputs: [ - { - internalType: "address", - name: "", - type: "address" - } - ], + outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function" }, { inputs: [ - { - internalType: "bytes", - name: "paymasterAndData", - type: "bytes" - } - ], - name: "parsePaymasterAndData", - outputs: [ - { - internalType: "uint48", - name: "validUntil", - type: "uint48" - }, - { - internalType: "uint48", - name: "validAfter", - type: "uint48" - }, - { - internalType: "bytes", - name: "signature", - type: "bytes" - } + { internalType: "enum PostOpMode", name: "mode", type: "uint8" }, + { internalType: "bytes", name: "context", type: "bytes" }, + { internalType: "uint256", name: "actualGasCost", type: "uint256" } ], - stateMutability: "pure", + name: "postOp", + outputs: [], + stateMutability: "nonpayable", type: "function" }, { - inputs: [ - { - internalType: "enum IPaymaster.PostOpMode", - name: "mode", - type: "uint8" - }, - { - internalType: "bytes", - name: "context", - type: "bytes" - }, - { - internalType: "uint256", - name: "actualGasCost", - type: "uint256" - } - ], - name: "postOp", + inputs: [{ internalType: "address", name: "_signer", type: "address" }], + name: "removeSigner", outputs: [], stateMutability: "nonpayable", type: "function" @@ -420,36 +918,38 @@ export const VERIFYING_PAYMASTER_V06_ABI = [ }, { inputs: [ - { - internalType: "address", - name: "", - type: "address" - } + { internalType: "address", name: "_treasury", type: "address" } ], - name: "senderNonce", + name: "setTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "signers", outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256" - } + { internalType: "bool", name: "isValidSigner", type: "bool" } ], stateMutability: "view", type: "function" }, { inputs: [ - { - internalType: "address", - name: "newOwner", - type: "address" - } + { internalType: "address", name: "newOwner", type: "address" } ], name: "transferOwnership", outputs: [], stateMutability: "nonpayable", type: "function" }, + { + inputs: [], + name: "treasury", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function" + }, { inputs: [], name: "unlockStake", @@ -466,21 +966,9 @@ export const VERIFYING_PAYMASTER_V06_ABI = [ name: "sender", type: "address" }, - { - internalType: "uint256", - name: "nonce", - type: "uint256" - }, - { - internalType: "bytes", - name: "initCode", - type: "bytes" - }, - { - internalType: "bytes", - name: "callData", - type: "bytes" - }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "bytes", name: "initCode", type: "bytes" }, + { internalType: "bytes", name: "callData", type: "bytes" }, { internalType: "uint256", name: "callGasLimit", @@ -511,56 +999,23 @@ export const VERIFYING_PAYMASTER_V06_ABI = [ name: "paymasterAndData", type: "bytes" }, - { - internalType: "bytes", - name: "signature", - type: "bytes" - } + { internalType: "bytes", name: "signature", type: "bytes" } ], internalType: "struct UserOperation", name: "userOp", type: "tuple" }, - { - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - internalType: "uint256", - name: "maxCost", - type: "uint256" - } + { internalType: "bytes32", name: "userOpHash", type: "bytes32" }, + { internalType: "uint256", name: "maxCost", type: "uint256" } ], name: "validatePaymasterUserOp", outputs: [ - { - internalType: "bytes", - name: "context", - type: "bytes" - }, - { - internalType: "uint256", - name: "validationData", - type: "uint256" - } + { internalType: "bytes", name: "context", type: "bytes" }, + { internalType: "uint256", name: "validationData", type: "uint256" } ], stateMutability: "nonpayable", type: "function" }, - { - inputs: [], - name: "verifyingSigner", - outputs: [ - { - internalType: "address", - name: "", - type: "address" - } - ], - stateMutability: "view", - type: "function" - }, { inputs: [ { @@ -581,11 +1036,7 @@ export const VERIFYING_PAYMASTER_V06_ABI = [ name: "withdrawAddress", type: "address" }, - { - internalType: "uint256", - name: "amount", - type: "uint256" - } + { internalType: "uint256", name: "amount", type: "uint256" } ], name: "withdrawTo", outputs: [], diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/schema.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/schema.ts index 6d728920..1bee9706 100644 --- a/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/schema.ts +++ b/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/schema.ts @@ -237,7 +237,7 @@ export const pmGetPaymasterData = z eip7677UserOperationSchema, addressSchema, hexNumberSchema, - z.union([z.object({}), z.null()]) + z.union([z.object({ token: addressSchema }), z.null()]) ]), z.tuple([eip7677UserOperationSchema, addressSchema, hexNumberSchema]) ]) @@ -251,7 +251,7 @@ export const pmGetPaymasterStubDataParamsSchema = z eip7677UserOperationSchema, addressSchema, hexNumberSchema, - z.union([z.object({}), z.null()]) + z.union([z.object({ token: addressSchema }), z.null()]) ]), z.tuple([eip7677UserOperationSchema, addressSchema, hexNumberSchema]) ]) diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/utils.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/utils.ts index bc36a92d..01d8a4c3 100644 --- a/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/utils.ts +++ b/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/utils.ts @@ -1,6 +1,8 @@ -import { http, createWalletClient } from "viem" +import { http, type Address, type Hex, createWalletClient } from "viem" import { mnemonicToAccount } from "viem/accounts" import { foundry } from "viem/chains" +import { ERC20_ADDRESS } from "../../../src/erc20-utils" +import { RpcError, ValidationErrors } from "./schema" /// Returns the bigger of two BigInts. export const maxBigInt = (a: bigint, b: bigint) => { @@ -24,3 +26,21 @@ export const getAnvilWalletClient = (anvilRpc: string) => { return walletClient } + +export const isTokenSupported = async (token: Address) => { + if (token !== ERC20_ADDRESS) { + throw new RpcError( + "Token is not supported", + ValidationErrors.InvalidFields + ) + } +} + +export type PaymasterMode = + | { + mode: "verifying" + } + | { + mode: "erc20" + token: Address + } diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/verifyingPaymasters.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/verifyingPaymasters.ts deleted file mode 100644 index 85c87428..00000000 --- a/packages/permissionless-test/mock-aa-infra/mock-paymaster/helpers/verifyingPaymasters.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { - http, - type Account, - type Address, - type Chain, - type Hex, - type Transport, - type WalletClient, - concat, - createPublicClient, - getContract, - getContractAddress, - pad, - parseEther, - slice -} from "viem" -import { foundry } from "viem/chains" -import { VERIFYING_PAYMASTER_V06_ABI, VERIFYING_PAYMASTER_V07_ABI } from "./abi" - -const DETERMINISTIC_DEPLOYER = "0x4e59b44847b379578588920ca78fbf26c0b4956c" - -// Creates the call that deploys the VerifyingPaymaster v0.7 -const VERIFYING_PAYMASTER_V07_CALL = (owner: Address): Hex => - concat([ - "0x000000000000000000000000000000000000000000000000000000000000000060c06040523480156200001157600080fd5b506040516200145938038062001459833981016040819052620000349162000236565b8233806200005d57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b62000068816200009b565b506200007481620000eb565b6001600160a01b03908116608052821660a0526200009281620001ae565b505050620002b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516301ffc9a760e01b815263122a0e9b60e31b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa15801562000137573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200015d91906200028a565b620001ab5760405162461bcd60e51b815260206004820152601e60248201527f49456e747279506f696e7420696e74657266616365206d69736d617463680000604482015260640162000054565b50565b620001b8620001ef565b6001600160a01b038116620001e457604051631e4fbdf760e01b81526000600482015260240162000054565b620001ab816200009b565b6000546001600160a01b031633146200021e5760405163118cdaa760e01b815233600482015260240162000054565b565b6001600160a01b0381168114620001ab57600080fd5b6000806000606084860312156200024c57600080fd5b8351620002598162000220565b60208501519093506200026c8162000220565b60408501519092506200027f8162000220565b809150509250925092565b6000602082840312156200029d57600080fd5b81518015158114620002ae57600080fd5b9392505050565b60805160a051611146620003136000396000818161013401526109a40152600081816102640152818161031a015281816103b1015281816105ab01528181610645015281816106b501528181610742015261080a01526111466000f3fe6080604052600436106100e85760003560e01c80638da5cb5b1161008a578063c23a5cea11610059578063c23a5cea1461029b578063c399ec88146102bb578063d0e30db0146102d0578063f2fde38b146102d857600080fd5b80638da5cb5b1461020457806394d4ad6014610222578063b0d691fe14610252578063bb9fe6bf1461028657600080fd5b806352b7512c116100c657806352b7512c146101735780635829c5f5146101a1578063715018a6146101cf5780637c627b21146101e457600080fd5b80630396cb60146100ed578063205c28781461010257806323d9ac9b14610122575b600080fd5b6101006100fb366004610cec565b6102f8565b005b34801561010e57600080fd5b5061010061011d366004610d2e565b610383565b34801561012e57600080fd5b506101567f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561017f57600080fd5b5061019361018e366004610d73565b6103f5565b60405161016a929190610dc1565b3480156101ad57600080fd5b506101c16101bc366004610e31565b610419565b60405190815260200161016a565b3480156101db57600080fd5b50610100610529565b3480156101f057600080fd5b506101006101ff366004610ed8565b61053d565b34801561021057600080fd5b506000546001600160a01b0316610156565b34801561022e57600080fd5b5061024261023d366004610f43565b610559565b60405161016a9493929190610f85565b34801561025e57600080fd5b506101567f000000000000000000000000000000000000000000000000000000000000000081565b34801561029257600080fd5b506101006105a1565b3480156102a757600080fd5b506101006102b6366004610fd1565b61061e565b3480156102c757600080fd5b506101c161069d565b61010061072d565b3480156102e457600080fd5b506101006102f3366004610fd1565b61078f565b6103006107d2565b604051621cb65b60e51b815263ffffffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630396cb609034906024016000604051808303818588803b15801561036757600080fd5b505af115801561037b573d6000803e3d6000fd5b505050505050565b61038b6107d2565b60405163040b850f60e31b81526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063205c287890604401600060405180830381600087803b15801561036757600080fd5b606060006104016107ff565b61040c85858561086f565b915091505b935093915050565b600083358060208601356104306040880188610fee565b60405161043e929190611035565b6040519081900390206104546060890189610fee565b604051610462929190611035565b604051908190039020608089013561047d60e08b018b610fee565b61048c91603491601491611045565b6104959161106f565b604080516001600160a01b0390971660208801528601949094526060850192909252608084015260a08084019190915260c08084019290925287013560e0830152860135610100820152466101208201523061014082015265ffffffffffff80861661016083015284166101808201526101a001604051602081830303815290604052805190602001209150509392505050565b6105316107d2565b61053b6000610a27565b565b6105456107ff565b6105528585858585610a77565b5050505050565b600080368161056b8560348189611045565b810190610578919061108d565b9094509250858561058b603460406110c0565b610596928290611045565b949793965094505050565b6105a96107d2565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb9fe6bf6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561060457600080fd5b505af1158015610618573d6000803e3d6000fd5b50505050565b6106266107d2565b60405163611d2e7560e11b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c23a5cea90602401600060405180830381600087803b15801561068957600080fd5b505af1158015610552573d6000803e3d6000fd5b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610704573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072891906110e1565b905090565b60405163b760faf960e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b760faf99034906024016000604051808303818588803b15801561068957600080fd5b6107976107d2565b6001600160a01b0381166107c657604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6107cf81610a27565b50565b6000546001600160a01b0316331461053b5760405163118cdaa760e01b81523360048201526024016107bd565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461053b5760405162461bcd60e51b815260206004820152601560248201527414d95b99195c881b9bdd08115b9d1c9e541bda5b9d605a1b60448201526064016107bd565b606060008080368161088761023d60e08b018b610fee565b9296509094509250905060408114806108a05750604181145b610914576040805162461bcd60e51b81526020600482015260248101919091527f566572696679696e675061796d61737465723a20696e76616c6964207369676e60448201527f6174757265206c656e67746820696e207061796d6173746572416e644461746160648201526084016107bd565b60006109576109248b8787610419565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b90506109998184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610aaf92505050565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146109fc576109dd60018686610adb565b6040518060200160405280600081525090965096505050505050610411565b610a0860008686610adb565b6040805160208101909152600081529b909a5098505050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60405162461bcd60e51b815260206004820152600d60248201526c6d757374206f7665727269646560981b60448201526064016107bd565b600080600080610abf8686610b13565b925092509250610acf8282610b60565b50909150505b92915050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610b03576000610b06565b60015b60ff161717949350505050565b60008060008351604103610b4d5760208401516040850151606086015160001a610b3f88828585610c1d565b955095509550505050610b59565b50508151600091506002905b9250925092565b6000826003811115610b7457610b746110fa565b03610b7d575050565b6001826003811115610b9157610b916110fa565b03610baf5760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115610bc357610bc36110fa565b03610be45760405163fce698f760e01b8152600481018290526024016107bd565b6003826003811115610bf857610bf86110fa565b03610c19576040516335e2f38360e21b8152600481018290526024016107bd565b5050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610c585750600091506003905082610ce2565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610cac573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610cd857506000925060019150829050610ce2565b9250600091508190505b9450945094915050565b600060208284031215610cfe57600080fd5b813563ffffffff81168114610d1257600080fd5b9392505050565b6001600160a01b03811681146107cf57600080fd5b60008060408385031215610d4157600080fd5b8235610d4c81610d19565b946020939093013593505050565b60006101208284031215610d6d57600080fd5b50919050565b600080600060608486031215610d8857600080fd5b833567ffffffffffffffff811115610d9f57600080fd5b610dab86828701610d5a565b9660208601359650604090950135949350505050565b604081526000835180604084015260005b81811015610def5760208187018101516060868401015201610dd2565b506000606082850101526060601f19601f8301168401019150508260208301529392505050565b803565ffffffffffff81168114610e2c57600080fd5b919050565b600080600060608486031215610e4657600080fd5b833567ffffffffffffffff811115610e5d57600080fd5b610e6986828701610d5a565b935050610e7860208501610e16565b9150610e8660408501610e16565b90509250925092565b60008083601f840112610ea157600080fd5b50813567ffffffffffffffff811115610eb957600080fd5b602083019150836020828501011115610ed157600080fd5b9250929050565b600080600080600060808688031215610ef057600080fd5b853560038110610eff57600080fd5b9450602086013567ffffffffffffffff811115610f1b57600080fd5b610f2788828901610e8f565b9699909850959660408101359660609091013595509350505050565b60008060208385031215610f5657600080fd5b823567ffffffffffffffff811115610f6d57600080fd5b610f7985828601610e8f565b90969095509350505050565b600065ffffffffffff808716835280861660208401525060606040830152826060830152828460808401376000608084840101526080601f19601f850116830101905095945050505050565b600060208284031215610fe357600080fd5b8135610d1281610d19565b6000808335601e1984360301811261100557600080fd5b83018035915067ffffffffffffffff82111561102057600080fd5b602001915036819003821315610ed157600080fd5b8183823760009101908152919050565b6000808585111561105557600080fd5b8386111561106257600080fd5b5050820193919092039150565b80356020831015610ad557600019602084900360031b1b1692915050565b600080604083850312156110a057600080fd5b6110a983610e16565b91506110b760208401610e16565b90509250929050565b80820180821115610ad557634e487b7160e01b600052601160045260246000fd5b6000602082840312156110f357600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fdfea26469706673582212209da0f81924019274222346779de206a7e6bccf682a1e50527de363f369f94d0564736f6c634300081700330000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032", - pad(owner), - pad(owner) - ]) - -// Creates the call that deploys the VerifyingPaymaster v0.6 -const VERIFYING_PAYMASTER_V06_CALL = (owner: Address): Hex => - concat([ - "0x000000000000000000000000000000000000000000000000000000000000000060c06040523480156200001157600080fd5b5060405162001401380380620014018339810160408190526200003491620001ad565b81620000403362000066565b6001600160a01b03908116608052811660a0526200005e81620000b6565b5050620001ec565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b620000c062000139565b6001600160a01b0381166200012b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b620001368162000066565b50565b6000546001600160a01b03163314620001955760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000122565b565b6001600160a01b03811681146200013657600080fd5b60008060408385031215620001c157600080fd5b8251620001ce8162000197565b6020840151909250620001e18162000197565b809150509250929050565b60805160a0516111b76200024a600039600081816101340152610a310152600081816102360152818161031a015281816103b1015281816104ac01528181610540015281816105b701528181610644015261083e01526111b76000f3fe6080604052600436106100e85760003560e01c8063a9a234091161008a578063c399ec8811610059578063c399ec881461028d578063d0e30db0146102a2578063f2fde38b146102aa578063f465c77e146102ca57600080fd5b8063a9a2340914610204578063b0d691fe14610224578063bb9fe6bf14610258578063c23a5cea1461026d57600080fd5b8063715018a6116100c6578063715018a6146101735780638da5cb5b1461018857806394d4ad60146101a657806394e1fc19146101d657600080fd5b80630396cb60146100ed578063205c28781461010257806323d9ac9b14610122575b600080fd5b6101006100fb366004610d63565b6102f8565b005b34801561010e57600080fd5b5061010061011d366004610da5565b610383565b34801561012e57600080fd5b506101567f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561017f57600080fd5b506101006103f5565b34801561019457600080fd5b506000546001600160a01b0316610156565b3480156101b257600080fd5b506101c66101c1366004610e13565b610409565b60405161016a9493929190610e55565b3480156101e257600080fd5b506101f66101f1366004610ed5565b610446565b60405190815260200161016a565b34801561021057600080fd5b5061010061021f366004610f33565b610488565b34801561023057600080fd5b506101567f000000000000000000000000000000000000000000000000000000000000000081565b34801561026457600080fd5b506101006104a2565b34801561027957600080fd5b50610100610288366004610f93565b610519565b34801561029957600080fd5b506101f661059f565b61010061062f565b3480156102b657600080fd5b506101006102c5366004610f93565b610691565b3480156102d657600080fd5b506102ea6102e5366004610fb0565b61070f565b60405161016a929190611044565b610300610733565b604051621cb65b60e51b815263ffffffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630396cb609034906024016000604051808303818588803b15801561036757600080fd5b505af115801561037b573d6000803e3d6000fd5b505050505050565b61038b610733565b60405163040b850f60e31b81526001600160a01b038381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063205c287890604401600060405180830381600087803b15801561036757600080fd5b6103fd610733565b610407600061078d565b565b600080368161041c605460148789611066565b8101906104299190611090565b909450925061043b8560548189611066565b949793965094505050565b6000610451846107dd565b463085856040516020016104699594939291906110c3565b6040516020818303038152906040528051906020012090509392505050565b610490610833565b61049c848484846108a3565b50505050565b6104aa610733565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb9fe6bf6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561050557600080fd5b505af115801561049c573d6000803e3d6000fd5b610521610733565b60405163611d2e7560e11b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c23a5cea90602401600060405180830381600087803b15801561058457600080fd5b505af1158015610598573d6000803e3d6000fd5b5050505050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610606573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062a919061110b565b905090565b60405163b760faf960e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b760faf99034906024016000604051808303818588803b15801561058457600080fd5b610699610733565b6001600160a01b0381166107035760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61070c8161078d565b50565b6060600061071b610833565b6107268585856108db565b915091505b935093915050565b6000546001600160a01b031633146104075760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106fa565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60603660006107f0610120850185611124565b9150915083610120610180828503038082016040519650602081018701604052808752508183602088013780604083850101836020890101375050505050919050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146104075760405162461bcd60e51b815260206004820152601560248201527414d95b99195c881b9bdd08115b9d1c9e541bda5b9d605a1b60448201526064016106fa565b60405162461bcd60e51b815260206004820152600d60248201526c6d757374206f7665727269646560981b60448201526064016106fa565b60606000808036816108f46101c16101208b018b611124565b92965090945092509050604081148061090d5750604181145b610981576040805162461bcd60e51b81526020600482015260248101919091527f566572696679696e675061796d61737465723a20696e76616c6964207369676e60448201527f6174757265206c656e67746820696e207061796d6173746572416e644461746160648201526084016106fa565b60006109e46109918b8787610446565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050610a268184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ab492505050565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610a8957610a6a60018686610ad8565b604051806020016040528060008152509096509650505050505061072b565b610a9560008686610ad8565b6040805160208101909152600081529b909a5098505050505050505050565b6000806000610ac38585610b10565b91509150610ad081610b55565b509392505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610b00576000610b03565b60015b60ff161717949350505050565b6000808251604103610b465760208301516040840151606085015160001a610b3a87828585610c9f565b94509450505050610b4e565b506000905060025b9250929050565b6000816004811115610b6957610b6961116b565b03610b715750565b6001816004811115610b8557610b8561116b565b03610bd25760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016106fa565b6002816004811115610be657610be661116b565b03610c335760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016106fa565b6003816004811115610c4757610c4761116b565b0361070c5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016106fa565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610cd65750600090506003610d5a565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015610d2a573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610d5357600060019250925050610d5a565b9150600090505b94509492505050565b600060208284031215610d7557600080fd5b813563ffffffff81168114610d8957600080fd5b9392505050565b6001600160a01b038116811461070c57600080fd5b60008060408385031215610db857600080fd5b8235610dc381610d90565b946020939093013593505050565b60008083601f840112610de357600080fd5b50813567ffffffffffffffff811115610dfb57600080fd5b602083019150836020828501011115610b4e57600080fd5b60008060208385031215610e2657600080fd5b823567ffffffffffffffff811115610e3d57600080fd5b610e4985828601610dd1565b90969095509350505050565b600065ffffffffffff808716835280861660208401525060606040830152826060830152828460808401376000608084840101526080601f19601f850116830101905095945050505050565b60006101608284031215610eb457600080fd5b50919050565b803565ffffffffffff81168114610ed057600080fd5b919050565b600080600060608486031215610eea57600080fd5b833567ffffffffffffffff811115610f0157600080fd5b610f0d86828701610ea1565b935050610f1c60208501610eba565b9150610f2a60408501610eba565b90509250925092565b60008060008060608587031215610f4957600080fd5b843560038110610f5857600080fd5b9350602085013567ffffffffffffffff811115610f7457600080fd5b610f8087828801610dd1565b9598909750949560400135949350505050565b600060208284031215610fa557600080fd5b8135610d8981610d90565b600080600060608486031215610fc557600080fd5b833567ffffffffffffffff811115610fdc57600080fd5b610fe886828701610ea1565b9660208601359650604090950135949350505050565b6000815180845260005b8181101561102457602081850181015186830182015201611008565b506000602082860101526020601f19601f83011685010191505092915050565b6040815260006110576040830185610ffe565b90508260208301529392505050565b6000808585111561107657600080fd5b8386111561108357600080fd5b5050820193919092039150565b600080604083850312156110a357600080fd5b6110ac83610eba565b91506110ba60208401610eba565b90509250929050565b60a0815260006110d660a0830188610ffe565b6020830196909652506001600160a01b0393909316604084015265ffffffffffff918216606084015216608090910152919050565b60006020828403121561111d57600080fd5b5051919050565b6000808335601e1984360301811261113b57600080fd5b83018035915067ffffffffffffffff82111561115657600080fd5b602001915036819003821315610b4e57600080fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220bc69dcc52cd6c4ebdf52276b6a56f83b85831b738e3b681ab51ab0bbab6a03c164736f6c634300081100330000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789", - pad(owner) - ]) - -export const setupVerifyingPaymasterV07 = async ( - walletClient: WalletClient, - anvilRpc: string -) => { - const data = VERIFYING_PAYMASTER_V07_CALL(walletClient.account.address) - - const publicClient = createPublicClient({ - transport: http(anvilRpc), - chain: foundry - }) - - await walletClient - .sendTransaction({ - to: DETERMINISTIC_DEPLOYER, - data - }) - .then((hash) => publicClient.waitForTransactionReceipt({ hash })) - - const address = getContractAddress({ - opcode: "CREATE2", - from: DETERMINISTIC_DEPLOYER, - salt: slice(data, 0, 32), - bytecode: slice(data, 32) - }) - - const verifyingPaymaster = getContract({ - address, - abi: VERIFYING_PAYMASTER_V07_ABI, - client: walletClient - }) - - await verifyingPaymaster.write.deposit({ - value: parseEther("50") - }) - - return verifyingPaymaster -} - -export const setupVerifyingPaymasterV06 = async ( - walletClient: WalletClient, - anvilRpc: string -) => { - const data = VERIFYING_PAYMASTER_V06_CALL(walletClient.account.address) - - const publicClient = createPublicClient({ - transport: http(anvilRpc), - chain: foundry - }) - - await walletClient - .sendTransaction({ - to: DETERMINISTIC_DEPLOYER, - data - }) - .then((hash) => publicClient.waitForTransactionReceipt({ hash })) - - const address = getContractAddress({ - opcode: "CREATE2", - from: DETERMINISTIC_DEPLOYER, - salt: slice(data, 0, 32), - bytecode: slice(data, 32) - }) - - const verifyingPaymaster = getContract({ - address, - abi: VERIFYING_PAYMASTER_V06_ABI, - client: walletClient - }) - - await verifyingPaymaster.write.deposit({ - value: parseEther("50") - }) - - return verifyingPaymaster -} diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/index.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/index.ts index 158b84b8..814e750e 100644 --- a/packages/permissionless-test/mock-aa-infra/mock-paymaster/index.ts +++ b/packages/permissionless-test/mock-aa-infra/mock-paymaster/index.ts @@ -4,12 +4,13 @@ import { defineInstance } from "prool" import { http, createPublicClient } from "viem" import { createBundlerClient } from "viem/account-abstraction" import { foundry } from "viem/chains" +import { deployErc20Token } from "../../src/erc20-utils" import { getAnvilWalletClient } from "./helpers/utils" -import { - setupVerifyingPaymasterV06, - setupVerifyingPaymasterV07 -} from "./helpers/verifyingPaymasters" import { createRpcHandler } from "./relay" +import { + SingletonPaymasterV06, + SingletonPaymasterV07 +} from "./singletonPaymasters" export const paymaster = defineInstance( ({ @@ -26,25 +27,28 @@ export const paymaster = defineInstance( name: "mock-paymaster", start: async ({ port = _port }) => { const walletClient = getAnvilWalletClient(anvilRpc) - const verifyingPaymasterV07 = await setupVerifyingPaymasterV07( - walletClient, - anvilRpc - ) - const verifyingPaymasterV06 = await setupVerifyingPaymasterV06( - walletClient, - anvilRpc - ) - const publicClient = createPublicClient({ transport: http(anvilRpc), chain: foundry }) - const bundler = createBundlerClient({ chain: foundry, transport: http(altoRpc) }) + const singletonPaymasterV07 = new SingletonPaymasterV07( + walletClient, + anvilRpc + ) + const singletonPaymasterV06 = new SingletonPaymasterV06( + walletClient, + anvilRpc + ) + + await singletonPaymasterV06.setup() + await singletonPaymasterV07.setup() + await deployErc20Token(walletClient, publicClient) + app.register(cors, { origin: "*", methods: ["POST", "GET", "OPTIONS"] @@ -52,10 +56,8 @@ export const paymaster = defineInstance( const rpcHandler = createRpcHandler( bundler, - verifyingPaymasterV07, - verifyingPaymasterV06, - publicClient, - walletClient + singletonPaymasterV07, + singletonPaymasterV06 ) app.post("/", {}, rpcHandler) diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts index 07852581..2d7c55ce 100644 --- a/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts +++ b/packages/permissionless-test/mock-aa-infra/mock-paymaster/relay.ts @@ -1,19 +1,9 @@ import util from "node:util" import type { FastifyReply, FastifyRequest } from "fastify" import { - type Account, type Address, BaseError, - type Chain, - type Client, - type GetContractReturnType, - type Hex, - type PublicClient, type RpcRequestError, - type Transport, - type WalletClient, - concat, - encodeAbiParameters, getAddress, toHex } from "viem" @@ -23,13 +13,8 @@ import { entryPoint06Address, entryPoint07Address } from "viem/account-abstraction" -import { readContract } from "viem/actions" import { fromZodError } from "zod-validation-error" -import { getPackedUserOperation } from "../../../permissionless" -import { - VERIFYING_PAYMASTER_V06_ABI, - VERIFYING_PAYMASTER_V07_ABI -} from "./helpers/abi" +import { ERC20_ADDRESS } from "../../src/erc20-utils" import { InternalBundlerError, type JsonRpcSchema, @@ -41,24 +26,31 @@ import { pmGetPaymasterStubDataParamsSchema, pmSponsorUserOperationParamsSchema } from "./helpers/schema" -import { maxBigInt } from "./helpers/utils" +import { + type PaymasterMode, + isTokenSupported, + maxBigInt +} from "./helpers/utils" +import { + type SingletonPaymasterV06, + type SingletonPaymasterV07, + getDummyPaymasterData +} from "./singletonPaymasters" const handleMethodV06 = async ( userOperation: UserOperation<"0.6">, + paymasterMode: PaymasterMode, bundler: BundlerClient, - verifyingPaymasterV06: GetContractReturnType< - typeof VERIFYING_PAYMASTER_V06_ABI - >, - publicClient: Client, - walletClient: WalletClient, + singletonPaymasterV06: SingletonPaymasterV06, estimateGas: boolean ) => { let op = { ...userOperation, - paymasterAndData: concat([ - verifyingPaymasterV06.address, - "0x000000000000000000000000000000000000000000000000000000006602f66a0000000000000000000000000000000000000000000000000000000000000000dba7a71bd49ae0174b1e4577b28f8b7c262d4085cfa192f1c19b516c85d2d1ef17eadeb549d71caf5d5f24fb6519088c1c13427343843131dd6ec19a3c6a350e1b" - ]) + ...getDummyPaymasterData( + true, + singletonPaymasterV06.singletonPaymaster.address, + paymasterMode + ) } const callGasLimit = userOperation.callGasLimit @@ -100,47 +92,11 @@ const handleMethodV06 = async ( ) } - const validAfter = 0 - const validUntil = Math.floor(Date.now() / 1000) + 6000 - op.paymasterAndData = concat([ - verifyingPaymasterV06.address, - encodeAbiParameters( - [ - { name: "validUntil", type: "uint48" }, - { name: "validAfter", type: "uint48" } - ], - [validUntil, validAfter] - ), - toHex(0, { size: 65 }) - ]) - - const hash = await readContract(publicClient, { - abi: VERIFYING_PAYMASTER_V06_ABI, - functionName: "getHash", - address: verifyingPaymasterV06.address, - args: [{ ...op, initCode: op.initCode ?? "0x" }, validUntil, validAfter] - }) - - const sig = await walletClient.signMessage({ - message: { raw: hash } - }) - const paymasterAndData = concat([ - verifyingPaymasterV06.address, - encodeAbiParameters( - [ - { name: "validUntil", type: "uint48" }, - { name: "validAfter", type: "uint48" } - ], - [validUntil, validAfter] - ), - sig - ]) - const result = { preVerificationGas: toHex(op.preVerificationGas), callGasLimit: toHex(op.callGasLimit), verificationGasLimit: toHex(op.verificationGasLimit || 0), - paymasterAndData + ...(await singletonPaymasterV06.encodePaymasterData(op, paymasterMode)) } return result @@ -148,19 +104,14 @@ const handleMethodV06 = async ( const handleMethodV07 = async ( userOperation: UserOperation<"0.7">, + paymasterMode: PaymasterMode, bundler: BundlerClient, - verifyingPaymasterV07: GetContractReturnType< - typeof VERIFYING_PAYMASTER_V07_ABI - >, - publicClient: Client, - walletClient: WalletClient, + singletonPaymasterV07: SingletonPaymasterV07, estimateGas: boolean ) => { let op = { ...userOperation, - paymaster: verifyingPaymasterV07.address, - paymasterData: - "0x000000000000000000000000000000000000000000000000000000006602f66a0000000000000000000000000000000000000000000000000000000000000000dba7a71bd49ae0174b1e4577b28f8b7c262d4085cfa192f1c19b516c85d2d1ef17eadeb549d71caf5d5f24fb6519088c1c13427343843131dd6ec19a3c6a350e1b" as Hex + ...singletonPaymasterV07.getDummyPaymasterData(paymasterMode) } const callGasLimit = userOperation.callGasLimit @@ -203,42 +154,6 @@ const handleMethodV07 = async ( ) } - const validAfter = 0 - const validUntil = Math.floor(Date.now() / 1000) + 6000 - op.paymasterData = concat([ - encodeAbiParameters( - [ - { name: "validUntil", type: "uint48" }, - { name: "validAfter", type: "uint48" } - ], - [validUntil, validAfter] - ), - toHex(0, { size: 65 }) - ]) - op.paymaster = verifyingPaymasterV07.address - - const hash = await readContract(publicClient, { - abi: VERIFYING_PAYMASTER_V07_ABI, - functionName: "getHash", - address: verifyingPaymasterV07.address, - args: [getPackedUserOperation(op), validUntil, validAfter] - }) - - const sig = await walletClient.signMessage({ - message: { raw: hash } - }) - const paymaster = verifyingPaymasterV07.address - const paymasterData = concat([ - encodeAbiParameters( - [ - { name: "validUntil", type: "uint48" }, - { name: "validAfter", type: "uint48" } - ], - [validUntil, validAfter] - ), - sig - ]) - const result = { preVerificationGas: toHex(op.preVerificationGas), callGasLimit: toHex(op.callGasLimit), @@ -247,8 +162,7 @@ const handleMethodV07 = async ( ), paymasterPostOpGasLimit: toHex(op.paymasterPostOpGasLimit || 0), verificationGasLimit: toHex(op.verificationGasLimit || 0), - paymaster, - paymasterData + ...(await singletonPaymasterV07.encodePaymasterData(op, paymasterMode)) } return result @@ -256,14 +170,8 @@ const handleMethodV07 = async ( const handleMethod = async ( bundler: BundlerClient, - verifyingPaymasterV07: GetContractReturnType< - typeof VERIFYING_PAYMASTER_V07_ABI - >, - verifyingPaymasterV06: GetContractReturnType< - typeof VERIFYING_PAYMASTER_V06_ABI - >, - publicClient: PublicClient, - walletClient: WalletClient, + singletonPaymasterV07: SingletonPaymasterV07, + singletonPaymasterV06: SingletonPaymasterV06, parsedBody: JsonRpcSchema ) => { if (parsedBody.method === "pm_sponsorUserOperation") { @@ -283,10 +191,9 @@ const handleMethod = async ( if (entryPoint === entryPoint07Address) { return await handleMethodV07( userOperation, + { mode: "verifying" }, bundler, - verifyingPaymasterV07, - publicClient, - walletClient, + singletonPaymasterV07, true ) } @@ -294,10 +201,9 @@ const handleMethod = async ( if (entryPoint === entryPoint06Address) { return await handleMethodV06( userOperation, + { mode: "verifying" }, bundler, - verifyingPaymasterV06, - publicClient, - walletClient, + singletonPaymasterV06, true ) } @@ -320,7 +226,9 @@ const handleMethod = async ( ) } - const [, entryPoint] = params.data + const [, entryPoint, , data] = params.data + + const paymasterMode = getPaymasterMode(data) const sponsorData = { name: "Pimlico", @@ -329,11 +237,9 @@ const handleMethod = async ( if (entryPoint === entryPoint07Address) { return { - paymaster: verifyingPaymasterV07.address, - paymasterData: - "0x00000000000000000000000000000000000000000000000000000101010101010000000000000000000000000000000000000000000000000000000000000000cd91f19f0f19ce862d7bec7b7d9b95457145afc6f639c28fd0360f488937bfa41e6eedcd3a46054fd95fcd0e3ef6b0bc0a615c4d975eef55c8a3517257904d5b1c", + ...singletonPaymasterV07.getDummyPaymasterData(paymasterMode), paymasterVerificationGasLimit: toHex(50_000n), - paymasterPostOpGasLimit: toHex(20_000n), + paymasterPostOpGasLimit: toHex(100_000n), sponsor: sponsorData, isFinal: false } @@ -341,7 +247,7 @@ const handleMethod = async ( if (entryPoint === entryPoint06Address) { return { - paymasterAndData: `${verifyingPaymasterV06.address}00000000000000000000000000000000000000000000000000000101010101010000000000000000000000000000000000000000000000000000000000000000cd91f19f0f19ce862d7bec7b7d9b95457145afc6f639c28fd0360f488937bfa41e6eedcd3a46054fd95fcd0e3ef6b0bc0a615c4d975eef55c8a3517257904d5b1c`, + ...singletonPaymasterV06.getDummyPaymasterData(paymasterMode), sponsor: sponsorData, isFinal: false } @@ -363,28 +269,31 @@ const handleMethod = async ( ) } - const [userOperation, entryPoint] = params.data + const [userOperation, entryPoint, , data] = params.data + const paymasterMode = getPaymasterMode(data) if (entryPoint === entryPoint07Address) { - return await handleMethodV07( + const { paymaster, paymasterData } = await handleMethodV07( userOperation as UserOperation<"0.7">, + paymasterMode, bundler, - verifyingPaymasterV07, - publicClient, - walletClient, + singletonPaymasterV07, false ) + + return { paymaster, paymasterData } } if (entryPoint === entryPoint06Address) { - return await handleMethodV06( + const { paymasterAndData } = await handleMethodV06( userOperation, + paymasterMode, bundler, - verifyingPaymasterV06, - publicClient, - walletClient, + singletonPaymasterV06, false ) + + return { paymasterAndData } } throw new RpcError( @@ -422,6 +331,11 @@ const handleMethod = async ( const quotes = { [getAddress("0xffffffffffffffffffffffffffffffffffffffff")]: { + exchangeRateNativeToUsd: "0x1a2b3c4d5e6f7890abcdef", + exchangeRate: "0x3a7b9c8d6e5f4321", + postOpGas: "0x1a2b3c" + }, + [ERC20_ADDRESS]: { exchangeRateNativeToUsd: "0x5cc717fbb3450c0000000", exchangeRate: "0x5cc717fbb3450c0000", postOpGas: "0xc350" @@ -430,9 +344,9 @@ const handleMethod = async ( let paymaster: Address if (entryPoint === entryPoint07Address) { - paymaster = verifyingPaymasterV07.address + paymaster = singletonPaymasterV07.singletonPaymaster.address } else { - paymaster = verifyingPaymasterV06.address + paymaster = singletonPaymasterV06.singletonPaymaster.address } return { @@ -454,14 +368,8 @@ const handleMethod = async ( export const createRpcHandler = ( bundler: BundlerClient, - verifyingPaymasterV07: GetContractReturnType< - typeof VERIFYING_PAYMASTER_V07_ABI - >, - verifyingPaymasterV06: GetContractReturnType< - typeof VERIFYING_PAYMASTER_V06_ABI - >, - publicClient: PublicClient, - walletClient: WalletClient + singletonPaymasterV07: SingletonPaymasterV07, + singletonPaymasterV06: SingletonPaymasterV06 ) => { return async (request: FastifyRequest, _reply: FastifyReply) => { const body = request.body @@ -476,10 +384,8 @@ export const createRpcHandler = ( try { const result = await handleMethod( bundler, - verifyingPaymasterV07, - verifyingPaymasterV06, - publicClient, - walletClient, + singletonPaymasterV07, + singletonPaymasterV06, parsedBody.data ) @@ -508,3 +414,13 @@ export const createRpcHandler = ( } } } + +const getPaymasterMode = (data: any): PaymasterMode => { + if (data !== null && "token" in data) { + isTokenSupported(data.token) + + return { mode: "erc20", token: data.token } + } + + return { mode: "verifying" } +} diff --git a/packages/permissionless-test/mock-aa-infra/mock-paymaster/singletonPaymasters.ts b/packages/permissionless-test/mock-aa-infra/mock-paymaster/singletonPaymasters.ts new file mode 100644 index 00000000..ca8be1ca --- /dev/null +++ b/packages/permissionless-test/mock-aa-infra/mock-paymaster/singletonPaymasters.ts @@ -0,0 +1,381 @@ +import { + http, + type Account, + type Address, + type Chain, + type GetContractReturnType, + type Hex, + type PublicClient, + type Transport, + type WalletClient, + concat, + createPublicClient, + encodePacked, + getContract, + getContractAddress, + getCreate2Address, + pad, + parseEther, + slice, + toBytes +} from "viem" +import { + type UserOperation, + toPackedUserOperation +} from "viem/account-abstraction" +import { foundry } from "viem/chains" +import { getPublicClient } from "../../src/utils" +import { + SINGLETON_PAYMASTER_V06_ABI, + SINGLETON_PAYMASTER_V07_ABI +} from "./helpers/abi" +import type { PaymasterMode } from "./helpers/utils" + +const DETERMINISTIC_DEPLOYER = "0x4e59b44847b379578588920ca78fbf26c0b4956c" + +const EXCHANGE_RATE = 30_000_000 +const POST_OP_GAS_OVERHEAD = 100_000 + +export const getDummyPaymasterData = ( + isV6: boolean, + paymaster: Address, + paymasterMode: PaymasterMode +): { paymaster: Address; paymasterData: Hex } | { paymasterAndData: Hex } => { + let encodedDummyData: Hex + + const validUntil = 0 + const validAfter = 0 + const mode = paymasterMode.mode === "verifying" ? 0 : 1 + + if (paymasterMode.mode === "verifying") { + encodedDummyData = encodePacked( + [ + "uint8", // mode + "uint48", // validUntil + "uint48", // validAfter + "bytes" // signature + ], + [ + mode, + validUntil, + validAfter, + "0xcd91f19f0f19ce862d7bec7b7d9b95457145afc6f639c28fd0360f488937bfa41e6eedcd3a46054fd95fcd0e3ef6b0bc0a615c4d975eef55c8a3517257904d5b1c" + ] + ) + } else { + encodedDummyData = encodePacked( + [ + "uint8", // mode + "uint48", // validUntil + "uint48", // validAfter + "address", // token + "uint128", // postOpGasOverhead + "uint256", // exchangeRate + "bytes" // signature + ], + [ + mode, + validUntil, + validAfter, + paymasterMode.token, + POST_OP_GAS_OVERHEAD, + EXCHANGE_RATE, + "0xcd91f19f0f19ce862d7bec7b7d9b95457145afc6f639c28fd0360f488937bfa41e6eedcd3a46054fd95fcd0e3ef6b0bc0a615c4d975eef55c8a3517257904d5b1c" + ] + ) + } + + if (isV6) { + return { + paymasterAndData: concat([paymaster, encodedDummyData]) + } + } + + return { + paymaster, + paymasterData: encodedDummyData + } +} + +// Creates the call that deploys the SingletonPaymaster v0.7 +const SINGLETON_PAYMASTER_V07_CALL = (owner: Address): Hex => + concat([ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x610160604052600060a052600160c052605060e052600c6101005260346101205260146101405234801561003257600080fd5b50604051612634380380612634833981016040819052610051916101aa565b828282808383806001600160a01b03811661008657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61008f81610128565b50506001600160a01b031660805260005b81518110156100fa5760018060008484815181106100c0576100c061029d565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff19169115159190911790556001016100a0565b5050600280546001600160a01b0319166001600160a01b039390931692909217909155506102b39350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811461018f57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b6000806000606084860312156101bf57600080fd5b6101c884610178565b92506101d660208501610178565b60408501519092506001600160401b038111156101f257600080fd5b8401601f8101861361020357600080fd5b80516001600160401b0381111561021c5761021c610194565b604051600582901b90603f8201601f191681016001600160401b038111828210171561024a5761024a610194565b60405291825260208184018101929081018984111561026857600080fd5b6020850194505b8385101561028e5761028085610178565b81526020948501940161026f565b50809450505050509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e0516101005161012051610140516122b36103816000396000505060008181610c020152610dc7015260008181610665015261140801526000818161069901526115a4015260008181610c2e01528181610d0401528181610fb201526112a601526000818161063401528181610c5f01528181610cc50152818161110401526111e7015260008181610327015281816104370152818161058c01528181610700015281816107cd01528181610856015281816109090152610b6201526122b36000f3fe6080604052600436106101445760003560e01c80637c627b21116100c0578063c399ec8811610074578063eb12d61e11610059578063eb12d61e1461039b578063f0f44260146103bb578063f2fde38b146103db57600080fd5b8063c399ec881461037e578063d0e30db01461039357600080fd5b8063b0d691fe116100a5578063b0d691fe14610315578063bb9fe6bf14610349578063c23a5cea1461035e57600080fd5b80637c627b21146102ca5780638da5cb5b146102ea57600080fd5b80635525dcfb1161011757806363b241aa116100fc57806363b241aa14610255578063715018a614610275578063736c0d5b1461028a57600080fd5b80635525dcfb146101d557806361d027b31461020357600080fd5b80630396cb60146101495780630e316ab71461015e578063205c28781461017e57806352b7512c1461019e575b600080fd5b61015c610157366004611ba1565b6103fb565b005b34801561016a57600080fd5b5061015c610179366004611c00565b6104ad565b34801561018a57600080fd5b5061015c610199366004611c1d565b610538565b3480156101aa57600080fd5b506101be6101b9366004611c62565b6105d0565b6040516101cc929190611cb0565b60405180910390f35b3480156101e157600080fd5b506101f56101f0366004611d23565b6105f3565b6040519081526020016101cc565b34801561020f57600080fd5b506002546102309073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101cc565b34801561026157600080fd5b506101f5610270366004611d55565b610630565b34801561028157600080fd5b5061015c6106c6565b34801561029657600080fd5b506102ba6102a5366004611c00565b60016020526000908152604090205460ff1681565b60405190151581526020016101cc565b3480156102d657600080fd5b5061015c6102e5366004611dab565b6106da565b3480156102f657600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610230565b34801561032157600080fd5b506102307f000000000000000000000000000000000000000000000000000000000000000081565b34801561035557600080fd5b5061015c6106f6565b34801561036a57600080fd5b5061015c610379366004611c00565b610780565b34801561038a57600080fd5b506101f5610825565b61015c6108db565b3480156103a757600080fd5b5061015c6103b6366004611c00565b610963565b3480156103c757600080fd5b5061015c6103d6366004611c00565b6109eb565b3480156103e757600080fd5b5061015c6103f6366004611c00565b610a8e565b610403610af7565b6040517f0396cb6000000000000000000000000000000000000000000000000000000000815263ffffffff821660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690630396cb609034906024016000604051808303818588803b15801561049157600080fd5b505af11580156104a5573d6000803e3d6000fd5b505050505050565b6104b5610af7565b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905590519182527f3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b91015b60405180910390a150565b610540610af7565b6040517f205c287800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063205c287890604401600060405180830381600087803b15801561049157600080fd5b606060006105dc610b4a565b6105e7858585610be9565b91509150935093915050565b6000670de0b6b3a7640000826106098587611e77565b6106139088611e8e565b61061d9190611e77565b6106279190611ea1565b95945050505050565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168360ff16036106935761068c827f000000000000000000000000000000000000000000000000000000000000000060ff16610d50565b90506106c0565b61068c827f000000000000000000000000000000000000000000000000000000000000000060ff16610d50565b92915050565b6106ce610af7565b6106d86000610ecd565b565b6106e2610b4a565b6106ef8585858585610f42565b5050505050565b6106fe610af7565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663bb9fe6bf6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561076657600080fd5b505af115801561077a573d6000803e3d6000fd5b50505050565b610788610af7565b6040517fc23a5cea00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c23a5cea90602401600060405180830381600087803b15801561081157600080fd5b505af11580156106ef573d6000803e3d6000fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d69190611edc565b905090565b6040517fb760faf90000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b760faf99034906024016000604051808303818588803b15801561081157600080fd5b61096b610af7565b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602081815260409283902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690921790915590519182527f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f24910161052d565b6109f3610af7565b6002546040805173ffffffffffffffffffffffffffffffffffffffff928316815291831660208301527f4ab5be82436d353e61ca18726e984e561f5c1cc7c6d38b29d2553c790434705a910160405180910390a1600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610a96610af7565b73ffffffffffffffffffffffffffffffffffffffff8116610aeb576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024015b60405180910390fd5b610af481610ecd565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106d8576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610ae2565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f53656e646572206e6f7420456e747279506f696e7400000000000000000000006044820152606401610ae2565b60606000803681610c26610c0060e08a018a611ef5565b7f000000000000000000000000000000000000000000000000000000000000000061103e565b9250925092507f000000000000000000000000000000000000000000000000000000000000000060ff168360ff1614158015610c8857507f000000000000000000000000000000000000000000000000000000000000000060ff168360ff1614155b15610cbf576040517f654a4f2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606060007f000000000000000000000000000000000000000000000000000000000000000060ff168560ff1603610d0257610cfc8a85858c6110de565b90925090505b7f000000000000000000000000000000000000000000000000000000000000000060ff168560ff1603610d4157610d3b8a85858c61128b565b90925090505b90999098509650505050505050565b60008083356020850135608086013560a087013560c0880135610d7660408a018a611ef5565b604051610d84929190611f61565b604051908190039020610d9a60608b018b611ef5565b604051610da8929190611f61565b604051908190039020610dbe60e08c018c611ef5565b600090610deb8d7f0000000000000000000000000000000000000000000000000000000000000000611e8e565b92610df893929190611f71565b604051610e06929190611f61565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff90991660208301528101969096526060860194909452608085019290925260a084015260c083015260e082015261010081019190915261012001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301819052469183019190915230606083015291506080016040516020818303038152906040528051906020012091505092915050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000806000806000610f54898961134d565b5050945094509450945094506000610f8088846fffffffffffffffffffffffffffffffff1689876105f3565b600254909150610faa908690889073ffffffffffffffffffffffffffffffffffffffff16846113a2565b6040805160ff7f000000000000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff8781166020830152918101839052606081018690529087169083907f7a270f29ae17e8e2304ff1245deb50c3b6206bca82928d904f3e284d35c5ffd29060800160405180910390a35050505050505050505050565b6000368161104d846001611e8e565b851015611086576040517fcc32193e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868587611096826001611e8e565b926110a393929190611f71565b6110ac91611f9b565b60f81c905036600088886110c1896001611e8e565b6110cc928290611f71565b939a9099509297509195505050505050565b606060008060003660006110f289896113ff565b9350935093509350600061115c6111297f00000000000000000000000000000000000000000000000000000000000000008d610630565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b905060006111a08285858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061150a92505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205491925060ff909116906111db82158989611534565b90508d356040805160ff7f0000000000000000000000000000000000000000000000000000000000000000168152600060208201819052918101829052606081019190915273ffffffffffffffffffffffffffffffffffffffff91909116908c907f7a270f29ae17e8e2304ff1245deb50c3b6206bca82928d904f3e284d35c5ffd29060800160405180910390a36040805160208101909152600081529e909d509b505050505050505050505050565b606060008061129a868661156c565b905060006112cb6111297f00000000000000000000000000000000000000000000000000000000000000008a610630565b905060006112dd828460a0015161150a565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020908152604082205486519187015193945060ff169261131e91841591611534565b9050600061133b8c8760600151886080015189604001518d61181e565b9c919b50909950505050505050505050565b600080808080808080611362898b018b612021565b9050806000015181602001518260400151836060015184608001518560a001518660c0015197509750975097509750975097505092959891949750929550565b60405181606052826040528360601b602c526f23b872dd000000000000000000000000600c52602060006064601c6000895af13d1560016000511417166113f157637939f4246000526004601cfd5b600060605260405250505050565b600080368160ff7f000000000000000000000000000000000000000000000000000000000000000016851015611461576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611470600682888a611f71565b611479916120e3565b60d01c9050600061148e600c6006898b611f71565b611497916120e3565b60d01c90503660006114ac89600c818d611f71565b9092509050604081148015906114c3575060418114155b156114fa576040517ff95eeeac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9299919850965090945092505050565b60008060008061151a8686611952565b92509250925061152a828261199f565b5090949350505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b8561155c57600061155f565b60015b60ff161717949350505050565b6040805160c0810182526000808252602082018190529181018290526060808201839052608082019290925260a081019190915260ff7f0000000000000000000000000000000000000000000000000000000000000000168210156115fd576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061160c6006828587611f71565b611615916120e3565b60d01c9050600061162a600c60068688611f71565b611633916120e3565b60d01c905060006116486020600c8789611f71565b61165191612148565b60601c9050600061166660306020888a611f71565b61166f916121ad565b60801c9050600061168460506030898b611f71565b61168d91612212565b905036600061169f896050818d611f71565b909250905073ffffffffffffffffffffffffffffffffffffffff85166116f1576040517f33c1dac900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260000361172b576040517f5b33c69600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040811480159061173d575060418114155b15611774576040517ff95eeeac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518060c001604052808965ffffffffffff1681526020018865ffffffffffff168152602001866fffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff16815260200185815260200184848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509152509b9a5050505050505050505050565b6040805160e081019091526060908061183a6020890189611c00565b73ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001846fffffffffffffffffffffffffffffffff1681526020018381526020016000815260200160008152506040516020016119389190600060e08201905073ffffffffffffffffffffffffffffffffffffffff835116825273ffffffffffffffffffffffffffffffffffffffff6020840151166020830152604083015160408301526fffffffffffffffffffffffffffffffff60608401511660608301526080830151608083015260a083015160a083015260c083015160c083015292915050565b604051602081830303815290604052905095945050505050565b6000806000835160410361198c5760208401516040850151606086015160001a61197e88828585611aa7565b955095509550505050611998565b50508151600091506002905b9250925092565b60008260038111156119b3576119b361224e565b036119bc575050565b60018260038111156119d0576119d061224e565b03611a07576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115611a1b57611a1b61224e565b03611a55576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610ae2565b6003826003811115611a6957611a6961224e565b03611aa3576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610ae2565b5050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611ae25750600091506003905082611b97565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611b36573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611b8d57506000925060019150829050611b97565b9250600091508190505b9450945094915050565b600060208284031215611bb357600080fd5b813563ffffffff81168114611bc757600080fd5b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610af457600080fd5b8035611bfb81611bce565b919050565b600060208284031215611c1257600080fd5b8135611bc781611bce565b60008060408385031215611c3057600080fd5b8235611c3b81611bce565b946020939093013593505050565b60006101208284031215611c5c57600080fd5b50919050565b600080600060608486031215611c7757600080fd5b833567ffffffffffffffff811115611c8e57600080fd5b611c9a86828701611c49565b9660208601359650604090950135949350505050565b604081526000835180604084015260005b81811015611cde5760208187018101516060868401015201611cc1565b5060006060828501015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150508260208301529392505050565b60008060008060808587031215611d3957600080fd5b5050823594602084013594506040840135936060013592509050565b60008060408385031215611d6857600080fd5b823560ff81168114611d7957600080fd5b9150602083013567ffffffffffffffff811115611d9557600080fd5b611da185828601611c49565b9150509250929050565b600080600080600060808688031215611dc357600080fd5b853560038110611dd257600080fd5b9450602086013567ffffffffffffffff811115611dee57600080fd5b8601601f81018813611dff57600080fd5b803567ffffffffffffffff811115611e1657600080fd5b886020828401011115611e2857600080fd5b959860209190910197509495604081013595606090910135945092505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176106c0576106c0611e48565b808201808211156106c0576106c0611e48565b600082611ed7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215611eee57600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611f2a57600080fd5b83018035915067ffffffffffffffff821115611f4557600080fd5b602001915036819003821315611f5a57600080fd5b9250929050565b8183823760009101908152919050565b60008085851115611f8157600080fd5b83861115611f8e57600080fd5b5050820193919092039150565b80357fff000000000000000000000000000000000000000000000000000000000000008116906001841015611ffa577fff00000000000000000000000000000000000000000000000000000000000000808560010360031b1b82161691505b5092915050565b80356fffffffffffffffffffffffffffffffff81168114611bfb57600080fd5b600060e082840312801561203457600080fd5b6000905060405160e0810181811067ffffffffffffffff82111715612080577f4e487b710000000000000000000000000000000000000000000000000000000083526041600452602483fd5b60405261208c84611bf0565b815261209a60208501611bf0565b6020820152604084810135908201526120b560608501612001565b60608201526080848101359082015260a0808501359082015260c09384013593810193909352509092915050565b80357fffffffffffff00000000000000000000000000000000000000000000000000008116906006841015611ffa577fffffffffffff0000000000000000000000000000000000000000000000000000808560060360031b1b82161691505092915050565b80357fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008116906014841015611ffa577fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808560140360031b1b82161691505092915050565b80357fffffffffffffffffffffffffffffffff000000000000000000000000000000008116906010841015611ffa577fffffffffffffffffffffffffffffffff00000000000000000000000000000000808560100360031b1b82161691505092915050565b803560208310156106c0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea2646970667358221220d4b47765504d1aee07971ecb33f299cd13465059fbfeb55e32bdeb75ec9e629264736f6c634300081a00330000000000000000000000000000000071727de22e5e9d8baf0edac6f37da032", + pad(owner), + "0x00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001", // couldn't get encodeAbiParameters with type address[] to work + pad(owner) + ]) + +// Creates the call that deploys the SingletonPaymaster v0.6 +const SINGLETON_PAYMASTER_V06_CALL = (owner: Address): Hex => + concat([ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x610140604052600060a052600160c052605060e052600c6101005260146101205234801561002c57600080fd5b5060405161270838038061270883398101604081905261004b916101a4565b828282808383806001600160a01b03811661008057604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61008981610122565b50506001600160a01b031660805260005b81518110156100f45760018060008484815181106100ba576100ba610297565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905560010161009a565b5050600280546001600160a01b0319166001600160a01b039390931692909217909155506102ad9350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811461018957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b6000806000606084860312156101b957600080fd5b6101c284610172565b92506101d060208501610172565b60408501519092506001600160401b038111156101ec57600080fd5b8401601f810186136101fd57600080fd5b80516001600160401b038111156102165761021661018e565b604051600582901b90603f8201601f191681016001600160401b03811182821017156102445761024461018e565b60405291825260208184018101929081018984111561026257600080fd5b6020850194505b838510156102885761027a85610172565b815260209485019401610269565b50809450505050509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051610100516101205161239561037360003960008181610e980152610fc70152600081816108da01526114f501526000818161090e0152611691015260008181610d7801528181610ff3015281816110c901526114450152600081816108a9015281816110240152818161108a0152818161129b01526113870152600081816102d501528181610433015281816105880152818161064101528181610708015281816107980152818161084b0152610bd201526123956000f3fe6080604052600436106101445760003560e01c8063b0d691fe116100c0578063dd16f84711610074578063f0f4426011610059578063f0f4426014610389578063f2fde38b146103a9578063f465c77e146103c957600080fd5b8063dd16f84714610349578063eb12d61e1461036957600080fd5b8063c23a5cea116100a5578063c23a5cea1461030c578063c399ec881461032c578063d0e30db01461034157600080fd5b8063b0d691fe146102c3578063bb9fe6bf146102f757600080fd5b806361d027b311610117578063736c0d5b116100fc578063736c0d5b146102385780638da5cb5b14610278578063a9a23409146102a357600080fd5b806361d027b3146101d1578063715018a61461022357600080fd5b80630396cb60146101495780630e316ab71461015e578063205c28781461017e5780635525dcfb1461019e575b600080fd5b61015c610157366004611c95565b6103f7565b005b34801561016a57600080fd5b5061015c610179366004611ced565b6104a9565b34801561018a57600080fd5b5061015c610199366004611d0a565b610534565b3480156101aa57600080fd5b506101be6101b9366004611d36565b6105cc565b6040519081526020015b60405180910390f35b3480156101dd57600080fd5b506002546101fe9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c8565b34801561022f57600080fd5b5061015c610609565b34801561024457600080fd5b50610268610253366004611ced565b60016020526000908152604090205460ff1681565b60405190151581526020016101c8565b34801561028457600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101fe565b3480156102af57600080fd5b5061015c6102be366004611d68565b61061d565b3480156102cf57600080fd5b506101fe7f000000000000000000000000000000000000000000000000000000000000000081565b34801561030357600080fd5b5061015c610637565b34801561031857600080fd5b5061015c610327366004611ced565b6106bb565b34801561033857600080fd5b506101be610767565b61015c61081d565b34801561035557600080fd5b506101be610364366004611e13565b6108a5565b34801561037557600080fd5b5061015c610384366004611ced565b61093b565b34801561039557600080fd5b5061015c6103a4366004611ced565b6109c3565b3480156103b557600080fd5b5061015c6103c4366004611ced565b610a66565b3480156103d557600080fd5b506103e96103e4366004611e69565b610acf565b6040516101c8929190611eb7565b6103ff610af2565b6040517f0396cb6000000000000000000000000000000000000000000000000000000000815263ffffffff821660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690630396cb609034906024016000604051808303818588803b15801561048d57600080fd5b505af11580156104a1573d6000803e3d6000fd5b505050505050565b6104b1610af2565b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905590519182527f3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b91015b60405180910390a150565b61053c610af2565b6040517f205c287800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063205c287890604401600060405180830381600087803b15801561048d57600080fd5b6000670de0b6b3a7640000826105e28587611f59565b6105ec9088611f70565b6105f69190611f59565b6106009190611f83565b95945050505050565b610611610af2565b61061b6000610b45565b565b610625610bba565b61063184848484610c59565b50505050565b61063f610af2565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663bb9fe6bf6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156106a757600080fd5b505af1158015610631573d6000803e3d6000fd5b6106c3610af2565b6040517fc23a5cea00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c23a5cea90602401600060405180830381600087803b15801561074c57600080fd5b505af1158015610760573d6000803e3d6000fd5b5050505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156107f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108189190611fbe565b905090565b6040517fb760faf90000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b760faf99034906024016000604051808303818588803b15801561074c57600080fd5b60007f000000000000000000000000000000000000000000000000000000000000000060ff168360ff160361090857610901827f000000000000000000000000000000000000000000000000000000000000000060ff16610e08565b9050610935565b610901827f000000000000000000000000000000000000000000000000000000000000000060ff16610e08565b92915050565b610943610af2565b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602081815260409283902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690921790915590519182527f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f249101610529565b6109cb610af2565b6002546040805173ffffffffffffffffffffffffffffffffffffffff928316815291831660208301527f4ab5be82436d353e61ca18726e984e561f5c1cc7c6d38b29d2553c790434705a910160405180910390a1600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610a6e610af2565b73ffffffffffffffffffffffffffffffffffffffff8116610ac3576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024015b60405180910390fd5b610acc81610b45565b50565b60606000610adb610bba565b610ae6858585610fad565b91509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461061b576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610aba565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461061b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f53656e646572206e6f7420456e747279506f696e7400000000000000000000006044820152606401610aba565b6000806000806000806000610c6e8a8a611115565b96509650965096509650965096506000818303610c8c575081610ca2565b610c9f83610c9a4885611f70565b61116a565b90505b6000610cc28a876fffffffffffffffffffffffffffffffff16848a6105cc565b905060028d6002811115610cd857610cd8611fd7565b14610df957600254600090610d07908a908c9073ffffffffffffffffffffffffffffffffffffffff1685611182565b905080610d70576040517f1db0f4fb00000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610aba565b6040805160ff7f000000000000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff8b81166020830152918101849052606081018a9052908b169087907f7a270f29ae17e8e2304ff1245deb50c3b6206bca82928d904f3e284d35c5ffd29060800160405180910390a3505b50505050505050505050505050565b600080610e186020850185611ced565b6020850135608086013560a087013560c088013560e08901356101008a0135610e4460608c018c612006565b604051610e52929190612072565b60405180910390208b8060400190610e6a9190612006565b604051610e78929190612072565b604051908190039020610e8f6101208e018e612006565b600090610ebc8f7f0000000000000000000000000000000000000000000000000000000000000000611f70565b92610ec993929190612082565b604051610ed7929190612072565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff909b1660208301528101989098526060880196909652608087019490945260a086019290925260c085015260e084015261010083015261012082015261014081019190915261016001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301819052469183019190915230606083015291506080016040516020818303038152906040528051906020012091505092915050565b60606000803681610feb610fc56101208a018a612006565b7f00000000000000000000000000000000000000000000000000000000000000006111d5565b9250925092507f000000000000000000000000000000000000000000000000000000000000000060ff168360ff161415801561104d57507f000000000000000000000000000000000000000000000000000000000000000060ff168360ff1614155b15611084576040517f654a4f2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606060007f000000000000000000000000000000000000000000000000000000000000000060ff168560ff16036110c7576110c18a85858c611275565b90925090505b7f000000000000000000000000000000000000000000000000000000000000000060ff168560ff1603611106576111008a85858c61142a565b90925090505b90999098509650505050505050565b60008080808080808061112a898b018b6120cc565b9050806000015181602001518260400151836060015184608001518560a001518660c0015197509750975097509750975097505092959891949750929550565b6000818310611179578161117b565b825b9392505050565b600060405182606052836040528460601b602c526f23b872dd000000000000000000000000600c52602060006064601c60008a5af13d156001600051141716915060006060528060405250949350505050565b600036816111e4846001611f70565b85101561121d576040517fcc32193e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600086858761122d826001611f70565b9261123a93929190612082565b6112439161218e565b60f81c90503660008888611258896001611f70565b611263928290612082565b939a9099509297509195505050505050565b6060600080600036600061128989896114ec565b935093509350935060006112f36112c07f00000000000000000000000000000000000000000000000000000000000000008d6108a5565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b905060006113378285858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115f792505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205491925060ff9091169061137282158989611621565b905061138160208f018f611ced565b604080517f000000000000000000000000000000000000000000000000000000000000000060ff1681526000602082018190528183018190526060820152905173ffffffffffffffffffffffffffffffffffffffff92909216918d917f7a270f29ae17e8e2304ff1245deb50c3b6206bca82928d904f3e284d35c5ffd2919081900360800190a36040805160208101909152600081529e909d509b505050505050505050505050565b60606000806114398686611659565b9050600061146a6112c07f00000000000000000000000000000000000000000000000000000000000000008a6108a5565b9050600061147c828460a001516115f7565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020908152604082205486519187015193945060ff16926114bd91841591611621565b905060006114da8c8760600151886080015189604001518d61190b565b9c919b50909950505050505050505050565b600080368160ff7f00000000000000000000000000000000000000000000000000000000000000001685101561154e576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061155d600682888a612082565b611566916121f4565b60d01c9050600061157b600c6006898b612082565b611584916121f4565b60d01c905036600061159989600c818d612082565b9092509050604081148015906115b0575060418114155b156115e7576040517ff95eeeac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9299919850965090945092505050565b6000806000806116078686611a46565b9250925092506116178282611a93565b5090949350505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b8561164957600061164c565b60015b60ff161717949350505050565b6040805160c0810182526000808252602082018190529181018290526060808201839052608082019290925260a081019190915260ff7f0000000000000000000000000000000000000000000000000000000000000000168210156116ea576040517ff96ce32900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006116f96006828587612082565b611702916121f4565b60d01c90506000611717600c60068688612082565b611720916121f4565b60d01c905060006117356020600c8789612082565b61173e91612259565b60601c9050600061175360306020888a612082565b61175c916122be565b60801c9050600061177160506030898b612082565b61177a91612323565b905036600061178c896050818d612082565b909250905073ffffffffffffffffffffffffffffffffffffffff85166117de576040517f33c1dac900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600003611818576040517f5b33c69600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040811480159061182a575060418114155b15611861576040517ff95eeeac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518060c001604052808965ffffffffffff1681526020018865ffffffffffff168152602001866fffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff16815260200185815260200184848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509152509b9a5050505050505050505050565b6040805160e08101909152606090806119276020890189611ced565b73ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001846fffffffffffffffffffffffffffffffff1681526020018381526020018760e001358152602001876101000135815250604051602001611a2c9190600060e08201905073ffffffffffffffffffffffffffffffffffffffff835116825273ffffffffffffffffffffffffffffffffffffffff6020840151166020830152604083015160408301526fffffffffffffffffffffffffffffffff60608401511660608301526080830151608083015260a083015160a083015260c083015160c083015292915050565b604051602081830303815290604052905095945050505050565b60008060008351604103611a805760208401516040850151606086015160001a611a7288828585611b9b565b955095509550505050611a8c565b50508151600091506002905b9250925092565b6000826003811115611aa757611aa7611fd7565b03611ab0575050565b6001826003811115611ac457611ac4611fd7565b03611afb576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115611b0f57611b0f611fd7565b03611b49576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610aba565b6003826003811115611b5d57611b5d611fd7565b03611b97576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610aba565b5050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611bd65750600091506003905082611c8b565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611c2a573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611c8157506000925060019150829050611c8b565b9250600091508190505b9450945094915050565b600060208284031215611ca757600080fd5b813563ffffffff8116811461117b57600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610acc57600080fd5b8035611ce881611cbb565b919050565b600060208284031215611cff57600080fd5b813561117b81611cbb565b60008060408385031215611d1d57600080fd5b8235611d2881611cbb565b946020939093013593505050565b60008060008060808587031215611d4c57600080fd5b5050823594602084013594506040840135936060013592509050565b60008060008060608587031215611d7e57600080fd5b843560038110611d8d57600080fd5b9350602085013567ffffffffffffffff811115611da957600080fd5b8501601f81018713611dba57600080fd5b803567ffffffffffffffff811115611dd157600080fd5b876020828401011115611de357600080fd5b949760209190910196509394604001359392505050565b60006101608284031215611e0d57600080fd5b50919050565b60008060408385031215611e2657600080fd5b823560ff81168114611e3757600080fd5b9150602083013567ffffffffffffffff811115611e5357600080fd5b611e5f85828601611dfa565b9150509250929050565b600080600060608486031215611e7e57600080fd5b833567ffffffffffffffff811115611e9557600080fd5b611ea186828701611dfa565b9660208601359650604090950135949350505050565b604081526000835180604084015260005b81811015611ee55760208187018101516060868401015201611ec8565b5060006060828501015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150508260208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761093557610935611f2a565b8082018082111561093557610935611f2a565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215611fd057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261203b57600080fd5b83018035915067ffffffffffffffff82111561205657600080fd5b60200191503681900382131561206b57600080fd5b9250929050565b8183823760009101908152919050565b6000808585111561209257600080fd5b8386111561209f57600080fd5b5050820193919092039150565b80356fffffffffffffffffffffffffffffffff81168114611ce857600080fd5b600060e08284031280156120df57600080fd5b6000905060405160e0810181811067ffffffffffffffff8211171561212b577f4e487b710000000000000000000000000000000000000000000000000000000083526041600452602483fd5b60405261213784611cdd565b815261214560208501611cdd565b602082015260408481013590820152612160606085016120ac565b60608201526080848101359082015260a0808501359082015260c09384013593810193909352509092915050565b80357fff0000000000000000000000000000000000000000000000000000000000000081169060018410156121ed577fff00000000000000000000000000000000000000000000000000000000000000808560010360031b1b82161691505b5092915050565b80357fffffffffffff000000000000000000000000000000000000000000000000000081169060068410156121ed577fffffffffffff0000000000000000000000000000000000000000000000000000808560060360031b1b82161691505092915050565b80357fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081169060148410156121ed577fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808560140360031b1b82161691505092915050565b80357fffffffffffffffffffffffffffffffff0000000000000000000000000000000081169060108410156121ed577fffffffffffffffffffffffffffffffff00000000000000000000000000000000808560100360031b1b82161691505092915050565b80356020831015610935577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b169291505056fea2646970667358221220b198dacaa988aafcb9441005f2a899880d533689da493c4dc98e301d7822f21a64736f6c634300081a00330000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789", + pad(owner), + "0x00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001", // couldn't get encodeAbiParameters with type address[] to work + pad(owner) + ]) + +const SINGLETON_PAYMASTER_V06_ADDRESS = (owner: Address) => + getCreate2Address({ + from: DETERMINISTIC_DEPLOYER, + salt: slice(SINGLETON_PAYMASTER_V06_CALL(owner), 0, 32), + bytecode: slice(SINGLETON_PAYMASTER_V06_CALL(owner), 32) + }) + +const SINGLETON_PAYMASTER_V07_ADDRESS = (owner: Address) => + getCreate2Address({ + from: DETERMINISTIC_DEPLOYER, + salt: slice(SINGLETON_PAYMASTER_V07_CALL(owner), 0, 32), + bytecode: slice(SINGLETON_PAYMASTER_V07_CALL(owner), 32) + }) + +export class SingletonPaymasterV07 { + private anvilRpc: string + private walletClient: WalletClient + public singletonPaymaster: GetContractReturnType< + typeof SINGLETON_PAYMASTER_V07_ABI, + { + public: PublicClient + wallet: WalletClient + } + > + + constructor( + walletClient: WalletClient, + anvilRpc: string + ) { + this.walletClient = walletClient + this.singletonPaymaster = getContract({ + address: SINGLETON_PAYMASTER_V07_ADDRESS( + walletClient.account.address + ), + abi: SINGLETON_PAYMASTER_V07_ABI, + client: { + wallet: walletClient as WalletClient, + public: getPublicClient(anvilRpc) + } + }) + this.anvilRpc = anvilRpc + } + + public getDummyPaymasterData(paymasterMode: PaymasterMode): { + paymaster: Address + paymasterData: Hex + } { + return getDummyPaymasterData( + false, + this.singletonPaymaster.address, + paymasterMode + ) as { + paymaster: Address + paymasterData: Hex + } + } + + async encodePaymasterData( + op: UserOperation<"0.7">, + paymasterMode: PaymasterMode + ) { + const validAfter = 0 + const validUntil = Math.floor(Date.now() / 1000) + 60_000 + + const mode = paymasterMode.mode === "verifying" ? 0 : 1 + op.paymaster = this.singletonPaymaster.address + op.paymasterData = encodePacked( + ["uint8", "uint48", "uint48"], + [mode, validUntil, validAfter] + ) + + // if ERC-20 mode, add extra ERC-20 fields + if (paymasterMode.mode === "erc20") { + op.paymasterData = encodePacked( + ["bytes", "address", "uint128", "uint256"], + [ + op.paymasterData, + paymasterMode.token, + POST_OP_GAS_OVERHEAD, + EXCHANGE_RATE + ] + ) + } + + const hash = await this.singletonPaymaster.read.getHash([ + mode, + toPackedUserOperation(op) + ]) + + const sig = await this.walletClient.signMessage({ + message: { raw: toBytes(hash) } + }) + + return { + paymaster: this.singletonPaymaster.address, + paymasterData: encodePacked( + ["bytes", "bytes"], + [op.paymasterData, sig] + ) + } + } + + async setup() { + const data = SINGLETON_PAYMASTER_V07_CALL( + this.walletClient.account.address + ) + + const publicClient = createPublicClient({ + transport: http(this.anvilRpc), + chain: foundry + }) + + await this.walletClient + .sendTransaction({ + to: DETERMINISTIC_DEPLOYER, + data + }) + .then((hash) => publicClient.waitForTransactionReceipt({ hash })) + + const address = getContractAddress({ + opcode: "CREATE2", + from: DETERMINISTIC_DEPLOYER, + salt: slice(data, 0, 32), + bytecode: slice(data, 32) + }) + + const singletonPaymaster = getContract({ + address, + abi: SINGLETON_PAYMASTER_V07_ABI, + client: this.walletClient + }) + + await singletonPaymaster.write.deposit({ + value: parseEther("50") + }) + + return singletonPaymaster + } +} + +export class SingletonPaymasterV06 { + private walletClient: WalletClient + public singletonPaymaster: GetContractReturnType< + typeof SINGLETON_PAYMASTER_V06_ABI, + { + public: PublicClient + wallet: WalletClient + } + > + private anvilRpc: string + + constructor( + walletClient: WalletClient, + anvilRpc: string + ) { + this.walletClient = walletClient + this.singletonPaymaster = getContract({ + address: SINGLETON_PAYMASTER_V06_ADDRESS( + walletClient.account.address + ), + abi: SINGLETON_PAYMASTER_V06_ABI, + client: { + wallet: this.walletClient, + public: getPublicClient(anvilRpc) + } + }) + this.anvilRpc = anvilRpc + } + + public getDummyPaymasterData(paymasterMode: PaymasterMode): { + paymasterAndData: Hex + } { + return getDummyPaymasterData( + true, + this.singletonPaymaster.address, + paymasterMode + ) as { + paymasterAndData: Hex + } + } + + async encodePaymasterData( + op: UserOperation<"0.6">, + paymasterMode: PaymasterMode + ) { + const validAfter = 0 + const validUntil = Math.floor(Date.now() / 1000) + 60_000 + const mode = paymasterMode.mode === "verifying" ? 0 : 1 + op.paymasterAndData = encodePacked( + ["address", "uint8", "uint48", "uint48"], + [this.singletonPaymaster.address, mode, validUntil, validAfter] + ) + + if (paymasterMode.mode === "erc20") { + op.paymasterAndData = encodePacked( + ["bytes", "address", "uint128", "uint256"], + [ + op.paymasterAndData, + paymasterMode.token, + POST_OP_GAS_OVERHEAD, + EXCHANGE_RATE + ] + ) + } + + const hash = await this.singletonPaymaster.read.getHash([ + mode, + { + ...op, + initCode: op.initCode || "0x", + paymasterAndData: op.paymasterAndData || "0x" + } + ]) + const sig = await this.walletClient.signMessage({ + message: { raw: hash } + }) + + return { + paymasterAndData: encodePacked( + ["bytes", "bytes"], + [op.paymasterAndData, sig] + ) + } + } + + async setup() { + const data = SINGLETON_PAYMASTER_V06_CALL( + this.walletClient.account.address + ) + + const publicClient = createPublicClient({ + transport: http(this.anvilRpc), + chain: foundry + }) + + await this.walletClient + .sendTransaction({ + to: DETERMINISTIC_DEPLOYER, + data + }) + .then((hash) => publicClient.waitForTransactionReceipt({ hash })) + + const address = getContractAddress({ + opcode: "CREATE2", + from: DETERMINISTIC_DEPLOYER, + salt: slice(data, 0, 32), + bytecode: slice(data, 32) + }) + + const singletonPaymaster = getContract({ + address, + abi: SINGLETON_PAYMASTER_V06_ABI, + client: this.walletClient + }) + + await singletonPaymaster.write.deposit({ + value: parseEther("50") + }) + + return singletonPaymaster + } +} diff --git a/packages/permissionless-test/src/erc20-utils.ts b/packages/permissionless-test/src/erc20-utils.ts new file mode 100644 index 00000000..014521d2 --- /dev/null +++ b/packages/permissionless-test/src/erc20-utils.ts @@ -0,0 +1,80 @@ +import { + type Account, + type Address, + type Chain, + type PublicClient, + type Transport, + type WalletClient, + concat, + encodeFunctionData, + getCreate2Address, + hexToBigInt, + pad, + parseAbi, + toHex +} from "viem" +import { getAnvilWalletClient, getPublicClient } from "./utils" + +const ERC20_BYTECODE = concat([ + "0x60a060405234801561001057600080fd5b50604051610ff0380380610ff083398101604081905261002f9161022c565b6040518060400160405280600981526020016805465737445524332360bc1b8152506040518060400160405280600381526020016205432360ec1b815250816003908161007c919061034d565b506004610089828261034d565b5050506100a63369d3c21bcecceda10000006100b160201b60201c565b60ff166080526104a3565b6001600160a01b0382166100e457600060405163ec442f0560e01b81526004016100db9190610430565b60405180910390fd5b6100f0600083836100f4565b5050565b6001600160a01b03831661011f5780600260008282546101149190610454565b9091555061017e9050565b6001600160a01b0383166000908152602081905260409020548181101561015f5783818360405163391434e360e21b81526004016100db9392919061046d565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b03821661019a576002805482900390556101b9565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516101fc9190610495565b60405180910390a3505050565b60ff8116811461021857600080fd5b50565b805161022681610209565b92915050565b60006020828403121561024157610241600080fd5b600061024d848461021b565b949350505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052602260045260246000fd5b60028104600182168061029557607f821691505b6020821081036102a7576102a761026b565b50919050565b60006102266102b98381565b90565b6102c5836102ad565b815460001960089490940293841b1916921b91909117905550565b60006102ed8184846102bc565b505050565b818110156100f0576103056000826102e0565b6001016102f2565b601f8211156102ed576000818152602090206020601f850104810160208510156103345750805b6103466020601f8601048301826102f2565b5050505050565b81516001600160401b0381111561036657610366610255565b6103708254610281565b61037b82828561030d565b6020601f8311600181146103af57600084156103975750858201515b600019600886021c1981166002860217865550610408565b600085815260208120601f198616915b828110156103df57888501518255602094850194600190920191016103bf565b868310156103fb5784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b60006001600160a01b038216610226565b61042a81610410565b82525050565b602081016102268284610421565b634e487b7160e01b600052601160045260246000fd5b808201808211156102265761022661043e565b8061042a565b6060810161047b8286610421565b6104886020830185610467565b61024d6040830184610467565b602081016102268284610467565b608051610b326104be60003960006101650152610b326000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063313ce56711610081578063a9059cbb1161005b578063a9059cbb146101cf578063dd62ed3e146101e2578063fb4dcefa1461022857600080fd5b8063313ce5671461016357806370a082311461019157806395d89b41146101c757600080fd5b806318160ddd116100b257806318160ddd1461012c57806323b872dd1461013d5780632d688ca81461015057600080fd5b806305ea5c22146100d957806306fdde03146100ee578063095ea7b31461010c575b600080fd5b6100ec6100e7366004610868565b61023b565b005b6100f661024b565b604051610103919061092c565b60405180910390f35b61011f61011a366004610944565b6102dd565b604051610103919061098b565b6002545b604051610103919061099f565b61011f61014b366004610868565b6102f7565b6100ec61015e366004610944565b61031b565b7f000000000000000000000000000000000000000000000000000000000000000060405161010391906109b6565b61013061019f3660046109c4565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100f6610329565b61011f6101dd366004610944565b610338565b6101306101f03660046109ed565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6100ec6102363660046109ed565b610346565b61024683838361037c565b505050565b60606003805461025a90610a4f565b80601f016020809104026020016040519081016040528092919081815260200182805461028690610a4f565b80156102d35780601f106102a8576101008083540402835291602001916102d3565b820191906000526020600020905b8154815290600101906020018083116102b657829003601f168201915b5050505050905090565b6000336102eb81858561037c565b60019150505b92915050565b600033610305858285610389565b610310858585610441565b506001949350505050565b61032582826104ec565b5050565b60606004805461025a90610a4f565b6000336102eb818585610441565b61032582826103778573ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b610441565b6102468383836001610548565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461043b578181101561042c578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161042393929190610a84565b60405180910390fd5b61043b84848484036000610548565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166104915760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b73ffffffffffffffffffffffffffffffffffffffff82166104e15760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b61024683838361068e565b73ffffffffffffffffffffffffffffffffffffffff821661053c5760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b6103256000838361068e565b73ffffffffffffffffffffffffffffffffffffffff84166105985760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b73ffffffffffffffffffffffffffffffffffffffff83166105e85760006040517f94280d620000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600160209081526040808320938716835292905220829055801561043b578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610680919061099f565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff83166106c65780600260008282546106bb9190610ae9565b909155506107589050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020548181101561072c578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161042393929190610a84565b73ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090209082900390555b73ffffffffffffffffffffffffffffffffffffffff8216610781576002805482900390556107ad565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090208054820190555b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161080a919061099f565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff82166102f1565b61083e81610817565b811461084957600080fd5b50565b80356102f181610835565b8061083e565b80356102f181610857565b60008060006060848603121561088057610880600080fd5b600061088c868661084c565b935050602061089d8682870161084c565b92505060406108ae8682870161085d565b9150509250925092565b60005b838110156108d35781810151838201526020016108bb565b50506000910152565b60006108e6825190565b8084526020840193506108fd8185602086016108b8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920192915050565b6020808252810161093d81846108dc565b9392505050565b6000806040838503121561095a5761095a600080fd5b6000610966858561084c565b92505060206109778582860161085d565b9150509250929050565b8015155b82525050565b602081016102f18284610981565b80610985565b602081016102f18284610999565b60ff8116610985565b602081016102f182846109ad565b6000602082840312156109d9576109d9600080fd5b60006109e5848461084c565b949350505050565b60008060408385031215610a0357610a03600080fd5b6000610a0f858561084c565b92505060206109778582860161084c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600281046001821680610a6357607f821691505b602082108103610a7557610a75610a20565b50919050565b61098581610817565b60608101610a928286610a7b565b610a9f6020830185610999565b6109e56040830184610999565b602081016102f18284610a7b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102f1576102f1610aba56fea2646970667358221220d40f68e247510ec8b7876d327ac47b949de248d0626aaf2670151c5e84ee6b4a64736f6c634300081a0033", + pad(toHex(18n)) // constructor args (token_decimals) +]) + +export const deployErc20Token = async ( + walletClient: WalletClient, + publicClient: PublicClient +) => { + if ( + (await publicClient.getCode({ address: ERC20_ADDRESS })) === undefined + ) { + await walletClient.sendTransaction({ + to: "0x4e59b44847b379578588920ca78fbf26c0b4956c", + data: concat([ + "0x0000000000000000000000000000000000000000000000000000000000000000", + ERC20_BYTECODE + ]) + }) + } +} + +export const tokenBalanceOf = async (holder: Address, anvilRpc: string) => { + const publicClient = getPublicClient(anvilRpc) + + const balance = await publicClient.call({ + to: ERC20_ADDRESS, + value: 0n, + data: encodeFunctionData({ + abi: parseAbi(["function balanceOf(address)"]), + args: [holder] + }) + }) + + return hexToBigInt(balance.data ?? "0x") +} + +export const sudoMintTokens = async ({ + amount, + to, + anvilRpc +}: { + amount: bigint + to: Address + anvilRpc: string +}) => { + const walletClient = getAnvilWalletClient({ addressIndex: 0, anvilRpc }) + + await walletClient.sendTransaction({ + to: ERC20_ADDRESS, + value: 0n, + data: encodeFunctionData({ + abi: parseAbi(["function sudoMint(address, uint256)"]), + args: [to, amount] + }) + }) +} + +export const ERC20_ADDRESS = getCreate2Address({ + from: "0x4e59b44847b379578588920ca78fbf26c0b4956c", + salt: "0x0000000000000000000000000000000000000000000000000000000000000000", + bytecode: ERC20_BYTECODE +}) diff --git a/packages/permissionless-test/src/utils.ts b/packages/permissionless-test/src/utils.ts index bf2fa01d..aa823318 100644 --- a/packages/permissionless-test/src/utils.ts +++ b/packages/permissionless-test/src/utils.ts @@ -1,14 +1,4 @@ -import { - http, - type Account, - type Address, - type Chain, - type Transport, - type WalletClient, - createPublicClient, - createWalletClient, - parseEther -} from "viem" +import { http, createPublicClient, createWalletClient } from "viem" import { type SmartAccount, createBundlerClient, @@ -199,9 +189,12 @@ export const getPimlicoClient = ({ export const getPublicClient = (anvilRpc: string) => { const transport = http(anvilRpc, { - onFetchRequest: async (request) => { - // console.log("fetching", await request.json()) - } + //onFetchRequest: async (req) => { + // console.log(await req.json(), "request") + //}, + //onFetchResponse: async (response) => { + // console.log(await response.clone().json(), "response") + //} }) return createPublicClient({ @@ -211,39 +204,6 @@ export const getPublicClient = (anvilRpc: string) => { }) } -const usedWallets = new Set
() - -export const fund = async ({ - to, - anvilRpc -}: { to: Address; anvilRpc: string }) => { - let funder: WalletClient - - const wallets = Array.from({ length: 10 }, (_, index) => - getAnvilWalletClient({ addressIndex: index, anvilRpc }) - ) - const publicClient = getPublicClient(anvilRpc) - - do { - const availableFunders = wallets.filter( - (wallet) => !usedWallets.has(wallet.account.address) - ) - const randomIndex = Math.floor(Math.random() * availableFunders.length) - funder = availableFunders[randomIndex] - } while (!funder) - - // mark the funder as used - usedWallets.add(funder.account.address) - - const hash = await funder.sendTransaction({ - to, - value: parseEther("1") - }) - - // wait for funding confirmation - await publicClient.waitForTransactionReceipt({ hash }) -} - export const getSimpleAccountClient = async < entryPointVersion extends "0.6" | "0.7" >({ diff --git a/packages/permissionless/clients/createSmartAccountClient.ts b/packages/permissionless/clients/createSmartAccountClient.ts index 024b0437..b501a771 100644 --- a/packages/permissionless/clients/createSmartAccountClient.ts +++ b/packages/permissionless/clients/createSmartAccountClient.ts @@ -1,20 +1,23 @@ -import type { - BundlerRpcSchema, - Chain, - Client, - ClientConfig, - EstimateFeesPerGasReturnType, - Prettify, - RpcSchema, - Transport +import { + type BundlerRpcSchema, + type Chain, + type Client, + type ClientConfig, + type EstimateFeesPerGasReturnType, + type Prettify, + type RpcSchema, + type Transport, + createClient } from "viem" import { type BundlerActions, type BundlerClientConfig, type PaymasterActions, + type PrepareUserOperationParameters, type SmartAccount, type UserOperationRequest, - createBundlerClient + bundlerActions, + type prepareUserOperation as viemPrepareUserOperation } from "viem/account-abstraction" import { type SmartAccountActions, @@ -101,6 +104,8 @@ export type SmartAccountClientConfig< userOperation: UserOperationRequest }) => Promise>) | undefined + /** Prepare User Operation configuration. */ + prepareUserOperation?: typeof viemPrepareUserOperation | undefined } | undefined } @@ -134,17 +139,43 @@ export function createSmartAccountClient( userOperation } = parameters - const client = createBundlerClient({ - ...parameters, - client: client_, - chain: parameters.chain ?? client_?.chain, - key, - name, - transport: bundlerTransport, - paymaster, - paymasterContext, - userOperation - }) + const client = Object.assign( + createClient({ + ...parameters, + chain: parameters.chain ?? client_?.chain, + transport: bundlerTransport, + key, + name, + type: "bundlerClient" // TODO: is this okay? + }), + { client: client_, paymaster, paymasterContext, userOperation } + ) + + if (parameters.userOperation?.prepareUserOperation) { + const customPrepareUserOp = + parameters.userOperation.prepareUserOperation + + return client + .extend(bundlerActions) + .extend((client) => ({ + prepareUserOperation: ( + args: PrepareUserOperationParameters + ) => { + return customPrepareUserOp(client, args) + } + })) + .extend(bundlerActions) + .extend((client) => ({ + prepareUserOperation: ( + args: PrepareUserOperationParameters + ) => { + return customPrepareUserOp(client, args) + } + })) + .extend(smartAccountActions()) as SmartAccountClient + } - return client.extend(smartAccountActions()) as unknown as SmartAccountClient + return client + .extend(bundlerActions) + .extend(smartAccountActions()) as SmartAccountClient } diff --git a/packages/permissionless/experimental/pimlico/index.ts b/packages/permissionless/experimental/pimlico/index.ts new file mode 100644 index 00000000..80c0e415 --- /dev/null +++ b/packages/permissionless/experimental/pimlico/index.ts @@ -0,0 +1,2 @@ +import { prepareUserOperationForErc20Paymaster } from "./utils/prepareUserOperationForErc20Paymaster" +export { prepareUserOperationForErc20Paymaster } diff --git a/packages/permissionless/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.test.ts b/packages/permissionless/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.test.ts new file mode 100644 index 00000000..add364b1 --- /dev/null +++ b/packages/permissionless/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.test.ts @@ -0,0 +1,195 @@ +import { http, parseEther, zeroAddress } from "viem" +import { + entryPoint06Address, + entryPoint07Address +} from "viem/account-abstraction" +import { foundry } from "viem/chains" +import { describe, expect } from "vitest" +import { + ERC20_ADDRESS, + sudoMintTokens, + tokenBalanceOf +} from "../../../../permissionless-test/src/erc20-utils.ts" +import { testWithRpc } from "../../../../permissionless-test/src/testWithRpc.ts" +import { + getCoreSmartAccounts, + getPublicClient +} from "../../../../permissionless-test/src/utils" +import { createSmartAccountClient } from "../../../clients/createSmartAccountClient.ts" +import { createPimlicoClient } from "../../../clients/pimlico.ts" +import { prepareUserOperationForErc20Paymaster } from "./prepareUserOperationForErc20Paymaster.ts" + +describe.each(getCoreSmartAccounts())( + "prepareUserOperationForErc20Paymaster $name", + ({ + getSmartAccountClient, + supportsEntryPointV06, + supportsEntryPointV07 + }) => { + testWithRpc.skipIf(!supportsEntryPointV06)( + "prepareUserOperationForErc20Paymaster_v06", + async ({ rpc }) => { + const { anvilRpc } = rpc + + const account = ( + await getSmartAccountClient({ + entryPoint: { + version: "0.6" + }, + ...rpc + }) + ).account + + const pimlicoClient = createPimlicoClient({ + transport: http(rpc.paymasterRpc), + entryPoint: { + address: entryPoint06Address, + version: "0.6" + } + }) + + const publicClient = getPublicClient(anvilRpc) + + const smartAccountClient = createSmartAccountClient({ + // @ts-ignore + client: getPublicClient(anvilRpc), + account, + paymaster: pimlicoClient, + chain: foundry, + userOperation: { + prepareUserOperation: + prepareUserOperationForErc20Paymaster(pimlicoClient) + }, + bundlerTransport: http(rpc.altoRpc) + }) + + const INITIAL_TOKEN_BALANCE = parseEther("100") + const INTIAL_ETH_BALANCE = await publicClient.getBalance({ + address: smartAccountClient.account.address + }) + + sudoMintTokens({ + amount: INITIAL_TOKEN_BALANCE, + to: smartAccountClient.account.address, + anvilRpc + }) + + const opHash = await smartAccountClient.sendUserOperation({ + calls: [ + { + to: zeroAddress, + data: "0x", + value: 0n + } + ], + paymasterContext: { + token: ERC20_ADDRESS + } + }) + + const receipt = + await smartAccountClient.waitForUserOperationReceipt({ + hash: opHash + }) + + expect(receipt).toBeTruthy() + expect(receipt).toBeTruthy() + expect(receipt.success).toBeTruthy() + + const FINAL_TOKEN_BALANCE = await tokenBalanceOf( + smartAccountClient.account.address, + rpc.anvilRpc + ) + const FINAL_ETH_BALANCE = await publicClient.getBalance({ + address: smartAccountClient.account.address + }) + + expect(FINAL_TOKEN_BALANCE).toBeLessThan(INITIAL_TOKEN_BALANCE) // Token balance should be deducted + expect(FINAL_ETH_BALANCE).toEqual(INTIAL_ETH_BALANCE) // There should be no ETH balance change + } + ) + + testWithRpc.skipIf(!supportsEntryPointV07)( + "prepareUserOperationForErc20Paymaster_v07", + async ({ rpc }) => { + const { anvilRpc } = rpc + + const account = ( + await getSmartAccountClient({ + entryPoint: { + version: "0.7" + }, + ...rpc + }) + ).account + + const publicClient = getPublicClient(anvilRpc) + + const pimlicoClient = createPimlicoClient({ + transport: http(rpc.paymasterRpc), + entryPoint: { + address: entryPoint07Address, + version: "0.7" + } + }) + + const smartAccountClient = createSmartAccountClient({ + // @ts-ignore + client: getPublicClient(anvilRpc), + account, + paymaster: pimlicoClient, + chain: foundry, + userOperation: { + prepareUserOperation: + prepareUserOperationForErc20Paymaster(pimlicoClient) + }, + bundlerTransport: http(rpc.altoRpc) + }) + + const INITIAL_TOKEN_BALANCE = parseEther("100") + const INTIAL_ETH_BALANCE = await publicClient.getBalance({ + address: smartAccountClient.account.address + }) + + sudoMintTokens({ + amount: INITIAL_TOKEN_BALANCE, + to: smartAccountClient.account.address, + anvilRpc + }) + + const opHash = await smartAccountClient.sendUserOperation({ + calls: [ + { + to: zeroAddress, + data: "0x", + value: 0n + } + ], + paymasterContext: { + token: ERC20_ADDRESS + } + }) + + const receipt = + await smartAccountClient.waitForUserOperationReceipt({ + hash: opHash + }) + + expect(receipt).toBeTruthy() + expect(receipt).toBeTruthy() + expect(receipt.success).toBeTruthy() + + const FINAL_TOKEN_BALANCE = await tokenBalanceOf( + smartAccountClient.account.address, + rpc.anvilRpc + ) + const FINAL_ETH_BALANCE = await publicClient.getBalance({ + address: smartAccountClient.account.address + }) + + expect(FINAL_TOKEN_BALANCE).toBeLessThan(INITIAL_TOKEN_BALANCE) // Token balance should be deducted + expect(FINAL_ETH_BALANCE).toEqual(INTIAL_ETH_BALANCE) // There should be no ETH balance change + } + ) + } +) diff --git a/packages/permissionless/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.ts b/packages/permissionless/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.ts new file mode 100644 index 00000000..df3c4993 --- /dev/null +++ b/packages/permissionless/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.ts @@ -0,0 +1,270 @@ +import { + type Address, + type Chain, + type Client, + type ContractFunctionParameters, + type Transport, + encodeFunctionData, + erc20Abi, + getAddress, + maxUint256 +} from "viem" +import { + type BundlerClient, + type PrepareUserOperationParameters, + type PrepareUserOperationRequest, + type PrepareUserOperationReturnType, + type SmartAccount, + type UserOperation, + type UserOperationCall, + getPaymasterData as getPaymasterData_, + prepareUserOperation +} from "viem/account-abstraction" +import { getChainId as getChainId_ } from "viem/actions" +import { readContract } from "viem/actions" +import { getAction, parseAccount } from "viem/utils" +import { getTokenQuotes } from "../../../actions/pimlico" + +export const prepareUserOperationForErc20Paymaster = + (pimlicoClient: Client) => + async < + account extends SmartAccount | undefined, + const calls extends readonly unknown[], + const request extends PrepareUserOperationRequest< + account, + accountOverride, + calls + >, + accountOverride extends SmartAccount | undefined = undefined + >( + client: Client, + parameters_: PrepareUserOperationParameters< + account, + accountOverride, + calls, + request + > + ): Promise< + PrepareUserOperationReturnType + > => { + const parameters = parameters_ as PrepareUserOperationParameters + const account_ = client.account + + if (!account_) throw new Error("Account not found") + const account = parseAccount(account_) + + const bundlerClient = client as unknown as BundlerClient + + const paymasterContext = parameters.paymasterContext + ? parameters.paymasterContext + : bundlerClient?.paymasterContext + + if ( + typeof paymasterContext === "object" && + paymasterContext !== null && + "token" in paymasterContext && + typeof paymasterContext.token === "string" + ) { + //////////////////////////////////////////////////////////////////////////////// + // Inject custom approval before calling prepareUserOperation + //////////////////////////////////////////////////////////////////////////////// + + const token = getAddress(paymasterContext.token) + + let chainId: number | undefined + async function getChainId(): Promise { + if (chainId) return chainId + if (client.chain) return client.chain.id + const chainId_ = await getAction( + client, + getChainId_, + "getChainId" + )({}) + chainId = chainId_ + return chainId + } + + const quotes = await getAction( + pimlicoClient, + getTokenQuotes, + "getTokenQuotes" + )({ + tokens: [token], + chain: + pimlicoClient.chain ?? client.chain ?? account.client.chain, + entryPointAddress: account.entryPoint.address + }) + + const { + postOpGas, + exchangeRate, + paymaster: paymasterERC20Address + } = quotes[0] + + const callsWithDummyApproval = [ + { + abi: erc20Abi, + functionName: "approve", + args: [paymasterERC20Address, maxUint256], // dummy approval to ensure simulation passes + to: paymasterContext.token + }, + ...(parameters.calls ? parameters.calls : []) + ] + + if (parameters.callData) { + throw new Error( + "parameter callData is not supported with prepareUserOperationForErc20Paymaster" + ) + } + + //////////////////////////////////////////////////////////////////////////////// + // Call prepareUserOperation + //////////////////////////////////////////////////////////////////////////////// + + const userOperation = await getAction( + client, + prepareUserOperation, + "prepareUserOperation" + )({ + ...parameters, + calls: callsWithDummyApproval + } as unknown as PrepareUserOperationParameters) + + //////////////////////////////////////////////////////////////////////////////// + // Call pimlico_getTokenQuotes and calculate the approval amount needed for op + //////////////////////////////////////////////////////////////////////////////// + + const maxFeePerGas = userOperation.maxFeePerGas + + const userOperationMaxGas = + userOperation.preVerificationGas + + userOperation.callGasLimit + + userOperation.verificationGasLimit + + (userOperation.paymasterPostOpGasLimit || 0n) + + (userOperation.paymasterVerificationGasLimit || 0n) + + const userOperationMaxCost = userOperationMaxGas * maxFeePerGas + + // using formula here https://github.com/pimlicolabs/singleton-paymaster/blob/main/src/base/BaseSingletonPaymaster.sol#L334-L341 + const maxCostInToken = + ((userOperationMaxCost + postOpGas * maxFeePerGas) * + exchangeRate) / + BigInt(1e18) + + //////////////////////////////////////////////////////////////////////////////// + // Check if we need to approve the token + // If the user has existing approval that is sufficient, skip approval injection + //////////////////////////////////////////////////////////////////////////////// + + const publicClient = account.client + + const allowance = await getAction( + publicClient, + readContract, + "readContract" + )({ + abi: erc20Abi, + functionName: "allowance", + args: [account.address, paymasterERC20Address], + address: token + }) + + const hasSufficientApproval = allowance >= maxCostInToken + + const finalCalls = hasSufficientApproval + ? parameters.calls + : [ + { + abi: erc20Abi, + functionName: "approve", + args: [paymasterERC20Address, maxCostInToken], + to: paymasterContext.token + }, + ...parameters.calls + ] + + userOperation.callData = await account.encodeCalls( + finalCalls.map((call_) => { + const call = call_ as + | UserOperationCall + | (ContractFunctionParameters & { + to: Address + value: bigint + }) + if ("abi" in call) + return { + data: encodeFunctionData(call), + to: call.to, + value: call.value + } as UserOperationCall + return call as UserOperationCall + }) + ) + parameters.calls = finalCalls + + //////////////////////////////////////////////////////////////////////////////// + // Declare Paymaster properties. (taken from viem) + //////////////////////////////////////////////////////////////////////////////// + + const paymaster = parameters.paymaster ?? bundlerClient?.paymaster + const { getPaymasterData } = (() => { + // If `paymaster: true`, we will assume the Bundler Client supports Paymaster Actions. + if (paymaster === true) + return { + getPaymasterData: (parameters: any) => + getAction( + bundlerClient, + getPaymasterData_, + "getPaymasterData" + )(parameters) + } + + // If Actions are passed to `paymaster` (via Paymaster Client or directly), we will use them. + if ( + typeof paymaster === "object" && + paymaster.getPaymasterData + ) { + const { getPaymasterData } = paymaster + return { + getPaymasterData + } + } + + throw new Error( + "Expected paymaster: cannot sponsor ERC-20 without paymaster" + ) + })() + + //////////////////////////////////////////////////////////////////////////////// + // Re-calculate Paymaster data fields. + //////////////////////////////////////////////////////////////////////////////// + + const paymasterData = await getPaymasterData({ + chainId: await getChainId(), + entryPointAddress: account.entryPoint.address, + context: paymasterContext, + ...(userOperation as UserOperation) + }) + + return { + ...userOperation, + ...paymasterData + } as unknown as PrepareUserOperationReturnType< + account, + accountOverride, + calls, + request + > + } + + return (await getAction( + client, + prepareUserOperation, + "prepareUserOperation" + )(parameters)) as unknown as PrepareUserOperationReturnType< + account, + accountOverride, + calls, + request + > + } diff --git a/packages/permissionless/package.json b/packages/permissionless/package.json index fc9de444..e4d4632b 100644 --- a/packages/permissionless/package.json +++ b/packages/permissionless/package.json @@ -64,13 +64,13 @@ "import": "./_esm/errors/index.js", "default": "./_cjs/errors/index.js" }, - "./experimental": { - "types": "./_types/experimental/index.d.ts", - "import": "./_esm/experimental/index.js", - "default": "./_cjs/experimental/index.js" + "./experimental/pimlico": { + "types": "./_types/experimental/pimlico/index.d.ts", + "import": "./_esm/experimental/pimlico/index.js", + "default": "./_cjs/experimental/pimlico/index.js" } }, "peerDependencies": { - "viem": "^2.20.0" + "viem": "^2.21.2" } } diff --git a/packages/permissionless/pnpm-lock.yaml b/packages/permissionless/pnpm-lock.yaml new file mode 100644 index 00000000..3ec541b5 --- /dev/null +++ b/packages/permissionless/pnpm-lock.yaml @@ -0,0 +1,131 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + viem: + specifier: ^2.20.0 + version: 2.21.2 + +packages: + + '@adraffy/ens-normalize@1.10.0': + resolution: {integrity: sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==} + + '@noble/curves@1.4.0': + resolution: {integrity: sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==} + + '@noble/hashes@1.4.0': + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + + '@noble/hashes@1.5.0': + resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} + engines: {node: ^14.21.3 || >=16} + + '@scure/base@1.1.8': + resolution: {integrity: sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg==} + + '@scure/bip32@1.4.0': + resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} + + '@scure/bip39@1.4.0': + resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} + + abitype@1.0.5: + resolution: {integrity: sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + + isows@1.0.4: + resolution: {integrity: sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==} + peerDependencies: + ws: '*' + + viem@2.21.2: + resolution: {integrity: sha512-gTzwKbmyepEDUBKXs3GslTcg5KXfDIgQfHKNxIV9cs7Xout55F8NvHhNeBGBfuw1Ix4Vz8aCMFGYwX5a64CGFg==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + + webauthn-p256@0.0.5: + resolution: {integrity: sha512-drMGNWKdaixZNobeORVIqq7k5DsRC9FnG201K2QjeOoQLmtSDaSsVZdkg6n5jUALJKcAG++zBPJXmv6hy0nWFg==} + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + +snapshots: + + '@adraffy/ens-normalize@1.10.0': {} + + '@noble/curves@1.4.0': + dependencies: + '@noble/hashes': 1.4.0 + + '@noble/hashes@1.4.0': {} + + '@noble/hashes@1.5.0': {} + + '@scure/base@1.1.8': {} + + '@scure/bip32@1.4.0': + dependencies: + '@noble/curves': 1.4.0 + '@noble/hashes': 1.4.0 + '@scure/base': 1.1.8 + + '@scure/bip39@1.4.0': + dependencies: + '@noble/hashes': 1.5.0 + '@scure/base': 1.1.8 + + abitype@1.0.5: {} + + isows@1.0.4(ws@8.17.1): + dependencies: + ws: 8.17.1 + + viem@2.21.2: + dependencies: + '@adraffy/ens-normalize': 1.10.0 + '@noble/curves': 1.4.0 + '@noble/hashes': 1.4.0 + '@scure/bip32': 1.4.0 + '@scure/bip39': 1.4.0 + abitype: 1.0.5 + isows: 1.0.4(ws@8.17.1) + webauthn-p256: 0.0.5 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + webauthn-p256@0.0.5: + dependencies: + '@noble/curves': 1.4.0 + '@noble/hashes': 1.4.0 + + ws@8.17.1: {} diff --git a/packages/wagmi-demo/src/index.css b/packages/wagmi-demo/src/index.css index 0733a7ee..60b4e260 100644 --- a/packages/wagmi-demo/src/index.css +++ b/packages/wagmi-demo/src/index.css @@ -1,21 +1,21 @@ :root { - background-color: #181818; - color: rgba(255, 255, 255, 0.87); - color-scheme: light dark; - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - font-synthesis: none; - font-weight: 400; - line-height: 1.5; - text-rendering: optimizeLegibility; + background-color: #181818; + color: rgba(255, 255, 255, 0.87); + color-scheme: light dark; + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + font-synthesis: none; + font-weight: 400; + line-height: 1.5; + text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; } @media (prefers-color-scheme: light) { - :root { - background-color: #f8f8f8; - color: #181818; - } + :root { + background-color: #f8f8f8; + color: #181818; + } }