@@ -19,6 +19,7 @@ package types
1919import (
2020 "bytes"
2121 "encoding/binary"
22+ "errors"
2223 "fmt"
2324 "math/big"
2425
@@ -41,6 +42,9 @@ const (
4142 // array. baseFeeScalar is in the first four bytes of the segment, blobBaseFeeScalar the next
4243 // four.
4344 scalarSectionStart = 32 - BaseFeeScalarSlotOffset - 4
45+
46+ IsthmusL1AttributesLen = 176
47+ JovianL1AttributesLen = 178
4448)
4549
4650func init () {
5761 EcotoneL1AttributesSelector = []byte {0x44 , 0x0a , 0x5e , 0x20 }
5862 // IsthmusL1AttributesSelector is the selector indicating Isthmus style L1 gas attributes.
5963 IsthmusL1AttributesSelector = []byte {0x09 , 0x89 , 0x99 , 0xbe }
64+ // JovianL1AttributesSelector is the selector indicating Jovian style L1 gas attributes.
65+ JovianL1AttributesSelector = []byte {0x3d , 0xb6 , 0xbe , 0x2b }
6066
6167 // L1BlockAddr is the address of the L1Block contract which stores the L1 gas attributes.
6268 L1BlockAddr = common .HexToAddress ("0x4200000000000000000000000000000000000015" )
@@ -512,6 +518,57 @@ func extractL1GasParamsPostIsthmus(data []byte) (gasParams, error) {
512518 }, nil
513519}
514520
521+ // ExtractDAFootprintGasScalar extracts the DA footprint gas scalar from the L1 attributes transaction data
522+ // of a Jovian-enabled block.
523+ func ExtractDAFootprintGasScalar (data []byte ) (uint16 , error ) {
524+ if len (data ) < JovianL1AttributesLen {
525+ return 0 , fmt .Errorf ("L1 attributes transaction data too short for DA footprint gas scalar: %d" , len (data ))
526+ }
527+ // Future forks need to be added here
528+ if ! bytes .Equal (data [0 :4 ], JovianL1AttributesSelector ) {
529+ return 0 , fmt .Errorf ("L1 attributes transaction data does not have Jovian selector" )
530+ }
531+ daFootprintGasScalar := binary .BigEndian .Uint16 (data [JovianL1AttributesLen - 2 : JovianL1AttributesLen ])
532+ return daFootprintGasScalar , nil
533+ }
534+
535+ // CalcGasUsedJovian calculates the gas used for an OP Stack chain.
536+ // Jovian introduces a DA footprint block limit, which potentially increases the gasUsed.
537+ // CalcGasUsedJovian must not be called for pre-Jovian blocks.
538+ func CalcGasUsedJovian (txs []* Transaction , evmGasUsed uint64 ) (uint64 , error ) {
539+ if len (txs ) == 0 || ! txs [0 ].IsDepositTx () {
540+ return 0 , errors .New ("missing deposit transaction" )
541+ }
542+
543+ // First Jovian block doesn't set the DA footprint gas scalar yet and
544+ // it must not have user transactions.
545+ data := txs [0 ].Data ()
546+ if len (data ) == IsthmusL1AttributesLen {
547+ if ! txs [len (txs )- 1 ].IsDepositTx () {
548+ // sufficient to check last transaction because deposits precede non-deposit txs
549+ return 0 , errors .New ("unexpected non-deposit transactions in Jovian activation block" )
550+ }
551+ return evmGasUsed , nil
552+ } // ExtractDAFootprintGasScalar catches all invalid lengths
553+
554+ daFootprintGasScalar , err := ExtractDAFootprintGasScalar (data )
555+ if err != nil {
556+ return 0 , err
557+ }
558+ var cumulativeDAFootprint uint64
559+ for _ , tx := range txs {
560+ if tx .IsDepositTx () {
561+ continue
562+ }
563+ cumulativeDAFootprint += tx .RollupCostData ().EstimatedDASize ().Uint64 ()
564+ }
565+ daFootprint := uint64 (daFootprintGasScalar ) * cumulativeDAFootprint
566+ if evmGasUsed < daFootprint {
567+ return daFootprint , nil
568+ }
569+ return evmGasUsed , nil
570+ }
571+
515572// L1Cost computes the the data availability fee for transactions in blocks prior to the Ecotone
516573// upgrade. It is used by e2e tests so must remain exported.
517574func L1Cost (rollupDataGas uint64 , l1BaseFee , overhead , scalar * big.Int ) * big.Int {
@@ -572,13 +629,13 @@ func ExtractEcotoneFeeParams(l1FeeParams []byte) (l1BaseFeeScalar, l1BlobBaseFee
572629 offset := scalarSectionStart
573630 l1BaseFeeScalar = new (big.Int ).SetBytes (l1FeeParams [offset : offset + 4 ])
574631 l1BlobBaseFeeScalar = new (big.Int ).SetBytes (l1FeeParams [offset + 4 : offset + 8 ])
575- return
632+ return l1BaseFeeScalar , l1BlobBaseFeeScalar
576633}
577634
578635func ExtractOperatorFeeParams (operatorFeeParams common.Hash ) (operatorFeeScalar , operatorFeeConstant * big.Int ) {
579636 operatorFeeScalar = new (big.Int ).SetBytes (operatorFeeParams [20 :24 ])
580637 operatorFeeConstant = new (big.Int ).SetBytes (operatorFeeParams [24 :32 ])
581- return
638+ return operatorFeeScalar , operatorFeeConstant
582639}
583640
584641func bedrockCalldataGasUsed (costData RollupCostData ) (calldataGasUsed * big.Int ) {
0 commit comments