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

Commit 2a046c9

Browse files
authored
Refactor: use dependancy injection for gas overhead (#155)
1 parent 66c4fe0 commit 2a046c9

File tree

14 files changed

+126
-48
lines changed

14 files changed

+126
-48
lines changed

internal/config/networks.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package config
2+
3+
import "math/big"
4+
5+
var (
6+
EthereumChainID = big.NewInt(1)
7+
GoerliChainID = big.NewInt(5)
8+
ArbitrumOneChainID = big.NewInt(42161)
9+
ArbitrumGoerliChainID = big.NewInt(421613)
10+
)

internal/start/private.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/stackup-wallet/stackup-bundler/internal/logger"
1717
"github.com/stackup-wallet/stackup-bundler/pkg/bundler"
1818
"github.com/stackup-wallet/stackup-bundler/pkg/client"
19+
"github.com/stackup-wallet/stackup-bundler/pkg/gas"
1920
"github.com/stackup-wallet/stackup-bundler/pkg/jsonrpc"
2021
"github.com/stackup-wallet/stackup-bundler/pkg/mempool"
2122
"github.com/stackup-wallet/stackup-bundler/pkg/modules/checks"
@@ -56,6 +57,11 @@ func PrivateMode() {
5657
log.Fatal(err)
5758
}
5859

60+
ov := gas.NewDefaultOverhead()
61+
if chain.Cmp(config.ArbitrumOneChainID) == 0 || chain.Cmp(config.ArbitrumGoerliChainID) == 0 {
62+
ov.SetCalcPreVerificationGasFunc(gas.CalcArbitrumPVGWithEthClient(eth))
63+
}
64+
5965
mem, err := mempool.New(db)
6066
if err != nil {
6167
log.Fatal(err)
@@ -64,6 +70,7 @@ func PrivateMode() {
6470
check := checks.New(
6571
db,
6672
rpc,
73+
ov,
6774
conf.MaxVerificationGas,
6875
conf.MaxOpsForUnstakedSender,
6976
conf.BundlerCollectorTracer,
@@ -80,9 +87,9 @@ func PrivateMode() {
8087
paymaster := paymaster.New(db)
8188

8289
// Init Client
83-
c := client.New(mem, chain, conf.SupportedEntryPoints)
90+
c := client.New(mem, ov, chain, conf.SupportedEntryPoints)
8491
c.SetGetUserOpReceiptFunc(client.GetUserOpReceiptWithEthClient(eth))
85-
c.SetGetGasEstimateFunc(client.GetGasEstimateWithEthClient(rpc, chain, conf.BundlerErrorTracer))
92+
c.SetGetGasEstimateFunc(client.GetGasEstimateWithEthClient(rpc, ov, chain, conf.BundlerErrorTracer))
8693
c.SetGetUserOpByHashFunc(client.GetUserOpByHashWithEthClient(eth))
8794
c.UseLogger(logr)
8895
c.UseModules(

internal/start/searcher.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/stackup-wallet/stackup-bundler/internal/logger"
1818
"github.com/stackup-wallet/stackup-bundler/pkg/bundler"
1919
"github.com/stackup-wallet/stackup-bundler/pkg/client"
20+
"github.com/stackup-wallet/stackup-bundler/pkg/gas"
2021
"github.com/stackup-wallet/stackup-bundler/pkg/jsonrpc"
2122
"github.com/stackup-wallet/stackup-bundler/pkg/mempool"
2223
"github.com/stackup-wallet/stackup-bundler/pkg/modules/builder"
@@ -65,6 +66,8 @@ func SearcherMode() {
6566
)
6667
}
6768

69+
ov := gas.NewDefaultOverhead()
70+
6871
mem, err := mempool.New(db)
6972
if err != nil {
7073
log.Fatal(err)
@@ -73,6 +76,7 @@ func SearcherMode() {
7376
check := checks.New(
7477
db,
7578
rpc,
79+
ov,
7680
conf.MaxVerificationGas,
7781
conf.MaxOpsForUnstakedSender,
7882
conf.BundlerCollectorTracer,
@@ -82,9 +86,9 @@ func SearcherMode() {
8286
paymaster := paymaster.New(db)
8387

8488
// Init Client
85-
c := client.New(mem, chain, conf.SupportedEntryPoints)
89+
c := client.New(mem, ov, chain, conf.SupportedEntryPoints)
8690
c.SetGetUserOpReceiptFunc(client.GetUserOpReceiptWithEthClient(eth))
87-
c.SetGetGasEstimateFunc(client.GetGasEstimateWithEthClient(rpc, chain, conf.BundlerErrorTracer))
91+
c.SetGetGasEstimateFunc(client.GetGasEstimateWithEthClient(rpc, ov, chain, conf.BundlerErrorTracer))
8892
c.SetGetUserOpByHashFunc(client.GetUserOpByHashWithEthClient(eth))
8993
c.UseLogger(logr)
9094
c.UseModules(

pkg/client/client.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
// implements the required RPC methods as specified in EIP-4337.
2323
type Client struct {
2424
mempool *mempool.Mempool
25+
ov *gas.Overhead
2526
chainID *big.Int
2627
supportedEntryPoints []common.Address
2728
userOpHandler modules.UserOpHandlerFunc
@@ -35,11 +36,13 @@ type Client struct {
3536
// that are allowed to be added to the mempool.
3637
func New(
3738
mempool *mempool.Mempool,
39+
ov *gas.Overhead,
3840
chainID *big.Int,
3941
supportedEntryPoints []common.Address,
4042
) *Client {
4143
return &Client{
4244
mempool: mempool,
45+
ov: ov,
4346
chainID: chainID,
4447
supportedEntryPoints: supportedEntryPoints,
4548
userOpHandler: noop.UserOpHandler,
@@ -189,7 +192,7 @@ func (i *Client) EstimateUserOperationGas(op map[string]any, ep string) (*gas.Ga
189192
// with no zero bytes.
190193
l.Info("eth_estimateUserOperationGas ok")
191194
return &gas.GasEstimates{
192-
PreVerificationGas: gas.NewDefaultOverhead().CalcPreVerificationGas(userOp),
195+
PreVerificationGas: i.ov.CalcPreVerificationGas(userOp),
193196
VerificationGas: userOp.VerificationGasLimit,
194197
CallGasLimit: userOp.CallGasLimit,
195198
}, nil

pkg/client/utils.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,14 @@ func getGasEstimateNoop() GetGasEstimateFunc {
4444

4545
// GetGasEstimateWithEthClient returns an implementation of GetGasEstimateFunc that relies on an eth client to
4646
// fetch an estimate for verificationGasLimit and callGasLimit.
47-
func GetGasEstimateWithEthClient(rpc *rpc.Client, chain *big.Int, tracer string) GetGasEstimateFunc {
47+
func GetGasEstimateWithEthClient(
48+
rpc *rpc.Client,
49+
ov *gas.Overhead,
50+
chain *big.Int,
51+
tracer string,
52+
) GetGasEstimateFunc {
4853
return func(ep common.Address, op *userop.UserOperation) (verificationGas uint64, callGas uint64, err error) {
49-
return gas.EstimateGas(rpc, ep, op, chain, tracer)
54+
return gas.EstimateGas(rpc, ep, op, ov, chain, tracer)
5055
}
5156
}
5257

pkg/gas/estimate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func EstimateGas(
2020
rpc *rpc.Client,
2121
from common.Address,
2222
op *userop.UserOperation,
23+
ov *Overhead,
2324
chainID *big.Int,
2425
tracer string,
2526
) (verificationGas uint64, callGas uint64, err error) {
@@ -51,7 +52,6 @@ func EstimateGas(
5152
return 0, 0, err
5253
}
5354

54-
ov := NewDefaultOverhead()
5555
tg := big.NewInt(0).Div(sim.Paid, op.MaxFeePerGas)
5656
cgl := big.NewInt(0).Add(big.NewInt(0).Sub(tg, sim.PreOpGas), big.NewInt(int64(ov.fixed)))
5757
min := ov.NonZeroValueCall()

pkg/gas/overhead.go

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,37 @@ type Overhead struct {
2020
nonZeroValueCall float64
2121
callOpcode float64
2222
nonZeroValueStipend float64
23+
calcPVGFunc CalcPreVerificationGasFunc
24+
}
25+
26+
// NewDefaultOverhead returns an instance of Overhead using parameters defined by the Ethereum protocol.
27+
func NewDefaultOverhead() *Overhead {
28+
return &Overhead{
29+
fixed: 21000,
30+
perUserOp: 18300,
31+
perUserOpWord: 4,
32+
zeroByte: 4,
33+
nonZeroByte: 16,
34+
minBundleSize: 1,
35+
warmStorageRead: 100,
36+
nonZeroValueCall: 9000,
37+
callOpcode: 700,
38+
nonZeroValueStipend: 2300,
39+
calcPVGFunc: calcPVGFuncNoop(),
40+
}
41+
}
42+
43+
func (ov *Overhead) SetCalcPreVerificationGasFunc(fn CalcPreVerificationGasFunc) {
44+
ov.calcPVGFunc = fn
2345
}
2446

2547
// CalcPreVerificationGas returns an expected gas cost for processing a UserOperation from a batch.
2648
func (ov *Overhead) CalcPreVerificationGas(op *userop.UserOperation) *big.Int {
49+
g := ov.calcPVGFunc(op)
50+
if g != nil {
51+
return g
52+
}
53+
2754
packed := op.Pack()
2855
lengthInWord := float64(len(packed)+31) / 32
2956
callDataCost := float64(0)
@@ -47,19 +74,3 @@ func (ov *Overhead) NonZeroValueCall() *big.Int {
4774
int64(ov.fixed + ov.warmStorageRead + ov.nonZeroValueCall + ov.callOpcode + ov.nonZeroValueStipend),
4875
)
4976
}
50-
51-
// NewDefaultOverhead returns an instance of Overhead using parameters defined by the Ethereum protocol.
52-
func NewDefaultOverhead() *Overhead {
53-
return &Overhead{
54-
fixed: 21000,
55-
perUserOp: 18300,
56-
perUserOpWord: 4,
57-
zeroByte: 4,
58-
nonZeroByte: 16,
59-
minBundleSize: 1,
60-
warmStorageRead: 100,
61-
nonZeroValueCall: 9000,
62-
callOpcode: 700,
63-
nonZeroValueStipend: 2300,
64-
}
65-
}

pkg/gas/pvg.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package gas
2+
3+
import (
4+
"math/big"
5+
6+
"github.com/ethereum/go-ethereum/ethclient"
7+
"github.com/stackup-wallet/stackup-bundler/pkg/userop"
8+
)
9+
10+
type CalcPreVerificationGasFunc = func(op *userop.UserOperation) *big.Int
11+
12+
func calcPVGFuncNoop() CalcPreVerificationGasFunc {
13+
return func(op *userop.UserOperation) *big.Int {
14+
return nil
15+
}
16+
}
17+
18+
func CalcArbitrumPVGWithEthClient(eth *ethclient.Client) CalcPreVerificationGasFunc {
19+
return func(op *userop.UserOperation) *big.Int {
20+
return big.NewInt(0)
21+
}
22+
}

pkg/modules/builder/utils.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ package builder
22

33
import (
44
mapset "github.com/deckarep/golang-set/v2"
5+
"github.com/stackup-wallet/stackup-bundler/internal/config"
56
)
67

78
var (
89
// CompatibleChainIDs is a set of chainIDs that support the Block Builder API.
9-
CompatibleChainIDs = mapset.NewSet[uint64](1, 5)
10+
CompatibleChainIDs = mapset.NewSet(config.EthereumChainID.Uint64(), config.GoerliChainID.Uint64())
1011
)

pkg/modules/checks/callgas.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
)
99

1010
// ValidateCallGasLimit checks the callGasLimit is at least the cost of a CALL with non-zero value.
11-
func ValidateCallGasLimit(op *userop.UserOperation) error {
12-
cg := gas.NewDefaultOverhead().NonZeroValueCall()
11+
func ValidateCallGasLimit(op *userop.UserOperation, ov *gas.Overhead) error {
12+
cg := ov.NonZeroValueCall()
1313
if op.CallGasLimit.Cmp(cg) < 0 {
1414
return fmt.Errorf("callGasLimit: below expected gas of %s", cg.String())
1515
}

0 commit comments

Comments
 (0)