Giter VIP home page Giter VIP logo

stackup-bundler's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stackup-bundler's Issues

make: air: No such file or directory

I am getting the following error even though I have done the previously mentioned steps:

make dev-private-mode
air -c .air.private-mode.toml
make: air: No such file or directory
make: *** [dev-private-mode] Error 1

Any idea what else I might be missing?

method "eth_estimateUserOperationGas" is returning "execution reverted"

When trying to construct a transaction where the amount to be sent is close to the balance of the address (while still accounting for the gas fees), the rpc method "eth_estimateUserOperationGas" is returning "execution reverted".

Trying to send 0.005 ETH and the balance is 0.01 ETH.

Error message:
'{"error":{"code":-32521,"data":null,"message":"execution reverted"},"id":52,"jsonrpc":"2.0"}'

PS: It works fine if I lower the amount to 0.004 ETH.

BSC Testnet: simpleAccount transfer results in runtime error

I'm attempting to execute ERC4337 in BSC Testnet. I'm running a StackUp bundler, where the ERC4337_BUNDLER_ETH_CLIENT_URL in .env is set to "https://data-seed-prebsc-1-s1.binance.org:8545", which is an RPC URL provided in https://docs.bnbchain.org/docs/BSCtestnet.

When I attempted to run yarn run simpleAccount transfer --to <address> --amount <eth> following the guide at https://docs.stackup.sh/docs/guides/quickstart, I got the following error:

{"level":"info","bundler_mode":"private","client_id":"127.0.0.1","opsSeen":0,"opsIncluded":0,"v":0,"logger":"stackup_bundler/relayer/filter_by_client","caller":"/server2/weihan/bsc-stackup-bundler/pkg/modules/relay/relayer.go:139","time":"2023-03-23T05:30:36Z","message":"client ok"}
{"level":"info","bundler_mode":"private","client_id":"127.0.0.1","method":"POST","status_code":200,"body_size":41,"path":"/","latency":"216.936µs","rpc_method":"eth_chainId","v":0,"logger":"stackup_bundler/http","caller":"/server2/weihan/bsc-stackup-bundler/internal/logger/middleware.go:60","time":"2023-03-23T05:30:36Z"}
{"level":"info","bundler_mode":"private","client_id":"127.0.0.1","opsSeen":0,"opsIncluded":0,"v":0,"logger":"stackup_bundler/relayer/filter_by_client","caller":"/server2/weihan/bsc-stackup-bundler/pkg/modules/relay/relayer.go:139","time":"2023-03-23T05:30:36Z","message":"client ok"}
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x612a85]

goroutine 87 [running]:
math/big.(*Int).Cmp(0x0?, 0x0?)
	/server2/go/src/math/big/int.go:324 +0x25
github.com/stackup-wallet/stackup-bundler/pkg/modules/checks.ValidateFeePerGas(0xc0005b8210, 0x0?)
	/server2/weihan/bsc-stackup-bundler/pkg/modules/checks/gasfee.go:17 +0x3b
github.com/stackup-wallet/stackup-bundler/pkg/modules/checks.(*Standalone).ValidateOpValues.func1.6()
	/server2/weihan/bsc-stackup-bundler/pkg/modules/checks/standalone.go:64 +0x25
golang.org/x/sync/errgroup.(*Group).Go.func1()
	/root/go/pkg/mod/golang.org/x/[email protected]/errgroup/errgroup.go:57 +0x67
created by golang.org/x/sync/errgroup.(*Group).Go
	/root/go/pkg/mod/golang.org/x/[email protected]/errgroup/errgroup.go:54 +0x8d

Any clue why this is happening?

Does not support querying transactions that are more than a few days old

Hi, when I called the eth_getUserOperationByHash interface, I found that older transactions could not be found.

I found the following code:

func filterUserOperationEvent(
	eth *ethclient.Client,
	userOpHash string,
	entryPoint common.Address,
) (*entrypoint.EntrypointUserOperationEventIterator, error) {
	ep, err := entrypoint.NewEntrypoint(entryPoint, eth)
	if err != nil {
		return nil, err
	}
	bn, err := eth.BlockNumber(context.Background())
	if err != nil {
		return nil, err
	}
	toBlk := big.NewInt(0).SetUint64(bn)
	startBlk := big.NewInt(0)
	sub10kBlk := big.NewInt(0).Sub(toBlk, big.NewInt(10000))
	if sub10kBlk.Cmp(startBlk) > 0 {
		startBlk = sub10kBlk
	}

	return ep.FilterUserOperationEvent(
		&bind.FilterOpts{Start: startBlk.Uint64()},
		[][32]byte{common.HexToHash(userOpHash)},
		[]common.Address{},
		[]common.Address{},
	)
}

This code queries the latest 10,000 blocks, but in actual use, we may need to query older historical transactions. This affects eth_getUserOperationByHash and eth_getUserOperationReceipt.

I think a possible fix is to always listen to all UserOperationEvents of the current entryPoint and store them in the database.

I very much hope this problem can be fixed, thank you.

Bundler gets compensated less than transaction fees on BSC Testnet

I was testing out the Stackup bundler on BSC testnet, by running the example from eth-infinitism's repo:
https://github.com/eth-infinitism/bundler .

What I noticed though is that the bundler gets compensated less than the transaction fees for the bundled transaction:
https://testnet.bscscan.com/tx/0x47e98ba99b7963d0ebbf8b67d732bb5580f1cafb91a5846aaca7227877f4564d

As you can see the transaction fees are 0.00085717 BNB, whereas the bundler gets compensated 0.0001303665 BNB.

The logs from the bundler did not show any error during the run. I wonder how it is possible that the bundler accepted to serve such a UserOperation if in the end the compensation does not cover the transaction fees?

Estimation reverted user operations are not excluded from the bundle transaction?

I think we may need to exclude the removed user operation from consideration for next estimation loop.

file /pkg/modules/relay/relayer.go :

// SendUserOperation returns a BatchHandler that is used by the Bundler to send batches in a regular EOA
// transaction.
func (r *Relayer) SendUserOperation() modules.BatchHandlerFunc {
	return func(ctx *modules.BatchHandlerCtx) error {
		opts := transaction.Opts{
			EOA:         r.eoa,
			Eth:         r.eth,
			ChainID:     ctx.ChainID,
			EntryPoint:  ctx.EntryPoint,
			Batch:       ctx.Batch,
			Beneficiary: r.beneficiary,
			BaseFee:     ctx.BaseFee,
			Tip:         ctx.Tip,
			GasPrice:    ctx.GasPrice,
			GasLimit:    0,
			WaitTimeout: r.waitTimeout,
		}
		// Estimate gas for handleOps() and drop all userOps that cause unexpected reverts.
		estRev := []string{}
		for len(ctx.Batch) > 0 {
			est, revert, err := transaction.EstimateHandleOpsGas(&opts)

			if err != nil {
				return err
			} else if revert != nil {
				ctx.MarkOpIndexForRemoval(revert.OpIndex)
				estRev = append(estRev, revert.Reason)

				// Exclude the removed user operation from consideration for next estimation loop.
				opts.Batch =  ctx.Batch
			} else {
				opts.GasLimit = est
				break
			}
		}
		ctx.Data["estimate_revert_reasons"] = estRev

		...
	}
}```

Clear expiration flag after user operation removed?

After we removed the expired user operation, we might need to clear the expiration datetime for it like delete(e.seenAt, userOpHash). This is because if the bundle transaction is successfully mined to block but reverted due to some reason, user tends to send the user operation again to the mempool, and will never be included to next bundle transaction due to expiration drop.

// DropExpired returns a BatchHandlerFunc that will drop UserOperations from the mempool if it has been around
// for longer than the TTL duration.
func (e *ExpireHandler) DropExpired() modules.BatchHandlerFunc {
	return func(ctx *modules.BatchHandlerCtx) error {
		end := len(ctx.Batch) - 1
		for i := end; i >= 0; i-- {
			hash := ctx.Batch[i].GetUserOpHash(ctx.EntryPoint, ctx.ChainID)
			if seenAt, ok := e.seenAt[hash]; !ok {
				e.seenAt[hash] = time.Now()
			} else if seenAt.Add(e.ttl).Before(time.Now()) {
				ctx.MarkOpIndexForRemoval(i)
			}
		}
		return nil
	}
}

Bundler: factory has forbidden write to factory slot

Deployed a local Bundler running in private mode against a Geth node (version 1.13.13-stable-7f131dcb) in dev mode (geth --http --http.api eth,net,web3,debug --dev --dev.period 13 --keystore c:\temp\gethkeys --ipcdisable).
When trying to submit a UserOperation through the Bundler, getting
{
"level": "error",
"bundler_mode": "private",
"entrypoint": "0x9DeCd0823a4D84FaC1f400c316781cB5b047d95C",
"chain_id": "1337",
"userop_hash": "0xa9836a25b1b0e7926c858c7170425e7aebb0ea8452b7e4108e939535aa4d006b",
"error": "factory has forbidden write to factory slot 0x0e42a5c8605986aaf1fab719abda81e87d7793549e47e765191b8c12c69383ba",
"logger": "stackup_bundler/client/eth_sendUserOperation",
"caller": "C:/Temp/Bundler/stackup-bundler-main/pkg/client/client.go:153",
"time": "2024-02-23T10:00:14+10:00",
"message": "eth_sendUserOperation error"
}

Same UserOperation works when submitted directly to the Entrypoint via Geth.

`eth_supportedEntryPoints` is not supported in a batched request

If you include an eth_supportedEntryPoints request in a batch, it returns an error saying the method is unsupported.

Example request:

curl --location 'https://api.stackup.sh/v1/node/key' \
--header 'Content-Type: application/json' \
--data '[
    {
        "method": "eth_chainId",
        "params": [],
        "id": 1,
        "jsonrpc": "2.0"
    },
    {
        "method": "eth_supportedEntryPoints",
        "params": [],
        "id": 2,
        "jsonrpc": "2.0"
    }
]'

Response:

[
    {
        "jsonrpc": "2.0",
        "id": 1,
        "result": "0x13881"
    },
    {
        "jsonrpc": "2.0",
        "id": 2,
        "error": {
            "code": -32601,
            "message": "the method eth_supportedEntryPoints does not exist/is not available"
        }
    }
]

I discovered this when working on a project that uses ethers v6, which batches requests by default. I had to disable batching to use the bundler.

estimateUserOperationGas() : paymasterAndData should not be mandatory

When I call the method estimateUserOperationGas() with a UserOperation containing a paymasterAndData with a zero address, I have this error :
{"OpIndex":0,"Reason":"AA30 paymaster not deployed"}

My source code :

String paymasterAndData = Hash.sha3("0x0000000000000000000000000000000000000000");
UserOperation uo = new UserOperation(accountContractAddress, nonce, Hash.sha3(initCode), Hash.sha3(callData), BigInteger.ZERO,
                BigInteger.ZERO, BigInteger.ZERO, calcMaxFeePerGas(maxPriorityFeePerGas, web3j), maxPriorityFeePerGas, paymasterAndData, Hash.sha3("0x0000000000000000000000000000000000000000000000000000000000000000"));
EthUserOperationGas uoGas = this.bundler.ethEstimateUserOperationGas(uo, entryPointAddress).send();

If I set null value for paymasterAndData, I've this error :
"1 error(s) decoding:\n\n* '' has unset fields: paymasterAndData"

My source code :

String paymasterAndData = null;
UserOperation uo = new UserOperation(accountContractAddress, nonce, Hash.sha3(initCode), Hash.sha3(callData), BigInteger.ZERO,
                BigInteger.ZERO, BigInteger.ZERO, calcMaxFeePerGas(maxPriorityFeePerGas, web3j), maxPriorityFeePerGas, paymasterAndData, Hash.sha3("0x0000000000000000000000000000000000000000000000000000000000000000"));
EthUserOperationGas uoGas = this.bundler.ethEstimateUserOperationGas(uo, entryPointAddress).send();

Cannot install dependencies

There are a bunch of dependencies resulted in no route to host
e.g. https://storage.googleapis.com/proxy-golang-org-prod/be2a76eb9bba21a5-github.com:ethereum:go-ethereum-v1.11.5.zip

github.com/stackup-wallet/stackup-bundler/internal/start imports
	github.com/metachris/flashbotsrpc imports
	github.com/ethereum/go-ethereum/accounts: github.com/ethereum/[email protected]: Get "https://storage.googleapis.com/proxy-golang-org-prod/be2a76eb9bba21a5-github.com:ethereum:go-ethereum-v1.11.5.zip?Expires=1695961700&GoogleAccessId=gcs-urlsigner-prod%40golang-modproxy.iam.gserviceaccount.com&Signature=A4FLOtgO1gSGLHdjK68sLWnHu6DDXcFm0j%2FQKUIAiAMxCEh%2BEIwHY4fkjBU04RzPmbNp%2BulFKZKAHzVQ%2Fuij4RQnYoTLIMX74kMYO2o41DYdawtOGZ55YAaN5zXmUE56cSlGV4AlxNrSlVjoaxb9fnDMRLYzs2Y3%2FXNIxkX0Ne7BhiT%2BZj%2FeiJ%2FiKOxyd81y6IeReNzISnvgOxx%2BDFeqO4MJLH2qb0j1pCNDm3Xm4iJcBDocp8UrSnNqU3SzosHCdwKnuJnUTNZO3UDrmpHKC0njbn8lKY4XLYHEWLvz40TsfZOrcwexa3e939kNufJ2LEj1waWE6Fdwb5J1kO0M%2BQ%3D%3D": dial tcp [2404:6800:4005:80b::201b]:443: connect: no route to host

Error AA95 out of gas on legacy gas price

This error occurred when I tested on a chain that doesn't enable EIP-1559. It seems like there may be a miscalculation in gas.

request body

{ 
  method: 'eth_estimateUserOperationGas',
  ...,
  maxFeePerGas: '0x1', // <-- a value is different when test on EIP-1559 enable/disable chain
  maxPriorityFeePerGas: '0x1' // <-- a value is different when test on EIP-1559 enable/disable chain
}
response

{"error":{"code":-32500,"data":{"OpIndex":0,"Reason":"AA95 out of gas"},"message":"AA95 out of gas"},"id":43,"jsonrpc":"2.0"}
Step to reproduce for error case
1. run geth local with Berlin hardfork (EIP-1559 disabled)
2. deploy AA contracts
3. run stackup-bundler
4. run stackup-example-4337 scripts
Step to reproduce for success case
1. run geth local with London hardfork (EIP-1559 enabled)
2. deploy AA contracts
3. run stackup-bundler
4. run stackup-example-4337 scripts

Method not found Error

I connected Bundler to Hardhat and when I used userop.js to create a simple account it throws the Method Not Found Error.

Here is the error:

Error: missing revert data in call exception; Transaction reverted without a reason string [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (data="0x", transaction={"to":"0x4EE6eCAD1c2Dae9f525404De8555724e3c35d07B","data":"0x9b249f690000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005846b142dd1e924fab83ecc3c08e4d46e82f005e0e5fbfb9cf000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000000000000000000000","accessList":null}, error={"reason":"processing response error","code":"SERVER_ERROR","body":"{\"error\":{\"code\":-32601,\"data\":\"Method not found\",\"message\":\"Method not found\"},\"id\":44,\"jsonrpc\":\"2.0\"}","error":{"code":-32601,"data":"Method not found"},"requestBody":"{\"method\":\"eth_call\",\"params\":[{\"to\":\"0x4ee6ecad1c2dae9f525404de8555724e3c35d07b\",\"data\":\"0x9b249f690000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005846b142dd1e924fab83ecc3c08e4d46e82f005e0e5fbfb9cf000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000000000000000000000\"},\"latest\"],\"id\":44,\"jsonrpc\":\"2.0\"}","requestMethod":"POST","url":"http://localhost:4337/rpc"}, code=CALL_EXCEPTION, version=providers/5.7.2)

It seems like it does not recognize eth_call as a valid method.

eth_call method not found on bundler

I am trying to run the SimpleAccount ERC-4337 example here:
https://docs.stackup.sh/docs/getting-started

For this I am using the stackup bundler running locally on port 3000. So my config looks like this:

{
  "rpcUrl": "http://localhost:3000",
  "signingKey": "0x876d6e83487dc265a65066449b6fce5a1edfddfb0d67b71df8a9306c5324f192",
  "entryPoint": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
  "simpleAccountFactory": "0x9406Cc6185a346906296840746125a0E44976454",
  "paymaster": {
    "rpcUrl": "http://localhost:3000",
    "context": {}
  }
}

I guess the rpcUrl is the url where the bundler and node are running, and I'm only running the bundler on localhost:3000.

Is there a way to run the SimpleAccount example with the bundler and node on separate urls?

Gas Price Suggesting may cause loss to the bundler

Before sending a bundle transaction, gas price has to be estimated base on the current network status and max gas price settings of all batch user operations. The current method used is to calculate the average gas price of the entire batch without considering the max available gas limit each user operation may consume. This may cause some loss of gas fee to the bundler.

Let's say, we have three user operations (op0, op1, op2) as a batch, with gas price of (10 Gwei, 20 Gwei, 30 Gwei) and max gas limit of (300k, 200k, 100k) respectively. The estimated gas price from chain rpc is 10 Gwei, so that all user operation can be included in a bundle transaction.

If we don't take gas limit of each user operation into consideration, the suggested gas price for this bundle transaction would be MAX(10 Gwei, (10+20+30)/3 Gwei) = 20Gwei. Assumed the gas estimate is very accurate so that all gas limit of each user opearion is fully consumed, so the bundler would take (100k + 200k + 300k) * 20 Gwei = 12000k Gwei gas fee, whereas the prefunded gas fee from all user operations is 300k * 10 Gwei + 200k * 20 Gwei + 100k * 30Gwei = 10000k Gwei. As a result, the bundler would loss an extra of 2000k Gwei gas fee.

entryPoint: Implementation not supported

  • Deployed entry point contract on Sepolia Testnet.
  • Passed Sepolia Testnet rpc for ERC4337_BUNDLER_ETH_CLIENT_URL in .env .
  • Started the bundler with make dev-private-mode
  • Using curl for eth_sendUserOperation post method.
    curl --request POST \ --url http://localhost:4337 \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "jsonrpc": "2.0", "id": 1, "method": "eth_sendUserOperation", "params": [ { "sender": "0x0000000000000000000000000000000000000000", "nonce": "0x0", "initCode": "0x", "callData": "0x", "callGasLimit": "0x0", "verificationGasLimit": "0x0", "preVerificationGas": "0x0", "maxFeePerGas": "0x0", "maxPriorityFeePerGas": "0x0", "paymasterAndData": "0x", "signature": "0x" }, "0x9F28189720ab5Ff29126FBE8f4F50E0bDE2644BE" ] } '
  • Getting - {"error":{"code":-32601,"data":"entryPoint: Implementation not supported","message":"entryPoint: Implementation not supported"},"id":1,"jsonrpc":"2.0"}

error: "Missing/invalid userOpHash" when querying userOpHash with secondary entryPoints

Summary

Hi team, we have been using the stackup bundler on our app chain testnet, and we ran into the following issue today, when we deploy a new EntryPoint and add that to ERC4337_BUNDLER_SUPPORTED_ENTRY_POINTS variable as a secondary entrypoint address.

ERC4337_BUNDLER_SUPPORTED_ENTRY_POINTS=0xC25Dc675669907Aee390C0144eA8bB3DFd33a4c7

We now set it to

ERC4337_BUNDLER_SUPPORTED_ENTRY_POINTS=0xC25Dc675669907Aee390C0144eA8bB3DFd33a4c7,0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789

We tried sending the tx to the new 0x5FF13... entrypoint and it worked, but querying the status with eth_getUserOperationReceipt result in invalidOpHash error. Here is a more comprehensive log:

2023-10-31T03:38:05.898418+00:00 app: 
{"level":"info","bundler_mode":"private","entrypoint":"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789","chain_id":"901","userop_hash":"0x89bf9a0667fe7f78846367e360024e2a599e79f2c0149a242fc27c9421c83e28","v":0,"logger":"stackup_bundler/client/eth_sendUserOperation","caller":"/tmp/build_e7170bdc/pkg/client/client.go:138","time":"2023-10-31T03:38:05Z","message":"eth_sendUserOperation ok"}
2023-10-31T03:38:05.898473+00:00 app: {"level":"info","bundler_mode":"private","client_id":"***********","method":"POST","status_code":200,"body_size":103,"path":"/","latency":"1.117860191s","rpc_method":"eth_sendUserOperation","v":0,"logger":"stackup_bundler/http","caller":"/tmp/build_e7170bdc/internal/logger/middleware.go:60","time":"2023-10-31T03:38:05Z"}

# Return error when requesting userOp status
{"level":"error","bundler_mode":"private","userop_hash":"0x89bf9a0667fe7f78846367e360024e2a599e79f2c0149a242fc27c9421c83e28","error":"Missing/invalid userOpHash","logger":"stackup_bundler/client/eth_getUserOperationReceipt","caller":"/tmp/build_e7170bdc/pkg/client/client.go:207","time":"2023-10-31T03:38:08Z","message":"eth_getUserOperationReceipt error"}
2023-10-31T03:38:08.451507+00:00 app: {"level":"info","bundler_mode":"private","client_id":"***********","method":"POST","status_code":200,"body_size":124,"path":"/","latency":"140.114496ms","rpc_method":"eth_getUserOperationReceipt","v":0,"logger":"stackup_bundler/http","caller":"/tmp/build_e7170bdc/internal/logger/middleware.go:60","time":"2023-10-31T03:38:08Z"}

# 0x89bf9a0... is correctly batched and submitted on-chain 
2023-10-31T03:38:11.432767+00:00 app: {"level":"info","bundler_mode":"private","entrypoint":"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789","chain_id":"901","batch_userop_hashes":["0x89bf9a0667fe7f78846367e360024e2a599e79f2c0149a242fc27c9421c83e28"],"dropped_userop_hashes":[],"relayer_est_revert_reasons":[],"txn_hash":"0xb5aeb6f1a53cdcdd2263396a5d5633da1c8cbfcf480885bd84798db577d688e7","duration":"5.223555446s","v":0,"logger":"stackup_bundler/bundler/run","caller":"/tmp/build_e7170bdc/pkg/bundler/bundler.go:189","time":"2023-10-31T03:38:11Z","message":"bundler run ok"}

# Return error when requesting userOp status
2023-10-31T03:38:12.920433+00:00 app: {"level":"error","bundler_mode":"private","userop_hash":"0x89bf9a0667fe7f78846367e360024e2a599e79f2c0149a242fc27c9421c83e28","error":"Missing/invalid userOpHash","logger":"stackup_bundler/client/eth_getUserOperationReceipt","caller":"/tmp/build_e7170bdc/pkg/client/client.go:207","time":"2023-10-31T03:38:12Z","message":"eth_getUserOperationReceipt error"}

I tried restarting the bundler with only the new entryPoint, and everything works smoothly. So I assume the error came from setting multiple entryPoints

eth_estimateUserOperationGas some error

error: {
code: -32500,
data: { OpIndex: 0, Reason: 'AA50 postOp reverted: PM: postOp reverted' },
message: 'AA50 postOp reverted: PM: postOp reverted'
}
my paymaster need approve first, and created the approved calldata, the execution succeeded and then it will do the transferFrom in the postOp method. I actually got the transaction to work, but it returns me an error when using the eth_estimateUserOperationGas. I don't know what's causing this,maybe a bug?

polygon with blockpi RPC

i had error on polygon with blockpi RPC
{"level":"error","bundler_mode":"private","entrypoint":"0x0576a174D229E3cFA37253523E645A78A0C91B57","chain_id":"137","userop_hash":"0xbf613401ca45443bd8ea27c63408d8ca5c2d87d73877619ea0c346566ce4b3b3","error":"invalid character 'S' after object key:value pair","logger":"stackup_bundler/client/eth_sendUserOperation","caller":"/app/pkg/client/client.go:132","time":"2023-03-29T11:37:11Z","message":"eth_sendUserOperation error"}

EstimateGas - The debug trace call fails with error - invalid 3rd argument: options 'tracer': invalid tracer value\"

this error is when using Alchemy
also tried it with Chainstack archive node and the error there is different - invalid n char - Chainstack returns an empty body.

testing it with

yarn run simpleAccount transfer -t 0x...... -amt 0.000001
import { ethers } from "ethers";
import { Client, Presets } from "userop";
import { CLIOpts } from "../../src";

// @ts-ignore
import config from "../../config.json";

export default async function main(t: string, amt: string, opts: CLIOpts) {
  const paymasterMiddleware = opts.withPM
    ? Presets.Middleware.verifyingPaymaster(
      config.paymaster.rpcUrl,
      config.paymaster.context
    )
    : undefined;
  const simpleAccount = await Presets.Builder.SimpleAccount.init(
    new ethers.Wallet(config.signingKey),
    config.rpcUrl,
    { paymasterMiddleware, overrideBundlerRpc: config.overrideBundlerRpc }
  );
  const client = await Client.init(config.rpcUrl);

  const target = ethers.utils.getAddress(t);
  const value = ethers.utils.parseEther(amt);
  const res = await client.sendUserOperation(
    simpleAccount.execute(target, value, "0x"),
    {
      dryRun: opts.dryRun,
      onBuild: (op) => console.log("Signed UserOperation:", op),
    }
  );
  console.log(`UserOpHash: ${res.userOpHash}`);

  console.log("Waiting for transaction...");
  const ev = await res.wait();
  console.log(`Transaction hash: ${ev?.transactionHash ?? null}`);
}

Here is the call Trace

Calling debug_traceCall {From:0x0000000000000000000000000000000000000000 To:0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 Data:0xd6383f940000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000027084ae486058932bb1bd91f96b9877154539dcc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4e1c00000000000000000000000000000000000000000000000000000000000005208000000000000000000000000000000000000000000000000000000062afc27fa000000000000000000000000000000000000000000000000000000062afc27fa00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf0000000000000000000000007411c22b287003007eea1beee2f748a6d359c9b4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084b61d27f60000000000000000000000001e54945fbf1872e34d76b7d72151b861704df8b2000000000000000000000000000000000000000000000000000000e8d4a51000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041b94414f17f0414dff3e88a036339f50e1373bc5c4e6b3a9b83cd3a1fc7625d440d12f3724aabe32be8141dec4155d6f1f8fcd3a59dbee61608f533a66ebc317a1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000} 

Incompatibility between UserOperation struct & PackedUserOperation due to EntryPoint v0.7 changes

Changes in the recent UserOperation structure to PackedUserOperation causes transaction to revert in new Accounts. (refer to AA's PR)

One Example would be SimpleAccount.sol, which inherits from BaseAccount:
Old version

function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
    external override virtual returns (uint256 validationData) {
        _requireFromEntryPoint();
        validationData = _validateSignature(userOp, userOpHash);
        _validateNonce(userOp.nonce);
        _payPrefund(missingAccountFunds);
    }

New Version

function validateUserOp(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash,
        uint256 missingAccountFunds
    ) external virtual override returns (uint256 validationData) {
        _requireFromEntryPoint();
        validationData = _validateSignature(userOp, userOpHash);
        _validateNonce(userOp.nonce);
        _payPrefund(missingAccountFunds);
    }

I use stackups pkg to obtain the OpHash and Signature for UserOp, which is incompatible with the newer version of validateUserOp, so the transaction would always revert.

Would it be possible to add support for EntryPoint v0.7 changes?

[buggy Report] double-spending Revert

If I submit a double-payment UserOp to the bundler that I send to myself, the bundler loses the gas fee.

example)
i have AA wallet. and 0.9 MATIC but If you send me a UserOp that sends me 0.5 MATICs twice at the same time, here's what happens.
스크린샷 2023-04-06 오후 5 39 53

https://mumbai.polygonscan.com/tx/0x45398cc6941400527f572d6791f73321a9718751ab740b8e204dc53243ac4a66

MATIC assets in the bundler
0.740209563545382995 (before)
0.740145890405986468 (after)

I'm wondering why this happened and if it's possible to prevent these bugs.

Separation of UserOp signature validation vs paymaster signature validation

When an invalid signature is provided, the error message is Invalid UserOp signature or paymaster signature. Thinking that it might be useful to separate the error message (i.e. separate the validation logic of paymaster signature vs UserOp signature)? In that case, it is easier for developers to debug which signature went wrong.

Expired paymaster did not return error code as expected

Hi there, I encountered a bug like behavior when sending expired paymaster data to bundler. I implemented my own version of paymaster contract. As for the function _validatePaymasterUserOp , it looks something like this at the end:

function _validatePaymasterUserOp(
      UserOperation calldata userOp,
      bytes32 /*userOpHash*/,
      uint256 maxCost
  ) internal override returns (bytes memory context, uint256 validationData) {
 
      ...

      try this._validatePriceFeed(priceFeed, signature) {
          // if success, returns (context,validationData) for further stage
          return (
              abi.encode(
                  userOp.getSender(),
                  priceFeed.token,
                  userOp.maxFeePerGas,
                  userOp.maxPriorityFeePerGas,
                  maxTokenCost,
                  maxCost
              ),
              packValidationData(
                  false,
                  priceFeed.timestamp + 2 minutes,
                  priceFeed.timestamp
              )
          );
      } catch {
          // if fail, returns (context,validationData) too,
          // but context would be empty (we don't need it) and validationData would return sigFailed
          return ("", SIG_VALIDATION_FAILED);
      }
  }

We pass on valid time range using the timestamp of price feed from a verified off-chain oracle. According to EIP 4337 spec and entrypoint code, this should revert the userOp if out of time range. In fact, if I send userOp with expired paymaster data to a self-host Stackup bundler, I do see logs like this below:
Screen Shot 2023-03-29 at 4 05 57 PM

However, on the client side, I didn't get this error response. I got the userOpHash as response as if it was a valid userOp.
My guess is it's a bug on the bundler side, but maybe I missed some details and implemented the paymaster incorrectly. (The paymaster does work if the time range is valid tho.)

Please let me know your thought on this, thank you! 😊

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.