-
Notifications
You must be signed in to change notification settings - Fork 651
/
effectivegasprice.go
120 lines (95 loc) · 4.29 KB
/
effectivegasprice.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package pool
import (
"bytes"
"math/big"
"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/0xPolygonHermez/zkevm-node/state"
)
// EffectiveGasPrice implements the effective gas prices calculations and checks
type EffectiveGasPrice struct {
cfg EffectiveGasPriceCfg
}
// NewEffectiveGasPrice creates and initializes an instance of EffectiveGasPrice
func NewEffectiveGasPrice(cfg EffectiveGasPriceCfg) *EffectiveGasPrice {
if (cfg.EthTransferGasPrice != 0) && (cfg.EthTransferL1GasPriceFactor != 0) {
log.Fatalf("configuration error. Only one of the following config params EthTransferGasPrice or EthTransferL1GasPriceFactor from Pool.effectiveGasPrice section can be set to a value different to 0")
}
return &EffectiveGasPrice{
cfg: cfg,
}
}
// IsEnabled return if effectiveGasPrice calculation is enabled
func (e *EffectiveGasPrice) IsEnabled() bool {
return e.cfg.Enabled
}
// GetFinalDeviation return the value for the config parameter FinalDeviationPct
func (e *EffectiveGasPrice) GetFinalDeviation() uint64 {
return e.cfg.FinalDeviationPct
}
// GetTxAndL2GasPrice return the tx gas price and l2 suggested gas price to use in egp calculations
// If egp is disabled we will use a "simulated" tx and l2 gas price, that is calculated using the L2GasPriceSuggesterFactor config param
func (e *EffectiveGasPrice) GetTxAndL2GasPrice(txGasPrice *big.Int, l1GasPrice uint64, l2GasPrice uint64) (egpTxGasPrice *big.Int, egpL2GasPrice uint64) {
if !e.cfg.Enabled {
// If egp is not enabled we use the L2GasPriceSuggesterFactor to calculate the "simulated" suggested L2 gas price
gp := new(big.Int).SetUint64(uint64(e.cfg.L2GasPriceSuggesterFactor * float64(l1GasPrice)))
return gp, gp.Uint64()
} else {
return txGasPrice, l2GasPrice
}
}
// CalculateBreakEvenGasPrice calculates the break even gas price for a transaction
func (e *EffectiveGasPrice) CalculateBreakEvenGasPrice(rawTx []byte, txGasPrice *big.Int, txGasUsed uint64, l1GasPrice uint64) (*big.Int, error) {
const ethTransferGas = 21000
if l1GasPrice == 0 {
return nil, ErrZeroL1GasPrice
}
if txGasUsed == 0 {
// Returns tx.GasPrice as the breakEvenGasPrice
return txGasPrice, nil
}
// If the tx is a ETH transfer (gas == 21000) then check if we need to return a "fix" effective gas price
if txGasUsed == ethTransferGas {
if e.cfg.EthTransferGasPrice != 0 {
return new(big.Int).SetUint64(e.cfg.EthTransferGasPrice), nil
} else if e.cfg.EthTransferL1GasPriceFactor != 0 {
ethGasPrice := uint64(float64(l1GasPrice) * e.cfg.EthTransferL1GasPriceFactor)
if ethGasPrice == 0 {
ethGasPrice = 1
}
return new(big.Int).SetUint64(ethGasPrice), nil
}
}
// Get L2 Min Gas Price
l2MinGasPrice := uint64(float64(l1GasPrice) * e.cfg.L1GasPriceFactor)
txZeroBytes := uint64(bytes.Count(rawTx, []byte{0}))
txNonZeroBytes := uint64(len(rawTx)) - txZeroBytes + state.EfficiencyPercentageByteLength
// Calculate BreakEvenGasPrice
totalTxPrice := (txGasUsed * l2MinGasPrice) +
((txNonZeroBytes*e.cfg.ByteGasCost)+(txZeroBytes*e.cfg.ZeroByteGasCost))*l1GasPrice
breakEvenGasPrice := new(big.Int).SetUint64(uint64(float64(totalTxPrice/txGasUsed) * e.cfg.NetProfit))
if breakEvenGasPrice.Cmp(new(big.Int).SetUint64(0)) == 0 {
breakEvenGasPrice.SetUint64(1)
}
return breakEvenGasPrice, nil
}
// CalculateEffectiveGasPrice calculates the final effective gas price for a tx
func (e *EffectiveGasPrice) CalculateEffectiveGasPrice(rawTx []byte, txGasPrice *big.Int, txGasUsed uint64, l1GasPrice uint64, l2GasPrice uint64) (*big.Int, error) {
breakEvenGasPrice, err := e.CalculateBreakEvenGasPrice(rawTx, txGasPrice, txGasUsed, l1GasPrice)
if err != nil {
return nil, err
}
bfL2GasPrice := new(big.Float).SetUint64(l2GasPrice)
bfTxGasPrice := new(big.Float).SetInt(txGasPrice)
ratioPriority := new(big.Float).SetFloat64(1.0)
if bfL2GasPrice.Cmp(new(big.Float).SetUint64(0)) == 1 && bfTxGasPrice.Cmp(bfL2GasPrice) == 1 {
//ratioPriority = (txGasPrice / l2GasPrice)
ratioPriority = new(big.Float).Quo(bfTxGasPrice, bfL2GasPrice)
}
bfEffectiveGasPrice := new(big.Float).Mul(new(big.Float).SetInt(breakEvenGasPrice), ratioPriority)
effectiveGasPrice := new(big.Int)
bfEffectiveGasPrice.Int(effectiveGasPrice)
if effectiveGasPrice.Cmp(new(big.Int).SetUint64(0)) == 0 {
return nil, state.ErrEffectiveGasPriceIsZero
}
return effectiveGasPrice, nil
}