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

Commit 121fad8

Browse files
authored
Fix CGL estimate for deeper call stacks (#220)
1 parent 0e0fdba commit 121fad8

File tree

18 files changed

+185
-71
lines changed

18 files changed

+185
-71
lines changed

.air.private-mode.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ tmp_dir = "tmp"
1414
follow_symlink = false
1515
full_bin = ""
1616
include_dir = []
17-
include_ext = ["go", "tpl", "tmpl", "html"]
17+
include_ext = ["go", "tpl", "tmpl", "html", "js"]
1818
kill_delay = "0s"
1919
log = "build-errors.log"
2020
send_interrupt = false

.air.searcher-mode.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ tmp_dir = "tmp"
1414
follow_symlink = false
1515
full_bin = ""
1616
include_dir = []
17-
include_ext = ["go", "tpl", "tmpl", "html"]
17+
include_ext = ["go", "tpl", "tmpl", "html", "js"]
1818
kill_delay = "0s"
1919
log = "build-errors.log"
2020
send_interrupt = false

e2e/src/errors.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export const errorCodes = {
22
executionReverted: -32521,
3+
invalidFields: -32602,
34
};

e2e/test/withoutPaymaster.test.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ethers } from "ethers";
22
import { Presets, Client } from "userop";
33
import { fundIfRequired } from "../src/helpers";
44
import { erc20ABI, testGasABI } from "../src/abi";
5+
import { errorCodes } from "../src/errors";
56
import config from "../config";
67

78
describe("Without Paymaster", () => {
@@ -19,8 +20,8 @@ describe("Without Paymaster", () => {
1920
client = await Client.init(config.nodeUrl, {
2021
overrideBundlerRpc: config.bundlerUrl,
2122
});
22-
client.waitTimeoutMs = 5000;
23-
client.waitIntervalMs = 500;
23+
client.waitTimeoutMs = 2000;
24+
client.waitIntervalMs = 100;
2425
acc = await Presets.Builder.SimpleAccount.init(signer, config.nodeUrl, {
2526
overrideBundlerRpc: config.bundlerUrl,
2627
});
@@ -105,6 +106,21 @@ describe("Without Paymaster", () => {
105106
expect(event?.args.success).toBe(true);
106107
});
107108

109+
test("Sender cannot exceed the max batch gas limit", async () => {
110+
expect.assertions(1);
111+
try {
112+
await client.sendUserOperation(
113+
acc.execute(
114+
config.testGas,
115+
0,
116+
testGas.interface.encodeFunctionData("recursiveCall", [32, 32])
117+
)
118+
);
119+
} catch (error: any) {
120+
expect(error?.error.code).toBe(errorCodes.invalidFields);
121+
}
122+
});
123+
108124
describe("With increasing call stack size", () => {
109125
describe("With zero value calls", () => {
110126
[0, 2, 4, 8, 16].forEach((depth) => {

internal/config/values.go

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/gin-gonic/gin"
1111
"github.com/spf13/viper"
1212
"github.com/stackup-wallet/stackup-bundler/pkg/signer"
13-
"github.com/stackup-wallet/stackup-bundler/pkg/tracer"
1413
)
1514

1615
type Values struct {
@@ -21,6 +20,7 @@ type Values struct {
2120
DataDirectory string
2221
SupportedEntryPoints []common.Address
2322
MaxVerificationGas *big.Int
23+
MaxBatchGasLimit *big.Int
2424
MaxOpsForUnstakedSender int
2525
Beneficiary string
2626

@@ -33,10 +33,8 @@ type Values struct {
3333
BlocksInTheFuture int
3434

3535
// Undocumented variables.
36-
DebugMode bool
37-
GinMode string
38-
BundlerCollectorTracer string
39-
BundlerErrorTracer string
36+
DebugMode bool
37+
GinMode string
4038
}
4139

4240
func envArrayToAddressSlice(s string) []common.Address {
@@ -61,6 +59,7 @@ func GetValues() *Values {
6159
viper.SetDefault("erc4337_bundler_data_directory", "/tmp/stackup_bundler")
6260
viper.SetDefault("erc4337_bundler_supported_entry_points", "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789")
6361
viper.SetDefault("erc4337_bundler_max_verification_gas", 1500000)
62+
viper.SetDefault("erc4337_bundler_max_batch_gas_limit", 25000000)
6463
viper.SetDefault("erc4337_bundler_max_ops_for_unstaked_sender", 4)
6564
viper.SetDefault("erc4337_bundler_blocks_in_the_future", 25)
6665
viper.SetDefault("erc4337_bundler_debug_mode", false)
@@ -87,6 +86,7 @@ func GetValues() *Values {
8786
_ = viper.BindEnv("erc4337_bundler_supported_entry_points")
8887
_ = viper.BindEnv("erc4337_bundler_beneficiary")
8988
_ = viper.BindEnv("erc4337_bundler_max_verification_gas")
89+
_ = viper.BindEnv("erc4337_bundler_max_batch_gas_limit")
9090
_ = viper.BindEnv("erc4337_bundler_max_ops_for_unstaked_sender")
9191
_ = viper.BindEnv("erc4337_bundler_relayer_banned_threshold")
9292
_ = viper.BindEnv("erc4337_bundler_relayer_banned_time_window")
@@ -119,12 +119,6 @@ func GetValues() *Values {
119119
}
120120
}
121121

122-
// Load js tracers from embedded file
123-
trc, err := tracer.NewTracers()
124-
if err != nil {
125-
panic(err)
126-
}
127-
128122
// Return Values
129123
privateKey := viper.GetString("erc4337_bundler_private_key")
130124
ethClientUrl := viper.GetString("erc4337_bundler_eth_client_url")
@@ -133,6 +127,7 @@ func GetValues() *Values {
133127
supportedEntryPoints := envArrayToAddressSlice(viper.GetString("erc4337_bundler_supported_entry_points"))
134128
beneficiary := viper.GetString("erc4337_bundler_beneficiary")
135129
maxVerificationGas := big.NewInt(int64(viper.GetInt("erc4337_bundler_max_verification_gas")))
130+
maxBatchGasLimit := big.NewInt(int64(viper.GetInt("erc4337_bundler_max_batch_gas_limit")))
136131
maxOpsForUnstakedSender := viper.GetInt("erc4337_bundler_max_ops_for_unstaked_sender")
137132
relayerBannedThreshold := viper.GetInt("erc4337_bundler_relayer_banned_threshold")
138133
relayerBannedTimeWindow := viper.GetInt("erc4337_bundler_relayer_banned_time_window") * int(time.Second)
@@ -148,14 +143,13 @@ func GetValues() *Values {
148143
SupportedEntryPoints: supportedEntryPoints,
149144
Beneficiary: beneficiary,
150145
MaxVerificationGas: maxVerificationGas,
146+
MaxBatchGasLimit: maxBatchGasLimit,
151147
MaxOpsForUnstakedSender: maxOpsForUnstakedSender,
152148
RelayerBannedThreshold: relayerBannedThreshold,
153149
RelayerBannedTimeWindow: time.Duration(relayerBannedTimeWindow),
154150
EthBuilderUrl: ethBuilderUrl,
155151
BlocksInTheFuture: blocksInTheFuture,
156152
DebugMode: debugMode,
157153
GinMode: ginMode,
158-
BundlerCollectorTracer: trc.BundlerCollectorTracer,
159-
BundlerErrorTracer: trc.BundlerErrorTracer,
160154
}
161155
}

internal/start/private.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ func PrivateMode() {
6464
ov.SetCalcPreVerificationGasFunc(gas.CalcArbitrumPVGWithEthClient(rpc, conf.SupportedEntryPoints[0]))
6565
ov.SetPreVerificationGasBufferFactor(16)
6666
}
67-
if chain.Cmp(config.OptimismChainID) == 0 || chain.Cmp(config.OptimismGoerliChainID) == 0 || chain.Cmp(config.BaseGoerliChainID) == 0 {
67+
if chain.Cmp(config.OptimismChainID) == 0 || chain.Cmp(config.OptimismGoerliChainID) == 0 ||
68+
chain.Cmp(config.BaseGoerliChainID) == 0 {
6869
ov.SetCalcPreVerificationGasFunc(
6970
gas.CalcOptimismPVGWithEthClient(rpc, chain, conf.SupportedEntryPoints[0]),
7071
)
@@ -81,8 +82,8 @@ func PrivateMode() {
8182
rpc,
8283
ov,
8384
conf.MaxVerificationGas,
85+
conf.MaxBatchGasLimit,
8486
conf.MaxOpsForUnstakedSender,
85-
conf.BundlerCollectorTracer,
8687
)
8788

8889
relayer := relay.New(db, eoa, eth, chain, beneficiary, logr)
@@ -98,7 +99,7 @@ func PrivateMode() {
9899
// Init Client
99100
c := client.New(mem, ov, chain, conf.SupportedEntryPoints)
100101
c.SetGetUserOpReceiptFunc(client.GetUserOpReceiptWithEthClient(eth))
101-
c.SetGetGasEstimateFunc(client.GetGasEstimateWithEthClient(rpc, ov, chain, conf.BundlerErrorTracer))
102+
c.SetGetGasEstimateFunc(client.GetGasEstimateWithEthClient(rpc, ov, chain))
102103
c.SetGetUserOpByHashFunc(client.GetUserOpByHashWithEthClient(eth))
103104
c.UseLogger(logr)
104105
c.UseModules(
@@ -118,6 +119,7 @@ func PrivateMode() {
118119
gasprice.SortByGasPrice(),
119120
gasprice.FilterUnderpriced(),
120121
batch.SortByNonce(),
122+
batch.MaintainGasLimit(conf.MaxBatchGasLimit),
121123
check.CodeHashes(),
122124
check.PaymasterDeposit(),
123125
relayer.SendUserOperation(),

internal/start/searcher.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ func SearcherMode() {
8080
rpc,
8181
ov,
8282
conf.MaxVerificationGas,
83+
conf.MaxBatchGasLimit,
8384
conf.MaxOpsForUnstakedSender,
84-
conf.BundlerCollectorTracer,
8585
)
8686
// TODO: Create separate go-routine for tracking transactions sent to the block builder.
8787
builder := builder.New(eoa, eth, fb, beneficiary, conf.BlocksInTheFuture)
@@ -90,7 +90,7 @@ func SearcherMode() {
9090
// Init Client
9191
c := client.New(mem, ov, chain, conf.SupportedEntryPoints)
9292
c.SetGetUserOpReceiptFunc(client.GetUserOpReceiptWithEthClient(eth))
93-
c.SetGetGasEstimateFunc(client.GetGasEstimateWithEthClient(rpc, ov, chain, conf.BundlerErrorTracer))
93+
c.SetGetGasEstimateFunc(client.GetGasEstimateWithEthClient(rpc, ov, chain))
9494
c.SetGetUserOpByHashFunc(client.GetUserOpByHashWithEthClient(eth))
9595
c.UseLogger(logr)
9696
c.UseModules(
@@ -111,6 +111,7 @@ func SearcherMode() {
111111
gasprice.SortByGasPrice(),
112112
gasprice.FilterUnderpriced(),
113113
batch.SortByNonce(),
114+
batch.MaintainGasLimit(conf.MaxBatchGasLimit),
114115
check.CodeHashes(),
115116
check.PaymasterDeposit(),
116117
builder.SendUserOperation(),

pkg/client/utils.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,15 @@ func GetGasEstimateWithEthClient(
4848
rpc *rpc.Client,
4949
ov *gas.Overhead,
5050
chain *big.Int,
51-
tracer string,
5251
) GetGasEstimateFunc {
5352
return func(ep common.Address, op *userop.UserOperation) (verificationGas uint64, callGas uint64, err error) {
54-
return gas.EstimateGas(rpc, ep, op, ov, chain, tracer)
53+
return gas.EstimateGas(&gas.EstimateInput{
54+
Rpc: rpc,
55+
EntryPoint: ep,
56+
Op: op,
57+
Ov: ov,
58+
ChainID: chain,
59+
})
5560
}
5661
}
5762

pkg/entrypoint/execution/trace.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ type TraceInput struct {
2626
Op *userop.UserOperation
2727
ChainID *big.Int
2828

29-
// Tracer for debug_traceCall
30-
CustomTracer string
31-
3229
// Optional params for simulateHandleOps
3330
Target common.Address
3431
Data []byte
@@ -94,7 +91,7 @@ func TraceSimulateHandleOp(in *TraceInput) (*TraceOutput, error) {
9491
Data: tx.Data(),
9592
}
9693
opts := utils.TraceCallOpts{
97-
Tracer: in.CustomTracer,
94+
Tracer: tracer.Loaded.BundlerErrorTracer,
9895
}
9996
if err := in.Rpc.CallContext(context.Background(), &res, "debug_traceCall", &req, "latest", &opts); err != nil {
10097
return nil, err

pkg/entrypoint/simulation/tracevalidation.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ func TraceSimulateValidation(
2626
entryPoint common.Address,
2727
op *userop.UserOperation,
2828
chainID *big.Int,
29-
customTracer string,
3029
stakes EntityStakes,
3130
) ([]common.Address, error) {
3231
ep, err := entrypoint.NewEntrypoint(entryPoint, ethclient.NewClient(rpc))
@@ -51,7 +50,7 @@ func TraceSimulateValidation(
5150
Data: tx.Data(),
5251
}
5352
opts := utils.TraceCallOpts{
54-
Tracer: customTracer,
53+
Tracer: tracer.Loaded.BundlerCollectorTracer,
5554
}
5655
if err := rpc.CallContext(context.Background(), &res, "debug_traceCall", &req, "latest", &opts); err != nil {
5756
return nil, err

0 commit comments

Comments
 (0)