From abd64ad7a7b3cb37489f568909723295babf5ab7 Mon Sep 17 00:00:00 2001 From: Paul Cramer Date: Tue, 11 Jun 2024 13:29:31 -0400 Subject: [PATCH] Update paymaster will sponsor --- docs/pages/guides/paymasters.mdx | 73 ++++++++++++-------------------- 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/docs/pages/guides/paymasters.mdx b/docs/pages/guides/paymasters.mdx index 889cc48..7b5d8aa 100644 --- a/docs/pages/guides/paymasters.mdx +++ b/docs/pages/guides/paymasters.mdx @@ -36,68 +36,45 @@ for more on this. The code below is built specifically for Smart Wallet. It would need to be updated to support other smart accounts. :::code-group ```ts twoslash [utils.ts] -import { ENTRYPOINT_ADDRESS_V06, UserOperation } from "permissionless"; -import { - Address, - BlockTag, - Hex, - decodeAbiParameters, - decodeFunctionData, -} from "viem"; +import { UserOperation } from "permissionless"; +import { Address, Hex, decodeFunctionData } from "viem"; import { baseSepolia } from "viem/chains"; -import {client} from "./config" -import { - coinbaseSmartWalletABI, - coinbaseSmartWalletFactoryAddress, - coinbaseSmartWalletProxyBytecode, - coinbaseSmartWalletV1Implementation, - erc1967ProxyImplementationSlot, - magicSpendAddress -} from "./constants" -import { myNFTABI, myNFTAddress } from "./myNFT"; +import { client } from "./config"; +import { coinbaseSmartWalletABI, magicSpendAddress } from "./constants"; +import { myNFTABI, myNFTAddress } from "@/ABIs/myNFT"; +import { isValidAAEntrypoint } from "@coinbase/onchainkit/wallet"; +import { isWalletASmartWallet } from "@coinbase/onchainkit/wallet"; +import type { IsValidAAEntrypointOptions } from "@coinbase/onchainkit/wallet"; +import type { IsWalletASmartWalletOptions } from "@coinbase/onchainkit/wallet"; // @noErrors export async function willSponsor({ chainId, entrypoint, userOp, -}: { chainId: number; entrypoint: string; userOp: UserOperation<"v0.6"> }) { +}: { + chainId: number; + entrypoint: string; + userOp: UserOperation<"v0.6">; +}) { // check chain id if (chainId !== baseSepolia.id) return false; + // check entrypoint // not strictly needed given below check on implementation address, but leaving as example - if (entrypoint.toLowerCase() !== ENTRYPOINT_ADDRESS_V06.toLowerCase()) + if (!isValidAAEntrypoint({ entrypoint } as IsValidAAEntrypointOptions)) return false; try { // check the userOp.sender is a proxy with the expected bytecode - const code = await client.getBytecode({ address: userOp.sender }); - - if (!code) { - // no code at address, check that the initCode is deploying a Coinbase Smart Wallet - // factory address is first 20 bytes of initCode after '0x' - const factoryAddress = userOp.initCode.slice(0, 42); - if (factoryAddress.toLowerCase() !== coinbaseSmartWalletFactoryAddress.toLowerCase()) - return false; - } else { - // code at address, check that it is a proxy to the expected implementation - if (code != coinbaseSmartWalletProxyBytecode) return false; - - // check that userOp.sender proxies to expected implementation - const implementation = await client.request<{ - Parameters: [Address, Hex, BlockTag]; - ReturnType: Hex; - }>({ - method: "eth_getStorageAt", - params: [userOp.sender, erc1967ProxyImplementationSlot, "latest"], - }); - const implementationAddress = decodeAbiParameters( - [{ type: "address" }], - implementation - )[0]; - if (implementationAddress != coinbaseSmartWalletV1Implementation) - return false; - } + // check that userOp.sender proxies to expected implementation + if ( + !(await isWalletASmartWallet({ + client, + userOp, + } as IsWalletASmartWalletOptions)) + ) + return false; // check that userOp.callData is making a call we want to sponsor const calldata = decodeFunctionData({ @@ -114,6 +91,7 @@ export async function willSponsor({ value: bigint; data: Hex; }[]; + // modify if want to allow batch calls to your contract if (calls.length > 2) return false; @@ -135,6 +113,7 @@ export async function willSponsor({ abi: myNFTABI, data: calls[callToCheckIndex].data, }); + if (innerCalldata.functionName !== "safeMint") return false; return true;