Skip to content

Commit

Permalink
4337 Gas metering: Pimlico VerifyingPaymaster results, refactorings…
Browse files Browse the repository at this point in the history
…, groundwork for `ERC20Paymaster` (#401)

This PR updates the Pimlico benchmarking code to use the new v0.7
entrypoint and the new paymaster from Pimlico. Partially fixes
#294 (Partially
because there are blockers related to the ERC20 Paymaster; I will
describe them below)

## Current Blockers For ERC20 Paymaster
- They use the official Circle's USDC deployments on testnets with no
liquidity, and the faucet drips 10 USDC daily. One user op costs around
7.
- There are some problems with gas pricing. Currently, it wants roughly
7 USDC for a user operation on Base Sepolia (approximately 2x higher
than the native token fee) and 537 USDC on Sepolia.

The Pimlico team have been informed regarding the same at the time of
writing this issue. Slack
[Link](https://5afe.slack.com/archives/C05JA2HFQ1J/p1716898930935779?thread_ts=1715862769.219249&cid=C05JA2HFQ1J).

## Changes completed/in-progress
- Using `base-sepolia` as well (`sepolia` sometimes has a high gas cost)
- Using new signing struct with the latest 4337 Safe Module
- Update of dependencies used in the Pimlico benchmark
- Code refactors and type improvements
- NPM scripts now explicitly contain the paymaster they should use
- Addition of `VERBOSE` environment variable that outputs handy logging
data to the console, which is very useful for debugging.
[Example](https://dashboard.tenderly.co/mikhail-gnosis/project/simulator/8f7d3c77-b98c-49fd-badf-b35e4f5310c5?trace=0.1.0.0.2.4.2.1.4.0.0.2.0)

---------

Co-authored-by: Mikhail <[email protected]>
  • Loading branch information
remedcu and mmv08 authored Jun 4, 2024
1 parent 091a468 commit 53e28a5
Show file tree
Hide file tree
Showing 18 changed files with 1,762 additions and 1,296 deletions.
22 changes: 12 additions & 10 deletions examples/4337-gas-metering/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,27 @@
PRIVATE_KEY = "0x..." # Add "0x" to Private Key if not already added.

# Pimlico Values
PIMLICO_CHAIN = "mumbai" # or "goerli"
PIMLICO_CHAIN_ID = "80001"
PIMLICO_RPC_URL = "https://rpc.ankr.com/polygon_mumbai"
PIMLICO_CHAIN = "base-sepolia" # or "sepolia"
PIMLICO_CHAIN_ID = "84532" # or "11155111"
PIMLICO_RPC_URL = "https://rpc.ankr.com/base_sepolia" # or "https://rpc.ankr.com/eth_sepolia"
PIMLICO_API_KEY = "" # https://dashboard.pimlico.io/apikeys
PIMLICO_GAS_POLICY = "" # https://dashboard.pimlico.io/sponsorship-policies
PIMLICO_ENTRYPOINT_ADDRESS = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
PIMLICO_MULTISEND_ADDRESS = "0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526" # https://github.com/safe-global/safe-deployments/blob/main/src/assets/v1.4.1/multi_send.json
PIMLICO_ERC20_PAYMASTER_ADDRESS = "0x32aCDFeA07a614E52403d2c1feB747aa8079A353" # https://docs.pimlico.io/erc20-paymaster/reference/contracts
PIMLICO_USDC_TOKEN_ADDRESS = "0x0FA8781a83E46826621b3BC094Ea2A0212e71B23" # Mumbai USDC Address used by Pimlico
PIMLICO_ERC20_PAYMASTER_ADDRESS = "0x00000000002E3A39aFEf1132214fEee5a55ce127" # https://docs.pimlico.io/paymaster/erc20-paymaster/contract-addresses
PIMLICO_USDC_TOKEN_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e" # Sepolia USDC Address used by Pimlico
# Make sure all nonce are unique for it to deploy account when run initially.
PIMLICO_NONCE = "1"
PIMLICO_NONCE = "3"
# Pimlico Token Operation Values (Based on the chain selected, these values should also change accordingly.)
PIMLICO_ERC20_TOKEN_CONTRACT = "0x255de08fb52fde17a3aab145de8e2ffb7fd0310f"
PIMLICO_ERC721_TOKEN_CONTRACT = "0x16bc5fba06f3f5875e915c0ba6963377eb6651e1"
PIMLICO_ERC20_TOKEN_CONTRACT = "0x0b3ff6382bd1a8a74f23d39b4d131a08cea2502a"
PIMLICO_ERC721_TOKEN_CONTRACT = "0xf13eca34092D27cbF91cD377eFB261704C687a05"

# Alchemy Values
ALCHEMY_CHAIN = "sepolia" # or "goerli"
ALCHEMY_CHAIN_ID = "11155111"
ALCHEMY_RPC_URL = "https://eth-sepolia.g.alchemy.com/v2/Your_API_Key"
ALCHEMY_API_KEY = "" # https://dashboard.alchemy.com/apps
ALCHEMY_GAS_POLICY = "" # https://dashboard.alchemy.com/gas-manager
ALCHEMY_ENTRYPOINT_ADDRESS = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
ALCHEMY_ENTRYPOINT_ADDRESS = "0x0000000071727De22E5E9d8BAf0edAc6f37da032"
ALCHEMY_MULTISEND_ADDRESS = "0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526" # https://github.com/safe-global/safe-deployments/blob/main/src/assets/v1.4.1/multi_send.json
# Make sure all nonce are unique for it to deploy account when run initially.
ALCHEMY_NONCE = "2"
Expand All @@ -46,6 +45,9 @@ GELATO_ERC721_TOKEN_CONTRACT = "0xf13eca34092D27cbF91cD377eFB261704C687a05"
# Safe Values
SAFE_VERSION = "1.4.1"

# Verbose Logging
VERBOSE = "true" # Set to "true" for verbose logging.

# Publicly Mintable ERC20 and ERC721 Token for easier testing. Can be used for Token Operation Values.
# ERC20 Token Goerli: https://goerli.etherscan.io/token/0x3Aa475E24F7c076632467444b593E332Bc3355F9
# ERC721 Token Goerli: https://goerli.etherscan.io/token/0xf190c05f968c53962604454ebfa380e5cda600d7
Expand Down
42 changes: 21 additions & 21 deletions examples/4337-gas-metering/README.md

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions examples/4337-gas-metering/alchemy/alchemy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import dotenv from 'dotenv'
import { getAccountNonce } from 'permissionless'
import { ENTRYPOINT_ADDRESS_V06, getAccountNonce } from 'permissionless'
import { Network, Alchemy } from 'alchemy-sdk'
import { setTimeout } from 'timers/promises'
import { PublicClient, Hash, Transport, createPublicClient, formatEther, http, parseEther, zeroAddress } from 'viem'
Expand Down Expand Up @@ -103,9 +103,8 @@ const alchemy = new Alchemy(settings)

const initCode = await getAccountInitCode({
owner: signer.address,
addModuleLibAddress: chainAddresses.ADD_MODULES_LIB_ADDRESS,
safeModuleSetupAddress: chainAddresses.SAFE_MODULE_SETUP_ADDRESS,
safe4337ModuleAddress: chainAddresses.SAFE_4337_MODULE_ADDRESS,
safeProxyFactoryAddress: chainAddresses.SAFE_PROXY_FACTORY_ADDRESS,
safeSingletonAddress: chainAddresses.SAFE_SINGLETON_ADDRESS,
saltNonce: saltNonce,
multiSendAddress: multiSendAddress,
Expand All @@ -115,9 +114,9 @@ const initCode = await getAccountInitCode({
console.log('\nInit Code Created.')

const senderAddress = await getAccountAddress({
publicClient: publicClient,
client: publicClient,
owner: signer.address,
addModuleLibAddress: chainAddresses.ADD_MODULES_LIB_ADDRESS,
safeModuleSetupAddress: chainAddresses.SAFE_MODULE_SETUP_ADDRESS,
safe4337ModuleAddress: chainAddresses.SAFE_4337_MODULE_ADDRESS,
safeProxyFactoryAddress: chainAddresses.SAFE_PROXY_FACTORY_ADDRESS,
safeSingletonAddress: chainAddresses.SAFE_SINGLETON_ADDRESS,
Expand All @@ -141,7 +140,7 @@ if (contractCode) {
}

const newNonce = await getAccountNonce(publicClient, {
entryPoint: entryPointAddress,
entryPoint: ENTRYPOINT_ADDRESS_V06,
sender: senderAddress,
})
console.log('\nNonce for the sender received from EntryPoint.')
Expand All @@ -160,14 +159,15 @@ const txCallData: `0x${string}` = await createCallData(
const sponsoredUserOperation: UserOperation = {
sender: senderAddress,
nonce: newNonce,
initCode: contractCode ? '0x' : initCode,
factory: chainAddresses.SAFE_PROXY_FACTORY_ADDRESS,
factoryData: contractCode ? '0x' : initCode,
callData: txCallData,
callGasLimit: 1n, // All Gas Values will be filled by Estimation Response Data.
verificationGasLimit: 1n,
preVerificationGas: 1n,
maxFeePerGas: 1n,
maxPriorityFeePerGas: 1n,
paymasterAndData: '0x',
paymasterData: '0x',
signature: '0x',
}

Expand Down
34 changes: 15 additions & 19 deletions examples/4337-gas-metering/gelato/gelato.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import dotenv from 'dotenv'
import { Address, Hash, PublicClient, createPublicClient, http, zeroAddress } from 'viem'
import { Address, Hash, createPublicClient, http, zeroAddress } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { baseSepolia, sepolia } from 'viem/chains'
import { getAccountAddress, getGelatoAccountInitCode, getGelatoCallData, prepareForGelatoTx } from '../utils/safe'
Expand Down Expand Up @@ -50,30 +50,26 @@ if (!privateKey) {
throw new Error('Please populate .env file with demo Private Key. Recommended to not use your personal private key.')
}

// Check if the network is supported.
if (chain != 'sepolia' && chain != 'base-sepolia') {
throw new Error('Current code only support limited networks. Please make required changes if you want to use custom network.')
}

const signer = privateKeyToAccount(privateKey as Hash)
console.log('Signer Extracted from Private Key.')

let publicClient
if (chain == 'sepolia') {
publicClient = createPublicClient({
transport: http(rpcURL),
chain: sepolia,
})
} else if (chain == 'base-sepolia') {
publicClient = createPublicClient({
transport: http(rpcURL),
chain: baseSepolia,
}) as PublicClient
} else {
throw new Error('Current code only support limited networks. Please make required changes if you want to use custom network.')
}
const viemChain = chain === 'sepolia' ? sepolia : baseSepolia
const publicClient = createPublicClient({
transport: http(rpcURL),
chain: viemChain,
})

// Creating the Account Init Code.
let requestData = await getGelatoAccountInitCode({
owner: signer.address,
publicClient: publicClient,
client: publicClient,
txType: txType,
addModuleLibAddress: chainAddresses.ADD_MODULES_LIB_ADDRESS,
safeModuleSetupAddress: chainAddresses.SAFE_MODULE_SETUP_ADDRESS,
safe4337ModuleAddress: chainAddresses.SAFE_4337_MODULE_ADDRESS,
safeSingletonAddress: chainAddresses.SAFE_SINGLETON_ADDRESS,
saltNonce: saltNonce,
Expand All @@ -86,9 +82,9 @@ console.log('\nInit Code Created.')
// Creating the Counterfactual Safe Address.
const senderAddress = await getAccountAddress({
owner: signer.address,
publicClient: publicClient,
client: publicClient,
txType: txType,
addModuleLibAddress: chainAddresses.ADD_MODULES_LIB_ADDRESS,
safeModuleSetupAddress: chainAddresses.SAFE_MODULE_SETUP_ADDRESS,
safe4337ModuleAddress: chainAddresses.SAFE_4337_MODULE_ADDRESS,
safeProxyFactoryAddress: chainAddresses.SAFE_PROXY_FACTORY_ADDRESS,
safeSingletonAddress: chainAddresses.SAFE_SINGLETON_ADDRESS,
Expand Down
30 changes: 15 additions & 15 deletions examples/4337-gas-metering/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@
"gelato:native-transfer:1balance": "tsx ./gelato/gelato.ts native-transfer",
"gelato:erc20:1balance": "tsx ./gelato/gelato.ts erc20",
"gelato:erc721:1balance": "tsx ./gelato/gelato.ts erc721",
"pimlico:account": "tsx ./pimlico/pimlico.ts account",
"pimlico:account:paymaster": "tsx ./pimlico/pimlico.ts account paymaster=true",
"pimlico:native-transfer": "tsx ./pimlico/pimlico.ts native-transfer",
"pimlico:native-transfer:paymaster": "tsx ./pimlico/pimlico.ts native-transfer paymaster=true",
"pimlico:erc20": "tsx ./pimlico/pimlico.ts erc20",
"pimlico:erc20:paymaster": "tsx ./pimlico/pimlico.ts erc20 paymaster=true",
"pimlico:erc721": "tsx ./pimlico/pimlico.ts erc721",
"pimlico:erc721:paymaster": "tsx ./pimlico/pimlico.ts erc721 paymaster=true",
"pimlico": "tsx ./pimlico/pimlico.ts"
"pimlico:account:erc20-paymaster": "tsx ./pimlico/pimlico.ts account",
"pimlico:account:verifying-paymaster": "tsx ./pimlico/pimlico.ts account verifyingPaymaster=true",
"pimlico:native-transfer:erc20-paymaster": "tsx ./pimlico/pimlico.ts native-transfer",
"pimlico:native-transfer:verifying-paymaster": "tsx ./pimlico/pimlico.ts native-transfer verifyingPaymaster=true",
"pimlico:erc20:erc20-paymaster": "tsx ./pimlico/pimlico.ts erc20",
"pimlico:erc20:verifying-paymaster": "tsx ./pimlico/pimlico.ts erc20 verifyingPaymaster=true",
"pimlico:erc721:erc20-paymaster": "tsx ./pimlico/pimlico.ts erc721",
"pimlico:erc721:verifying-paymaster": "tsx ./pimlico/pimlico.ts erc721 verifyingPaymaster=true"
},
"repository": {
"type": "git",
Expand All @@ -52,15 +51,16 @@
"@alchemy/aa-accounts": "2.4.0",
"@alchemy/aa-alchemy": "2.4.0",
"@alchemy/aa-core": "2.3.1",
"@gelatonetwork/relay-sdk": "^5.5.6",
"alchemy-sdk": "3.1.2",
"dotenv": "16.4.5",
"permissionless": "0.0.35",
"viem": "2.9.3"
"ethers": "^6.12.1",
"permissionless": "0.1.29",
"viem": "2.12.5"
},
"devDependencies": {
"@gelatonetwork/relay-sdk": "^5.5.6",
"@types/node": "20.11.30",
"tsx": "4.7.1",
"typescript": "^5.4.3"
"@types/node": "20.12.12",
"tsx": "4.11.0",
"typescript": "^5.4.5"
}
}
Loading

0 comments on commit 53e28a5

Please sign in to comment.