-
Notifications
You must be signed in to change notification settings - Fork 488
/
Copy pathArbGasInfo.go
283 lines (234 loc) · 10.5 KB
/
ArbGasInfo.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
package precompiles
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/offchainlabs/nitro/arbos/l1pricing"
"github.com/offchainlabs/nitro/arbos/storage"
"github.com/offchainlabs/nitro/util/arbmath"
)
// ArbGasInfo provides insight into the cost of using the rollup.
type ArbGasInfo struct {
Address addr // 0x6c
}
var storageArbGas = big.NewInt(int64(storage.StorageWriteCost))
const AssumedSimpleTxSize = 140
// GetPricesInWeiWithAggregator gets prices in wei when using the provided aggregator
func (con ArbGasInfo) GetPricesInWeiWithAggregator(
c ctx,
evm mech,
aggregator addr,
) (huge, huge, huge, huge, huge, huge, error) {
if c.State.ArbOSVersion() < params.ArbosVersion_4 {
return con._preVersion4_GetPricesInWeiWithAggregator(c, evm, aggregator)
}
l1GasPrice, err := c.State.L1PricingState().PricePerUnit()
if err != nil {
return nil, nil, nil, nil, nil, nil, err
}
var l2GasPrice *big.Int
if evm.Context.BaseFeeInBlock != nil {
l2GasPrice = evm.Context.BaseFeeInBlock
} else {
l2GasPrice = evm.Context.BaseFee
}
// aggregators compress calldata, so we must estimate accordingly
weiForL1Calldata := arbmath.BigMulByUint(l1GasPrice, params.TxDataNonZeroGasEIP2028)
// the cost of a simple tx without calldata
perL2Tx := arbmath.BigMulByUint(weiForL1Calldata, AssumedSimpleTxSize)
// nitro's compute-centric l2 gas pricing has no special compute component that rises independently
perArbGasBase, err := c.State.L2PricingState().MinBaseFeeWei()
if err != nil {
return nil, nil, nil, nil, nil, nil, err
}
if arbmath.BigLessThan(l2GasPrice, perArbGasBase) {
perArbGasBase = l2GasPrice
}
perArbGasCongestion := arbmath.BigSub(l2GasPrice, perArbGasBase)
perArbGasTotal := l2GasPrice
weiForL2Storage := arbmath.BigMul(l2GasPrice, storageArbGas)
return perL2Tx, weiForL1Calldata, weiForL2Storage, perArbGasBase, perArbGasCongestion, perArbGasTotal, nil
}
func (con ArbGasInfo) _preVersion4_GetPricesInWeiWithAggregator(
c ctx,
evm mech,
aggregator addr,
) (huge, huge, huge, huge, huge, huge, error) {
l1GasPrice, err := c.State.L1PricingState().PricePerUnit()
if err != nil {
return nil, nil, nil, nil, nil, nil, err
}
var l2GasPrice *big.Int
if evm.Context.BaseFeeInBlock != nil {
l2GasPrice = evm.Context.BaseFeeInBlock
} else {
l2GasPrice = evm.Context.BaseFee
}
// aggregators compress calldata, so we must estimate accordingly
weiForL1Calldata := arbmath.BigMulByUint(l1GasPrice, params.TxDataNonZeroGasEIP2028)
// the cost of a simple tx without calldata
perL2Tx := arbmath.BigMulByUint(weiForL1Calldata, AssumedSimpleTxSize)
// nitro's compute-centric l2 gas pricing has no special compute component that rises independently
perArbGasBase := l2GasPrice
perArbGasCongestion := common.Big0
perArbGasTotal := l2GasPrice
weiForL2Storage := arbmath.BigMul(l2GasPrice, storageArbGas)
return perL2Tx, weiForL1Calldata, weiForL2Storage, perArbGasBase, perArbGasCongestion, perArbGasTotal, nil
}
// GetPricesInWei gets prices in wei when using the caller's preferred aggregator
func (con ArbGasInfo) GetPricesInWei(c ctx, evm mech) (huge, huge, huge, huge, huge, huge, error) {
return con.GetPricesInWeiWithAggregator(c, evm, addr{})
}
// GetPricesInArbGasWithAggregator gets prices in ArbGas when using the provided aggregator
func (con ArbGasInfo) GetPricesInArbGasWithAggregator(c ctx, evm mech, aggregator addr) (huge, huge, huge, error) {
if c.State.ArbOSVersion() < params.ArbosVersion_4 {
return con._preVersion4_GetPricesInArbGasWithAggregator(c, evm, aggregator)
}
l1GasPrice, err := c.State.L1PricingState().PricePerUnit()
if err != nil {
return nil, nil, nil, err
}
var l2GasPrice *big.Int
if evm.Context.BaseFeeInBlock != nil {
l2GasPrice = evm.Context.BaseFeeInBlock
} else {
l2GasPrice = evm.Context.BaseFee
}
// aggregators compress calldata, so we must estimate accordingly
weiForL1Calldata := arbmath.BigMulByUint(l1GasPrice, params.TxDataNonZeroGasEIP2028)
weiPerL2Tx := arbmath.BigMulByUint(weiForL1Calldata, AssumedSimpleTxSize)
gasForL1Calldata := common.Big0
gasPerL2Tx := common.Big0
if l2GasPrice.Sign() > 0 {
gasForL1Calldata = arbmath.BigDiv(weiForL1Calldata, l2GasPrice)
gasPerL2Tx = arbmath.BigDiv(weiPerL2Tx, l2GasPrice)
}
return gasPerL2Tx, gasForL1Calldata, storageArbGas, nil
}
func (con ArbGasInfo) _preVersion4_GetPricesInArbGasWithAggregator(c ctx, evm mech, aggregator addr) (huge, huge, huge, error) {
l1GasPrice, err := c.State.L1PricingState().PricePerUnit()
if err != nil {
return nil, nil, nil, err
}
var l2GasPrice *big.Int
if evm.Context.BaseFeeInBlock != nil {
l2GasPrice = evm.Context.BaseFeeInBlock
} else {
l2GasPrice = evm.Context.BaseFee
}
// aggregators compress calldata, so we must estimate accordingly
weiForL1Calldata := arbmath.BigMulByUint(l1GasPrice, params.TxDataNonZeroGasEIP2028)
gasForL1Calldata := common.Big0
if l2GasPrice.Sign() > 0 {
gasForL1Calldata = arbmath.BigDiv(weiForL1Calldata, l2GasPrice)
}
perL2Tx := big.NewInt(AssumedSimpleTxSize)
return perL2Tx, gasForL1Calldata, storageArbGas, nil
}
// GetPricesInArbGas gets prices in ArbGas when using the caller's preferred aggregator
func (con ArbGasInfo) GetPricesInArbGas(c ctx, evm mech) (huge, huge, huge, error) {
return con.GetPricesInArbGasWithAggregator(c, evm, addr{})
}
// GetGasAccountingParams gets the rollup's speed limit, pool size, and tx gas limit
func (con ArbGasInfo) GetGasAccountingParams(c ctx, evm mech) (huge, huge, huge, error) {
l2pricing := c.State.L2PricingState()
speedLimit, _ := l2pricing.SpeedLimitPerSecond()
maxTxGasLimit, err := l2pricing.PerBlockGasLimit()
return arbmath.UintToBig(speedLimit), arbmath.UintToBig(maxTxGasLimit), arbmath.UintToBig(maxTxGasLimit), err
}
// GetMinimumGasPrice gets the minimum gas price needed for a transaction to succeed
func (con ArbGasInfo) GetMinimumGasPrice(c ctx, evm mech) (huge, error) {
return c.State.L2PricingState().MinBaseFeeWei()
}
// GetL1BaseFeeEstimate gets the current estimate of the L1 basefee
func (con ArbGasInfo) GetL1BaseFeeEstimate(c ctx, evm mech) (huge, error) {
return c.State.L1PricingState().PricePerUnit()
}
// GetL1BaseFeeEstimateInertia gets how slowly ArbOS updates its estimate of the L1 basefee
func (con ArbGasInfo) GetL1BaseFeeEstimateInertia(c ctx, evm mech) (uint64, error) {
return c.State.L1PricingState().Inertia()
}
// GetL1RewardRate gets the L1 pricer reward rate
func (con ArbGasInfo) GetL1RewardRate(c ctx, evm mech) (uint64, error) {
return c.State.L1PricingState().PerUnitReward()
}
// GetL1RewardRecipient gets the L1 pricer reward recipient
func (con ArbGasInfo) GetL1RewardRecipient(c ctx, evm mech) (common.Address, error) {
return c.State.L1PricingState().PayRewardsTo()
}
// GetL1GasPriceEstimate gets the current estimate of the L1 basefee
func (con ArbGasInfo) GetL1GasPriceEstimate(c ctx, evm mech) (huge, error) {
return con.GetL1BaseFeeEstimate(c, evm)
}
// GetCurrentTxL1GasFees gets the fee paid to the aggregator for posting this tx
func (con ArbGasInfo) GetCurrentTxL1GasFees(c ctx, evm mech) (huge, error) {
return c.txProcessor.PosterFee, nil
}
// GetGasBacklog gets the backlogged amount of gas burnt in excess of the speed limit
func (con ArbGasInfo) GetGasBacklog(c ctx, evm mech) (uint64, error) {
return c.State.L2PricingState().GasBacklog()
}
// GetPricingInertia gets how slowly ArbOS updates the L2 basefee in response to backlogged gas
func (con ArbGasInfo) GetPricingInertia(c ctx, evm mech) (uint64, error) {
return c.State.L2PricingState().PricingInertia()
}
// GetGasBacklogTolerance gets the forgivable amount of backlogged gas ArbOS will ignore when raising the basefee
func (con ArbGasInfo) GetGasBacklogTolerance(c ctx, evm mech) (uint64, error) {
return c.State.L2PricingState().BacklogTolerance()
}
// GetL1PricingSurplus gets the surplus of funds for L1 batch posting payments (may be negative)
func (con ArbGasInfo) GetL1PricingSurplus(c ctx, evm mech) (*big.Int, error) {
if c.State.ArbOSVersion() < params.ArbosVersion_10 {
return con._preversion10_GetL1PricingSurplus(c, evm)
}
ps := c.State.L1PricingState()
return ps.GetL1PricingSurplus()
}
func (con ArbGasInfo) _preversion10_GetL1PricingSurplus(c ctx, evm mech) (*big.Int, error) {
ps := c.State.L1PricingState()
fundsDueForRefunds, err := ps.BatchPosterTable().TotalFundsDue()
if err != nil {
return nil, err
}
fundsDueForRewards, err := ps.FundsDueForRewards()
if err != nil {
return nil, err
}
haveFunds := evm.StateDB.GetBalance(l1pricing.L1PricerFundsPoolAddress)
needFunds := arbmath.BigAdd(fundsDueForRefunds, fundsDueForRewards)
return arbmath.BigSub(haveFunds.ToBig(), needFunds), nil
}
// GetPerBatchGasCharge gets the base charge (in L1 gas) attributed to each data batch in the calldata pricer
func (con ArbGasInfo) GetPerBatchGasCharge(c ctx, evm mech) (int64, error) {
return c.State.L1PricingState().PerBatchGasCost()
}
// GetAmortizedCostCapBips gets the cost amortization cap in basis points
func (con ArbGasInfo) GetAmortizedCostCapBips(c ctx, evm mech) (uint64, error) {
return c.State.L1PricingState().AmortizedCostCapBips()
}
// GetL1FeesAvailable gets the available funds from L1 fees
func (con ArbGasInfo) GetL1FeesAvailable(c ctx, evm mech) (huge, error) {
return c.State.L1PricingState().L1FeesAvailable()
}
// GetL1PricingEquilibrationUnits gets the equilibration units parameter for L1 price adjustment algorithm
func (con ArbGasInfo) GetL1PricingEquilibrationUnits(c ctx, evm mech) (*big.Int, error) {
return c.State.L1PricingState().EquilibrationUnits()
}
// GetLastL1PricingUpdateTime gets the last time the L1 calldata pricer was updated
func (con ArbGasInfo) GetLastL1PricingUpdateTime(c ctx, evm mech) (uint64, error) {
return c.State.L1PricingState().LastUpdateTime()
}
// GetL1PricingFundsDueForRewards gets the amount of L1 calldata payments due for rewards (per the L1 reward rate)
func (con ArbGasInfo) GetL1PricingFundsDueForRewards(c ctx, evm mech) (*big.Int, error) {
return c.State.L1PricingState().FundsDueForRewards()
}
// GetL1PricingUnitsSinceUpdate gets the amount of L1 calldata posted since the last update
func (con ArbGasInfo) GetL1PricingUnitsSinceUpdate(c ctx, evm mech) (uint64, error) {
return c.State.L1PricingState().UnitsSinceUpdate()
}
// GetLastL1PricingSurplus gets the L1 pricing surplus as of the last update (may be negative)
func (con ArbGasInfo) GetLastL1PricingSurplus(c ctx, evm mech) (*big.Int, error) {
return c.State.L1PricingState().LastSurplus()
}