From f5b4e4dc942134bcf26a174e79bdfa418444828d Mon Sep 17 00:00:00 2001 From: i-norden Date: Wed, 1 Nov 2023 14:56:14 -0500 Subject: [PATCH] ToMessage method for transaction_arguments --- pkg/eth/transaction_arguments.go | 88 ++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/pkg/eth/transaction_arguments.go b/pkg/eth/transaction_arguments.go index f837c500..3b974215 100644 --- a/pkg/eth/transaction_arguments.go +++ b/pkg/eth/transaction_arguments.go @@ -1,9 +1,15 @@ package eth import ( + "errors" + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" + "github.com/sirupsen/logrus" ) // TransactionArgs represents the arguments to construct a new transaction @@ -47,3 +53,85 @@ func (args *TransactionArgs) data() []byte { } return nil } + +// ToMessage converts the transaction arguments to the Message type used by the +// core evm. This method is used in calls and traces that do not require a real +// live transaction. +func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*core.Message, error) { + // Reject invalid combinations of pre- and post-1559 fee styles + if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { + return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") + } + // Set sender address or use zero address if none specified. + addr := args.from() + + // Set default gas & gas price if none were set + gas := globalGasCap + if gas == 0 { + gas = uint64(math.MaxUint64 / 2) + } + if args.Gas != nil { + gas = uint64(*args.Gas) + } + if globalGasCap != 0 && globalGasCap < gas { + logrus.Warn("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap) + gas = globalGasCap + } + var ( + gasPrice *big.Int + gasFeeCap *big.Int + gasTipCap *big.Int + ) + if baseFee == nil { + // If there's no basefee, then it must be a non-1559 execution + gasPrice = new(big.Int) + if args.GasPrice != nil { + gasPrice = args.GasPrice.ToInt() + } + gasFeeCap, gasTipCap = gasPrice, gasPrice + } else { + // A basefee is provided, necessitating 1559-type execution + if args.GasPrice != nil { + // User specified the legacy gas field, convert to 1559 gas typing + gasPrice = args.GasPrice.ToInt() + gasFeeCap, gasTipCap = gasPrice, gasPrice + } else { + // User specified 1559 gas fields (or none), use those + gasFeeCap = new(big.Int) + if args.MaxFeePerGas != nil { + gasFeeCap = args.MaxFeePerGas.ToInt() + } + gasTipCap = new(big.Int) + if args.MaxPriorityFeePerGas != nil { + gasTipCap = args.MaxPriorityFeePerGas.ToInt() + } + // Backfill the legacy gasPrice for EVM execution, unless we're all zeroes + gasPrice = new(big.Int) + if gasFeeCap.BitLen() > 0 || gasTipCap.BitLen() > 0 { + gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap) + } + } + } + value := new(big.Int) + if args.Value != nil { + value = args.Value.ToInt() + } + data := args.data() + var accessList types.AccessList + if args.AccessList != nil { + accessList = *args.AccessList + } + msg := &core.Message{ + From: addr, + To: args.To, + Value: value, + GasLimit: gas, + GasPrice: gasPrice, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + Data: data, + AccessList: accessList, + SkipAccountChecks: true, + } + return msg, nil +}