From 5b86f58a265be6e211b8415826d0816814c39823 Mon Sep 17 00:00:00 2001 From: Xiaozhou Li Date: Sun, 7 Apr 2024 12:44:49 -0700 Subject: [PATCH] improve gas control in legacy tx (#74) --- eth/options.go | 24 +++++++++++++----------- eth/transactor.go | 19 ++++++++++--------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/eth/options.go b/eth/options.go index c05de33..bf6f77c 100644 --- a/eth/options.go +++ b/eth/options.go @@ -5,6 +5,7 @@ package eth import ( "math/big" "strconv" + "strings" "time" "github.com/celer-network/goutils/log" @@ -15,15 +16,16 @@ type txOptions struct { ethValue *big.Int nonce uint64 // Legacy Tx gas price - minGasGwei uint64 - maxGasGwei uint64 - addGasGwei uint64 - forceGasGwei *uint64 // use pointer to allow forcing zero gas + minGasGwei float64 + maxGasGwei float64 + addGasGwei float64 + forceGasGwei *float64 // use pointer to allow forcing zero gas // EIP-1559 Tx gas price maxFeePerGasGwei uint64 // aka GasFeeCap in gwei maxPriorityFeePerGasGwei float64 // aka GasTipCap in gwei addPriorityFeePerGasGwei float64 - addPriorityFeeRatio float64 + // For both Legacy and EIP-1559, use suggested * (1 + addGasFeeRatio) + addGasFeeRatio float64 // Gas limit gasLimit uint64 addGasEstimateRatio float64 @@ -92,19 +94,19 @@ func WithNonce(n uint64) TxOption { }) } -func WithMinGasGwei(g uint64) TxOption { +func WithMinGasGwei(g float64) TxOption { return newFuncTxOption(func(o *txOptions) { o.minGasGwei = g }) } -func WithMaxGasGwei(g uint64) TxOption { +func WithMaxGasGwei(g float64) TxOption { return newFuncTxOption(func(o *txOptions) { o.maxGasGwei = g }) } -func WithAddGasGwei(g uint64) TxOption { +func WithAddGasGwei(g float64) TxOption { return newFuncTxOption(func(o *txOptions) { o.addGasGwei = g }) @@ -113,7 +115,7 @@ func WithAddGasGwei(g uint64) TxOption { func WithForceGasGwei(g string) TxOption { return newFuncTxOption(func(o *txOptions) { if g != "" { - gwei, err := strconv.ParseUint(g, 10, 64) + gwei, err := strconv.ParseFloat(strings.TrimSpace(g), 64) if err != nil { log.Errorln("invalid ForceGasGwei", g) return @@ -141,9 +143,9 @@ func WithAddPriorityFeePerGasGwei(g float64) TxOption { }) } -func WithAddPriorityFeeRatio(r float64) TxOption { +func WithAddGassFeeRatio(r float64) TxOption { return newFuncTxOption(func(o *txOptions) { - o.addPriorityFeeRatio = r + o.addGasFeeRatio = r }) } diff --git a/eth/transactor.go b/eth/transactor.go index cb7b9e3..cda2269 100644 --- a/eth/transactor.go +++ b/eth/transactor.go @@ -241,8 +241,7 @@ func (t *Transactor) determineGas(method TxMethod, signer *bind.TransactOpts, tx // 1. Determine gas price // Only accept legacy flags or EIP-1559 flags, not both hasLegacyFlags := txopts.forceGasGwei != nil || txopts.minGasGwei > 0 || txopts.maxGasGwei > 0 || txopts.addGasGwei > 0 - has1559Flags := txopts.maxFeePerGasGwei > 0 || txopts.maxPriorityFeePerGasGwei > 0 || - txopts.addPriorityFeePerGasGwei > 0 || txopts.addPriorityFeeRatio > 0 + has1559Flags := txopts.maxFeePerGasGwei > 0 || txopts.maxPriorityFeePerGasGwei > 0 || txopts.addPriorityFeePerGasGwei > 0 if hasLegacyFlags && has1559Flags { return ErrConflictingGasFlags } @@ -295,15 +294,15 @@ func determine1559GasPrice(signer *bind.TransactOpts, txopts txOptions, client * } if txopts.maxPriorityFeePerGasGwei > 0 { signer.GasTipCap = new(big.Int).SetUint64(uint64(txopts.maxPriorityFeePerGasGwei * 1e9)) - } else if txopts.addPriorityFeePerGasGwei > 0 || txopts.addPriorityFeeRatio > 0 { + } else if txopts.addPriorityFeePerGasGwei > 0 || txopts.addGasFeeRatio > 0 { suggestedGasTipCap, err := client.SuggestGasTipCap(context.Background()) if err != nil { return fmt.Errorf("failed to call SuggestGasTipCap: %w", err) } if txopts.addPriorityFeePerGasGwei > 0 { signer.GasTipCap = new(big.Int).SetUint64(uint64(txopts.addPriorityFeePerGasGwei*1e9) + suggestedGasTipCap.Uint64()) - } else if txopts.addPriorityFeeRatio > 0 { - signer.GasTipCap = new(big.Int).SetUint64(uint64(float64(suggestedGasTipCap.Uint64()) * (1 + txopts.addGasEstimateRatio))) + } else if txopts.addGasFeeRatio > 0 { + signer.GasTipCap = new(big.Int).SetUint64(uint64(float64(suggestedGasTipCap.Uint64()) * (1 + txopts.addGasFeeRatio))) } } return nil @@ -313,7 +312,7 @@ func determine1559GasPrice(signer *bind.TransactOpts, txopts txOptions, client * func determineLegacyGasPrice( signer *bind.TransactOpts, txopts txOptions, client *ethclient.Client) error { if txopts.forceGasGwei != nil { - signer.GasPrice = new(big.Int).SetUint64(*txopts.forceGasGwei * 1e9) + signer.GasPrice = new(big.Int).SetUint64(uint64(*txopts.forceGasGwei * 1e9)) return nil } gasPrice, err := client.SuggestGasPrice(context.Background()) @@ -321,18 +320,20 @@ func determineLegacyGasPrice( return fmt.Errorf("failed to call SuggestGasPrice: %w", err) } if txopts.addGasGwei > 0 { // Add gas price to the suggested value to speed up transactions - addPrice := new(big.Int).SetUint64(txopts.addGasGwei * 1e9) + addPrice := new(big.Int).SetUint64(uint64(txopts.addGasGwei * 1e9)) gasPrice.Add(gasPrice, addPrice) + } else if txopts.addGasFeeRatio > 0 { + gasPrice = new(big.Int).SetUint64(uint64(float64(gasPrice.Uint64()) * (1 + txopts.addGasFeeRatio))) } if txopts.minGasGwei > 0 { // gas can't be lower than minGas - minPrice := new(big.Int).SetUint64(txopts.minGasGwei * 1e9) + minPrice := new(big.Int).SetUint64(uint64(txopts.minGasGwei * 1e9)) // minPrice is larger than suggested, use minPrice if minPrice.Cmp(gasPrice) > 0 { gasPrice = minPrice } } if txopts.maxGasGwei > 0 { // maxGas 0 means no cap on gas price - maxPrice := new(big.Int).SetUint64(txopts.maxGasGwei * 1e9) + maxPrice := new(big.Int).SetUint64(uint64(txopts.maxGasGwei * 1e9)) // GasPrice is larger than allowed cap, use maxPrice but log warning if maxPrice.Cmp(gasPrice) < 0 { log.Warnf("suggested gas price %s larger than cap %s", gasPrice, maxPrice)