diff --git a/.changeset/sixty-rabbits-repair.md b/.changeset/sixty-rabbits-repair.md new file mode 100644 index 00000000..42c9abdb --- /dev/null +++ b/.changeset/sixty-rabbits-repair.md @@ -0,0 +1,5 @@ +--- +"permissionless": patch +--- + +Fixed getSenderAddress, when rpc returns an UnknownRpcError diff --git a/packages/permissionless-test/abi/entryPointV06Abi.ts b/packages/permissionless-test/abi/entryPointV06Abi.ts deleted file mode 100644 index cf80b534..00000000 --- a/packages/permissionless-test/abi/entryPointV06Abi.ts +++ /dev/null @@ -1,1309 +0,0 @@ -export const ENTRYPOINT_V06_ABI = [ - { - inputs: [ - { - internalType: "uint256", - name: "preOpGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "paid", - type: "uint256" - }, - { - internalType: "uint48", - name: "validAfter", - type: "uint48" - }, - { - internalType: "uint48", - name: "validUntil", - type: "uint48" - }, - { - internalType: "bool", - name: "targetSuccess", - type: "bool" - }, - { - internalType: "bytes", - name: "targetResult", - type: "bytes" - } - ], - name: "ExecutionResult", - type: "error" - }, - { - inputs: [ - { - internalType: "uint256", - name: "opIndex", - type: "uint256" - }, - { - internalType: "string", - name: "reason", - type: "string" - } - ], - name: "FailedOp", - type: "error" - }, - { - inputs: [ - { - internalType: "address", - name: "sender", - type: "address" - } - ], - name: "SenderAddressResult", - type: "error" - }, - { - inputs: [ - { - internalType: "address", - name: "aggregator", - type: "address" - } - ], - name: "SignatureValidationFailed", - type: "error" - }, - { - inputs: [ - { - components: [ - { - internalType: "uint256", - name: "preOpGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "prefund", - type: "uint256" - }, - { - internalType: "bool", - name: "sigFailed", - type: "bool" - }, - { - internalType: "uint48", - name: "validAfter", - type: "uint48" - }, - { - internalType: "uint48", - name: "validUntil", - type: "uint48" - }, - { - internalType: "bytes", - name: "paymasterContext", - type: "bytes" - } - ], - internalType: "struct IEntryPoint.ReturnInfo", - name: "returnInfo", - type: "tuple" - }, - { - components: [ - { - internalType: "uint256", - name: "stake", - type: "uint256" - }, - { - internalType: "uint256", - name: "unstakeDelaySec", - type: "uint256" - } - ], - internalType: "struct IStakeManager.StakeInfo", - name: "senderInfo", - type: "tuple" - }, - { - components: [ - { - internalType: "uint256", - name: "stake", - type: "uint256" - }, - { - internalType: "uint256", - name: "unstakeDelaySec", - type: "uint256" - } - ], - internalType: "struct IStakeManager.StakeInfo", - name: "factoryInfo", - type: "tuple" - }, - { - components: [ - { - internalType: "uint256", - name: "stake", - type: "uint256" - }, - { - internalType: "uint256", - name: "unstakeDelaySec", - type: "uint256" - } - ], - internalType: "struct IStakeManager.StakeInfo", - name: "paymasterInfo", - type: "tuple" - } - ], - name: "ValidationResult", - type: "error" - }, - { - inputs: [ - { - components: [ - { - internalType: "uint256", - name: "preOpGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "prefund", - type: "uint256" - }, - { - internalType: "bool", - name: "sigFailed", - type: "bool" - }, - { - internalType: "uint48", - name: "validAfter", - type: "uint48" - }, - { - internalType: "uint48", - name: "validUntil", - type: "uint48" - }, - { - internalType: "bytes", - name: "paymasterContext", - type: "bytes" - } - ], - internalType: "struct IEntryPoint.ReturnInfo", - name: "returnInfo", - type: "tuple" - }, - { - components: [ - { - internalType: "uint256", - name: "stake", - type: "uint256" - }, - { - internalType: "uint256", - name: "unstakeDelaySec", - type: "uint256" - } - ], - internalType: "struct IStakeManager.StakeInfo", - name: "senderInfo", - type: "tuple" - }, - { - components: [ - { - internalType: "uint256", - name: "stake", - type: "uint256" - }, - { - internalType: "uint256", - name: "unstakeDelaySec", - type: "uint256" - } - ], - internalType: "struct IStakeManager.StakeInfo", - name: "factoryInfo", - type: "tuple" - }, - { - components: [ - { - internalType: "uint256", - name: "stake", - type: "uint256" - }, - { - internalType: "uint256", - name: "unstakeDelaySec", - type: "uint256" - } - ], - internalType: "struct IStakeManager.StakeInfo", - name: "paymasterInfo", - type: "tuple" - }, - { - components: [ - { - internalType: "address", - name: "aggregator", - type: "address" - }, - { - components: [ - { - internalType: "uint256", - name: "stake", - type: "uint256" - }, - { - internalType: "uint256", - name: "unstakeDelaySec", - type: "uint256" - } - ], - internalType: "struct IStakeManager.StakeInfo", - name: "stakeInfo", - type: "tuple" - } - ], - internalType: "struct IEntryPoint.AggregatorStakeInfo", - name: "aggregatorInfo", - type: "tuple" - } - ], - name: "ValidationResultWithAggregation", - type: "error" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - indexed: true, - internalType: "address", - name: "sender", - type: "address" - }, - { - indexed: false, - internalType: "address", - name: "factory", - type: "address" - }, - { - indexed: false, - internalType: "address", - name: "paymaster", - type: "address" - } - ], - name: "AccountDeployed", - type: "event" - }, - { - anonymous: false, - inputs: [], - name: "BeforeExecution", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "account", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "totalDeposit", - type: "uint256" - } - ], - name: "Deposited", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "aggregator", - type: "address" - } - ], - name: "SignatureAggregatorChanged", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "account", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "totalStaked", - type: "uint256" - }, - { - indexed: false, - internalType: "uint256", - name: "unstakeDelaySec", - type: "uint256" - } - ], - name: "StakeLocked", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "account", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "withdrawTime", - type: "uint256" - } - ], - name: "StakeUnlocked", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "account", - type: "address" - }, - { - indexed: false, - internalType: "address", - name: "withdrawAddress", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "amount", - type: "uint256" - } - ], - name: "StakeWithdrawn", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - indexed: true, - internalType: "address", - name: "sender", - type: "address" - }, - { - indexed: true, - internalType: "address", - name: "paymaster", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "nonce", - type: "uint256" - }, - { - indexed: false, - internalType: "bool", - name: "success", - type: "bool" - }, - { - indexed: false, - internalType: "uint256", - name: "actualGasCost", - type: "uint256" - }, - { - indexed: false, - internalType: "uint256", - name: "actualGasUsed", - type: "uint256" - } - ], - name: "UserOperationEvent", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - indexed: true, - internalType: "address", - name: "sender", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "nonce", - type: "uint256" - }, - { - indexed: false, - internalType: "bytes", - name: "revertReason", - type: "bytes" - } - ], - name: "UserOperationRevertReason", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "account", - type: "address" - }, - { - indexed: false, - internalType: "address", - name: "withdrawAddress", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "amount", - type: "uint256" - } - ], - name: "Withdrawn", - type: "event" - }, - { - inputs: [], - name: "SIG_VALIDATION_FAILED", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256" - } - ], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { - internalType: "bytes", - name: "initCode", - type: "bytes" - }, - { - internalType: "address", - name: "sender", - type: "address" - }, - { - internalType: "bytes", - name: "paymasterAndData", - type: "bytes" - } - ], - name: "_validateSenderAndPaymaster", - outputs: [], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { - internalType: "uint32", - name: "unstakeDelaySec", - type: "uint32" - } - ], - name: "addStake", - outputs: [], - stateMutability: "payable", - type: "function" - }, - { - inputs: [ - { - internalType: "address", - name: "account", - type: "address" - } - ], - name: "balanceOf", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256" - } - ], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { - internalType: "address", - name: "account", - type: "address" - } - ], - name: "depositTo", - outputs: [], - stateMutability: "payable", - type: "function" - }, - { - inputs: [ - { - internalType: "address", - name: "", - type: "address" - } - ], - name: "deposits", - outputs: [ - { - internalType: "uint112", - name: "deposit", - type: "uint112" - }, - { - internalType: "bool", - name: "staked", - type: "bool" - }, - { - internalType: "uint112", - name: "stake", - type: "uint112" - }, - { - internalType: "uint32", - name: "unstakeDelaySec", - type: "uint32" - }, - { - internalType: "uint48", - name: "withdrawTime", - type: "uint48" - } - ], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { - internalType: "address", - name: "account", - type: "address" - } - ], - name: "getDepositInfo", - outputs: [ - { - components: [ - { - internalType: "uint112", - name: "deposit", - type: "uint112" - }, - { - internalType: "bool", - name: "staked", - type: "bool" - }, - { - internalType: "uint112", - name: "stake", - type: "uint112" - }, - { - internalType: "uint32", - name: "unstakeDelaySec", - type: "uint32" - }, - { - internalType: "uint48", - name: "withdrawTime", - type: "uint48" - } - ], - internalType: "struct IStakeManager.DepositInfo", - name: "info", - type: "tuple" - } - ], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { - internalType: "address", - name: "sender", - type: "address" - }, - { - internalType: "uint192", - name: "key", - type: "uint192" - } - ], - name: "getNonce", - outputs: [ - { - internalType: "uint256", - name: "nonce", - type: "uint256" - } - ], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { - internalType: "bytes", - name: "initCode", - type: "bytes" - } - ], - name: "getSenderAddress", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - components: [ - { - internalType: "address", - 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: "callGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "verificationGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "preVerificationGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxFeePerGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxPriorityFeePerGas", - type: "uint256" - }, - { - internalType: "bytes", - name: "paymasterAndData", - type: "bytes" - }, - { - internalType: "bytes", - name: "signature", - type: "bytes" - } - ], - internalType: "struct UserOperation", - name: "userOp", - type: "tuple" - } - ], - name: "getUserOpHash", - outputs: [ - { - internalType: "bytes32", - name: "", - type: "bytes32" - } - ], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { - components: [ - { - components: [ - { - internalType: "address", - 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: "callGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "verificationGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "preVerificationGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxFeePerGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxPriorityFeePerGas", - type: "uint256" - }, - { - internalType: "bytes", - name: "paymasterAndData", - type: "bytes" - }, - { - internalType: "bytes", - name: "signature", - type: "bytes" - } - ], - internalType: "struct UserOperation[]", - name: "userOps", - type: "tuple[]" - }, - { - internalType: "contract IAggregator", - name: "aggregator", - type: "address" - }, - { - internalType: "bytes", - name: "signature", - type: "bytes" - } - ], - internalType: "struct IEntryPoint.UserOpsPerAggregator[]", - name: "opsPerAggregator", - type: "tuple[]" - }, - { - internalType: "address payable", - name: "beneficiary", - type: "address" - } - ], - name: "handleAggregatedOps", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - components: [ - { - internalType: "address", - 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: "callGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "verificationGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "preVerificationGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxFeePerGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxPriorityFeePerGas", - type: "uint256" - }, - { - internalType: "bytes", - name: "paymasterAndData", - type: "bytes" - }, - { - internalType: "bytes", - name: "signature", - type: "bytes" - } - ], - internalType: "struct UserOperation[]", - name: "ops", - type: "tuple[]" - }, - { - internalType: "address payable", - name: "beneficiary", - type: "address" - } - ], - name: "handleOps", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - internalType: "uint192", - name: "key", - type: "uint192" - } - ], - name: "incrementNonce", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - internalType: "bytes", - name: "callData", - type: "bytes" - }, - { - components: [ - { - components: [ - { - internalType: "address", - name: "sender", - type: "address" - }, - { - internalType: "uint256", - name: "nonce", - type: "uint256" - }, - { - internalType: "uint256", - name: "callGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "verificationGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "preVerificationGas", - type: "uint256" - }, - { - internalType: "address", - name: "paymaster", - type: "address" - }, - { - internalType: "uint256", - name: "maxFeePerGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxPriorityFeePerGas", - type: "uint256" - } - ], - internalType: "struct EntryPoint.MemoryUserOp", - name: "mUserOp", - type: "tuple" - }, - { - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - internalType: "uint256", - name: "prefund", - type: "uint256" - }, - { - internalType: "uint256", - name: "contextOffset", - type: "uint256" - }, - { - internalType: "uint256", - name: "preOpGas", - type: "uint256" - } - ], - internalType: "struct EntryPoint.UserOpInfo", - name: "opInfo", - type: "tuple" - }, - { - internalType: "bytes", - name: "context", - type: "bytes" - } - ], - name: "innerHandleOp", - outputs: [ - { - internalType: "uint256", - name: "actualGasCost", - type: "uint256" - } - ], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - internalType: "address", - name: "", - type: "address" - }, - { - internalType: "uint192", - name: "", - type: "uint192" - } - ], - name: "nonceSequenceNumber", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256" - } - ], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { - components: [ - { - internalType: "address", - 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: "callGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "verificationGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "preVerificationGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxFeePerGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxPriorityFeePerGas", - type: "uint256" - }, - { - internalType: "bytes", - name: "paymasterAndData", - type: "bytes" - }, - { - internalType: "bytes", - name: "signature", - type: "bytes" - } - ], - internalType: "struct UserOperation", - name: "op", - type: "tuple" - }, - { - internalType: "address", - name: "target", - type: "address" - }, - { - internalType: "bytes", - name: "targetCallData", - type: "bytes" - } - ], - name: "simulateHandleOp", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - components: [ - { - internalType: "address", - 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: "callGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "verificationGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "preVerificationGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxFeePerGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxPriorityFeePerGas", - type: "uint256" - }, - { - internalType: "bytes", - name: "paymasterAndData", - type: "bytes" - }, - { - internalType: "bytes", - name: "signature", - type: "bytes" - } - ], - internalType: "struct UserOperation", - name: "userOp", - type: "tuple" - } - ], - name: "simulateValidation", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [], - name: "unlockStake", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - internalType: "address payable", - name: "withdrawAddress", - type: "address" - } - ], - name: "withdrawStake", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - internalType: "address payable", - name: "withdrawAddress", - type: "address" - }, - { - internalType: "uint256", - name: "withdrawAmount", - type: "uint256" - } - ], - name: "withdrawTo", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - stateMutability: "payable", - type: "receive" - } -] as const diff --git a/packages/permissionless-test/abi/entryPointV07Abi.ts b/packages/permissionless-test/abi/entryPointV07Abi.ts deleted file mode 100644 index 9583c638..00000000 --- a/packages/permissionless-test/abi/entryPointV07Abi.ts +++ /dev/null @@ -1,762 +0,0 @@ -export const ENTRYPOINT_V07_ABI = [ - { - inputs: [ - { internalType: "bool", name: "success", type: "bool" }, - { internalType: "bytes", name: "ret", type: "bytes" } - ], - name: "DelegateAndRevert", - type: "error" - }, - { - inputs: [ - { internalType: "uint256", name: "opIndex", type: "uint256" }, - { internalType: "string", name: "reason", type: "string" } - ], - name: "FailedOp", - type: "error" - }, - { - inputs: [ - { internalType: "uint256", name: "opIndex", type: "uint256" }, - { internalType: "string", name: "reason", type: "string" }, - { internalType: "bytes", name: "inner", type: "bytes" } - ], - name: "FailedOpWithRevert", - type: "error" - }, - { - inputs: [{ internalType: "bytes", name: "returnData", type: "bytes" }], - name: "PostOpReverted", - type: "error" - }, - { inputs: [], name: "ReentrancyGuardReentrantCall", type: "error" }, - { - inputs: [{ internalType: "address", name: "sender", type: "address" }], - name: "SenderAddressResult", - type: "error" - }, - { - inputs: [ - { internalType: "address", name: "aggregator", type: "address" } - ], - name: "SignatureValidationFailed", - type: "error" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - indexed: true, - internalType: "address", - name: "sender", - type: "address" - }, - { - indexed: false, - internalType: "address", - name: "factory", - type: "address" - }, - { - indexed: false, - internalType: "address", - name: "paymaster", - type: "address" - } - ], - name: "AccountDeployed", - type: "event" - }, - { anonymous: false, inputs: [], name: "BeforeExecution", type: "event" }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "account", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "totalDeposit", - type: "uint256" - } - ], - name: "Deposited", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - indexed: true, - internalType: "address", - name: "sender", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "nonce", - type: "uint256" - }, - { - indexed: false, - internalType: "bytes", - name: "revertReason", - type: "bytes" - } - ], - name: "PostOpRevertReason", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "aggregator", - type: "address" - } - ], - name: "SignatureAggregatorChanged", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "account", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "totalStaked", - type: "uint256" - }, - { - indexed: false, - internalType: "uint256", - name: "unstakeDelaySec", - type: "uint256" - } - ], - name: "StakeLocked", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "account", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "withdrawTime", - type: "uint256" - } - ], - name: "StakeUnlocked", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "account", - type: "address" - }, - { - indexed: false, - internalType: "address", - name: "withdrawAddress", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "amount", - type: "uint256" - } - ], - name: "StakeWithdrawn", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - indexed: true, - internalType: "address", - name: "sender", - type: "address" - }, - { - indexed: true, - internalType: "address", - name: "paymaster", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "nonce", - type: "uint256" - }, - { - indexed: false, - internalType: "bool", - name: "success", - type: "bool" - }, - { - indexed: false, - internalType: "uint256", - name: "actualGasCost", - type: "uint256" - }, - { - indexed: false, - internalType: "uint256", - name: "actualGasUsed", - type: "uint256" - } - ], - name: "UserOperationEvent", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - indexed: true, - internalType: "address", - name: "sender", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "nonce", - type: "uint256" - } - ], - name: "UserOperationPrefundTooLow", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - indexed: true, - internalType: "address", - name: "sender", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "nonce", - type: "uint256" - }, - { - indexed: false, - internalType: "bytes", - name: "revertReason", - type: "bytes" - } - ], - name: "UserOperationRevertReason", - type: "event" - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "account", - type: "address" - }, - { - indexed: false, - internalType: "address", - name: "withdrawAddress", - type: "address" - }, - { - indexed: false, - internalType: "uint256", - name: "amount", - type: "uint256" - } - ], - name: "Withdrawn", - type: "event" - }, - { - inputs: [ - { internalType: "uint32", name: "unstakeDelaySec", type: "uint32" } - ], - name: "addStake", - outputs: [], - stateMutability: "payable", - type: "function" - }, - { - inputs: [{ internalType: "address", name: "account", type: "address" }], - name: "balanceOf", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { internalType: "address", name: "target", type: "address" }, - { internalType: "bytes", name: "data", type: "bytes" } - ], - name: "delegateAndRevert", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [{ internalType: "address", name: "account", type: "address" }], - name: "depositTo", - outputs: [], - stateMutability: "payable", - type: "function" - }, - { - inputs: [{ internalType: "address", name: "", type: "address" }], - name: "deposits", - outputs: [ - { internalType: "uint256", name: "deposit", type: "uint256" }, - { internalType: "bool", name: "staked", type: "bool" }, - { internalType: "uint112", name: "stake", type: "uint112" }, - { internalType: "uint32", name: "unstakeDelaySec", type: "uint32" }, - { internalType: "uint48", name: "withdrawTime", type: "uint48" } - ], - stateMutability: "view", - type: "function" - }, - { - inputs: [{ internalType: "address", name: "account", type: "address" }], - name: "getDepositInfo", - outputs: [ - { - components: [ - { - internalType: "uint256", - name: "deposit", - type: "uint256" - }, - { internalType: "bool", name: "staked", type: "bool" }, - { internalType: "uint112", name: "stake", type: "uint112" }, - { - internalType: "uint32", - name: "unstakeDelaySec", - type: "uint32" - }, - { - internalType: "uint48", - name: "withdrawTime", - type: "uint48" - } - ], - internalType: "struct IStakeManager.DepositInfo", - name: "info", - type: "tuple" - } - ], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { internalType: "address", name: "sender", type: "address" }, - { internalType: "uint192", name: "key", type: "uint192" } - ], - name: "getNonce", - outputs: [{ internalType: "uint256", name: "nonce", type: "uint256" }], - stateMutability: "view", - type: "function" - }, - { - inputs: [{ internalType: "bytes", name: "initCode", type: "bytes" }], - name: "getSenderAddress", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - components: [ - { - internalType: "address", - name: "sender", - type: "address" - }, - { internalType: "uint256", name: "nonce", type: "uint256" }, - { internalType: "bytes", name: "initCode", type: "bytes" }, - { internalType: "bytes", name: "callData", type: "bytes" }, - { - internalType: "bytes32", - name: "accountGasLimits", - type: "bytes32" - }, - { - internalType: "uint256", - name: "preVerificationGas", - type: "uint256" - }, - { - internalType: "bytes32", - name: "gasFees", - type: "bytes32" - }, - { - internalType: "bytes", - name: "paymasterAndData", - type: "bytes" - }, - { internalType: "bytes", name: "signature", type: "bytes" } - ], - internalType: "struct PackedUserOperation", - name: "userOp", - type: "tuple" - } - ], - name: "getUserOpHash", - outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { - components: [ - { - components: [ - { - internalType: "address", - name: "sender", - type: "address" - }, - { - internalType: "uint256", - name: "nonce", - type: "uint256" - }, - { - internalType: "bytes", - name: "initCode", - type: "bytes" - }, - { - internalType: "bytes", - name: "callData", - type: "bytes" - }, - { - internalType: "bytes32", - name: "accountGasLimits", - type: "bytes32" - }, - { - internalType: "uint256", - name: "preVerificationGas", - type: "uint256" - }, - { - internalType: "bytes32", - name: "gasFees", - type: "bytes32" - }, - { - internalType: "bytes", - name: "paymasterAndData", - type: "bytes" - }, - { - internalType: "bytes", - name: "signature", - type: "bytes" - } - ], - internalType: "struct PackedUserOperation[]", - name: "userOps", - type: "tuple[]" - }, - { - internalType: "contract IAggregator", - name: "aggregator", - type: "address" - }, - { internalType: "bytes", name: "signature", type: "bytes" } - ], - internalType: "struct IEntryPoint.UserOpsPerAggregator[]", - name: "opsPerAggregator", - type: "tuple[]" - }, - { - internalType: "address payable", - name: "beneficiary", - type: "address" - } - ], - name: "handleAggregatedOps", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - components: [ - { - internalType: "address", - name: "sender", - type: "address" - }, - { internalType: "uint256", name: "nonce", type: "uint256" }, - { internalType: "bytes", name: "initCode", type: "bytes" }, - { internalType: "bytes", name: "callData", type: "bytes" }, - { - internalType: "bytes32", - name: "accountGasLimits", - type: "bytes32" - }, - { - internalType: "uint256", - name: "preVerificationGas", - type: "uint256" - }, - { - internalType: "bytes32", - name: "gasFees", - type: "bytes32" - }, - { - internalType: "bytes", - name: "paymasterAndData", - type: "bytes" - }, - { internalType: "bytes", name: "signature", type: "bytes" } - ], - internalType: "struct PackedUserOperation[]", - name: "ops", - type: "tuple[]" - }, - { - internalType: "address payable", - name: "beneficiary", - type: "address" - } - ], - name: "handleOps", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [{ internalType: "uint192", name: "key", type: "uint192" }], - name: "incrementNonce", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { internalType: "bytes", name: "callData", type: "bytes" }, - { - components: [ - { - components: [ - { - internalType: "address", - name: "sender", - type: "address" - }, - { - internalType: "uint256", - name: "nonce", - type: "uint256" - }, - { - internalType: "uint256", - name: "verificationGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "callGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "paymasterVerificationGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "paymasterPostOpGasLimit", - type: "uint256" - }, - { - internalType: "uint256", - name: "preVerificationGas", - type: "uint256" - }, - { - internalType: "address", - name: "paymaster", - type: "address" - }, - { - internalType: "uint256", - name: "maxFeePerGas", - type: "uint256" - }, - { - internalType: "uint256", - name: "maxPriorityFeePerGas", - type: "uint256" - } - ], - internalType: "struct EntryPoint.MemoryUserOp", - name: "mUserOp", - type: "tuple" - }, - { - internalType: "bytes32", - name: "userOpHash", - type: "bytes32" - }, - { - internalType: "uint256", - name: "prefund", - type: "uint256" - }, - { - internalType: "uint256", - name: "contextOffset", - type: "uint256" - }, - { - internalType: "uint256", - name: "preOpGas", - type: "uint256" - } - ], - internalType: "struct EntryPoint.UserOpInfo", - name: "opInfo", - type: "tuple" - }, - { internalType: "bytes", name: "context", type: "bytes" } - ], - name: "innerHandleOp", - outputs: [ - { internalType: "uint256", name: "actualGasCost", type: "uint256" } - ], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { internalType: "address", name: "", type: "address" }, - { internalType: "uint192", name: "", type: "uint192" } - ], - name: "nonceSequenceNumber", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { internalType: "bytes4", name: "interfaceId", type: "bytes4" } - ], - name: "supportsInterface", - outputs: [{ internalType: "bool", name: "", type: "bool" }], - stateMutability: "view", - type: "function" - }, - { - inputs: [], - name: "unlockStake", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - internalType: "address payable", - name: "withdrawAddress", - type: "address" - } - ], - name: "withdrawStake", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - internalType: "address payable", - name: "withdrawAddress", - type: "address" - }, - { internalType: "uint256", name: "withdrawAmount", type: "uint256" } - ], - name: "withdrawTo", - outputs: [], - stateMutability: "nonpayable", - type: "function" - }, - { stateMutability: "payable", type: "receive" } -] as const diff --git a/packages/permissionless-test/abi/simpleAccountFactoryAbi.ts b/packages/permissionless-test/abi/simpleAccountFactoryAbi.ts deleted file mode 100644 index 8e6674d9..00000000 --- a/packages/permissionless-test/abi/simpleAccountFactoryAbi.ts +++ /dev/null @@ -1,74 +0,0 @@ -export const SimpleAccountFactoryAbi = [ - { - inputs: [ - { - internalType: "contract IEntryPoint", - name: "_entryPoint", - type: "address" - } - ], - stateMutability: "nonpayable", - type: "constructor" - }, - { - inputs: [], - name: "accountImplementation", - outputs: [ - { - internalType: "contract SimpleAccount", - name: "", - type: "address" - } - ], - stateMutability: "view", - type: "function" - }, - { - inputs: [ - { - internalType: "address", - name: "owner", - type: "address" - }, - { - internalType: "uint256", - name: "salt", - type: "uint256" - } - ], - name: "createAccount", - outputs: [ - { - internalType: "contract SimpleAccount", - name: "ret", - type: "address" - } - ], - stateMutability: "nonpayable", - type: "function" - }, - { - inputs: [ - { - internalType: "address", - name: "owner", - type: "address" - }, - { - internalType: "uint256", - name: "salt", - type: "uint256" - } - ], - name: "getAddress", - outputs: [ - { - internalType: "address", - name: "", - type: "address" - } - ], - stateMutability: "view", - type: "function" - } -] as const diff --git a/packages/permissionless-test/mock-aa-infra/docker-compose.yml b/packages/permissionless-test/mock-aa-infra/docker-compose.yml deleted file mode 100644 index b998c5c9..00000000 --- a/packages/permissionless-test/mock-aa-infra/docker-compose.yml +++ /dev/null @@ -1,19 +0,0 @@ -services: - anvil: - image: ghcr.io/foundry-rs/foundry:nightly-f6208d8db68f9acbe4ff8cd76958309efb61ea0b - ports: [ "8545:8545" ] - entrypoint: [ "anvil", "--host", "0.0.0.0", "--block-time", "0.1", "--accounts", "100", "--silent"] - platform: linux/amd64/v8 - - mock-paymaster: - build: ./mock-paymaster - ports: [ "3000:3000" ] - environment: - - ALTO_RPC=http://alto:4337 - - ANVIL_RPC=http://anvil:8545 - - alto: - build: ./alto - ports: [ "4337:4337" ] - environment: - ANVIL_RPC: "http://anvil:8545" diff --git a/packages/permissionless-test/src/common/utils.test.ts b/packages/permissionless-test/src/common/utils.test.ts deleted file mode 100644 index 4b62212f..00000000 --- a/packages/permissionless-test/src/common/utils.test.ts +++ /dev/null @@ -1,298 +0,0 @@ -import { - type Address, - type Hash, - type Hex, - type WalletClient, - concat, - encodeFunctionData, - parseAbi, - zeroAddress -} from "viem" -import { generatePrivateKey, privateKeyToAccount } from "viem/accounts" -import { foundry } from "viem/chains" -import { beforeAll, describe, expect, expectTypeOf, test } from "vitest" -import { - ENTRYPOINT_ADDRESS_V06, - ENTRYPOINT_ADDRESS_V07, - type GetSenderAddressParams, - deepHexlify, - getSenderAddress, - getUserOperationHash -} from "../../../permissionless" -import type { PackedUserOperation } from "../../../permissionless/types" -import { - getPackedUserOperation, - getRequiredPrefund, - signUserOperationHashWithECDSA -} from "../../../permissionless/utils" -import { - SIMPLE_ACCOUNT_FACTORY_V06, - SIMPLE_ACCOUNT_FACTORY_V07 -} from "../constants" -import { - ensureBundlerIsReady, - ensurePaymasterIsReady, - getAnvilWalletClient, - getBundlerClient, - getPublicClient, - getSafeClient -} from "../utils" - -const getAccountInitCode = async ( - factoryAddress: Address, - owner: WalletClient, - index = 0n -) => { - if (!owner.account) throw new Error("Owner account not found") - return { - factory: factoryAddress, - factoryData: encodeFunctionData({ - abi: parseAbi([ - "function createAccount(address,uint256) public returns (address)" - ]), - args: [owner.account.address, index] - }) - } -} - -describe("test public actions and utils", () => { - beforeAll(async () => { - await ensureBundlerIsReady() - await ensurePaymasterIsReady() - }) - - test("Test deep Hexlify", async () => { - console.log("Testing deep hexlify") - expect(deepHexlify("abcd")).toBe("abcd") - expect(deepHexlify(null)).toBe(null) - expect(deepHexlify(true)).toBe(true) - expect(deepHexlify(false)).toBe(false) - expect(deepHexlify(1n)).toBe("0x1") - expect( - deepHexlify({ - name: "Garvit", - balance: 1n - }) - ).toEqual({ - name: "Garvit", - balance: "0x1" - }) - }) - - test.each([ - ["v0.6", SIMPLE_ACCOUNT_FACTORY_V06, ENTRYPOINT_ADDRESS_V06], - ["v0.7", SIMPLE_ACCOUNT_FACTORY_V07, ENTRYPOINT_ADDRESS_V07] - ])( - "%s get sender address", - async (_version, factoryAddress, entryPoint) => { - const eoaWalletClient = getAnvilWalletClient(25) - - const { factory, factoryData } = await getAccountInitCode( - factoryAddress, - eoaWalletClient - ) - - const publicClient = getPublicClient() - - let args: GetSenderAddressParams - - if (entryPoint === ENTRYPOINT_ADDRESS_V06) { - args = { - initCode: concat([factory, factoryData]), - entryPoint: entryPoint - } - } else { - args = { - entryPoint: entryPoint, - factory, - factoryData - } - } - - const sender = await getSenderAddress(publicClient, args) - - expect(sender).not.toBeNull() - expect(sender).not.toBeUndefined() - expectTypeOf(sender).toMatchTypeOf
() - } - ) - - test.each([ - ["v0.7", ENTRYPOINT_ADDRESS_V07], - ["v0.6", ENTRYPOINT_ADDRESS_V06] - ])("%s getUserOperationHash", async (_version, entryPoint) => { - const bundlerClient = getBundlerClient(entryPoint) - const smartAccountClient = await getSafeClient({ - entryPoint - }) - - const userOperation = - await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccountClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - - const gasParameters = await bundlerClient.estimateUserOperationGas({ - //@ts-ignore - userOperation - }) - - userOperation.callGasLimit = gasParameters.callGasLimit - userOperation.verificationGasLimit = gasParameters.verificationGasLimit - userOperation.preVerificationGas = gasParameters.preVerificationGas - - const userOpHash = getUserOperationHash({ - userOperation, - entryPoint, - chainId: foundry.id - }) - - expect(userOpHash).length.greaterThan(0) - expectTypeOf(userOpHash).toBeString() - expectTypeOf(userOpHash).toMatchTypeOf() - }) - - test.each([ - ["v0.7", ENTRYPOINT_ADDRESS_V07], - ["v0.6", ENTRYPOINT_ADDRESS_V06] - ])("%s signUserOperationHashWithECDSA", async (_version, entryPoint) => { - const bundlerClient = getBundlerClient(entryPoint) - const smartAccountClient = await getSafeClient({ - entryPoint - }) - - const userOperation = - await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccountClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - - const gasParameters = await bundlerClient.estimateUserOperationGas({ - //@ts-ignore - userOperation - }) - - userOperation.callGasLimit = gasParameters.callGasLimit - userOperation.verificationGasLimit = gasParameters.verificationGasLimit - userOperation.preVerificationGas = gasParameters.preVerificationGas - - const userOpHash = getUserOperationHash({ - userOperation, - entryPoint, - chainId: foundry.id - }) - - userOperation.signature = await signUserOperationHashWithECDSA({ - client: smartAccountClient, - userOperation, - entryPoint: entryPoint, - chainId: foundry.id - }) - - expectTypeOf(userOperation.signature).toBeString() - expectTypeOf(userOperation.signature).toMatchTypeOf() - - const signature = await signUserOperationHashWithECDSA({ - client: smartAccountClient, - hash: userOpHash - }) - - await signUserOperationHashWithECDSA({ - account: smartAccountClient.account, - hash: userOpHash - }) - - await signUserOperationHashWithECDSA({ - account: smartAccountClient.account, - userOperation, - entryPoint: entryPoint, - chainId: foundry.id - }) - - await signUserOperationHashWithECDSA({ - account: privateKeyToAccount(generatePrivateKey()), - userOperation, - entryPoint: entryPoint, - chainId: foundry.id - }) - - expectTypeOf(userOpHash).toBeString() - expectTypeOf(userOpHash).toMatchTypeOf() - expect(userOpHash).length.greaterThan(0) - - expect(signature).toEqual(userOperation.signature) - }) - - test.each([ - ["v0.7", ENTRYPOINT_ADDRESS_V07], - ["v0.6", ENTRYPOINT_ADDRESS_V06] - ])("%s getRequiredGas", async (_version, entryPoint) => { - const bundlerClient = getBundlerClient(entryPoint) - const smartAccountClient = await getSafeClient({ - entryPoint - }) - - const userOperation = - await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccountClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - - const gasParameters = await bundlerClient.estimateUserOperationGas({ - //@ts-ignore - userOperation - }) - - userOperation.callGasLimit = gasParameters.callGasLimit - userOperation.verificationGasLimit = gasParameters.verificationGasLimit - userOperation.preVerificationGas = gasParameters.preVerificationGas - - const requiredGas = getRequiredPrefund({ - userOperation, - entryPoint - }) - - expect(requiredGas).toBe( - (gasParameters.callGasLimit + - gasParameters.verificationGasLimit + - gasParameters.preVerificationGas) * - userOperation.maxFeePerGas - ) - }) - - test("getPackedUserOperation", async () => { - const smartAccountClient = await getSafeClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - const userOperation = - await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccountClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - - const packedUserOperation = getPackedUserOperation(userOperation) - - expectTypeOf(packedUserOperation).toMatchTypeOf() - }) -}) diff --git a/packages/permissionless-test/src/constants.ts b/packages/permissionless-test/src/constants.ts deleted file mode 100644 index ec20334f..00000000 --- a/packages/permissionless-test/src/constants.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Address } from "viem" - -/* ========= V07 RELATED ========= */ - -export const SIMPLE_ACCOUNT_FACTORY_V07: Address = - "0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985" - -/* ========= V06 RELATED ========= */ - -export const SIMPLE_ACCOUNT_FACTORY_V06: Address = - "0x9406Cc6185a346906296840746125a0E44976454" - -/* */ diff --git a/packages/permissionless-test/src/ep-0.6/bundlerActions.test.ts b/packages/permissionless-test/src/ep-0.6/bundlerActions.test.ts deleted file mode 100644 index 716a31a1..00000000 --- a/packages/permissionless-test/src/ep-0.6/bundlerActions.test.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { type Chain, isHash, zeroAddress } from "viem" -import { foundry } from "viem/chains" -import { beforeAll, describe, expect, test } from "vitest" -import { - type BundlerClient, - WaitForUserOperationReceiptTimeoutError -} from "../../../permissionless" -import type { - ENTRYPOINT_ADDRESS_V06_TYPE, - UserOperation -} from "../../../permissionless/types" -import { - ENTRYPOINT_ADDRESS_V06, - getUserOperationHash -} from "../../../permissionless/utils" -import { - ensureBundlerIsReady, - ensurePaymasterIsReady, - fund, - getBundlerClient, - getSimpleAccountClient -} from "../utils" - -describe("V0.6 Bundler Actions", () => { - let bundlerClient: BundlerClient - - beforeAll(async () => { - bundlerClient = getBundlerClient(ENTRYPOINT_ADDRESS_V06) - await ensureBundlerIsReady() - await ensurePaymasterIsReady() - }) - - test("can handle eth_supportedEntryPoints", async () => { - const supportedEntryPoints = await bundlerClient.supportedEntryPoints() - - expect(Array.isArray(supportedEntryPoints)).toBe(true) - expect(supportedEntryPoints.length).toBeGreaterThan(0) - expect(supportedEntryPoints.includes(ENTRYPOINT_ADDRESS_V06)).toBe(true) - }) - - test("can handle eth_chainId", async () => { - const chainId = await bundlerClient.chainId() - - expect(chainId).toBeGreaterThan(0) - expect(chainId === foundry.id).toBe(true) - }) - - test("can handle eth_estimateUserOperationGas", async () => { - const simpleAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - - const userOperation = - (await simpleAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await simpleAccountClient.account.encodeCallData({ - to: "0x5af0d9827e0c53e4799bb226655a1de152a425a5", - data: "0x", - value: 0n - }) - } - })) as UserOperation<"v0.6"> - - const { preVerificationGas, verificationGasLimit, callGasLimit } = - await bundlerClient.estimateUserOperationGas({ - userOperation - }) - - expect(preVerificationGas).toBeTruthy() - expect(verificationGasLimit).toBeTruthy() - expect(callGasLimit).toBeTruthy() - }, 50000) - - test("can handle eth_sendUserOperation", async () => { - const smartAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - - await fund(smartAccountClient.account.address) - - const userOperation = - await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: "0x" - } - }) - - userOperation.signature = - await smartAccountClient.account.signUserOperation(userOperation) - - const opHash = await bundlerClient.sendUserOperation({ - userOperation - }) - - expect(isHash(opHash)).toBe(true) - - const userOperationReceipt = - await bundlerClient.waitForUserOperationReceipt({ - hash: opHash - }) - expect(userOperationReceipt).not.toBeNull() - expect(userOperationReceipt?.userOpHash).toBe(opHash) - expect(userOperationReceipt?.receipt.transactionHash).toBeTruthy() - - const receipt = await bundlerClient.getUserOperationReceipt({ - hash: opHash - }) - - expect(receipt?.receipt.transactionHash).toBe( - userOperationReceipt?.receipt.transactionHash - ) - - const userOperationFromUserOpHash = - await bundlerClient.getUserOperationByHash({ hash: opHash }) - - expect(userOperationFromUserOpHash).not.toBeNull() - expect(userOperationFromUserOpHash?.entryPoint).toBe( - ENTRYPOINT_ADDRESS_V06 - ) - expect(userOperationFromUserOpHash?.transactionHash).toBe( - userOperationReceipt?.receipt.transactionHash - ) - - for (const key in userOperationFromUserOpHash?.userOperation) { - const expected = userOperationFromUserOpHash?.userOperation[key] - const actual = userOperation[key] - - if (typeof expected === "string" && typeof actual === "string") { - expect(expected.toLowerCase()).toBe(actual.toLowerCase()) - } else { - expect(expected).toBe(actual) - } - } - }, 50000) - - test("wait for user operation receipt fail", async () => { - const smartAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - - await fund(smartAccountClient.account.address) - - const userOperation = - await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccountClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - - const gasParameters = await bundlerClient.estimateUserOperationGas({ - userOperation - }) - - userOperation.callGasLimit = gasParameters.callGasLimit - userOperation.verificationGasLimit = gasParameters.verificationGasLimit - userOperation.preVerificationGas = gasParameters.preVerificationGas - - const userOpHash = getUserOperationHash({ - userOperation, - entryPoint: ENTRYPOINT_ADDRESS_V06, - chainId: foundry.id - }) - - await expect(async () => - bundlerClient.waitForUserOperationReceipt({ - hash: userOpHash, - timeout: 100 - }) - ).rejects.toThrow(WaitForUserOperationReceiptTimeoutError) - }) -}) diff --git a/packages/permissionless-test/src/ep-0.6/coreSmartClientActions.test.ts b/packages/permissionless-test/src/ep-0.6/coreSmartClientActions.test.ts deleted file mode 100644 index 9b6754b7..00000000 --- a/packages/permissionless-test/src/ep-0.6/coreSmartClientActions.test.ts +++ /dev/null @@ -1,564 +0,0 @@ -import { - http, - type BaseError, - type Chain, - type PublicClient, - type Transport, - decodeEventLog, - getAddress, - getContract, - isAddress, - isHash, - parseEther, - zeroAddress -} from "viem" -import { generatePrivateKey, privateKeyToAccount } from "viem/accounts" -import { foundry } from "viem/chains" -import { beforeAll, describe, expect, test } from "vitest" -import { - type BundlerClient, - ENTRYPOINT_ADDRESS_V06, - createSmartAccountClient -} from "../../../permissionless" -import { - SignTransactionNotSupportedBySmartAccount, - signerToBiconomySmartAccount, - signerToEcdsaKernelSmartAccount, - signerToLightSmartAccount, - signerToSafeSmartAccount, - signerToSimpleSmartAccount, - signerToTrustSmartAccount -} from "../../../permissionless/accounts" -import type { PimlicoPaymasterClient } from "../../../permissionless/clients/pimlico" -import type { ENTRYPOINT_ADDRESS_V06_TYPE } from "../../../permissionless/types" -import { getUserOperationHash } from "../../../permissionless/utils" -import { ENTRYPOINT_V06_ABI } from "../../abi/entryPointV06Abi" -import { SIMPLE_ACCOUNT_FACTORY_V06 } from "../constants" -import type { AAParamType, ExistingSignerParamType } from "../types" -import { - ensureBundlerIsReady, - ensurePaymasterIsReady, - fund, - getBiconomyClient, - getBundlerClient, - getKernelEcdsaClient, - getLightAccountClient, - getPimlicoPaymasterClient, - getPublicClient, - getSafeClient, - getSimpleAccountClient, - getTrustAccountClient -} from "../utils" - -describe.each([ - { - name: "Trust", - getSmartAccountClient: async ( - conf: AAParamType - ) => getTrustAccountClient(conf), - getSmartAccountSigner: async (conf: ExistingSignerParamType) => - signerToTrustSmartAccount(conf.publicClient, { - address: conf.existingAddress, // this is the field we are testing - signer: privateKeyToAccount(conf.privateKey), - entryPoint: ENTRYPOINT_ADDRESS_V06 - }), - isEip1271Compliant: true - }, - { - name: "LightAccount v1.1.0", - getSmartAccountClient: async ( - conf: AAParamType - ) => getLightAccountClient(conf), - getSmartAccountSigner: async (conf: ExistingSignerParamType) => - signerToLightSmartAccount(conf.publicClient, { - address: conf.existingAddress, // this is the field we are testing - signer: privateKeyToAccount(conf.privateKey), - entryPoint: ENTRYPOINT_ADDRESS_V06, - lightAccountVersion: "1.1.0" - }), - isEip1271Compliant: true - }, - { - name: "Simple", - getSmartAccountClient: async ( - conf: AAParamType - ) => getSimpleAccountClient(conf), - getSmartAccountSigner: async (conf: ExistingSignerParamType) => - signerToSimpleSmartAccount(conf.publicClient, { - address: conf.existingAddress, // this is the field we are testing - signer: privateKeyToAccount(conf.privateKey), - entryPoint: ENTRYPOINT_ADDRESS_V06, - factoryAddress: SIMPLE_ACCOUNT_FACTORY_V06 - }), - isEip1271Compliant: false - }, - { - name: "Kernel", - getSmartAccountClient: async ( - conf: AAParamType - ) => getKernelEcdsaClient(conf), - getSmartAccountSigner: async (conf: ExistingSignerParamType) => - signerToEcdsaKernelSmartAccount(conf.publicClient, { - address: conf.existingAddress, // this is the field we are testing - signer: privateKeyToAccount(conf.privateKey), - entryPoint: ENTRYPOINT_ADDRESS_V06 - }), - isEip1271Compliant: true - }, - { - name: "Biconomy", - getSmartAccountClient: async ( - conf: AAParamType - ) => getBiconomyClient(conf), - getSmartAccountSigner: async (conf: ExistingSignerParamType) => - signerToBiconomySmartAccount(conf.publicClient, { - address: conf.existingAddress, // this is the field we are testing - signer: privateKeyToAccount(conf.privateKey), - entryPoint: ENTRYPOINT_ADDRESS_V06 - }), - isEip1271Compliant: true - }, - { - name: "Safe", - getSmartAccountClient: async ( - conf: AAParamType - ) => getSafeClient(conf), - getSmartAccountSigner: async (conf: ExistingSignerParamType) => - signerToSafeSmartAccount(conf.publicClient, { - address: conf.existingAddress, // this is the field we are testing - signer: privateKeyToAccount(conf.privateKey), - entryPoint: ENTRYPOINT_ADDRESS_V06, - safeVersion: "1.4.1" - }), - isEip1271Compliant: true - } -])( - "$name account should support all core functions", - ({ getSmartAccountClient, getSmartAccountSigner, isEip1271Compliant }) => { - let publicClient: PublicClient - let bundlerClient: BundlerClient - let paymasterClient: PimlicoPaymasterClient - - beforeAll(async () => { - publicClient = getPublicClient() - bundlerClient = getBundlerClient(ENTRYPOINT_ADDRESS_V06) - paymasterClient = getPimlicoPaymasterClient(ENTRYPOINT_ADDRESS_V06) - - await ensureBundlerIsReady() - await ensurePaymasterIsReady() - }) - - test("Can get get address", async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - const smartAccount = smartClient.account - - expect(isAddress(smartAccount.address)).toBe(true) - }) - - test("Calling signTransaction should throw not supported", async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - const smartAccount = smartClient.account - - await expect(async () => - smartAccount.signTransaction({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - ).rejects.toThrow(SignTransactionNotSupportedBySmartAccount) - }) - - test("Calling deployContract should throw not supported", async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - - await expect(async () => - smartClient.deployContract({ - abi: [], - bytecode: "0xff66" - }) - ).rejects.toThrowError(/^.*doesn't support account deployment.*$/i) - }) - - test.sequential( - "Can send transaction", - async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - - await fund(smartClient.account.address) - - const response = await smartClient.sendTransaction({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - - expect(isHash(response)).toBeTruthy() - }, - 10000 - ) - - test.sequential( - "Can send multiple transactions", - async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - - await fund(smartClient.account.address) - - const response = await smartClient.sendTransactions({ - transactions: [ - { - to: zeroAddress, - value: 0n, - data: "0x" - }, - { - to: zeroAddress, - value: 0n, - data: "0x" - } - ] - }) - - expect(isHash(response)).toBe(true) - }, - 10000 - ) - - test.sequential( - "Can write contract", - async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - - await fund(smartClient.account.address) - - const entryPointContract = getContract({ - abi: ENTRYPOINT_V06_ABI, - address: ENTRYPOINT_ADDRESS_V06, - client: { - public: getPublicClient(), - wallet: smartClient - } - }) - - const oldBalance = await entryPointContract.read.balanceOf([ - smartClient.account.address - ]) - - // @ts-ignore - const txHash = await entryPointContract.write.depositTo( - [smartClient.account.address], - { - value: parseEther("0.25") - } - ) - - expect(isHash(txHash)).toBe(true) - - const newBalance = await entryPointContract.read.balanceOf([ - smartClient.account.address - ]) - - //@ts-ignore - expect(newBalance - oldBalance).toBeGreaterThanOrEqual( - parseEther("0.25") - ) - }, - 10000 - ) - - test.sequential( - "Can send transaction with paymaster", - async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06, - paymasterClient - }) - - // derive expected hash so that we can search for it in logs - const op = await smartClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - op.signature = await smartClient.account.signUserOperation(op) - - const expectedHash = getUserOperationHash({ - userOperation: op, - entryPoint: ENTRYPOINT_ADDRESS_V06, - chainId: foundry.id - }) - - const response = await smartClient.sendTransaction({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - - expect(isHash(response)).toBe(true) - - const transactionReceipt = - await publicClient.waitForTransactionReceipt({ - hash: response - }) - - let eventFound = false - - for (const log of transactionReceipt.logs) { - try { - // biome-ignore lint/suspicious/noExplicitAny: - let event: any - try { - event = decodeEventLog({ - abi: ENTRYPOINT_V06_ABI, - ...log - }) - } catch { - continue - } - if ( - event.eventName === "UserOperationEvent" && - event.args.userOpHash === expectedHash - ) { - eventFound = true - const op = - await bundlerClient.getUserOperationByHash({ - hash: event.args.userOpHash - }) - expect(op?.userOperation.paymasterAndData).not.toBe( - "0x" - ) - } - } catch (e) { - const error = e as BaseError - if (error.name !== "AbiEventSignatureNotFoundError") - throw e - } - } - - expect(eventFound).toBeTruthy() - }, - 10000 - ) - - test.sequential( - "Can send multiple transactions with paymaster", - async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06, - paymasterClient - }) - - // derive expected hash so that we can search for it in logs - const op = await smartClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartClient.account.encodeCallData([ - { - to: zeroAddress, - value: 0n, - data: "0x" - }, - { - to: zeroAddress, - value: 0n, - data: "0x" - } - ]) - } - }) - op.signature = await smartClient.account.signUserOperation(op) - - const expectedHash = getUserOperationHash({ - userOperation: op, - entryPoint: ENTRYPOINT_ADDRESS_V06, - chainId: foundry.id - }) - - const response = await smartClient.sendTransactions({ - transactions: [ - { - to: zeroAddress, - value: 0n, - data: "0x" - }, - { - to: zeroAddress, - value: 0n, - data: "0x" - } - ] - }) - - expect(isHash(response)).toBeTruthy() - - const transactionReceipt = - await publicClient.waitForTransactionReceipt({ - hash: response - }) - - let eventFound = false - - for (const log of transactionReceipt.logs) { - // biome-ignore lint/suspicious/noExplicitAny: - let event: any - try { - event = decodeEventLog({ - abi: ENTRYPOINT_V06_ABI, - ...log - }) - } catch { - continue - } - if ( - event.eventName === "UserOperationEvent" && - event.args.userOpHash === expectedHash - ) { - eventFound = true - const op = await bundlerClient.getUserOperationByHash({ - hash: event.args.userOpHash - }) - expect(op?.userOperation.paymasterAndData).not.toBe( - "0x" - ) - } - } - - expect(eventFound).toBeTruthy() - }, - 10000 - ) - - test("Should work with existing (deployed) smart account", async () => { - const privateKey = generatePrivateKey() - - const existingClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06, - privateKey - }) - - // force a deployment - await fund(existingClient.account.address) - await existingClient.sendTransaction({ - to: zeroAddress - }) - - // create new simpleSmartAccount client from existing SmartAcocunt - const newSimpleSigner = await getSmartAccountSigner({ - publicClient, - privateKey, - existingAddress: existingClient.account.address - }) - - const newSimpleClient = createSmartAccountClient({ - chain: foundry, - account: newSimpleSigner, - bundlerTransport: http(ALTO_RPC) - }) - - const response = await newSimpleClient.sendTransaction({ - to: zeroAddress, - data: "0x", - value: parseEther("0.01") - }) - - expect(isHash(response)) - }, 25000) - - test("Can sign and verify message", async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - - if (!isEip1271Compliant) { - return await expect(async () => - smartClient.signMessage({ - message: "vires in numeris" - }) - ).rejects.toThrow() - } - - const signature = await smartClient.signMessage({ - message: "vires in numeris" - }) - - const isVerified = await publicClient.verifyMessage({ - address: smartClient.account.address, - message: "vires in numeris", - signature - }) - - expect(isVerified).toBeTruthy() - }) - - test("Can sign and verify typed data", async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - - const typedData = { - domain: { - name: "Ether Mail", - version: "1", - chainId: 1, - verifyingContract: getAddress( - "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" - ) - }, - types: { - Person: [ - { name: "name", type: "string" }, - { name: "wallet", type: "address" } - ], - Mail: [ - { name: "from", type: "Person" }, - { name: "to", type: "Person" }, - { name: "contents", type: "string" } - ] - }, - primaryType: "Mail" as const, - message: { - from: { - name: "Cow", - wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" - }, - to: { - name: "Bob", - wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" - }, - contents: "Hello, Bob!" - } - } - - if (!isEip1271Compliant) { - return await expect(async () => - smartClient.signTypedData(typedData) - ).rejects.toThrow() - } - - const signature = await smartClient.signTypedData(typedData) - - const isVerified = await publicClient.verifyTypedData({ - ...typedData, - address: smartClient.account.address, - signature - }) - - expect(isVerified).toBeTruthy() - }) - } -) diff --git a/packages/permissionless-test/src/ep-0.6/experiments.ts b/packages/permissionless-test/src/ep-0.6/experiments.ts deleted file mode 100644 index 191f88b7..00000000 --- a/packages/permissionless-test/src/ep-0.6/experiments.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { http, createClient, zeroAddress } from "viem" -import { generatePrivateKey } from "viem/accounts" -import { foundry } from "viem/chains" -import { describe, test } from "vitest" -import { - ENTRYPOINT_ADDRESS_V06, - createSmartAccountClient -} from "../../../permissionless" -import { privateKeyToSafeSmartAccount } from "../../../permissionless/accounts" -import { paymasterActionsEip7677 } from "../../../permissionless/experimental" -import type { ENTRYPOINT_ADDRESS_V06_TYPE } from "../../../permissionless/types" -import type { AAParamType } from "../types" -import { - PAYMASTER_RPC, - getPimlicoPaymasterClient, - getPublicClient, - getSafeClient -} from "../utils" - -describe.each([ - { - name: "Eip 7677 client", - - getSmartAccountClient: async ( - conf: AAParamType - ) => getSafeClient(conf) - } -])("$name test", ({ name, getSmartAccountClient }) => { - test("Can get stab data", async () => { - const publicClient = getPublicClient() - - const smartAccount = await privateKeyToSafeSmartAccount(publicClient, { - safeVersion: "1.4.1", - entryPoint: ENTRYPOINT_ADDRESS_V06, - privateKey: generatePrivateKey() - }) - const ALTO_RPC = "http://localhost:4337" - - const paymasterClient = getPimlicoPaymasterClient( - ENTRYPOINT_ADDRESS_V06 - ) - - const smartAccountClient = createSmartAccountClient({ - chain: foundry, - account: smartAccount, - bundlerTransport: http(ALTO_RPC) - }) - - const userOperaton = - await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccountClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - - const eip7677Client = createClient({ - chain: foundry, - transport: http(PAYMASTER_RPC) - }).extend(paymasterActionsEip7677(ENTRYPOINT_ADDRESS_V06)) - - await eip7677Client.getPaymasterData({ - userOperation: userOperaton - }) - - await eip7677Client.getPaymasterStubData({ - userOperation: userOperaton - }) - - // await eip7677Client.getPaymasterStubData({ - // userOperation: await smartClient.prepareUserOperationRequest({ - // userOperation: { - // callData: await smartClient.account.encodeCallData({ - // to: zeroAddress, - // value: 0n, - // data: "0x" - // }) - // } - // }) - // }) - }) -}) diff --git a/packages/permissionless-test/src/ep-0.6/pimlicoActions.test.ts b/packages/permissionless-test/src/ep-0.6/pimlicoActions.test.ts deleted file mode 100644 index 54cfd87f..00000000 --- a/packages/permissionless-test/src/ep-0.6/pimlicoActions.test.ts +++ /dev/null @@ -1,209 +0,0 @@ -import { - type Chain, - type PublicClient, - type Transport, - isHash, - isHex -} from "viem" -import { beforeAll, describe, expect, test } from "vitest" -import type { PimlicoBundlerClient } from "../../../permissionless/clients/pimlico" -import type { - ENTRYPOINT_ADDRESS_V06_TYPE, - UserOperation -} from "../../../permissionless/types" -import { ENTRYPOINT_ADDRESS_V06 } from "../../../permissionless/utils" -import { - ensureBundlerIsReady, - ensurePaymasterIsReady, - fund, - getPimlicoBundlerClient, - getPimlicoPaymasterClient, - getPublicClient, - getSimpleAccountClient -} from "../utils" - -describe("Pimlico Actions tests", () => { - let publicClient: PublicClient - let pimlicoBundlerClient: PimlicoBundlerClient - - beforeAll(async () => { - publicClient = getPublicClient() - pimlicoBundlerClient = getPimlicoBundlerClient(ENTRYPOINT_ADDRESS_V06) - - await ensureBundlerIsReady() - await ensurePaymasterIsReady() - }) - - describe("Pimlico Bundler actions", () => { - test("can fetch gas price", async () => { - const gasPrice = - await pimlicoBundlerClient.getUserOperationGasPrice() - - expect(gasPrice).toBeTruthy() - expect(gasPrice.slow).toBeTruthy() - expect(gasPrice.standard).toBeTruthy() - expect(gasPrice.fast).toBeTruthy() - expect(typeof gasPrice.slow.maxFeePerGas).toBe("bigint") - expect(gasPrice.slow.maxFeePerGas).toBeGreaterThan(0n) - expect(typeof gasPrice.slow.maxPriorityFeePerGas).toBe("bigint") - expect(gasPrice.slow.maxPriorityFeePerGas).toBeGreaterThan(0n) - expect(typeof gasPrice.standard.maxFeePerGas).toBe("bigint") - expect(gasPrice.standard.maxFeePerGas).toBeGreaterThan(0n) - expect(typeof gasPrice.standard.maxPriorityFeePerGas).toBe("bigint") - expect(gasPrice.standard.maxPriorityFeePerGas).toBeGreaterThan(0n) - expect(typeof gasPrice.fast.maxFeePerGas).toBe("bigint") - expect(gasPrice.fast.maxFeePerGas).toBeGreaterThan(0n) - expect(typeof gasPrice.fast.maxPriorityFeePerGas).toBe("bigint") - expect(gasPrice.fast.maxPriorityFeePerGas).toBeGreaterThan(0n) - }) - test("fetch user operation status", async () => {}) - }) - - describe("Pimlico paymaster actions ", () => { - test("can fetch paymasterAndData", async () => { - const { maxFeePerGas, maxPriorityFeePerGas } = - await publicClient.estimateFeesPerGas() - - const simpleAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06 - }) - - await fund(simpleAccountClient.account.address) - - const partialUserOp = - await simpleAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: - await simpleAccountClient.account.encodeCallData({ - to: "0x5af0d9827e0c53e4799bb226655a1de152a425a5", - data: "0x", - value: 0n - }) - } - }) - - const userOperation: UserOperation<"v0.6"> = { - ...partialUserOp, - maxFeePerGas: maxFeePerGas || 0n, - maxPriorityFeePerGas: maxPriorityFeePerGas || 0n, - callGasLimit: 0n, - verificationGasLimit: 0n, - preVerificationGas: 0n - } - - const pimlicoPaymasterClient = getPimlicoPaymasterClient( - ENTRYPOINT_ADDRESS_V06 - ) - - const result = await pimlicoPaymasterClient.sponsorUserOperation({ - userOperation - }) - - expect(result).toBeTruthy() - expect(typeof result.callGasLimit).toBe("bigint") - expect(result.callGasLimit).toBeGreaterThan(0n) - expect(typeof result.preVerificationGas).toBe("bigint") - expect(result.preVerificationGas).toBeGreaterThan(0n) - expect(typeof result.verificationGasLimit).toBe("bigint") - expect(result.verificationGasLimit).toBeGreaterThan(0n) - expect(result.paymasterAndData.length).toBeGreaterThan(0) - expect(isHex(result.paymasterAndData)).toBe(true) - }, 100000) - - test("can send userOperation with paymaster and data", async () => { - const smartClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06, - paymasterClient: getPimlicoPaymasterClient( - ENTRYPOINT_ADDRESS_V06 - ) - }) - const smartAccount = smartClient.account - - const op = await smartClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccount.encodeCallData({ - to: "0x5af0d9827e0c53e4799bb226655a1de152a425a5", - data: "0x", - value: 0n - }) - } - }) - - op.signature = await smartAccount.signUserOperation(op) - - const userOpHash = await pimlicoBundlerClient.sendUserOperation({ - userOperation: op - }) - expect(isHash(userOpHash)).toBe(true) - - const userOperationReceipt = - await pimlicoBundlerClient.waitForUserOperationReceipt({ - hash: userOpHash - }) - expect(userOperationReceipt).not.toBeNull() - expect(userOperationReceipt?.userOpHash).toBe(userOpHash) - expect( - userOperationReceipt?.receipt.transactionHash.length - ).toBeGreaterThan(0) - expect(userOperationReceipt?.receipt.transactionHash).not.toBeNull() - expect( - userOperationReceipt?.receipt.transactionHash - ).not.toBeUndefined() - const userOperationFromUserOpHash = - await pimlicoBundlerClient.getUserOperationByHash({ - hash: userOpHash - }) - expect(userOperationFromUserOpHash).not.toBeNull() - expect(userOperationFromUserOpHash?.entryPoint).toBe( - ENTRYPOINT_ADDRESS_V06 - ) - expect(userOperationFromUserOpHash?.transactionHash).toBe( - userOperationReceipt?.receipt.transactionHash - ) - - const userOperationStatus = - await pimlicoBundlerClient.getUserOperationStatus({ - hash: userOpHash - }) - expect(userOperationStatus).not.toBeNull() - expect(userOperationStatus).not.toBeUndefined() - expect(userOperationStatus.status).toBe("included") - expect(userOperationStatus.transactionHash).toBe( - userOperationReceipt?.receipt.transactionHash - ) - }, 100000) - }) - - test("Validating sponsorship policies", async () => { - const simpleAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06, - paymasterClient: getPimlicoPaymasterClient(ENTRYPOINT_ADDRESS_V06) - }) - - const userOperation = - await simpleAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await simpleAccountClient.account.encodeCallData({ - to: "0x5af0d9827e0c53e4799bb226655a1de152a425a5", - data: "0x", - value: 0n - }) - } - }) - - const pimlicoPaymasterClient = getPimlicoPaymasterClient( - ENTRYPOINT_ADDRESS_V06 - ) - - const validateSponsorshipPolicies = - await pimlicoPaymasterClient.validateSponsorshipPolicies({ - userOperation: userOperation, - sponsorshipPolicyIds: ["sp_crazy_kangaroo"] - }) - - expect(validateSponsorshipPolicies).toBeTruthy() - expect(validateSponsorshipPolicies.length).toBeGreaterThan(0) - expect(Array.isArray(validateSponsorshipPolicies)).toBe(true) - expect(validateSponsorshipPolicies.length).toBe(1) - }, 100000) -}) diff --git a/packages/permissionless-test/src/ep-0.6/safeSmartAccount.test.ts b/packages/permissionless-test/src/ep-0.6/safeSmartAccount.test.ts deleted file mode 100644 index ea031a92..00000000 --- a/packages/permissionless-test/src/ep-0.6/safeSmartAccount.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { isHash, zeroAddress } from "viem" -import { beforeAll, describe, expect, test } from "vitest" -import { ENTRYPOINT_ADDRESS_V06 } from "../../../permissionless" -import { - ensureBundlerIsReady, - ensurePaymasterIsReady, - fund, - getSafeClient -} from "../utils" - -describe("Safe Specific Actions V0.6", () => { - beforeAll(async () => { - await ensureBundlerIsReady() - await ensurePaymasterIsReady() - }) - - test("Can deploy with setup transaction", async () => { - const smartAccountClient = await getSafeClient({ - entryPoint: ENTRYPOINT_ADDRESS_V06, - setupTransactions: [ - { - to: zeroAddress, - data: "0xff", - value: 0n - } - ] - }) - - await fund(smartAccountClient.account.address) - - const response = await smartAccountClient.sendTransaction({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - - expect(isHash(response)).toBe(true) - }, 10000) -}) diff --git a/packages/permissionless-test/src/ep-0.7/bundlerActions.test.ts b/packages/permissionless-test/src/ep-0.7/bundlerActions.test.ts deleted file mode 100644 index 12468ff1..00000000 --- a/packages/permissionless-test/src/ep-0.7/bundlerActions.test.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { type Chain, isHash } from "viem" -import { foundry } from "viem/chains" -import { beforeAll, describe, expect, test } from "vitest" -import { - type BundlerClient, - ENTRYPOINT_ADDRESS_V07, - type UserOperation, - WaitForUserOperationReceiptTimeoutError, - getUserOperationHash -} from "../../../permissionless" -import type { ENTRYPOINT_ADDRESS_V07_TYPE } from "../../../permissionless/types" -import { - ensureBundlerIsReady, - ensurePaymasterIsReady, - fund, - getBundlerClient, - getPimlicoPaymasterClient, - getSimpleAccountClient -} from "../utils" - -describe("v0.7 Bundler Actions", () => { - let bundlerClient: BundlerClient - - beforeAll(async () => { - bundlerClient = getBundlerClient(ENTRYPOINT_ADDRESS_V07) - - await ensureBundlerIsReady() - await ensurePaymasterIsReady() - }) - - test("Supports eth_supportedEntryPoints", async () => { - const supportedEntryPoints = await bundlerClient.supportedEntryPoints() - - expect(Array.isArray(supportedEntryPoints)) - expect(supportedEntryPoints.length).toBeGreaterThan(0) - expect(supportedEntryPoints.includes(ENTRYPOINT_ADDRESS_V07)) - }) - - test("Supports eth_chainId", async () => { - const chainId = await bundlerClient.chainId() - - expect(chainId).toBe(foundry.id) - expect(chainId).toBeGreaterThan(0) - expect(chainId === foundry.id) - }) - - test("Supports eth_estimateUserOperationGas", async () => { - const smartAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07, - paymasterClient: getPimlicoPaymasterClient(ENTRYPOINT_ADDRESS_V07) - }) - - const userOperation = - (await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccountClient.account.encodeCallData({ - to: "0x5af0d9827e0c53e4799bb226655a1de152a425a5", - data: "0x", - value: 0n - }) - } - })) as UserOperation<"v0.7"> - - const { - preVerificationGas, - verificationGasLimit, - callGasLimit, - paymasterVerificationGasLimit, - paymasterPostOpGasLimit - } = await bundlerClient.estimateUserOperationGas({ - userOperation - }) - - expect(preVerificationGas).toBeTruthy() - expect(verificationGasLimit).toBeTruthy() - expect(callGasLimit).toBeTruthy() - expect(paymasterVerificationGasLimit).toBeTruthy() - expect(paymasterPostOpGasLimit).toBeTruthy() - }, 100000) - - test("Supports eth_sendUserOperation", async () => { - const smartAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - await fund(smartAccountClient.account.address) - - const op = await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccountClient.account.encodeCallData({ - to: "0x1111111111111111111111111111111111111111", - data: "0x", - value: 0n - }) - } - }) - op.signature = await smartAccountClient.account.signUserOperation(op) - - const opHash = await bundlerClient.sendUserOperation({ - userOperation: op - }) - - expect(isHash(opHash)).toBe(true) - - const userOperationReceipt = - await bundlerClient.waitForUserOperationReceipt({ - hash: opHash - }) - - expect(userOperationReceipt).not.toBeNull() - expect(userOperationReceipt?.userOpHash).toBe(opHash) - expect(userOperationReceipt?.receipt.transactionHash).toBeTruthy() - - const receipt = await bundlerClient.getUserOperationReceipt({ - hash: opHash - }) - - expect(receipt?.receipt.transactionHash).toBe( - userOperationReceipt?.receipt.transactionHash - ) - - //await new Promise((resolve) => setTimeout(resolve, 1000)) - - //const userOperationFromUserOpHash = - // await bundlerClient.getUserOperationByHash({ hash: opHash }) - - //expect(userOperationFromUserOpHash).not.toBeNull() - //expect(userOperationFromUserOpHash?.entryPoint).toBe( - // ENTRYPOINT_ADDRESS_V07 - //) - //expect(userOperationFromUserOpHash?.transactionHash).toBe( - // userOperationReceipt?.receipt.transactionHash - //) - - //for (const key in userOperationFromUserOpHash?.userOperation) { - // expect(userOperationFromUserOpHash?.userOperation[key]).toBe( - // op[key] - // ) - //} - }, 100000) - - test("Should handle eth_sendUserOperation failures", async () => { - const smartAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - const userOperation = - await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccountClient.account.encodeCallData({ - to: "0x5af0d9827e0c53e4799bb226655a1de152a425a5", - data: "0x", - value: 0n - }) - } - }) - - const gasParameters = await bundlerClient.estimateUserOperationGas({ - userOperation - }) - - userOperation.callGasLimit = gasParameters.callGasLimit - userOperation.verificationGasLimit = gasParameters.verificationGasLimit - userOperation.preVerificationGas = gasParameters.preVerificationGas - - const userOpHash = getUserOperationHash({ - userOperation, - entryPoint: ENTRYPOINT_ADDRESS_V07, - chainId: foundry.id - }) - - await expect( - bundlerClient.waitForUserOperationReceipt({ - hash: userOpHash, - timeout: 100 - }) - ).rejects.toThrow(WaitForUserOperationReceiptTimeoutError) - }) -}) diff --git a/packages/permissionless-test/src/ep-0.7/coreSmartClinetActions.test.ts b/packages/permissionless-test/src/ep-0.7/coreSmartClinetActions.test.ts deleted file mode 100644 index f4a0a7ba..00000000 --- a/packages/permissionless-test/src/ep-0.7/coreSmartClinetActions.test.ts +++ /dev/null @@ -1,532 +0,0 @@ -import { - http, - type BaseError, - type Chain, - type PublicClient, - type Transport, - decodeEventLog, - getAddress, - getContract, - isAddress, - isHash, - parseEther, - zeroAddress -} from "viem" -import { generatePrivateKey, privateKeyToAccount } from "viem/accounts" -import { foundry } from "viem/chains" -import { beforeAll, describe, expect, test } from "vitest" -import { - type BundlerClient, - ENTRYPOINT_ADDRESS_V07, - createSmartAccountClient -} from "../../../permissionless" -import { - SignTransactionNotSupportedBySmartAccount, - signerToEcdsaKernelSmartAccount, - signerToSafeSmartAccount, - signerToSimpleSmartAccount -} from "../../../permissionless/accounts" -import type { PimlicoPaymasterClient } from "../../../permissionless/clients/pimlico" -import type { ENTRYPOINT_ADDRESS_V07_TYPE } from "../../../permissionless/types" -import { getUserOperationHash } from "../../../permissionless/utils" -import { ENTRYPOINT_V07_ABI } from "../../abi/entryPointV07Abi" -import { SIMPLE_ACCOUNT_FACTORY_V07 } from "../constants" -import type { AAParamType, ExistingSignerParamType } from "../types" -import { - ALTO_RPC, - ensureBundlerIsReady, - ensurePaymasterIsReady, - fund, - getBundlerClient, - getKernelEcdsaClient, - getPimlicoPaymasterClient, - getPublicClient, - getSafeClient, - getSimpleAccountClient -} from "../utils" - -describe.each([ - { - name: "Simple", - getSmartAccountClient: async ( - conf: AAParamType - ) => getSimpleAccountClient(conf), - getSmartAccountSigner: async (conf: ExistingSignerParamType) => - signerToSimpleSmartAccount(conf.publicClient, { - address: conf.existingAddress, // this is the field we are testing - signer: privateKeyToAccount(conf.privateKey), - entryPoint: ENTRYPOINT_ADDRESS_V07, - factoryAddress: SIMPLE_ACCOUNT_FACTORY_V07 - }), - isEip1271Compliant: false - }, - { - name: "Kernel", - getSmartAccountClient: async ( - conf: AAParamType - ) => getKernelEcdsaClient(conf), - getSmartAccountSigner: async (conf: ExistingSignerParamType) => - signerToEcdsaKernelSmartAccount(conf.publicClient, { - address: conf.existingAddress, // this is the field we are testing - signer: privateKeyToAccount(conf.privateKey), - entryPoint: ENTRYPOINT_ADDRESS_V07 - }), - isEip1271Compliant: true - }, - //{ - // name: "Biconomy", - // getSmartAccountClient: async ( - // conf: AAParamType - // ) => getBiconomyClient(conf), - // getSmartAccountSigner: async (conf: ExistingSignerParamType) => - // signerToBiconomySmartAccount(conf.publicClient, { - // address: conf.existingAddress, // this is the field we are testing - // signer: privateKeyToAccount(conf.privateKey), - // entryPoint: ENTRYPOINT_ADDRESS_V07 - // }), - // isEip1271Compliant: true - //}, - { - name: "Safe", - getSmartAccountClient: async ( - conf: AAParamType - ) => getSafeClient(conf), - getSmartAccountSigner: async (conf: ExistingSignerParamType) => - signerToSafeSmartAccount(conf.publicClient, { - address: conf.existingAddress, // this is the field we are testing - signer: privateKeyToAccount(conf.privateKey), - entryPoint: ENTRYPOINT_ADDRESS_V07, - safeVersion: "1.4.1" - }), - isEip1271Compliant: true - } -])( - "$name account should support all core functions", - ({ getSmartAccountClient, getSmartAccountSigner, isEip1271Compliant }) => { - let publicClient: PublicClient - let bundlerClient: BundlerClient - let paymasterClient: PimlicoPaymasterClient - - beforeAll(async () => { - publicClient = getPublicClient() - bundlerClient = getBundlerClient(ENTRYPOINT_ADDRESS_V07) - paymasterClient = getPimlicoPaymasterClient(ENTRYPOINT_ADDRESS_V07) - - await ensureBundlerIsReady() - await ensurePaymasterIsReady() - }) - - test("Can get get address", async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - const smartAccount = smartClient.account - - expect(isAddress(smartAccount.address)).toBe(true) - }) - - test("Calling signTransaction should throw not supported", async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - const smartAccount = smartClient.account - - await expect(async () => - smartAccount.signTransaction({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - ).rejects.toThrow(SignTransactionNotSupportedBySmartAccount) - }) - - test("Calling deployContract should throw not supported", async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - await expect(async () => - smartClient.deployContract({ - abi: [], - bytecode: "0xff66" - }) - ).rejects.toThrowError(/^.*doesn't support account deployment.*$/i) - }) - - test.sequential( - "Can send transaction", - async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - await fund(smartClient.account.address) - - const response = await smartClient.sendTransaction({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - - expect(isHash(response)).toBeTruthy() - }, - 50000 - ) - - test.sequential( - "Can send multiple transactions", - async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - await fund(smartClient.account.address) - - const response = await smartClient.sendTransactions({ - transactions: [ - { - to: zeroAddress, - value: 0n, - data: "0x" - }, - { - to: zeroAddress, - value: 0n, - data: "0x" - } - ] - }) - - expect(isHash(response)).toBe(true) - }, - 50000 - ) - - test.sequential( - "Can write contract", - async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - await fund(smartClient.account.address) - - const entryPointContract = getContract({ - abi: ENTRYPOINT_V07_ABI, - address: ENTRYPOINT_ADDRESS_V07, - client: { - public: getPublicClient(), - wallet: smartClient - } - }) - - const oldBalance = await entryPointContract.read.balanceOf([ - smartClient.account.address - ]) - - // @ts-ignore - const txHash = await entryPointContract.write.depositTo( - [smartClient.account.address], - { - value: parseEther("0.25") - } - ) - - expect(isHash(txHash)).toBe(true) - - const newBalance = await entryPointContract.read.balanceOf([ - smartClient.account.address - ]) - - //@ts-ignore - expect(newBalance - oldBalance).toBeGreaterThanOrEqual( - parseEther("0.25") - ) - }, - 50000 - ) - - test.sequential( - "Can send transaction with paymaster", - async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07, - paymasterClient - }) - - // derive expected hash so that we can search for it in logs - const op = await smartClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - op.signature = await smartClient.account.signUserOperation(op) - - const expectedHash = getUserOperationHash({ - userOperation: op, - entryPoint: ENTRYPOINT_ADDRESS_V07, - chainId: foundry.id - }) - - const response = await smartClient.sendTransaction({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - - expect(isHash(response)).toBe(true) - - const transactionReceipt = - await publicClient.waitForTransactionReceipt({ - hash: response - }) - - let eventFound = false - - for (const log of transactionReceipt.logs) { - try { - // biome-ignore lint/suspicious/noExplicitAny: - let event: any - try { - event = decodeEventLog({ - abi: ENTRYPOINT_V07_ABI, - ...log - }) - } catch { - continue - } - if ( - event.eventName === "UserOperationEvent" && - event.args.userOpHash === expectedHash - ) { - eventFound = true - const op = - await bundlerClient.getUserOperationByHash({ - hash: event.args.userOpHash - }) - expect(op?.userOperation.paymasterAndData).not.toBe( - "0x" - ) - } - } catch (e) { - const error = e as BaseError - if (error.name !== "AbiEventSignatureNotFoundError") - throw e - } - } - - expect(eventFound).toBeTruthy() - }, - 10000 - ) - - test.sequential( - "Can send multiple transactions with paymaster", - async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07, - paymasterClient - }) - - // derive expected hash so that we can search for it in logs - const op = await smartClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartClient.account.encodeCallData([ - { - to: zeroAddress, - value: 0n, - data: "0x" - }, - { - to: zeroAddress, - value: 0n, - data: "0x" - } - ]) - } - }) - op.signature = await smartClient.account.signUserOperation(op) - - const expectedHash = getUserOperationHash({ - userOperation: op, - entryPoint: ENTRYPOINT_ADDRESS_V07, - chainId: foundry.id - }) - - const response = await smartClient.sendTransactions({ - transactions: [ - { - to: zeroAddress, - value: 0n, - data: "0x" - }, - { - to: zeroAddress, - value: 0n, - data: "0x" - } - ] - }) - - expect(isHash(response)).toBeTruthy() - - const transactionReceipt = - await publicClient.waitForTransactionReceipt({ - hash: response - }) - - let eventFound = false - - for (const log of transactionReceipt.logs) { - // biome-ignore lint/suspicious/noExplicitAny: - let event: any - try { - event = decodeEventLog({ - abi: ENTRYPOINT_V07_ABI, - ...log - }) - } catch { - continue - } - if ( - event.eventName === "UserOperationEvent" && - event.args.userOpHash === expectedHash - ) { - eventFound = true - const op = await bundlerClient.getUserOperationByHash({ - hash: event.args.userOpHash - }) - expect(op?.userOperation.paymasterAndData).not.toBe( - "0x" - ) - } - } - - expect(eventFound).toBeTruthy() - }, - 50000 - ) - - test("Should work with existing (deployed) smart account", async () => { - const privateKey = generatePrivateKey() - - const existingClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07, - privateKey - }) - - // force a deployment - await fund(existingClient.account.address) - await existingClient.sendTransaction({ - to: zeroAddress - }) - - // create new simpleSmartAccount client from existing SmartAcocunt - const newSimpleSigner = await getSmartAccountSigner({ - publicClient, - privateKey, - existingAddress: existingClient.account.address - }) - - const newSimpleClient = createSmartAccountClient({ - chain: foundry, - account: newSimpleSigner, - bundlerTransport: http(ALTO_RPC) - }) - - const response = await newSimpleClient.sendTransaction({ - to: zeroAddress, - data: "0x", - value: parseEther("0.01") - }) - - expect(isHash(response)) - }, 25000) - - test("Can sign and verify message", async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - if (!isEip1271Compliant) { - return await expect(async () => - smartClient.signMessage({ - message: "vires in numeris" - }) - ).rejects.toThrow() - } - - const signature = await smartClient.signMessage({ - message: "vires in numeris" - }) - - const isVerified = await publicClient.verifyMessage({ - address: smartClient.account.address, - message: "vires in numeris", - signature - }) - - expect(isVerified).toBeTruthy() - }) - - test("Can sign and verify typed data", async () => { - const smartClient = await getSmartAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - const typedData = { - domain: { - name: "Ether Mail", - version: "1", - chainId: 1, - verifyingContract: getAddress( - "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" - ) - }, - types: { - Person: [ - { name: "name", type: "string" }, - { name: "wallet", type: "address" } - ], - Mail: [ - { name: "from", type: "Person" }, - { name: "to", type: "Person" }, - { name: "contents", type: "string" } - ] - }, - primaryType: "Mail" as const, - message: { - from: { - name: "Cow", - wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" - }, - to: { - name: "Bob", - wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" - }, - contents: "Hello, Bob!" - } - } - - if (!isEip1271Compliant) { - return await expect(async () => - smartClient.signTypedData(typedData) - ).rejects.toThrow() - } - - const signature = await smartClient.signTypedData(typedData) - - const isVerified = await publicClient.verifyTypedData({ - ...typedData, - address: smartClient.account.address, - signature - }) - - expect(isVerified).toBeTruthy() - }) - } -) diff --git a/packages/permissionless-test/src/ep-0.7/experiments.ts b/packages/permissionless-test/src/ep-0.7/experiments.ts deleted file mode 100644 index ae3e9a79..00000000 --- a/packages/permissionless-test/src/ep-0.7/experiments.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { http, createClient, zeroAddress } from "viem" -import { generatePrivateKey } from "viem/accounts" -import { foundry } from "viem/chains" -import { describe, test } from "vitest" -import { - ENTRYPOINT_ADDRESS_V07, - createSmartAccountClient -} from "../../../permissionless" -import { privateKeyToSimpleSmartAccount } from "../../../permissionless/_types/accounts" -import { privateKeyToSafeSmartAccount } from "../../../permissionless/accounts" -import { paymasterActionsEip7677 } from "../../../permissionless/experimental" -import type { ENTRYPOINT_ADDRESS_V06_TYPE } from "../../../permissionless/types" -import { SIMPLE_ACCOUNT_FACTORY_V07 } from "../constants" -import type { AAParamType } from "../types" -import { - PAYMASTER_RPC, - getPimlicoPaymasterClient, - getPublicClient, - getSafeClient -} from "../utils" - -describe.each([ - { - name: "Eip 7677 client", - - getSmartAccountClient: async ( - conf: AAParamType - ) => getSafeClient(conf) - } -])("$name test", ({ name, getSmartAccountClient }) => { - test("Can get stab data", async () => { - const publicClient = getPublicClient() - - const smartAccount = await privateKeyToSimpleSmartAccount( - publicClient, - { - factoryAddress: SIMPLE_ACCOUNT_FACTORY_V07, - entryPoint: ENTRYPOINT_ADDRESS_V07, - privateKey: generatePrivateKey() - } - ) - const ALTO_RPC = "http://localhost:4337" - - const paymasterClient = getPimlicoPaymasterClient( - ENTRYPOINT_ADDRESS_V07 - ) - - const smartAccountClient = createSmartAccountClient({ - chain: foundry, - account: smartAccount, - bundlerTransport: http(ALTO_RPC) - }) - - const userOperaton = - await smartAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await smartAccountClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - - const eip7677Client = createClient({ - chain: foundry, - transport: http(PAYMASTER_RPC) - }).extend(paymasterActionsEip7677(ENTRYPOINT_ADDRESS_V07)) - - await eip7677Client.getPaymasterData({ - userOperation: { - ...userOperaton, - paymasterVerificationGasLimit: 0n, - paymasterPostOpGasLimit: 0n - } - }) - - await eip7677Client.getPaymasterStubData({ - userOperation: userOperaton - }) - - // await eip7677Client.getPaymasterStubData({ - // userOperation: await smartClient.prepareUserOperationRequest({ - // userOperation: { - // callData: await smartClient.account.encodeCallData({ - // to: zeroAddress, - // value: 0n, - // data: "0x" - // }) - // } - // }) - // }) - }) -}) diff --git a/packages/permissionless-test/src/ep-0.7/pimlicoActions.test.ts b/packages/permissionless-test/src/ep-0.7/pimlicoActions.test.ts deleted file mode 100644 index a7f815e8..00000000 --- a/packages/permissionless-test/src/ep-0.7/pimlicoActions.test.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { isAddress, isHash, zeroAddress } from "viem" -import { beforeAll, describe, expect, test } from "vitest" -import { ENTRYPOINT_ADDRESS_V07 } from "../../../permissionless" -import type { - PimlicoBundlerClient, - PimlicoPaymasterClient -} from "../../../permissionless/clients/pimlico" -import type { ENTRYPOINT_ADDRESS_V07_TYPE } from "../../../permissionless/types" -import { - ensureBundlerIsReady, - ensurePaymasterIsReady, - getPimlicoBundlerClient, - getPimlicoPaymasterClient, - getSimpleAccountClient -} from "../utils" - -describe("V.7 Pimlico Actions tests", () => { - let pimlicoBundlerClient: PimlicoBundlerClient - let pimlicoPaymasterClient: PimlicoPaymasterClient - - beforeAll(async () => { - pimlicoBundlerClient = getPimlicoBundlerClient(ENTRYPOINT_ADDRESS_V07) - pimlicoPaymasterClient = getPimlicoPaymasterClient( - ENTRYPOINT_ADDRESS_V07 - ) - - await ensureBundlerIsReady() - await ensurePaymasterIsReady() - }) - - describe("Pimlico Bundler actions", () => { - test("can fetch gas prices", async () => { - const gasPrice = - await pimlicoBundlerClient.getUserOperationGasPrice() - expect(gasPrice).toBeTruthy() - expect(gasPrice.slow).toBeTruthy() - expect(gasPrice.standard).toBeTruthy() - expect(gasPrice.fast).toBeTruthy() - expect(typeof gasPrice.slow.maxFeePerGas).toBe("bigint") - expect(gasPrice.slow.maxFeePerGas).toBeGreaterThan(0n) - expect(typeof gasPrice.slow.maxPriorityFeePerGas).toBe("bigint") - expect(gasPrice.slow.maxPriorityFeePerGas).toBeGreaterThan(0n) - expect(typeof gasPrice.standard.maxFeePerGas).toBe("bigint") - expect(gasPrice.standard.maxFeePerGas).toBeGreaterThan(0n) - expect(typeof gasPrice.standard.maxPriorityFeePerGas).toBe("bigint") - expect(gasPrice.standard.maxPriorityFeePerGas).toBeGreaterThan(0n) - expect(typeof gasPrice.fast.maxFeePerGas).toBe("bigint") - expect(gasPrice.fast.maxFeePerGas).toBeGreaterThan(0n) - expect(typeof gasPrice.fast.maxPriorityFeePerGas).toBe("bigint") - expect(gasPrice.fast.maxPriorityFeePerGas).toBeGreaterThan(0n) - }) - test("fetch user operation status", async () => {}) - }) - - describe("Pimlico paymaster actions ", () => { - test("can fetching paymaster and data", async () => { - const simpleAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - const userOperation = - await simpleAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: - await simpleAccountClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x69" - }) - } - }) - - const result = await pimlicoPaymasterClient.sponsorUserOperation({ - userOperation: userOperation - }) - - expect(result).toBeTruthy() - expect(typeof result.callGasLimit).toBe("bigint") - expect(result.callGasLimit).toBeGreaterThan(0n) - expect(typeof result.preVerificationGas).toBe("bigint") - expect(result.preVerificationGas).toBeGreaterThan(0n) - expect(typeof result.verificationGasLimit).toBe("bigint") - expect(result.verificationGasLimit).toBeGreaterThan(0n) - expect(result.paymasterData.length).toBeGreaterThan(0) - expect( - result.paymaster === undefined || isAddress(result.paymaster) - ).toBeTruthy() - }, 500000) - - test("can send userOperation with returned paymaster and data", async () => { - const simpleAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - let op = await simpleAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await simpleAccountClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - - const result = await pimlicoPaymasterClient.sponsorUserOperation({ - userOperation: op - }) - - op = { ...op, ...result } - op.signature = - await simpleAccountClient.account.signUserOperation(op) - - const opHash = await pimlicoBundlerClient.sendUserOperation({ - userOperation: op - }) - - expect(isHash(opHash)).toBe(true) - - const userOperationReceipt = - await pimlicoBundlerClient.waitForUserOperationReceipt({ - hash: opHash - }) - - expect(userOperationReceipt).toBeTruthy() - expect(userOperationReceipt?.userOpHash).toBe(opHash) - expect( - userOperationReceipt?.receipt.transactionHash.length - ).toBeGreaterThan(0) - expect(userOperationReceipt?.receipt.transactionHash).toBeTruthy() - - //const userOperationFromUserOpHash = - // await pimlicoBundlerClient.getUserOperationByHash({ - // hash: opHash - // }) - - //expect(userOperationFromUserOpHash).toBeTruthy() - //expect(userOperationFromUserOpHash?.entryPoint).toBe( - // ENTRYPOINT_ADDRESS_V07 - //) - //expect(userOperationFromUserOpHash?.transactionHash).toBe( - // userOperationReceipt?.receipt.transactionHash - //) - - //// for (const key in userOperationFromUserOpHash?.userOperation) { - //// expect(userOperationFromUserOpHash?.userOperation[key]).toBe(userOperation[key]) - //// } - - //const userOperationStatus = - // await pimlicoBundlerClient.getUserOperationStatus({ - // hash: opHash - // }) - - //expect(userOperationStatus).toBeTruthy() - //expect(userOperationStatus.status).toBe("included") - //expect(userOperationStatus.transactionHash).toBe( - // userOperationReceipt?.receipt.transactionHash - //) - }, 500000) - }) - - test("Validating sponsorship policies", async () => { - const simpleAccountClient = await getSimpleAccountClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07 - }) - - const userOperation = - await simpleAccountClient.prepareUserOperationRequest({ - userOperation: { - callData: await simpleAccountClient.account.encodeCallData({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - } - }) - - const validateSponsorshipPolicies = - await pimlicoPaymasterClient.validateSponsorshipPolicies({ - userOperation, - sponsorshipPolicyIds: ["sp_crazy_kangaroo"] - }) - - expect(validateSponsorshipPolicies).toBeTruthy() - expect(validateSponsorshipPolicies.length).toBeGreaterThan(0) - expect(Array.isArray(validateSponsorshipPolicies)).toBeTruthy() - expect(validateSponsorshipPolicies.length).toBe(1) - }, 500000) -}) diff --git a/packages/permissionless-test/src/ep-0.7/safeSmartAccount.test.ts b/packages/permissionless-test/src/ep-0.7/safeSmartAccount.test.ts deleted file mode 100644 index d09fc409..00000000 --- a/packages/permissionless-test/src/ep-0.7/safeSmartAccount.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { isHash, zeroAddress } from "viem" -import { beforeAll, describe, expect, test } from "vitest" -import { ENTRYPOINT_ADDRESS_V07 } from "../../../permissionless" -import { - ensureBundlerIsReady, - ensurePaymasterIsReady, - fund, - getSafeClient -} from "../utils" - -describe("Safe Specific Actions V0.7", () => { - beforeAll(async () => { - await ensureBundlerIsReady() - await ensurePaymasterIsReady() - }) - - test("Can deploy with setup transaction", async () => { - const smartAccountClient = await getSafeClient({ - entryPoint: ENTRYPOINT_ADDRESS_V07, - setupTransactions: [ - { - to: zeroAddress, - data: "0xff", - value: 0n - } - ] - }) - - await fund(smartAccountClient.account.address) - - const response = await smartAccountClient.sendTransaction({ - to: zeroAddress, - value: 0n, - data: "0x" - }) - - expect(isHash(response)).toBe(true) - }, 50000) -}) diff --git a/packages/permissionless/actions/public/getSenderAddress.test.ts b/packages/permissionless/actions/public/getSenderAddress.test.ts index dc8680de..8f9b494e 100644 --- a/packages/permissionless/actions/public/getSenderAddress.test.ts +++ b/packages/permissionless/actions/public/getSenderAddress.test.ts @@ -3,7 +3,7 @@ import { generatePrivateKey } from "viem/accounts" import { describe, expect } from "vitest" import { testWithRpc } from "../../../permissionless-test/src/testWithRpc" import { getSimpleAccountClient } from "../../../permissionless-test/src/utils" -import type { ENTRYPOINT_ADDRESS_V06_TYPE } from "../../_types/types" +import type { ENTRYPOINT_ADDRESS_V06_TYPE } from "../../types" import { ENTRYPOINT_ADDRESS_V06, ENTRYPOINT_ADDRESS_V07 } from "../../utils" import { getSenderAddress } from "./getSenderAddress" diff --git a/packages/permissionless/actions/public/getSenderAddress.ts b/packages/permissionless/actions/public/getSenderAddress.ts index 8f2099aa..4cca5a30 100644 --- a/packages/permissionless/actions/public/getSenderAddress.ts +++ b/packages/permissionless/actions/public/getSenderAddress.ts @@ -1,14 +1,15 @@ import { type Address, BaseError, - type CallExecutionErrorType, type Chain, type Client, type ContractFunctionExecutionErrorType, - type ContractFunctionRevertedErrorType, + ContractFunctionRevertedError, type Hex, - type RpcRequestErrorType, + InvalidInputRpcError, + RpcRequestError, type Transport, + UnknownRpcError, concat, decodeErrorResult } from "viem" @@ -132,10 +133,15 @@ export const getSenderAddress = async < args: [initCode || concat([factory as Hex, factoryData as Hex])] }) } catch (e) { - const err = e as ContractFunctionExecutionErrorType + const revertError = (e as ContractFunctionExecutionErrorType).walk( + (err) => + err instanceof ContractFunctionRevertedError || + err instanceof RpcRequestError || + err instanceof InvalidInputRpcError || + err instanceof UnknownRpcError + ) - if (err.cause.name === "ContractFunctionRevertedError") { - const revertError = err.cause as ContractFunctionRevertedErrorType + if (revertError instanceof ContractFunctionRevertedError) { const errorName = revertError.data?.errorName ?? "" if ( errorName === "SenderAddressResult" && @@ -146,84 +152,112 @@ export const getSenderAddress = async < } } - if (err.cause.name === "CallExecutionError") { - const callExecutionError = err.cause as CallExecutionErrorType - if (callExecutionError.cause.name === "RpcRequestError") { - const revertError = - callExecutionError.cause as RpcRequestErrorType + if (revertError instanceof RpcRequestError) { + const hexStringRegex = /0x[a-fA-F0-9]+/ + // biome-ignore lint/suspicious/noExplicitAny: + const match = (revertError as unknown as any).cause.data.match( + hexStringRegex + ) - const hexStringRegex = /0x[a-fA-F0-9]+/ - // biome-ignore lint/suspicious/noExplicitAny: - const match = (revertError as unknown as any).cause.data.match( - hexStringRegex + if (!match) { + throw new Error( + "Failed to parse revert bytes from RPC response" ) + } - if (!match) { - throw new Error( - "Failed to parse revert bytes from RPC response" - ) - } + const data: Hex = match[0] - const data: Hex = match[0] + const error = decodeErrorResult({ + abi: [ + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address" + } + ], + name: "SenderAddressResult", + type: "error" + } + ], + data + }) - const error = decodeErrorResult({ - abi: [ - { - inputs: [ - { - internalType: "address", - name: "sender", - type: "address" - } - ], - name: "SenderAddressResult", - type: "error" - } - ], - data - }) + return error.args[0] as Address + } + + if (revertError instanceof InvalidInputRpcError) { + const hexStringRegex = /0x[a-fA-F0-9]+/ + // biome-ignore lint/suspicious/noExplicitAny: + const match = (revertError as unknown as any).cause.data.match( + hexStringRegex + ) - return error.args[0] as Address + if (!match) { + throw new Error( + "Failed to parse revert bytes from RPC response" + ) } - if (callExecutionError.cause.name === "InvalidInputRpcError") { - //Ganache local testing returns "InvalidInputRpcError" with data in regular format - const revertError = - callExecutionError.cause as RpcRequestErrorType + const data: Hex = match[0] - const hexStringRegex = /0x[a-fA-F0-9]+/ - // biome-ignore lint/suspicious/noExplicitAny: - const match = (revertError as unknown as any).cause.data.match( - hexStringRegex - ) + const error = decodeErrorResult({ + abi: [ + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address" + } + ], + name: "SenderAddressResult", + type: "error" + } + ], + data + }) - if (!match) { - throw new Error( - "Failed to parse revert bytes from RPC response" - ) - } + return error.args[0] as Address + } - const data: Hex = match[0] + if (revertError instanceof UnknownRpcError) { + const parsedBody = JSON.parse( + (revertError as unknown as any).cause.body + ) + const revertData = parsedBody.error.data - const error = decodeErrorResult({ - abi: [ - { - inputs: [ - { - internalType: "address", - name: "sender", - type: "address" - } - ], - name: "SenderAddressResult", - type: "error" - } - ], - data - }) + const hexStringRegex = /0x[a-fA-F0-9]+/ + // biome-ignore lint/suspicious/noExplicitAny: + const match = revertData.match(hexStringRegex) - return error.args[0] as Address + if (!match) { + throw new Error( + "Failed to parse revert bytes from RPC response" + ) } + + const data: Hex = match[0] + + const error = decodeErrorResult({ + abi: [ + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address" + } + ], + name: "SenderAddressResult", + type: "error" + } + ], + data + }) + + return error.args[0] as Address } throw e