Skip to content

Commit de2c818

Browse files
authored
Merge pull request #472 from pimlicolabs/mock-paymaster/add-boosted
mock paymaster/add boosted
2 parents 925386e + 0a9c396 commit de2c818

File tree

10 files changed

+207
-133
lines changed

10 files changed

+207
-133
lines changed

.changeset/lucky-hats-push.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pimlico/mock-paymaster": patch
3+
---
4+
5+
Added boost_sendUserOperation support and forward unknown requests to bundler

bun.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"bun-types": "^1.0.7",
2424
"get-port": "^7.0.0",
2525
"ox": "0.8.0",
26-
"prool": "^0.0.23",
26+
"prool": "^0.0.25",
2727
"react": "^18.3.1",
2828
"react-dom": "^18.3.1",
2929
"rimraf": "^6.0.1",
@@ -47,13 +47,13 @@
4747
"zod": "^3.24.2",
4848
},
4949
"peerDependencies": {
50-
"prool": "^0.0.23",
50+
"prool": "^0.0.25",
5151
"viem": "^2.28.1",
5252
},
5353
},
5454
"packages/permissionless": {
5555
"name": "permissionless",
56-
"version": "0.2.56",
56+
"version": "0.2.57",
5757
"peerDependencies": {
5858
"ox": "^0.8.0",
5959
"viem": "^2.28.1",
@@ -1309,7 +1309,7 @@
13091309

13101310
"prom-client": ["prom-client@14.2.0", "", { "dependencies": { "tdigest": "^0.1.1" } }, "sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA=="],
13111311

1312-
"prool": ["prool@0.0.23", "", { "dependencies": { "change-case": "5.4.4", "eventemitter3": "^5.0.1", "execa": "^9.1.0", "get-port": "^7.1.0", "http-proxy": "^1.18.1", "tar": "7.2.0" }, "peerDependencies": { "@pimlico/alto": "*" }, "optionalPeers": ["@pimlico/alto"] }, "sha512-r1d0DIiVsp7aXqGiNGKmgrqJZa8GjMGEjsgjQO22DEClYYvK+HMPZTQ9diBqleGuwfiRk3lnsWRMbFTRmFbk9g=="],
1312+
"prool": ["prool@0.0.25", "", { "dependencies": { "change-case": "5.4.4", "eventemitter3": "^5.0.1", "execa": "^9.1.0", "get-port": "^7.1.0", "http-proxy": "^1.18.1", "tar": "7.2.0" }, "peerDependencies": { "@pimlico/alto": "*" }, "optionalPeers": ["@pimlico/alto"] }, "sha512-RKqgb4iEkKJAQC1U0frPs6DWuC2VRfrn3sRRz09lYVr8GkBjrSH7uQLeA5N0odCRD4x75DfRwOedQTxjMkrYuQ=="],
13131313

13141314
"protobufjs": ["protobufjs@7.4.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw=="],
13151315

bun.lockb

-4.58 KB
Binary file not shown.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"bun-types": "^1.0.7",
3131
"get-port": "^7.0.0",
3232
"ox": "0.8.0",
33-
"prool": "^0.0.23",
33+
"prool": "^0.0.25",
3434
"react": "^18.3.1",
3535
"react-dom": "^18.3.1",
3636
"rimraf": "^6.0.1",

packages/mock-paymaster/helpers/erc20-utils.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ import {
1919
import { privateKeyToAccount } from "viem/accounts"
2020
import { getChain, getPublicClient } from "./utils.js"
2121

22-
const erc20Bytecode = concat([
22+
export const erc20Bytecode = concat([
2323
"0x60a060405234801561001057600080fd5b50604051610ff0380380610ff083398101604081905261002f9161022c565b6040518060400160405280600981526020016805465737445524332360bc1b8152506040518060400160405280600381526020016205432360ec1b815250816003908161007c919061034d565b506004610089828261034d565b5050506100a63369d3c21bcecceda10000006100b160201b60201c565b60ff166080526104a3565b6001600160a01b0382166100e457600060405163ec442f0560e01b81526004016100db9190610430565b60405180910390fd5b6100f0600083836100f4565b5050565b6001600160a01b03831661011f5780600260008282546101149190610454565b9091555061017e9050565b6001600160a01b0383166000908152602081905260409020548181101561015f5783818360405163391434e360e21b81526004016100db9392919061046d565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b03821661019a576002805482900390556101b9565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516101fc9190610495565b60405180910390a3505050565b60ff8116811461021857600080fd5b50565b805161022681610209565b92915050565b60006020828403121561024157610241600080fd5b600061024d848461021b565b949350505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052602260045260246000fd5b60028104600182168061029557607f821691505b6020821081036102a7576102a761026b565b50919050565b60006102266102b98381565b90565b6102c5836102ad565b815460001960089490940293841b1916921b91909117905550565b60006102ed8184846102bc565b505050565b818110156100f0576103056000826102e0565b6001016102f2565b601f8211156102ed576000818152602090206020601f850104810160208510156103345750805b6103466020601f8601048301826102f2565b5050505050565b81516001600160401b0381111561036657610366610255565b6103708254610281565b61037b82828561030d565b6020601f8311600181146103af57600084156103975750858201515b600019600886021c1981166002860217865550610408565b600085815260208120601f198616915b828110156103df57888501518255602094850194600190920191016103bf565b868310156103fb5784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b60006001600160a01b038216610226565b61042a81610410565b82525050565b602081016102268284610421565b634e487b7160e01b600052601160045260246000fd5b808201808211156102265761022661043e565b8061042a565b6060810161047b8286610421565b6104886020830185610467565b61024d6040830184610467565b602081016102268284610467565b608051610b326104be60003960006101650152610b326000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063313ce56711610081578063a9059cbb1161005b578063a9059cbb146101cf578063dd62ed3e146101e2578063fb4dcefa1461022857600080fd5b8063313ce5671461016357806370a082311461019157806395d89b41146101c757600080fd5b806318160ddd116100b257806318160ddd1461012c57806323b872dd1461013d5780632d688ca81461015057600080fd5b806305ea5c22146100d957806306fdde03146100ee578063095ea7b31461010c575b600080fd5b6100ec6100e7366004610868565b61023b565b005b6100f661024b565b604051610103919061092c565b60405180910390f35b61011f61011a366004610944565b6102dd565b604051610103919061098b565b6002545b604051610103919061099f565b61011f61014b366004610868565b6102f7565b6100ec61015e366004610944565b61031b565b7f000000000000000000000000000000000000000000000000000000000000000060405161010391906109b6565b61013061019f3660046109c4565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100f6610329565b61011f6101dd366004610944565b610338565b6101306101f03660046109ed565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6100ec6102363660046109ed565b610346565b61024683838361037c565b505050565b60606003805461025a90610a4f565b80601f016020809104026020016040519081016040528092919081815260200182805461028690610a4f565b80156102d35780601f106102a8576101008083540402835291602001916102d3565b820191906000526020600020905b8154815290600101906020018083116102b657829003601f168201915b5050505050905090565b6000336102eb81858561037c565b60019150505b92915050565b600033610305858285610389565b610310858585610441565b506001949350505050565b61032582826104ec565b5050565b60606004805461025a90610a4f565b6000336102eb818585610441565b61032582826103778573ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b610441565b6102468383836001610548565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461043b578181101561042c578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161042393929190610a84565b60405180910390fd5b61043b84848484036000610548565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166104915760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b73ffffffffffffffffffffffffffffffffffffffff82166104e15760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b61024683838361068e565b73ffffffffffffffffffffffffffffffffffffffff821661053c5760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b6103256000838361068e565b73ffffffffffffffffffffffffffffffffffffffff84166105985760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b73ffffffffffffffffffffffffffffffffffffffff83166105e85760006040517f94280d620000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600160209081526040808320938716835292905220829055801561043b578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610680919061099f565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff83166106c65780600260008282546106bb9190610ae9565b909155506107589050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020548181101561072c578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161042393929190610a84565b73ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090209082900390555b73ffffffffffffffffffffffffffffffffffffffff8216610781576002805482900390556107ad565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090208054820190555b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161080a919061099f565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff82166102f1565b61083e81610817565b811461084957600080fd5b50565b80356102f181610835565b8061083e565b80356102f181610857565b60008060006060848603121561088057610880600080fd5b600061088c868661084c565b935050602061089d8682870161084c565b92505060406108ae8682870161085d565b9150509250925092565b60005b838110156108d35781810151838201526020016108bb565b50506000910152565b60006108e6825190565b8084526020840193506108fd8185602086016108b8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920192915050565b6020808252810161093d81846108dc565b9392505050565b6000806040838503121561095a5761095a600080fd5b6000610966858561084c565b92505060206109778582860161085d565b9150509250929050565b8015155b82525050565b602081016102f18284610981565b80610985565b602081016102f18284610999565b60ff8116610985565b602081016102f182846109ad565b6000602082840312156109d9576109d9600080fd5b60006109e5848461084c565b949350505050565b60008060408385031215610a0357610a03600080fd5b6000610a0f858561084c565b92505060206109778582860161084c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600281046001821680610a6357607f821691505b602082108103610a7557610a75610a20565b50919050565b61098581610817565b60608101610a928286610a7b565b610a9f6020830185610999565b6109e56040830184610999565b602081016102f18284610a7b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102f1576102f1610aba56fea2646970667358221220d40f68e247510ec8b7876d327ac47b949de248d0626aaf2670151c5e84ee6b4a64736f6c634300081a0033",
2424
pad(toHex(18n)) // constructor args (token_decimals)
2525
])
2626

27-
const create2Salt =
27+
export const create2Salt =
2828
"0x0000000000000000000000000000000000000000000000000000000000000000"
2929

3030
export const getPaymasterUtilityWallet = async (
@@ -62,19 +62,6 @@ export const getPaymasterUtilityWallet = async (
6262
return walletClient
6363
}
6464

65-
export const deployErc20Token = async (anvilRpc: string) => {
66-
const publicClient = await getPublicClient(anvilRpc)
67-
68-
if ((await publicClient.getCode({ address: erc20Address })) === undefined) {
69-
const walletClient = await getPaymasterUtilityWallet(anvilRpc)
70-
71-
await walletClient.sendTransaction({
72-
to: "0x4e59b44847b379578588920ca78fbf26c0b4956c",
73-
data: concat([create2Salt, erc20Bytecode])
74-
})
75-
}
76-
}
77-
7865
export const tokenBalanceOf = async (holder: Address, anvilRpc: string) => {
7966
const publicClient = await getPublicClient(anvilRpc)
8067

packages/mock-paymaster/index.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ import Fastify from "fastify"
33
import { defineInstance } from "prool"
44
import { http, createWalletClient } from "viem"
55
import { privateKeyToAccount } from "viem/accounts"
6-
import { deployErc20Token } from "./helpers/erc20-utils.js"
76
import { getChain } from "./helpers/utils.js"
87
import { createRpcHandler } from "./relay.js"
9-
import { deployPaymasters } from "./singletonPaymasters.js"
8+
import { setup } from "./setup.js"
109

1110
export const paymaster = defineInstance(
1211
({
@@ -31,11 +30,10 @@ export const paymaster = defineInstance(
3130
transport: http(anvilRpc)
3231
})
3332

34-
await deployPaymasters({
33+
await setup({
3534
anvilRpc,
3635
paymasterSigner: paymasterSigner.account.address
3736
})
38-
await deployErc20Token(anvilRpc)
3937

4038
app.register(cors, {
4139
origin: "*",

packages/mock-paymaster/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
},
2323
"peerDependencies": {
2424
"viem": "^2.28.1",
25-
"prool": "^0.0.23"
25+
"prool": "^0.0.25"
2626
},
2727
"dependencies": {
2828
"@fastify/cors": "^8.5.0",

packages/mock-paymaster/relay.ts

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ const handleMethod = async ({
175175
getSingletonPaymaster08Address(paymasterSigner.account.address)
176176
]
177177

178-
const epToPaymaster: Record<`0x${string}`, `0x${string}`> = {
178+
const epToPaymaster: Record<Address, Address> = {
179179
[entryPoint06Address]: paymaster06,
180180
[entryPoint07Address]: paymaster07,
181181
[entryPoint08Address]: paymaster08
@@ -287,15 +287,6 @@ const handleMethod = async ({
287287
]
288288
}
289289

290-
if (parsedBody.method === "pimlico_getUserOperationGasPrice") {
291-
return await bundlerClient.request({
292-
// @ts-ignore
293-
method: "pimlico_getUserOperationGasPrice",
294-
// @ts-ignore
295-
params: []
296-
})
297-
}
298-
299290
if (parsedBody.method === "pimlico_getTokenQuotes") {
300291
const params = pimlicoGetTokenQuotesSchema.safeParse(parsedBody.params)
301292

@@ -337,10 +328,31 @@ const handleMethod = async ({
337328
}
338329
}
339330

340-
throw new RpcError(
341-
`Attempted to call an unknown method ${parsedBody.method}`,
342-
ValidationErrors.InvalidFields
343-
)
331+
// If boosted userOp, forward to bundler's boost_sendUserOperation method.
332+
if (parsedBody.method === "eth_sendUserOperation") {
333+
const userOp = parsedBody.params[0] as any
334+
335+
const isBoosted =
336+
userOp.maxFeePerGas === "0x0" &&
337+
userOp.maxPriorityFeePerGas === "0x0"
338+
339+
if (isBoosted) {
340+
return await bundlerClient.request({
341+
// @ts-ignore
342+
method: "boost_sendUserOperation",
343+
// @ts-ignore
344+
params: parsedBody.params
345+
})
346+
}
347+
}
348+
349+
// Forward all other requests to the bundler
350+
return await bundlerClient.request({
351+
// @ts-ignore
352+
method: parsedBody.method,
353+
// @ts-ignore
354+
params: parsedBody.params ?? []
355+
})
344356
}
345357

346358
export const createRpcHandler = ({

packages/mock-paymaster/setup.ts

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import { type Address, concat, getContract, parseEther } from "viem"
2+
import {
3+
constants,
4+
getSingletonPaymaster06Address,
5+
getSingletonPaymaster06InitCode,
6+
getSingletonPaymaster07Address,
7+
getSingletonPaymaster07InitCode,
8+
getSingletonPaymaster08Address,
9+
getSingletonPaymaster08InitCode
10+
} from "./constants.js"
11+
import {
12+
singletonPaymaster06Abi,
13+
singletonPaymaster07Abi,
14+
singletonPaymaster08Abi
15+
} from "./helpers/abi.js"
16+
import {
17+
create2Salt,
18+
erc20Address,
19+
erc20Bytecode,
20+
getPaymasterUtilityWallet
21+
} from "./helpers/erc20-utils.js"
22+
import { getPublicClient } from "./helpers/utils.js"
23+
24+
export const deployPaymasters = async ({
25+
anvilRpc,
26+
paymasterSigner
27+
}: {
28+
anvilRpc: string
29+
paymasterSigner: Address
30+
}) => {
31+
const walletClient = await getPaymasterUtilityWallet(anvilRpc)
32+
const publicClient = await getPublicClient(anvilRpc)
33+
34+
let nonce = await publicClient.getTransactionCount({
35+
address: walletClient.account.address
36+
})
37+
38+
const paymaster06Address = getSingletonPaymaster06Address(paymasterSigner)
39+
const paymaster07Address = getSingletonPaymaster07Address(paymasterSigner)
40+
const paymaster08Address = getSingletonPaymaster08Address(paymasterSigner)
41+
42+
// Deploy singleton paymaster 06 if not already deployed.
43+
const paymaster06Code = await publicClient.getCode({
44+
address: paymaster06Address
45+
})
46+
if (!paymaster06Code) {
47+
const hash = await walletClient.sendTransaction({
48+
to: constants.deterministicDeployer,
49+
data: concat([
50+
constants.create2Salt,
51+
getSingletonPaymaster06InitCode(paymasterSigner)
52+
]),
53+
nonce: nonce++
54+
})
55+
await publicClient.waitForTransactionReceipt({ hash })
56+
}
57+
58+
// Deploy singleton paymaster 07 if not already deployed.
59+
const paymaster07Code = await publicClient.getCode({
60+
address: paymaster07Address
61+
})
62+
if (!paymaster07Code) {
63+
const hash = await walletClient.sendTransaction({
64+
to: constants.deterministicDeployer,
65+
data: concat([
66+
constants.create2Salt,
67+
getSingletonPaymaster07InitCode(paymasterSigner)
68+
]),
69+
nonce: nonce++
70+
})
71+
await publicClient.waitForTransactionReceipt({ hash })
72+
}
73+
74+
// Deploy singleton paymaster 08 if not already deployed.
75+
const paymaster08Code = await publicClient.getCode({
76+
address: paymaster08Address
77+
})
78+
if (!paymaster08Code) {
79+
const hash = await walletClient.sendTransaction({
80+
to: constants.deterministicDeployer,
81+
data: concat([
82+
constants.create2Salt,
83+
getSingletonPaymaster08InitCode(paymasterSigner)
84+
]),
85+
nonce: nonce++
86+
})
87+
await publicClient.waitForTransactionReceipt({ hash })
88+
}
89+
90+
const depositAmount = parseEther("50")
91+
92+
// Initialize contract instances and fund if needed.
93+
// Only check deposit balance if the contract was already deployed.
94+
95+
// Fund paymaster 06 if balance is less than deposit amount.
96+
const singletonPaymaster06 = getContract({
97+
address: paymaster06Address,
98+
abi: singletonPaymaster06Abi,
99+
client: walletClient
100+
})
101+
const deposit06 = await singletonPaymaster06.read.getDeposit()
102+
if (deposit06 < depositAmount) {
103+
await singletonPaymaster06.write.deposit({
104+
value: depositAmount,
105+
nonce: nonce++
106+
})
107+
}
108+
109+
// Fund paymaster 07 if balance is less than deposit amount.
110+
const singletonPaymaster07 = getContract({
111+
address: paymaster07Address,
112+
abi: singletonPaymaster07Abi,
113+
client: walletClient
114+
})
115+
const deposit07 = await singletonPaymaster07.read.getDeposit()
116+
if (deposit07 < depositAmount) {
117+
await singletonPaymaster07.write.deposit({
118+
value: depositAmount,
119+
nonce: nonce++
120+
})
121+
}
122+
123+
// Fund paymaster 08 if balance is less than deposit amount.
124+
const singletonPaymaster08 = getContract({
125+
address: paymaster08Address,
126+
abi: singletonPaymaster08Abi,
127+
client: walletClient
128+
})
129+
const deposit08 = await singletonPaymaster08.read.getDeposit()
130+
if (deposit08 < depositAmount) {
131+
await singletonPaymaster08.write.deposit({
132+
value: depositAmount,
133+
nonce: nonce++
134+
})
135+
}
136+
}
137+
138+
export const deployErc20Token = async (anvilRpc: string) => {
139+
const publicClient = await getPublicClient(anvilRpc)
140+
141+
if ((await publicClient.getCode({ address: erc20Address })) === undefined) {
142+
const walletClient = await getPaymasterUtilityWallet(anvilRpc)
143+
144+
await walletClient.sendTransaction({
145+
to: "0x4e59b44847b379578588920ca78fbf26c0b4956c",
146+
data: concat([create2Salt, erc20Bytecode])
147+
})
148+
}
149+
}
150+
151+
export const setup = async ({
152+
anvilRpc,
153+
paymasterSigner
154+
}: {
155+
anvilRpc: string
156+
paymasterSigner: Address
157+
}) => {
158+
await deployPaymasters({
159+
anvilRpc,
160+
paymasterSigner
161+
})
162+
await deployErc20Token(anvilRpc)
163+
}

0 commit comments

Comments
 (0)