-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add gas consumption for L1 data fees as well to fulfill the OP Stack Spec and compensate the sequencer for posting data on L1. To do this, a new decorator to the default AnteHandler to calculate the L1 data fee is added.
- Loading branch information
1 parent
7055b06
commit a6b24b1
Showing
6 changed files
with
172 additions
and
8 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package helpers | ||
|
||
import ( | ||
errorsmod "cosmossdk.io/errors" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||
) | ||
|
||
// NewL1DataAnteHandler has a single decorator (NewConsumeGasForL1DataDecorator) | ||
// to consume gas to compensate the sequencer for posting the transaction to Ethereum. | ||
func NewL1DataAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) { //nolint:gocritic // hugeparam | ||
if options.RollupKeeper == nil { | ||
return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "rollup keeper is required for ante builder") | ||
} | ||
|
||
anteDecorators := []sdk.AnteDecorator{ | ||
NewConsumeGasForL1DataDecorator(options.RollupKeeper), | ||
} | ||
|
||
return sdk.ChainAnteDecorators(anteDecorators...), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package helpers | ||
|
||
import ( | ||
"fmt" | ||
"math/big" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/ethereum/go-ethereum/rlp" | ||
rollupkeeper "github.com/polymerdao/monomer/x/rollup/keeper" | ||
) | ||
|
||
// ConsumeGasForL1DataDecorator will consume gas to compensate the sequencer | ||
// for posting the transaction to Ethereum. The gas cost is calculated based | ||
// on the Ecotone upgrade and the sequencer is expected to post the transaction | ||
// using blobs. | ||
type ConsumeGasForL1DataDecorator struct { | ||
rollupKeeper *rollupkeeper.Keeper | ||
} | ||
|
||
func NewConsumeGasForL1DataDecorator(rollupKeeper *rollupkeeper.Keeper) ConsumeGasForL1DataDecorator { | ||
return ConsumeGasForL1DataDecorator{ | ||
rollupKeeper: rollupKeeper, | ||
} | ||
} | ||
|
||
func (d ConsumeGasForL1DataDecorator) AnteHandle( | ||
ctx sdk.Context, //nolint:gocritic // hugeparam | ||
tx sdk.Tx, | ||
simulate bool, | ||
next sdk.AnteHandler, | ||
) (sdk.Context, error) { | ||
l1BlockInfo, err := d.rollupKeeper.GetL1BlockInfo(ctx) | ||
if err != nil { | ||
return ctx, fmt.Errorf("get l1 block info: %w", err) | ||
} | ||
|
||
baseFee := new(big.Int).SetBytes(l1BlockInfo.BaseFee) | ||
baseFeeScalar := big.NewInt(int64(l1BlockInfo.BaseFeeScalar)) | ||
blobBaseFee := new(big.Int).SetBytes(l1BlockInfo.BlobBaseFee) | ||
blobBaseFeeScalar := big.NewInt(int64(l1BlockInfo.BlobBaseFeeScalar)) | ||
|
||
l1GasUsed, err := getL1GasUsed(tx) | ||
if err != nil { | ||
return ctx, fmt.Errorf("get l1 gas used: %w", err) | ||
} | ||
|
||
const baseFeeMultiplier = 16 | ||
const divisor = 16e6 | ||
|
||
// scaledBaseFee calculation: scaledBaseFee = l1BaseFee * lBaseFeeScalar * 16 | ||
scaledBaseFee := new(big.Int).Mul(new(big.Int).Mul(baseFee, baseFeeScalar), big.NewInt(baseFeeMultiplier)) | ||
|
||
// scaledBlobBaseFee calculation: scaledBlobBaseFee = l1BlobBaseFee * l1BlobBaseFeeScalar | ||
scaledBlobBaseFee := new(big.Int).Mul(blobBaseFee, blobBaseFeeScalar) | ||
|
||
// l1DataCost calculation: l1DataCost = [l1GasUsed * (scaledBaseFee + scaledBlobBaseFee)] / 16e6 | ||
l1DataCost := new(big.Int).Div(new(big.Int).Mul(l1GasUsed, new(big.Int).Add(scaledBaseFee, scaledBlobBaseFee)), big.NewInt(divisor)) | ||
|
||
if !l1DataCost.IsUint64() { | ||
return ctx, fmt.Errorf("l1 data cost overflow: %s", l1DataCost) | ||
} | ||
|
||
ctx.GasMeter().ConsumeGas(l1DataCost.Uint64(), "l1 data") | ||
|
||
return next(ctx, tx, simulate) | ||
} | ||
|
||
// getL1GasUsed calculates the compressed size of a transaction when encoded with RLP. This is used to estimate | ||
// the gas cost of a transaction being posted to the L1 chain by the sequencer. | ||
func getL1GasUsed(tx sdk.Tx) (*big.Int, error) { | ||
txBz, err := rlp.EncodeToBytes(tx) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to rlp encode tx: %w", err) | ||
} | ||
|
||
const zeroCost = 4 | ||
const oneCost = 16 | ||
const signatureCost = 68 * 16 | ||
|
||
// l1GasUsed calculation: l1GasUsed = (zeroes * 4 + ones * 16) + signatureCost | ||
l1GasUsed := big.NewInt(signatureCost) | ||
for _, b := range txBz { | ||
if b == 0 { | ||
l1GasUsed.Add(l1GasUsed, big.NewInt(zeroCost)) | ||
} else { | ||
l1GasUsed.Add(l1GasUsed, big.NewInt(oneCost)) | ||
} | ||
} | ||
|
||
return l1GasUsed, nil | ||
} |