Skip to content
This repository was archived by the owner on Oct 20, 2024. It is now read-only.

Commit 19ee343

Browse files
authored
Remove redundant eth_call from eth_estimateUserOperationGas (#147)
1 parent 989aaa2 commit 19ee343

File tree

5 files changed

+46
-81
lines changed

5 files changed

+46
-81
lines changed

internal/start/private.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,7 @@ func PrivateMode() {
8282
// Init Client
8383
c := client.New(mem, chain, conf.SupportedEntryPoints)
8484
c.SetGetUserOpReceiptFunc(client.GetUserOpReceiptWithEthClient(eth))
85-
c.SetGetSimulateValidationFunc(client.GetSimulateValidationWithRpcClient(rpc))
86-
c.SetGetCallGasEstimateFunc(client.GetCallGasEstimateWithEthClient(rpc, chain, conf.BundlerErrorTracer))
85+
c.SetGetGasEstimateFunc(client.GetGasEstimateWithEthClient(rpc, chain, conf.BundlerErrorTracer))
8786
c.SetGetUserOpByHashFunc(client.GetUserOpByHashWithEthClient(eth))
8887
c.UseLogger(logr)
8988
c.UseModules(

internal/start/searcher.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ func SearcherMode() {
8484
// Init Client
8585
c := client.New(mem, chain, conf.SupportedEntryPoints)
8686
c.SetGetUserOpReceiptFunc(client.GetUserOpReceiptWithEthClient(eth))
87-
c.SetGetSimulateValidationFunc(client.GetSimulateValidationWithRpcClient(rpc))
88-
c.SetGetCallGasEstimateFunc(client.GetCallGasEstimateWithEthClient(rpc, chain, conf.BundlerErrorTracer))
87+
c.SetGetGasEstimateFunc(client.GetGasEstimateWithEthClient(rpc, chain, conf.BundlerErrorTracer))
8988
c.SetGetUserOpByHashFunc(client.GetUserOpByHashWithEthClient(eth))
9089
c.UseLogger(logr)
9190
c.UseModules(

pkg/client/client.go

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@ import (
2020
// Client controls the end to end process of adding incoming UserOperations to the mempool. It also
2121
// implements the required RPC methods as specified in EIP-4337.
2222
type Client struct {
23-
mempool *mempool.Mempool
24-
chainID *big.Int
25-
supportedEntryPoints []common.Address
26-
userOpHandler modules.UserOpHandlerFunc
27-
logger logr.Logger
28-
getUserOpReceipt GetUserOpReceiptFunc
29-
getSimulateValidation GetSimulateValidationFunc
30-
getCallGasEstimate GetCallGasEstimateFunc
31-
getUserOpByHash GetUserOpByHashFunc
23+
mempool *mempool.Mempool
24+
chainID *big.Int
25+
supportedEntryPoints []common.Address
26+
userOpHandler modules.UserOpHandlerFunc
27+
logger logr.Logger
28+
getUserOpReceipt GetUserOpReceiptFunc
29+
getGasEstimate GetGasEstimateFunc
30+
getUserOpByHash GetUserOpByHashFunc
3231
}
3332

3433
// New initializes a new ERC-4337 client which can be extended with modules for validating UserOperations
@@ -39,15 +38,14 @@ func New(
3938
supportedEntryPoints []common.Address,
4039
) *Client {
4140
return &Client{
42-
mempool: mempool,
43-
chainID: chainID,
44-
supportedEntryPoints: supportedEntryPoints,
45-
userOpHandler: noop.UserOpHandler,
46-
logger: logger.NewZeroLogr().WithName("client"),
47-
getUserOpReceipt: getUserOpReceiptNoop(),
48-
getSimulateValidation: getSimulateValidationNoop(),
49-
getCallGasEstimate: getCallGasEstimateNoop(),
50-
getUserOpByHash: getUserOpByHashNoop(),
41+
mempool: mempool,
42+
chainID: chainID,
43+
supportedEntryPoints: supportedEntryPoints,
44+
userOpHandler: noop.UserOpHandler,
45+
logger: logger.NewZeroLogr().WithName("client"),
46+
getUserOpReceipt: getUserOpReceiptNoop(),
47+
getGasEstimate: getGasEstimateNoop(),
48+
getUserOpByHash: getUserOpByHashNoop(),
5149
}
5250
}
5351

@@ -77,16 +75,11 @@ func (i *Client) SetGetUserOpReceiptFunc(fn GetUserOpReceiptFunc) {
7775
i.getUserOpReceipt = fn
7876
}
7977

80-
// SetGetSimulateValidationFunc defines a general function for fetching simulateValidation results given a
81-
// userOp and EntryPoint address. This function is called in *Client.EstimateUserOperationGas.
82-
func (i *Client) SetGetSimulateValidationFunc(fn GetSimulateValidationFunc) {
83-
i.getSimulateValidation = fn
84-
}
85-
86-
// SetGetCallGasEstimateFunc defines a general function for fetching an estimate for callGasLimit given a
87-
// userOp and EntryPoint address. This function is called in *Client.EstimateUserOperationGas.
88-
func (i *Client) SetGetCallGasEstimateFunc(fn GetCallGasEstimateFunc) {
89-
i.getCallGasEstimate = fn
78+
// SetGetGasEstimateFunc defines a general function for fetching an estimate for verificationGasLimit and
79+
// callGasLimit given a userOp and EntryPoint address. This function is called in
80+
// *Client.EstimateUserOperationGas.
81+
func (i *Client) SetGetGasEstimateFunc(fn GetGasEstimateFunc) {
82+
i.getGasEstimate = fn
9083
}
9184

9285
// SetGetUserOpByHashFunc defines a general function for fetching a userOp given a userOpHash, EntryPoint
@@ -169,13 +162,7 @@ func (i *Client) EstimateUserOperationGas(op map[string]any, ep string) (*gas.Ga
169162
hash := userOp.GetUserOpHash(epAddr, i.chainID)
170163
l = l.WithValues("userop_hash", hash)
171164

172-
sim, err := i.getSimulateValidation(epAddr, userOp)
173-
if err != nil {
174-
l.Error(err, "eth_estimateUserOperationGas error")
175-
return nil, err
176-
}
177-
178-
cg, err := i.getCallGasEstimate(epAddr, userOp)
165+
vg, cg, err := i.getGasEstimate(epAddr, userOp)
179166
if err != nil {
180167
l.Error(err, "eth_estimateUserOperationGas error")
181168
return nil, err
@@ -184,7 +171,7 @@ func (i *Client) EstimateUserOperationGas(op map[string]any, ep string) (*gas.Ga
184171
l.Info("eth_estimateUserOperationGas ok")
185172
return &gas.GasEstimates{
186173
PreVerificationGas: gas.NewDefaultOverhead().CalcPreVerificationGas(userOp),
187-
VerificationGas: sim.ReturnInfo.PreOpGas,
174+
VerificationGas: big.NewInt(int64(vg)),
188175
CallGasLimit: big.NewInt(int64(cg)),
189176
}, nil
190177
}

pkg/client/utils.go

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import (
88
"github.com/ethereum/go-ethereum/ethclient"
99
"github.com/ethereum/go-ethereum/rpc"
1010
"github.com/stackup-wallet/stackup-bundler/pkg/entrypoint/filter"
11-
"github.com/stackup-wallet/stackup-bundler/pkg/entrypoint/reverts"
12-
"github.com/stackup-wallet/stackup-bundler/pkg/entrypoint/simulation"
1311
"github.com/stackup-wallet/stackup-bundler/pkg/gas"
1412
"github.com/stackup-wallet/stackup-bundler/pkg/userop"
1513
)
@@ -33,41 +31,22 @@ func GetUserOpReceiptWithEthClient(eth *ethclient.Client) GetUserOpReceiptFunc {
3331
}
3432
}
3533

36-
// GetSimulateValidationFunc is a general interface for fetching simulateValidation results given a userOp
37-
// and EntryPoint address.
38-
type GetSimulateValidationFunc = func(ep common.Address, op *userop.UserOperation) (*reverts.ValidationResultRevert, error)
34+
// GetGasEstimateFunc is a general interface for fetching an estimate for verificationGasLimit and
35+
// callGasLimit given a userOp and EntryPoint address.
36+
type GetGasEstimateFunc = func(ep common.Address, op *userop.UserOperation) (verificationGas uint64, callGas uint64, err error)
3937

40-
func getSimulateValidationNoop() GetSimulateValidationFunc {
41-
return func(ep common.Address, op *userop.UserOperation) (*reverts.ValidationResultRevert, error) {
38+
func getGasEstimateNoop() GetGasEstimateFunc {
39+
return func(ep common.Address, op *userop.UserOperation) (verificationGas uint64, callGas uint64, err error) {
4240
//lint:ignore ST1005 This needs to match the bundler test spec.
43-
return nil, errors.New("Missing/invalid userOpHash")
44-
}
45-
}
46-
47-
// GetSimulateValidationWithRpcClient returns an implementation of GetSimulateValidationFunc that relies on a
48-
// rpc client to fetch simulateValidation results.
49-
func GetSimulateValidationWithRpcClient(rpc *rpc.Client) GetSimulateValidationFunc {
50-
return func(ep common.Address, op *userop.UserOperation) (*reverts.ValidationResultRevert, error) {
51-
return simulation.SimulateValidation(rpc, ep, op)
52-
}
53-
}
54-
55-
// GetCallGasEstimateFunc is a general interface for fetching an estimate for callGasLimit given a userOp and
56-
// EntryPoint address.
57-
type GetCallGasEstimateFunc = func(ep common.Address, op *userop.UserOperation) (uint64, error)
58-
59-
func getCallGasEstimateNoop() GetCallGasEstimateFunc {
60-
return func(ep common.Address, op *userop.UserOperation) (uint64, error) {
61-
//lint:ignore ST1005 This needs to match the bundler test spec.
62-
return 0, errors.New("Missing/invalid userOpHash")
41+
return 0, 0, errors.New("Missing/invalid userOpHash")
6342
}
6443
}
6544

66-
// GetCallGasEstimateWithEthClient returns an implementation of GetCallGasEstimateFunc that relies on an eth
67-
// client to fetch an estimate for callGasLimit.
68-
func GetCallGasEstimateWithEthClient(rpc *rpc.Client, chain *big.Int, tracer string) GetCallGasEstimateFunc {
69-
return func(ep common.Address, op *userop.UserOperation) (uint64, error) {
70-
return gas.CallGasEstimate(rpc, ep, op, chain, tracer)
45+
// GetGasEstimateWithEthClient returns an implementation of GetGasEstimateFunc that relies on an eth client to
46+
// fetch an estimate for verificationGasLimit and callGasLimit.
47+
func GetGasEstimateWithEthClient(rpc *rpc.Client, chain *big.Int, tracer string) GetGasEstimateFunc {
48+
return func(ep common.Address, op *userop.UserOperation) (verificationGas uint64, callGas uint64, err error) {
49+
return gas.EstimateGas(rpc, ep, op, chain, tracer)
7150
}
7251
}
7352

pkg/gas/callgas.go renamed to pkg/gas/estimate.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,45 @@ import (
1010
"github.com/stackup-wallet/stackup-bundler/pkg/userop"
1111
)
1212

13-
// CallGasEstimate uses the simulateHandleOp method on the EntryPoint to derive an estimate for callGasLimit.
13+
// EstimateGas uses the simulateHandleOp method on the EntryPoint to derive an estimate for
14+
// verificationGasLimit and callGasLimit.
1415
//
1516
// TODO: This function requires an eth_call and a debug_traceCall. It could probably be optimized further by
1617
// just using a debug_traceCall.
17-
func CallGasEstimate(
18+
func EstimateGas(
1819
rpc *rpc.Client,
1920
from common.Address,
2021
op *userop.UserOperation,
2122
chainID *big.Int,
2223
tracer string,
23-
) (uint64, error) {
24+
) (verificationGas uint64, callGas uint64, err error) {
2425
data, err := op.ToMap()
2526
if err != nil {
26-
return 0, err
27+
return 0, 0, err
2728
}
2829

2930
// Set MaxPriorityFeePerGas = MaxFeePerGas to simplify callGasLimit calculation.
3031
data["maxPriorityFeePerGas"] = hexutil.EncodeBig(op.MaxFeePerGas)
3132
simOp, err := userop.New(data)
3233
if err != nil {
33-
return 0, err
34+
return 0, 0, err
3435
}
3536

3637
sim, err := execution.SimulateHandleOp(rpc, from, simOp, common.Address{}, []byte{})
3738
if err != nil {
38-
return 0, err
39+
return 0, 0, err
3940
}
4041

4142
if err := execution.TraceSimulateHandleOp(rpc, from, op, chainID, tracer, common.Address{}, []byte{}); err != nil {
42-
return 0, err
43+
return 0, 0, err
4344
}
4445

4546
ov := NewDefaultOverhead()
4647
tg := big.NewInt(0).Div(sim.Paid, op.MaxFeePerGas)
4748
cgl := big.NewInt(0).Add(big.NewInt(0).Sub(tg, sim.PreOpGas), big.NewInt(int64(ov.fixed)))
4849
min := ov.NonZeroValueCall()
4950
if cgl.Cmp(min) >= 1 {
50-
return cgl.Uint64(), nil
51+
return sim.PreOpGas.Uint64(), cgl.Uint64(), nil
5152
}
52-
return min.Uint64(), nil
53+
return sim.PreOpGas.Uint64(), min.Uint64(), nil
5354
}

0 commit comments

Comments
 (0)