Skip to content
This repository was archived by the owner on Jul 13, 2022. It is now read-only.

Commit 0f46f86

Browse files
winor30P1sar
andauthored
Enable to set minimum gas price (#689)
* feat: add minGasPrice field to Config * feat: add minGasPrice field to Connection struct * feat: don't return a gasPrice lower than minGasPrice * fix: ethereum config test * fix: minimum gas price * chore: minGasPrice is big.NewInt(2) -> big.NewInt(0) because default minGasPrice is 0 * chore: fix test failed message * feat: add TestConnection_SafeEstimateGasSameMin minGasPrice and maxGasPrice is same case * chore: variableization of gasMultipler * feat: maxPrice > minPrice * fix: fixed the use of local variables to avoid changing the global MaxPrice * chore: just set minPrice to MaxGasPrice * fix: test data for ChainConfig Co-authored-by: Kirill <[email protected]>
1 parent facb88d commit 0f46f86

File tree

8 files changed

+95
-13
lines changed

8 files changed

+95
-13
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Ethereum chains support the following additional options:
8484
"erc721Handler": "0x1234...", // Address of erc721 handler (required)
8585
"genericHandler": "0x1234...", // Address of generic handler (required)
8686
"maxGasPrice": "0x1234", // Gas price for transactions (default: 20000000000)
87+
"minGasPrice": "0x1234", // Minimum gas price for transactions (default: 0)
8788
"gasLimit": "0x1234", // Gas limit for transactions (default: 6721975)
8889
"gasMultiplier": "1.25", // Multiplies the gas price by the supplied value (default: 1)
8990
"http": "true", // Whether the chain connection is ws or http (default: false)

chains/ethereum/chain.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func InitializeChain(chainCfg *core.ChainConfig, logger log15.Logger, sysErr cha
108108
}
109109

110110
stop := make(chan int)
111-
conn := connection.NewConnection(cfg.endpoint, cfg.http, kp, logger, cfg.gasLimit, cfg.maxGasPrice, cfg.gasMultiplier, cfg.egsApiKey, cfg.egsSpeed)
111+
conn := connection.NewConnection(cfg.endpoint, cfg.http, kp, logger, cfg.gasLimit, cfg.maxGasPrice, cfg.minGasPrice, cfg.gasMultiplier, cfg.egsApiKey, cfg.egsSpeed)
112112
err = conn.Connect()
113113
if err != nil {
114114
return nil, err

chains/ethereum/config.go

+15
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717

1818
const DefaultGasLimit = 6721975
1919
const DefaultGasPrice = 20000000000
20+
const DefaultMinGasPrice = 0
2021
const DefaultBlockConfirmations = 10
2122
const DefaultGasMultiplier = 1
2223

@@ -27,6 +28,7 @@ var (
2728
Erc721HandlerOpt = "erc721Handler"
2829
GenericHandlerOpt = "genericHandler"
2930
MaxGasPriceOpt = "maxGasPrice"
31+
MinGasPriceOpt = "minGasPrice"
3032
GasLimitOpt = "gasLimit"
3133
GasMultiplier = "gasMultiplier"
3234
HttpOpt = "http"
@@ -51,6 +53,7 @@ type Config struct {
5153
genericHandlerContract common.Address
5254
gasLimit *big.Int
5355
maxGasPrice *big.Int
56+
minGasPrice *big.Int
5457
gasMultiplier *big.Float
5558
http bool // Config for type of connection
5659
startBlock *big.Int
@@ -76,6 +79,7 @@ func parseChainConfig(chainCfg *core.ChainConfig) (*Config, error) {
7679
genericHandlerContract: utils.ZeroAddress,
7780
gasLimit: big.NewInt(DefaultGasLimit),
7881
maxGasPrice: big.NewInt(DefaultGasPrice),
82+
minGasPrice: big.NewInt(DefaultMinGasPrice),
7983
gasMultiplier: big.NewFloat(DefaultGasMultiplier),
8084
http: false,
8185
startBlock: big.NewInt(0),
@@ -117,6 +121,17 @@ func parseChainConfig(chainCfg *core.ChainConfig) (*Config, error) {
117121
}
118122
}
119123

124+
if minGasPrice, ok := chainCfg.Opts[MinGasPriceOpt]; ok {
125+
price := big.NewInt(0)
126+
_, pass := price.SetString(minGasPrice, 10)
127+
if pass {
128+
config.minGasPrice = price
129+
delete(chainCfg.Opts, MinGasPriceOpt)
130+
} else {
131+
return nil, errors.New("unable to parse min gas price")
132+
}
133+
}
134+
120135
if gasLimit, ok := chainCfg.Opts[GasLimitOpt]; ok {
121136
limit := big.NewInt(0)
122137
_, pass := limit.SetString(gasLimit, 10)

chains/ethereum/config_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func TestParseChainConfig(t *testing.T) {
3030
"gasLimit": "10",
3131
"gasMultiplier": "1",
3232
"maxGasPrice": "20",
33+
"minGasPrice": "0",
3334
"http": "true",
3435
"startBlock": "10",
3536
"blockConfirmations": "50",
@@ -56,6 +57,7 @@ func TestParseChainConfig(t *testing.T) {
5657
genericHandlerContract: common.HexToAddress("0x1234"),
5758
gasLimit: big.NewInt(10),
5859
maxGasPrice: big.NewInt(20),
60+
minGasPrice: big.NewInt(0),
5961
gasMultiplier: big.NewFloat(1),
6062
http: true,
6163
startBlock: big.NewInt(10),
@@ -87,6 +89,7 @@ func TestParseChainConfigWithNoBlockConfirmations(t *testing.T) {
8789
"gasLimit": "10",
8890
"gasMultiplier": "1",
8991
"maxGasPrice": "20",
92+
"minGasPrice": "0",
9093
"http": "true",
9194
"startBlock": "10",
9295
},
@@ -110,6 +113,7 @@ func TestParseChainConfigWithNoBlockConfirmations(t *testing.T) {
110113
genericHandlerContract: common.HexToAddress("0x1234"),
111114
gasLimit: big.NewInt(10),
112115
maxGasPrice: big.NewInt(20),
116+
minGasPrice: big.NewInt(0),
113117
gasMultiplier: big.NewFloat(1),
114118
http: true,
115119
startBlock: big.NewInt(10),
@@ -138,6 +142,7 @@ func TestChainConfigOneContract(t *testing.T) {
138142
"erc20Handler": "0x1234",
139143
"gasLimit": "10",
140144
"maxGasPrice": "20",
145+
"minGasPrice": "0",
141146
"gasMultiplier": "1",
142147
"http": "true",
143148
"startBlock": "10",
@@ -160,6 +165,7 @@ func TestChainConfigOneContract(t *testing.T) {
160165
erc20HandlerContract: common.HexToAddress("0x1234"),
161166
gasLimit: big.NewInt(10),
162167
maxGasPrice: big.NewInt(20),
168+
minGasPrice: big.NewInt(0),
163169
gasMultiplier: big.NewFloat(1),
164170
http: true,
165171
startBlock: big.NewInt(10),
@@ -249,6 +255,7 @@ func TestEthGasStationDefaultSpeed(t *testing.T) {
249255
"gasLimit": "10",
250256
"gasMultiplier": "1",
251257
"maxGasPrice": "20",
258+
"minGasPrice": "0",
252259
"http": "true",
253260
"startBlock": "10",
254261
"egsApiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
@@ -274,6 +281,7 @@ func TestEthGasStationDefaultSpeed(t *testing.T) {
274281
genericHandlerContract: common.HexToAddress("0x1234"),
275282
gasLimit: big.NewInt(10),
276283
maxGasPrice: big.NewInt(20),
284+
minGasPrice: big.NewInt(0),
277285
gasMultiplier: big.NewFloat(1),
278286
http: true,
279287
startBlock: big.NewInt(10),
@@ -303,6 +311,7 @@ func TestEthGasStationCustomSpeed(t *testing.T) {
303311
"gasLimit": "10",
304312
"gasMultiplier": "1",
305313
"maxGasPrice": "20",
314+
"minGasPrice": "0",
306315
"http": "true",
307316
"startBlock": "10",
308317
"egsApiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
@@ -328,6 +337,7 @@ func TestEthGasStationCustomSpeed(t *testing.T) {
328337
genericHandlerContract: common.HexToAddress("0x1234"),
329338
gasLimit: big.NewInt(10),
330339
maxGasPrice: big.NewInt(20),
340+
minGasPrice: big.NewInt(0),
331341
gasMultiplier: big.NewFloat(1),
332342
http: true,
333343
startBlock: big.NewInt(10),
@@ -357,6 +367,7 @@ func TestEthGasStationInvalidSpeed(t *testing.T) {
357367
"gasLimit": "10",
358368
"gasMultiplier": "1",
359369
"maxGasPrice": "20",
370+
"minGasPrice": "0",
360371
"http": "true",
361372
"startBlock": "10",
362373
"egsApiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
@@ -382,6 +393,7 @@ func TestEthGasStationInvalidSpeed(t *testing.T) {
382393
genericHandlerContract: common.HexToAddress("0x1234"),
383394
gasLimit: big.NewInt(10),
384395
maxGasPrice: big.NewInt(20),
396+
minGasPrice: big.NewInt(0),
385397
gasMultiplier: big.NewFloat(1),
386398
http: true,
387399
startBlock: big.NewInt(10),

chains/ethereum/test_utils_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func newTestLogger(name string) log15.Logger {
7070

7171
func newLocalConnection(t *testing.T, cfg *Config) *connection.Connection {
7272
kp := keystore.TestKeyRing.EthereumKeys[cfg.from]
73-
conn := connection.NewConnection(TestEndpoint, false, kp, TestLogger, big.NewInt(DefaultGasLimit), big.NewInt(DefaultGasPrice), big.NewFloat(DefaultGasMultiplier), "", "")
73+
conn := connection.NewConnection(TestEndpoint, false, kp, TestLogger, big.NewInt(DefaultGasLimit), big.NewInt(DefaultGasPrice), big.NewInt(DefaultMinGasPrice), big.NewFloat(DefaultGasMultiplier), "", "")
7474
err := conn.Connect()
7575
if err != nil {
7676
t.Fatal(err)

connections/ethereum/connection.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Connection struct {
2929
kp *secp256k1.Keypair
3030
gasLimit *big.Int
3131
maxGasPrice *big.Int
32+
minGasPrice *big.Int
3233
gasMultiplier *big.Float
3334
egsApiKey string
3435
egsSpeed string
@@ -43,13 +44,14 @@ type Connection struct {
4344
}
4445

4546
// NewConnection returns an uninitialized connection, must call Connection.Connect() before using.
46-
func NewConnection(endpoint string, http bool, kp *secp256k1.Keypair, log log15.Logger, gasLimit, gasPrice *big.Int, gasMultiplier *big.Float, gsnApiKey, gsnSpeed string) *Connection {
47+
func NewConnection(endpoint string, http bool, kp *secp256k1.Keypair, log log15.Logger, gasLimit, maxGasPrice, minGasPrice *big.Int, gasMultiplier *big.Float, gsnApiKey, gsnSpeed string) *Connection {
4748
return &Connection{
4849
endpoint: endpoint,
4950
http: http,
5051
kp: kp,
5152
gasLimit: gasLimit,
52-
maxGasPrice: gasPrice,
53+
maxGasPrice: maxGasPrice,
54+
minGasPrice: minGasPrice,
5355
gasMultiplier: gasMultiplier,
5456
egsApiKey: gsnApiKey,
5557
egsSpeed: gsnSpeed,
@@ -158,7 +160,9 @@ func (c *Connection) SafeEstimateGas(ctx context.Context) (*big.Int, error) {
158160
gasPrice := multiplyGasPrice(suggestedGasPrice, c.gasMultiplier)
159161

160162
// Check we aren't exceeding our limit
161-
if gasPrice.Cmp(c.maxGasPrice) == 1 {
163+
if gasPrice.Cmp(c.minGasPrice) == -1 {
164+
return c.minGasPrice, nil
165+
} else if gasPrice.Cmp(c.maxGasPrice) == 1 {
162166
return c.maxGasPrice, nil
163167
} else {
164168
return gasPrice, nil

connections/ethereum/connection_test.go

+57-8
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ var TestEndpoint = "ws://localhost:8545"
1919
var AliceKp = keystore.TestKeyRing.EthereumKeys[keystore.AliceKey]
2020
var GasLimit = big.NewInt(ethutils.DefaultGasLimit)
2121
var MaxGasPrice = big.NewInt(ethutils.DefaultMaxGasPrice)
22+
var MinGasPrice = big.NewInt(ethutils.DefaultMinGasPrice)
2223

2324
var GasMultipler = big.NewFloat(ethutils.DefaultGasMultiplier)
2425

2526
func TestConnect(t *testing.T) {
26-
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, MaxGasPrice, GasMultipler, "", "")
27+
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, MaxGasPrice, MinGasPrice, GasMultipler, "", "")
2728
err := conn.Connect()
2829
if err != nil {
2930
t.Fatal(err)
@@ -40,7 +41,7 @@ func TestContractCode(t *testing.T) {
4041
t.Fatal(err)
4142
}
4243

43-
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, MaxGasPrice, GasMultipler, "", "")
44+
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, MaxGasPrice, MinGasPrice, GasMultipler, "", "")
4445
err = conn.Connect()
4546
if err != nil {
4647
t.Fatal(err)
@@ -61,8 +62,12 @@ func TestContractCode(t *testing.T) {
6162
}
6263

6364
func TestConnection_SafeEstimateGas(t *testing.T) {
65+
// In the case of d := c.Add(a, b), since c==d, there is a risk that MaxGasPrice itself will be changed,
66+
// so the local variable maxGasPrice is defined by big.NewInt(0).
67+
maxGasPrice := big.NewInt(0)
6468
// MaxGasPrice is the constant price on the dev network, so we increase it here by 1 to ensure it adjusts
65-
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, MaxGasPrice.Add(MaxGasPrice, big.NewInt(1)), GasMultipler, "", "")
69+
maxGasPrice.Add(MaxGasPrice, big.NewInt(1))
70+
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, maxGasPrice, MinGasPrice, GasMultipler, "", "")
6671
err := conn.Connect()
6772
if err != nil {
6873
t.Fatal(err)
@@ -74,14 +79,14 @@ func TestConnection_SafeEstimateGas(t *testing.T) {
7479
t.Fatal(err)
7580
}
7681

77-
if price.Cmp(MaxGasPrice) == 0 {
82+
if price.Cmp(maxGasPrice) == 0 {
7883
t.Fatalf("Gas price should be less than max. Suggested: %s Max: %s", price.String(), MaxGasPrice.String())
7984
}
8085
}
8186

8287
func TestConnection_SafeEstimateGasMax(t *testing.T) {
8388
maxPrice := big.NewInt(1)
84-
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, maxPrice, GasMultipler, "", "")
89+
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, maxPrice, MinGasPrice, GasMultipler, "", "")
8590
err := conn.Connect()
8691
if err != nil {
8792
t.Fatal(err)
@@ -98,11 +103,55 @@ func TestConnection_SafeEstimateGasMax(t *testing.T) {
98103
}
99104
}
100105

106+
func TestConnection_SafeEstimateGasMin(t *testing.T) {
107+
minPrice := big.NewInt(1)
108+
// When gasMultipler is zero, the gasPrice is zero if the effect of the minPrice is removed.
109+
gasMultipler := big.NewFloat(0)
110+
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, MaxGasPrice, minPrice, gasMultipler, "", "")
111+
err := conn.Connect()
112+
if err != nil {
113+
t.Fatal(err)
114+
}
115+
defer conn.Close()
116+
117+
price, err := conn.SafeEstimateGas(context.Background())
118+
if err != nil {
119+
t.Fatal(err)
120+
}
121+
122+
if price.Cmp(minPrice) != 0 {
123+
t.Fatalf("Gas price should equal min. Suggested: %s Min: %s", price.String(), minPrice.String())
124+
}
125+
}
126+
127+
func TestConnection_SafeEstimateGasSameMin(t *testing.T) {
128+
// When GasMultipler is set to 1, the gas price is set to 2000000000, so the minPrice is set to the same price
129+
// and maxPrice is made larger than the minPrice by adding one.
130+
minPrice := MaxGasPrice
131+
maxGasPrice := big.NewInt(0)
132+
maxGasPrice.Add(MaxGasPrice, big.NewInt(1))
133+
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, maxGasPrice, minPrice, GasMultipler, "", "")
134+
err := conn.Connect()
135+
if err != nil {
136+
t.Fatal(err)
137+
}
138+
defer conn.Close()
139+
140+
price, err := conn.SafeEstimateGas(context.Background())
141+
if err != nil {
142+
t.Fatal(err)
143+
}
144+
145+
if price.Cmp(minPrice) != 0 {
146+
t.Fatalf("Gas price should equal min. Suggested: %s Min: %s", price.String(), minPrice.String())
147+
}
148+
}
149+
101150
func TestConnection_EstimateGasLondon(t *testing.T) {
102151
// Set TestEndpoint to Goerli endpoint when testing as the current Github CI doesn't use the London version of geth
103152
// Goerli commonly has a base fee of 7 wei with maxPriorityFeePerGas of 4.999999993 gwei
104153
maxGasPrice := big.NewInt(100000000000)
105-
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, maxGasPrice, GasMultipler, "", "")
154+
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, maxGasPrice, MinGasPrice, GasMultipler, "", "")
106155
err := conn.Connect()
107156
if err != nil {
108157
t.Fatal(err)
@@ -131,7 +180,7 @@ func TestConnection_EstimateGasLondonMax(t *testing.T) {
131180
// Set TestEndpoint to Goerli endpoint when testing as the current Github CI doesn't use the London version of geth
132181
// Goerli commonly has a base fee of 7 wei with maxPriorityFeePerGas of 4.999999993 gwei
133182
maxGasPrice := big.NewInt(100)
134-
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, maxGasPrice, GasMultipler, "", "")
183+
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, maxGasPrice, MinGasPrice, GasMultipler, "", "")
135184
err := conn.Connect()
136185
if err != nil {
137186
t.Fatal(err)
@@ -166,7 +215,7 @@ func TestConnection_EstimateGasLondonMin(t *testing.T) {
166215
// Set TestEndpoint to Goerli endpoint when testing as the current Github CI doesn't use the London version of geth
167216
// Goerli commonly has a base fee of 7 wei with maxPriorityFeePerGas of 4.999999993 gwei
168217
maxGasPrice := big.NewInt(1)
169-
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, maxGasPrice, GasMultipler, "", "")
218+
conn := NewConnection(TestEndpoint, false, AliceKp, log15.Root(), GasLimit, maxGasPrice, MinGasPrice, GasMultipler, "", "")
170219
err := conn.Connect()
171220
if err != nil {
172221
t.Fatal(err)

shared/ethereum/client.go

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
const DefaultGasLimit = 6721975
2424
const DefaultMaxGasPrice = 20000000000
25+
const DefaultMinGasPrice = 0
2526
const DefaultGasMultiplier = 1
2627

2728
var ExpectedBlockTime = time.Second

0 commit comments

Comments
 (0)