Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,12 @@ type Message struct {
// This field will be set to true for operations like RPC eth_call.
SkipNonceChecks bool

// When SkipFromEOACheck is true, the message sender is not checked to be an EOA.
SkipFromEOACheck bool
// When set, the message is not treated as a transaction, and certain
// transaction-specific checks are skipped:
//
// - From is not verified to be an EOA
// - GasLimit is not checked against the protocol defined tx gaslimit
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor wording in the new comment: "tx gaslimit" reads like a typo; consider using "tx gas limit" for clarity.

Suggested change
// - GasLimit is not checked against the protocol defined tx gaslimit
// - GasLimit is not checked against the protocol defined tx gas limit

Copilot uses AI. Check for mistakes.
SkipTransactionChecks bool
}

// TransactionToMessage converts a transaction into a Message.
Expand All @@ -167,7 +171,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, balanceFee, blo
AccessList: tx.AccessList(),
SetCodeAuthorizations: tx.SetCodeAuthorizations(),
SkipNonceChecks: false,
SkipFromEOACheck: false,
SkipTransactionChecks: false,
BalanceTokenFee: balanceFee,
}

Expand Down Expand Up @@ -317,7 +321,12 @@ func (st *StateTransition) preCheck() error {
msg.From.Hex(), stNonce)
}
}
if !msg.SkipFromEOACheck {
isOsaka := st.evm.ChainConfig().IsOsaka(st.evm.Context.BlockNumber)
if !msg.SkipTransactionChecks {
// Verify tx gas limit does not exceed EIP-7825 cap.
if isOsaka && msg.GasLimit > params.MaxTxGas {
return fmt.Errorf("%w (cap: %d, tx: %d)", ErrGasLimitTooHigh, params.MaxTxGas, msg.GasLimit)
}
// Make sure the sender is an EOA
code := st.state.GetCode(msg.From)
_, delegated := types.ParseDelegation(code)
Expand Down Expand Up @@ -359,10 +368,6 @@ func (st *StateTransition) preCheck() error {
return fmt.Errorf("%w (sender %v)", ErrEmptyAuthList, msg.From)
}
}
// Verify tx gas limit does not exceed EIP-7825 cap.
if st.evm.ChainConfig().IsOsaka(st.evm.Context.BlockNumber) && msg.GasLimit > params.MaxTxGas {
return fmt.Errorf("%w (cap: %d, tx: %d)", ErrGasLimitTooHigh, params.MaxTxGas, msg.GasLimit)
}
return st.buyGas()
}

Expand Down
22 changes: 11 additions & 11 deletions core/token_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,17 @@ func CallContractWithState(call ethereum.CallMsg, chain consensus.ChainContext,

// Execute the call.
msg := &Message{
From: call.From,
To: call.To,
Value: call.Value,
GasLimit: call.Gas,
GasPrice: call.GasPrice,
GasFeeCap: call.GasFeeCap,
GasTipCap: call.GasTipCap,
Data: call.Data,
AccessList: call.AccessList,
SkipNonceChecks: true,
SkipFromEOACheck: true,
From: call.From,
To: call.To,
Value: call.Value,
GasLimit: call.Gas,
GasPrice: call.GasPrice,
GasFeeCap: call.GasFeeCap,
GasTipCap: call.GasTipCap,
Data: call.Data,
AccessList: call.AccessList,
SkipNonceChecks: true,
SkipTransactionChecks: true,
}
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
if msg.To != nil {
Expand Down
2 changes: 1 addition & 1 deletion eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
return nil, err
}
var (
msg = args.ToMessage(api.backend, vmctx.BaseFee, true, true)
msg = args.ToMessage(api.backend, vmctx.BaseFee, true)
tx = args.ToTransaction(types.LegacyTxType)
traceConfig *TraceConfig
)
Expand Down
22 changes: 11 additions & 11 deletions ethclient/simulated/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -969,17 +969,17 @@ func (b *Backend) callContract(ctx context.Context, call ethereum.CallMsg, block

// Execute the call.
msg := &core.Message{
From: call.From,
To: call.To,
Value: call.Value,
GasLimit: call.Gas,
GasPrice: call.GasPrice,
GasFeeCap: call.GasFeeCap,
GasTipCap: call.GasTipCap,
Data: call.Data,
AccessList: call.AccessList,
SkipNonceChecks: true,
SkipFromEOACheck: true,
From: call.From,
To: call.To,
Value: call.Value,
GasLimit: call.Gas,
GasPrice: call.GasPrice,
GasFeeCap: call.GasFeeCap,
GasTipCap: call.GasTipCap,
Data: call.Data,
AccessList: call.AccessList,
SkipNonceChecks: true,
SkipTransactionChecks: true,
}
feeCapacity := stateDB.GetTRC21FeeCapacityFromState()
if msg.To != nil {
Expand Down
10 changes: 5 additions & 5 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1129,10 +1129,10 @@ func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.S
// Make sure the context is cancelled when the call has completed
// this makes sure resources are cleaned up.
defer cancel()
return applyMessage(ctx, b, args, state, block, timeout, new(core.GasPool).AddGas(globalGasCap), &blockCtx, &vm.Config{NoBaseFee: true}, precompiles, true)
return applyMessage(ctx, b, args, state, block, timeout, new(core.GasPool).AddGas(globalGasCap), &blockCtx, &vm.Config{NoBaseFee: true}, precompiles)
}

func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, block *types.Block, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext, vmConfig *vm.Config, precompiles vm.PrecompiledContracts, skipChecks bool) (*core.ExecutionResult, error) {
func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, block *types.Block, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext, vmConfig *vm.Config, precompiles vm.PrecompiledContracts) (*core.ExecutionResult, error) {
header := block.Header()
author, err := b.Engine().Author(header)
if err != nil {
Expand All @@ -1147,7 +1147,7 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s
if err := args.CallDefaults(gp.Gas(), blockContext.BaseFee, b.ChainConfig().ChainID); err != nil {
return nil, err
}
msg := args.ToMessage(b, header.BaseFee, skipChecks, skipChecks)
msg := args.ToMessage(b, header.BaseFee, true)
msg.BalanceTokenFee = new(big.Int).SetUint64(msg.GasLimit)
msg.BalanceTokenFee.Mul(msg.BalanceTokenFee, msg.GasPrice)
// Lower the basefee to 0 to avoid breaking EVM
Expand Down Expand Up @@ -1287,7 +1287,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
if err := args.CallDefaults(gasCap, estimationHeader.BaseFee, b.ChainConfig().ChainID); err != nil {
return 0, err
}
call := args.ToMessage(b, estimationHeader.BaseFee, true, true)
call := args.ToMessage(b, estimationHeader.BaseFee, true)

// Run the gas estimation andwrap any revertals into a custom return
estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
Expand Down Expand Up @@ -1763,7 +1763,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
statedb := db.Copy()
// Set the accesslist to the last al
args.AccessList = &accessList
msg := args.ToMessage(b, header.BaseFee, true, true)
msg := args.ToMessage(b, header.BaseFee, true)

feeCapacity := statedb.GetTRC21FeeCapacityFromState()
var balanceTokenFee *big.Int
Expand Down
2 changes: 1 addition & 1 deletion internal/ethapi/simulate.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
txes[i] = tx
tracer.reset(tx.Hash(), uint(i))
// EoA check is always skipped, even in validation mode.
msg := call.ToMessage(sim.b, header.BaseFee, !sim.validate, true)
msg := call.ToMessage(sim.b, header.BaseFee, !sim.validate)
evm.SetTxContext(core.NewEVMTxContext(msg))
result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions internal/ethapi/transaction_args.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int,
// 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(b AccountBackend, baseFee *big.Int, skipNonceCheck, skipEoACheck bool) *core.Message {
func (args *TransactionArgs) ToMessage(b AccountBackend, baseFee *big.Int, skipNonceCheck bool) *core.Message {
var (
gasPrice *big.Int
gasFeeCap *big.Int
Expand Down Expand Up @@ -347,7 +347,7 @@ func (args *TransactionArgs) ToMessage(b AccountBackend, baseFee *big.Int, skipN
AccessList: accessList,
SetCodeAuthorizations: args.AuthorizationList,
SkipNonceChecks: skipNonceCheck,
SkipFromEOACheck: skipEoACheck,
SkipTransactionChecks: true,
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/state_test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Mess
AccessList: accessList,
SetCodeAuthorizations: authList,
SkipNonceChecks: false,
SkipFromEOACheck: false,
SkipTransactionChecks: false,
}
return msg, nil
}
Expand Down
Loading