Skip to content

Commit

Permalink
Re-instate correct eip1559 gas price calcualtions (#197)
Browse files Browse the repository at this point in the history
* Re-instate correct eip1559 gas price calcualtions

In this commit dfd1d38

Ponti mistakenly removed gas price calculation for eip1559 style
transactions retreived via the RPC. This resulted in gasFeeCap being
returned for all transactions except depost transactions.

So this commit fixes that but also adds support for calculating gas
price for our migrated transactions as well.

Prior to the gingerbread hardfork celo stored the base fee in state as
opposed to on the block, this PR does not add code to be able to
retrieve the base fee from state, so for all pre-gingerbread eip1559
style transactions we have no way to calculate the gas price and
therefore will return null.

Post gingerbread celo added the base fee to the block, this enables us
to calculate the correct gas price for transactions using the native
currency. For transactions using alternative fee currencies we still
cannot calculate the correct gas price since we would need to look up
the base fee and exchange rate from the state and we havend added code
to do this.

Post cel2 for celo eip1559 style transactions the baseFee in fee
currency is stored on the receipt which means that we can calcualte the
correct base fee for all transactions.

Co-authored-by: Paul Lange <[email protected]>
  • Loading branch information
2 people authored and karlb committed Aug 20, 2024
1 parent 0664e39 commit 6d6172f
Show file tree
Hide file tree
Showing 4 changed files with 490 additions and 105 deletions.
16 changes: 11 additions & 5 deletions core/types/receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,11 +610,17 @@ func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, nu
rs[i].Type = txs[i].Type()
rs[i].TxHash = txs[i].Hash()

// The post transition CeloDynamicFeeV2Txs set the baseFee in the receipt
if rs[i].BaseFee == nil {
rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), baseFee)
} else {
rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), rs[i].BaseFee)
// Pre-gingerbred the base fee was stored in state, but we don't try to recover it here, since A) we don't have
// access to the objects required to get the state and B) retrieving the base fee is quite code heavy and we
// don't want to bring that code across from the celo L1 to op-geth. In the celo L1 we would return a nil base
// fee if the state was not available, so that is what we do here.
if config.IsGingerbread(new(big.Int).SetUint64(number)) {
// The post transition CeloDynamicFeeV2Txs set the baseFee in the receipt
if rs[i].BaseFee == nil {
rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), baseFee)
} else {
rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), rs[i].BaseFee)
}
}

// EIP-4844 blob transaction fields
Expand Down
39 changes: 30 additions & 9 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1589,21 +1589,42 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
result.ChainID = (*hexutil.Big)(tx.ChainId())
result.YParity = &yparity

case types.DynamicFeeTxType, types.CeloDynamicFeeTxV2Type, types.CeloDenominatedTxType:
case types.DynamicFeeTxType, types.CeloDynamicFeeTxType, types.CeloDynamicFeeTxV2Type, types.CeloDenominatedTxType:
al := tx.AccessList()
yparity := hexutil.Uint64(v.Sign())
result.Accesses = &al
result.ChainID = (*hexutil.Big)(tx.ChainId())
result.YParity = &yparity
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
// if the transaction has been mined, compute the effective gas price
if receipt != nil {

// Note that celo denominated txs always have the gas price denominated in celo (the native currency)
isNativeFeeCurrency := tx.FeeCurrency() == nil || tx.Type() == types.CeloDenominatedTxType
isGingerbread := config.IsGingerbread(new(big.Int).SetUint64(blockNumber))
isCel2 := config.IsCel2(blockTime)

if blockHash == (common.Hash{}) {
// This is a pending transaction, for pending transactions we set the gas price to gas fee cap.
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
} else if isGingerbread && isNativeFeeCurrency {
// Post gingerbread mined transaction with a native fee currency, we can compute the effective gas price.
result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee))
} else if isCel2 && tx.Type() == types.CeloDynamicFeeTxV2Type {
// Mined post Cel2 celoDynamicFeeTxV2 transaction, we can get the gas price from the receipt
// Assert that we should have a receipt
if receipt == nil {
panic(fmt.Sprintf("no corresponding receipt provided for celoDynamicFeeTxV2 transaction %s", tx.Hash().Hex()))
}
result.GasPrice = (*hexutil.Big)(receipt.EffectiveGasPrice)
} else {
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
// Otherwise this is either a:
// - pre-gingerbread transaction
// - post-gingerbread native fee currency transaction but no base fee was provided
// - post-gingerbread pre-cel2 transaction with a non-native fee currency
//
// In these cases we can't calculate the gas price.
result.GasPrice = nil
}

case types.BlobTxType:
al := tx.AccessList()
yparity := hexutil.Uint64(v.Sign())
Expand Down Expand Up @@ -1658,12 +1679,12 @@ func newRPCTransactionFromBlockIndex(ctx context.Context, b *types.Block, index
return nil
}
tx := txs[index]
rcpt := depositTxReceipt(ctx, b.Hash(), index, backend, tx)
rcpt := txReceipt(ctx, b.Hash(), index, backend, tx)
return newRPCTransaction(tx, b.Hash(), b.NumberU64(), b.Time(), index, b.BaseFee(), config, rcpt)
}

func depositTxReceipt(ctx context.Context, blockHash common.Hash, index uint64, backend Backend, tx *types.Transaction) *types.Receipt {
if tx.Type() != types.DepositTxType {
func txReceipt(ctx context.Context, blockHash common.Hash, index uint64, backend Backend, tx *types.Transaction) *types.Receipt {
if tx.Type() != types.DepositTxType && tx.Type() != types.CeloDynamicFeeTxV2Type {
return nil
}
receipts, err := backend.GetReceipts(ctx, blockHash)
Expand Down Expand Up @@ -1917,7 +1938,7 @@ func (api *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common
if err != nil {
return nil, err
}
rcpt := depositTxReceipt(ctx, blockHash, index, api.b, tx)
rcpt := txReceipt(ctx, blockHash, index, api.b, tx)
return newRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, api.b.ChainConfig(), rcpt), nil
}

Expand Down
Loading

0 comments on commit 6d6172f

Please sign in to comment.