2015-07-07 00:54:22 +00:00
// Copyright 2014 The go-ethereum Authors
2015-07-22 16:48:40 +00:00
// This file is part of the go-ethereum library.
2015-07-07 00:54:22 +00:00
//
2015-07-23 16:35:11 +00:00
// The go-ethereum library is free software: you can redistribute it and/or modify
2015-07-07 00:54:22 +00:00
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
2015-07-22 16:48:40 +00:00
// The go-ethereum library is distributed in the hope that it will be useful,
2015-07-07 00:54:22 +00:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
2015-07-22 16:48:40 +00:00
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015-07-07 00:54:22 +00:00
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
2015-07-22 16:48:40 +00:00
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
2015-07-07 00:54:22 +00:00
2014-12-04 09:28:02 +00:00
package core
2014-06-13 10:58:01 +00:00
import (
2020-05-19 10:28:20 +00:00
"fmt"
2015-03-09 17:05:56 +00:00
2020-05-26 16:53:50 +00:00
"github.com/holiman/uint256"
2023-01-13 18:12:18 +00:00
libcommon "github.com/ledgerwatch/erigon-lib/common"
2023-06-15 06:11:51 +00:00
"github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg"
2023-01-26 11:26:12 +00:00
types2 "github.com/ledgerwatch/erigon-lib/types"
2020-05-26 16:53:50 +00:00
2021-05-20 18:25:53 +00:00
cmath "github.com/ledgerwatch/erigon/common/math"
2022-10-26 11:03:47 +00:00
"github.com/ledgerwatch/erigon/common/u256"
2023-04-23 17:27:05 +00:00
"github.com/ledgerwatch/erigon/consensus/misc"
2021-05-20 18:25:53 +00:00
"github.com/ledgerwatch/erigon/core/vm"
2023-01-26 11:26:12 +00:00
"github.com/ledgerwatch/erigon/core/vm/evmtypes"
2021-10-13 01:30:09 +00:00
"github.com/ledgerwatch/erigon/crypto"
2021-05-20 18:25:53 +00:00
"github.com/ledgerwatch/erigon/params"
2014-06-13 10:58:01 +00:00
)
2021-10-13 01:30:09 +00:00
var emptyCodeHash = crypto . Keccak256Hash ( nil )
2014-06-13 11:06:27 +00:00
/ *
2015-09-02 10:55:11 +00:00
The State Transitioning Model
A state transition is a change made when a transaction is applied to the current world state
2018-07-24 10:17:12 +00:00
The state transitioning model does all the necessary work to work out a valid new state root .
2015-09-02 10:55:11 +00:00
1 ) Nonce handling
2 ) Pre pay gas
3 ) Create a new state object if the recipient is \ 0 * 32
4 ) Value transfer
== If contract creation ==
2022-08-10 12:04:13 +00:00
4 a ) Attempt to run transaction data
4 b ) If valid , use result as code for the new state object
2015-09-02 10:55:11 +00:00
== end ==
5 ) Run Script section
6 ) Derive new state root
* /
2014-06-13 10:58:01 +00:00
type StateTransition struct {
2017-01-04 19:17:24 +00:00
gp * GasPool
msg Message
gas uint64
2020-06-04 07:43:08 +00:00
gasPrice * uint256 . Int
2021-07-11 04:05:56 +00:00
gasFeeCap * uint256 . Int
2021-04-22 17:11:37 +00:00
tip * uint256 . Int
2017-11-13 11:47:27 +00:00
initialGas uint64
2020-05-26 16:53:50 +00:00
value * uint256 . Int
2017-01-04 19:17:24 +00:00
data [ ] byte
2022-11-30 01:31:13 +00:00
state evmtypes . IntraBlockState
2023-10-05 05:23:08 +00:00
evm * vm . EVM
2021-07-14 14:34:14 +00:00
//some pre-allocated intermediate variables
sharedBuyGas * uint256 . Int
sharedBuyGasBalance * uint256 . Int
2022-02-07 21:30:46 +00:00
2023-04-14 06:24:10 +00:00
isBor bool
2014-12-18 14:18:13 +00:00
}
2015-03-17 11:00:29 +00:00
// Message represents a message sent to a contract.
2014-12-18 14:18:13 +00:00
type Message interface {
2023-01-13 18:12:18 +00:00
From ( ) libcommon . Address
To ( ) * libcommon . Address
2014-12-18 14:18:13 +00:00
2020-06-04 07:43:08 +00:00
GasPrice ( ) * uint256 . Int
2021-04-22 17:11:37 +00:00
FeeCap ( ) * uint256 . Int
Tip ( ) * uint256 . Int
2017-11-13 11:47:27 +00:00
Gas ( ) uint64
2023-07-28 10:12:05 +00:00
BlobGas ( ) uint64
MaxFeePerBlobGas ( ) * uint256 . Int
2020-06-04 07:43:08 +00:00
Value ( ) * uint256 . Int
2014-12-18 14:18:13 +00:00
Nonce ( ) uint64
2016-07-11 09:58:10 +00:00
CheckNonce ( ) bool
2014-12-18 14:18:13 +00:00
Data ( ) [ ] byte
2023-01-26 11:26:12 +00:00
AccessList ( ) types2 . AccessList
2023-07-31 08:12:53 +00:00
BlobHashes ( ) [ ] libcommon . Hash
2022-10-26 11:03:47 +00:00
IsFree ( ) bool
2014-06-13 10:58:01 +00:00
}
2015-03-18 12:00:01 +00:00
2020-04-22 08:25:36 +00:00
// ExecutionResult includes all output after executing given evm
// message no matter the execution itself is successful or not.
type ExecutionResult struct {
2023-06-23 09:10:23 +00:00
UsedGas uint64 // Total used gas but include the refunded gas
Err error // Any error encountered during the execution(listed in core/vm/errors.go)
ReturnData [ ] byte // Returned data from evm(function result or data supplied with revert opcode)
2020-04-22 08:25:36 +00:00
}
// Unwrap returns the internal evm error which allows us for further
// analysis outside.
func ( result * ExecutionResult ) Unwrap ( ) error {
return result . Err
}
// Failed returns the indicator whether the execution is successful or not
func ( result * ExecutionResult ) Failed ( ) bool { return result . Err != nil }
// Return is a helper function to help caller distinguish between revert reason
// and function return. Return returns the data after execution if no error occurs.
func ( result * ExecutionResult ) Return ( ) [ ] byte {
if result . Err != nil {
return nil
}
2023-10-21 23:17:18 +00:00
return libcommon . CopyBytes ( result . ReturnData )
2020-04-22 08:25:36 +00:00
}
// Revert returns the concrete revert reason if the execution is aborted by `REVERT`
// opcode. Note the reason can be nil if no data supplied with revert opcode.
func ( result * ExecutionResult ) Revert ( ) [ ] byte {
if result . Err != vm . ErrExecutionReverted {
return nil
}
2023-10-21 23:17:18 +00:00
return libcommon . CopyBytes ( result . ReturnData )
2020-04-22 08:25:36 +00:00
}
2017-11-13 11:47:27 +00:00
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
2023-01-26 11:26:12 +00:00
func IntrinsicGas ( data [ ] byte , accessList types2 . AccessList , isContractCreation bool , isHomestead , isEIP2028 , isEIP3860 bool ) ( uint64 , error ) {
// Zero and non-zero bytes are priced differently
2022-10-31 12:40:41 +00:00
dataLen := uint64 ( len ( data ) )
2023-01-26 11:26:12 +00:00
dataNonZeroLen := uint64 ( 0 )
for _ , byt := range data {
if byt != 0 {
dataNonZeroLen ++
2022-10-31 12:40:41 +00:00
}
2015-04-08 18:47:32 +00:00
}
2021-12-07 17:24:59 +00:00
2023-06-15 06:11:51 +00:00
gas , status := txpoolcfg . CalcIntrinsicGas ( dataLen , dataNonZeroLen , accessList , isContractCreation , isHomestead , isEIP2028 , isEIP3860 )
if status != txpoolcfg . Success {
2023-01-26 11:26:12 +00:00
return 0 , ErrGasUintOverflow
2021-02-25 14:26:57 +00:00
}
2017-11-13 11:47:27 +00:00
return gas , nil
2015-04-08 18:47:32 +00:00
}
2016-03-31 22:30:21 +00:00
// NewStateTransition initialises and returns a new state transition object.
2023-10-05 05:23:08 +00:00
func NewStateTransition ( evm * vm . EVM , msg Message , gp * GasPool ) * StateTransition {
2022-02-07 21:30:46 +00:00
isBor := evm . ChainConfig ( ) . Bor != nil
2016-03-31 22:30:21 +00:00
return & StateTransition {
2021-07-11 04:05:56 +00:00
gp : gp ,
evm : evm ,
msg : msg ,
gasPrice : msg . GasPrice ( ) ,
gasFeeCap : msg . FeeCap ( ) ,
tip : msg . Tip ( ) ,
value : msg . Value ( ) ,
data : msg . Data ( ) ,
2021-12-06 14:58:53 +00:00
state : evm . IntraBlockState ( ) ,
2021-07-14 14:34:14 +00:00
sharedBuyGas : uint256 . NewInt ( 0 ) ,
sharedBuyGasBalance : uint256 . NewInt ( 0 ) ,
2022-02-07 21:30:46 +00:00
2023-04-14 06:24:10 +00:00
isBor : isBor ,
2014-12-18 14:18:13 +00:00
}
2016-03-31 22:30:21 +00:00
}
// ApplyMessage computes the new state by applying the given message
// against the old state within the environment.
//
// ApplyMessage returns the bytes returned by any EVM execution (if it took place),
// the gas used (which includes gas refunds) and an error if it failed. An error always
// indicates a core error meaning that the message would always fail for that particular
// state and would never be accepted within a block.
2021-02-12 16:47:32 +00:00
// `refunds` is false when it is not required to apply gas refunds
// `gasBailout` is true when it is not required to fail transaction if the balance is not enough to pay gas.
2023-10-22 14:23:40 +00:00
// for trace_call to replicate OE/Parity behaviour
2023-10-05 05:23:08 +00:00
func ApplyMessage ( evm * vm . EVM , msg Message , gp * GasPool , refunds bool , gasBailout bool ) ( * ExecutionResult , error ) {
2021-02-12 16:47:32 +00:00
return NewStateTransition ( evm , msg , gp ) . TransitionDb ( refunds , gasBailout )
2014-06-13 10:58:01 +00:00
}
2018-04-10 13:33:25 +00:00
// to returns the recipient of the message.
2023-01-13 18:12:18 +00:00
func ( st * StateTransition ) to ( ) libcommon . Address {
2018-04-10 13:33:25 +00:00
if st . msg == nil || st . msg . To ( ) == nil /* contract creation */ {
2023-01-13 18:12:18 +00:00
return libcommon . Address { }
2015-08-30 08:19:10 +00:00
}
2018-04-10 13:33:25 +00:00
return * st . msg . To ( )
2014-06-13 10:58:01 +00:00
}
2021-02-12 16:47:32 +00:00
func ( st * StateTransition ) buyGas ( gasBailout bool ) error {
2023-09-19 08:45:19 +00:00
gasVal := st . sharedBuyGas
gasVal . SetUint64 ( st . msg . Gas ( ) )
gasVal , overflow := gasVal . MulOverflow ( gasVal , st . gasPrice )
2021-12-06 08:00:54 +00:00
if overflow {
return fmt . Errorf ( "%w: address %v" , ErrInsufficientFunds , st . msg . From ( ) . Hex ( ) )
}
2023-05-08 05:20:10 +00:00
2023-07-28 10:12:05 +00:00
// compute blob fee for eip-4844 data blobs if any
2023-09-19 08:45:19 +00:00
blobGasVal := new ( uint256 . Int )
2023-05-08 05:20:10 +00:00
if st . evm . ChainRules ( ) . IsCancun {
2023-11-29 02:29:16 +00:00
if st . evm . Context . ExcessBlobGas == nil {
2023-07-28 10:12:05 +00:00
return fmt . Errorf ( "%w: Cancun is active but ExcessBlobGas is nil" , ErrInternalFailure )
2023-05-08 05:20:10 +00:00
}
2023-11-29 02:29:16 +00:00
blobGasPrice , err := misc . GetBlobGasPrice ( st . evm . ChainConfig ( ) , * st . evm . Context . ExcessBlobGas )
2023-05-08 05:20:10 +00:00
if err != nil {
return err
}
2023-09-19 08:45:19 +00:00
blobGasVal , overflow = blobGasVal . MulOverflow ( blobGasPrice , new ( uint256 . Int ) . SetUint64 ( st . msg . BlobGas ( ) ) )
2023-05-08 05:20:10 +00:00
if overflow {
2023-09-19 08:45:19 +00:00
return fmt . Errorf ( "%w: overflow converting blob gas: %v" , ErrInsufficientFunds , blobGasVal )
2023-05-08 05:20:10 +00:00
}
2023-07-28 10:12:05 +00:00
if err := st . gp . SubBlobGas ( st . msg . BlobGas ( ) ) ; err != nil {
2023-06-23 09:10:23 +00:00
return err
}
2023-05-08 05:20:10 +00:00
}
2023-09-19 08:45:19 +00:00
balanceCheck := gasVal
2021-07-11 04:05:56 +00:00
if st . gasFeeCap != nil {
2021-07-14 14:34:14 +00:00
balanceCheck = st . sharedBuyGasBalance . SetUint64 ( st . msg . Gas ( ) )
2021-12-06 08:00:54 +00:00
balanceCheck , overflow = balanceCheck . MulOverflow ( balanceCheck , st . gasFeeCap )
if overflow {
return fmt . Errorf ( "%w: address %v" , ErrInsufficientFunds , st . msg . From ( ) . Hex ( ) )
}
balanceCheck , overflow = balanceCheck . AddOverflow ( balanceCheck , st . value )
if overflow {
return fmt . Errorf ( "%w: address %v" , ErrInsufficientFunds , st . msg . From ( ) . Hex ( ) )
}
2023-09-19 08:45:19 +00:00
balanceCheck , overflow = balanceCheck . AddOverflow ( balanceCheck , blobGasVal )
2023-05-08 05:20:10 +00:00
if overflow {
return fmt . Errorf ( "%w: address %v" , ErrInsufficientFunds , st . msg . From ( ) . Hex ( ) )
}
2021-06-03 07:09:56 +00:00
}
2022-08-10 12:04:13 +00:00
var subBalance = false
2021-06-03 07:09:56 +00:00
if have , want := st . state . GetBalance ( st . msg . From ( ) ) , balanceCheck ; have . Cmp ( want ) < 0 {
2021-02-12 16:47:32 +00:00
if ! gasBailout {
2021-03-12 17:26:06 +00:00
return fmt . Errorf ( "%w: address %v have %v want %v" , ErrInsufficientFunds , st . msg . From ( ) . Hex ( ) , have , want )
2021-02-12 16:47:32 +00:00
}
} else {
2022-06-14 19:33:30 +00:00
subBalance = true
2014-06-13 10:58:01 +00:00
}
2017-11-13 11:47:27 +00:00
if err := st . gp . SubGas ( st . msg . Gas ( ) ) ; err != nil {
2021-06-03 07:09:56 +00:00
if ! gasBailout {
return err
}
2014-06-13 10:58:01 +00:00
}
2017-11-13 11:47:27 +00:00
st . gas += st . msg . Gas ( )
st . initialGas = st . msg . Gas ( )
2023-05-08 05:20:10 +00:00
2022-06-14 19:33:30 +00:00
if subBalance {
2023-09-19 08:45:19 +00:00
st . state . SubBalance ( st . msg . From ( ) , gasVal )
st . state . SubBalance ( st . msg . From ( ) , blobGasVal )
2022-06-14 19:33:30 +00:00
}
2014-06-13 10:58:01 +00:00
return nil
}
2023-01-13 18:12:18 +00:00
func CheckEip1559TxGasFeeCap ( from libcommon . Address , gasFeeCap , tip , baseFee * uint256 . Int , isFree bool ) error {
2022-10-26 11:03:47 +00:00
if gasFeeCap . Lt ( tip ) {
2022-05-30 12:56:07 +00:00
return fmt . Errorf ( "%w: address %v, tip: %s, gasFeeCap: %s" , ErrTipAboveFeeCap ,
2022-08-29 13:26:36 +00:00
from . Hex ( ) , tip , gasFeeCap )
2022-05-30 12:56:07 +00:00
}
2022-10-26 11:03:47 +00:00
if baseFee != nil && gasFeeCap . Lt ( baseFee ) && ! isFree {
2022-05-30 12:56:07 +00:00
return fmt . Errorf ( "%w: address %v, gasFeeCap: %s baseFee: %s" , ErrFeeCapTooLow ,
from . Hex ( ) , gasFeeCap , baseFee )
}
return nil
}
2019-05-27 13:51:49 +00:00
// DESCRIBED: docs/programmers_guide/guide.md#nonce
2021-02-12 16:47:32 +00:00
func ( st * StateTransition ) preCheck ( gasBailout bool ) error {
2018-04-10 13:33:25 +00:00
// Make sure this transaction's nonce is correct.
if st . msg . CheckNonce ( ) {
2020-12-04 11:22:19 +00:00
stNonce := st . state . GetNonce ( st . msg . From ( ) )
if msgNonce := st . msg . Nonce ( ) ; stNonce < msgNonce {
return fmt . Errorf ( "%w: address %v, tx: %d state: %d" , ErrNonceTooHigh ,
st . msg . From ( ) . Hex ( ) , msgNonce , stNonce )
} else if stNonce > msgNonce {
return fmt . Errorf ( "%w: address %v, tx: %d state: %d" , ErrNonceTooLow ,
st . msg . From ( ) . Hex ( ) , msgNonce , stNonce )
2021-12-07 17:24:59 +00:00
} else if stNonce + 1 < stNonce {
return fmt . Errorf ( "%w: address %v, nonce: %d" , ErrNonceMax ,
st . msg . From ( ) . Hex ( ) , stNonce )
2016-07-11 09:58:10 +00:00
}
2021-07-27 02:39:41 +00:00
2022-02-25 12:51:29 +00:00
// Make sure the sender is an EOA (EIP-3607)
2023-01-13 18:12:18 +00:00
if codeHash := st . state . GetCodeHash ( st . msg . From ( ) ) ; codeHash != emptyCodeHash && codeHash != ( libcommon . Hash { } ) {
// libcommon.Hash{} means that the sender is not in the state.
2022-02-25 12:51:29 +00:00
// Historically there were transactions with 0 gas price and non-existing sender,
// so we have to allow that.
return fmt . Errorf ( "%w: address %v, codehash: %s" , ErrSenderNoEOA ,
st . msg . From ( ) . Hex ( ) , codeHash )
}
2021-10-13 01:30:09 +00:00
}
2021-07-11 04:05:56 +00:00
// Make sure the transaction gasFeeCap is greater than the block's baseFee.
2021-12-06 14:58:53 +00:00
if st . evm . ChainRules ( ) . IsLondon {
2021-07-11 04:05:56 +00:00
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
2021-12-06 14:58:53 +00:00
if ! st . evm . Config ( ) . NoBaseFee || ! st . gasFeeCap . IsZero ( ) || ! st . tip . IsZero ( ) {
2023-11-29 02:29:16 +00:00
if err := CheckEip1559TxGasFeeCap ( st . msg . From ( ) , st . gasFeeCap , st . tip , st . evm . Context . BaseFee , st . msg . IsFree ( ) ) ; err != nil {
2022-05-30 12:56:07 +00:00
return err
2021-07-11 04:05:56 +00:00
}
2021-04-22 17:11:37 +00:00
}
}
2023-07-28 10:12:05 +00:00
if st . msg . BlobGas ( ) > 0 && st . evm . ChainRules ( ) . IsCancun {
2023-11-29 02:29:16 +00:00
if st . evm . Context . ExcessBlobGas == nil {
2023-07-28 10:12:05 +00:00
return fmt . Errorf ( "%w: Cancun is active but ExcessBlobGas is nil" , ErrInternalFailure )
2023-06-02 20:26:19 +00:00
}
2023-11-29 02:29:16 +00:00
blobGasPrice , err := misc . GetBlobGasPrice ( st . evm . ChainConfig ( ) , * st . evm . Context . ExcessBlobGas )
2023-05-08 05:20:10 +00:00
if err != nil {
return err
}
2023-07-28 10:12:05 +00:00
maxFeePerBlobGas := st . msg . MaxFeePerBlobGas ( )
if blobGasPrice . Cmp ( maxFeePerBlobGas ) > 0 {
return fmt . Errorf ( "%w: address %v, maxFeePerBlobGas: %v blobGasPrice: %v, excessBlobGas: %v" ,
ErrMaxFeePerBlobGas ,
2023-11-29 02:29:16 +00:00
st . msg . From ( ) . Hex ( ) , st . msg . MaxFeePerBlobGas ( ) , blobGasPrice , st . evm . Context . ExcessBlobGas )
2023-05-08 05:20:10 +00:00
}
}
2021-02-12 16:47:32 +00:00
return st . buyGas ( gasBailout )
2014-06-19 11:41:17 +00:00
}
2017-11-13 11:47:27 +00:00
// TransitionDb will transition the state by applying the current message and
2020-04-22 08:25:36 +00:00
// returning the evm execution result with following fields.
//
2022-08-10 12:04:13 +00:00
// - used gas:
// total gas used (including gas being refunded)
// - returndata:
// the returned data from evm
// - concrete execution error:
// various **EVM** error which aborts the execution,
// e.g. ErrOutOfGas, ErrExecutionReverted
2020-04-22 08:25:36 +00:00
//
// However if any consensus issue encountered, return the error directly with
// nil evm execution result.
2021-02-12 16:47:32 +00:00
func ( st * StateTransition ) TransitionDb ( refunds bool , gasBailout bool ) ( * ExecutionResult , error ) {
2023-11-29 02:29:16 +00:00
coinbase := st . evm . Context . Coinbase
2023-05-01 16:26:24 +00:00
2022-02-07 21:30:46 +00:00
var input1 * uint256 . Int
var input2 * uint256 . Int
if st . isBor {
input1 = st . state . GetBalance ( st . msg . From ( ) ) . Clone ( )
2023-05-01 16:26:24 +00:00
input2 = st . state . GetBalance ( coinbase ) . Clone ( )
2022-02-07 21:30:46 +00:00
}
2020-04-22 08:25:36 +00:00
// First check this message satisfies all consensus rules before
// applying the message. The rules include these clauses
//
// 1. the nonce of the message caller is correct
// 2. caller has enough balance to cover transaction fee(gaslimit * gasprice)
// 3. the amount of gas required is available in the block
// 4. the purchased gas is enough to cover intrinsic usage
// 5. there is no overflow when calculating intrinsic gas
// 6. caller has enough balance to cover asset transfer for **topmost** call
2021-07-26 14:09:39 +00:00
// Check clauses 1-3 and 6, buy gas if everything is correct
2021-02-12 16:47:32 +00:00
if err := st . preCheck ( gasBailout ) ; err != nil {
2020-04-22 08:25:36 +00:00
return nil , err
2014-06-19 11:41:17 +00:00
}
2022-12-18 04:36:57 +00:00
if st . evm . Config ( ) . Debug {
st . evm . Config ( ) . Tracer . CaptureTxStart ( st . initialGas )
defer func ( ) {
st . evm . Config ( ) . Tracer . CaptureTxEnd ( st . gas )
} ( )
}
2017-05-11 01:55:48 +00:00
msg := st . msg
2018-04-10 13:33:25 +00:00
sender := vm . AccountRef ( msg . From ( ) )
2017-05-08 09:09:35 +00:00
contractCreation := msg . To ( ) == nil
2022-10-14 12:00:00 +00:00
rules := st . evm . ChainRules ( )
2022-11-22 15:07:31 +00:00
vmConfig := st . evm . Config ( )
isEIP3860 := vmConfig . HasEip3860 ( rules )
2017-05-11 01:55:48 +00:00
2020-04-22 08:25:36 +00:00
// Check clauses 4-5, subtract intrinsic gas if everything is correct
2022-11-22 15:07:31 +00:00
gas , err := IntrinsicGas ( st . data , st . msg . AccessList ( ) , contractCreation , rules . IsHomestead , rules . IsIstanbul , isEIP3860 )
2018-02-14 20:02:51 +00:00
if err != nil {
2020-04-22 08:25:36 +00:00
return nil , err
2018-02-14 20:02:51 +00:00
}
2020-04-22 08:25:36 +00:00
if st . gas < gas {
2020-12-04 11:22:19 +00:00
return nil , fmt . Errorf ( "%w: have %d, want %d" , ErrIntrinsicGas , st . gas , gas )
2014-06-13 10:58:01 +00:00
}
2020-04-22 08:25:36 +00:00
st . gas -= gas
2014-06-13 10:58:01 +00:00
2021-08-03 19:58:18 +00:00
var bailout bool
// Gas bailout (for trace_call) should only be applied if there is not sufficient balance to perform value transfer
if gasBailout {
2023-11-29 02:29:16 +00:00
if ! msg . Value ( ) . IsZero ( ) && ! st . evm . Context . CanTransfer ( st . state , msg . From ( ) , msg . Value ( ) ) {
2021-08-03 19:58:18 +00:00
bailout = true
}
}
2022-10-31 12:40:41 +00:00
// Check whether the init code size has been exceeded.
2022-11-22 15:07:31 +00:00
if isEIP3860 && contractCreation && len ( st . data ) > params . MaxInitCodeSize {
2022-10-31 12:40:41 +00:00
return nil , fmt . Errorf ( "%w: code size %v limit %v" , ErrMaxInitCodeSizeExceeded , len ( st . data ) , params . MaxInitCodeSize )
}
2023-05-01 16:26:24 +00:00
// Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin)
// - reset transient storage(eip 1153)
st . state . Prepare ( rules , msg . From ( ) , coinbase , msg . To ( ) , vm . ActivePrecompiles ( rules ) , msg . AccessList ( ) )
2021-02-25 14:26:57 +00:00
2016-12-06 01:16:03 +00:00
var (
2020-04-22 08:25:36 +00:00
ret [ ] byte
vmerr error // vm errors do not effect consensus and are therefore not assigned to err
2016-12-06 01:16:03 +00:00
)
2015-11-27 14:40:29 +00:00
if contractCreation {
2020-04-14 12:49:38 +00:00
// The reason why we don't increment nonce here is that we need the original
// nonce to calculate the address of the contract that is being created
// It does get incremented inside the `Create` call, after the computation
// of the contract's address, but before the execution of the code.
2020-04-22 08:25:36 +00:00
ret , _ , st . gas , vmerr = st . evm . Create ( sender , st . data , st . gas , st . value )
2014-07-07 11:59:09 +00:00
} else {
2015-03-24 14:23:16 +00:00
// Increment the nonce for the next transaction
2018-04-10 13:33:25 +00:00
st . state . SetNonce ( msg . From ( ) , st . state . GetNonce ( sender . Address ( ) ) + 1 )
2021-08-03 19:58:18 +00:00
ret , st . gas , vmerr = st . evm . Call ( sender , st . to ( ) , st . data , st . gas , st . value , bailout )
2015-07-06 09:54:11 +00:00
}
2020-12-09 18:24:08 +00:00
if refunds {
2022-10-14 12:00:00 +00:00
if rules . IsLondon {
2021-05-14 07:57:18 +00:00
// After EIP-3529: refunds are capped to gasUsed / 5
2021-05-11 09:54:20 +00:00
st . refundGas ( params . RefundQuotientEIP3529 )
2021-05-02 09:34:19 +00:00
} else {
2021-05-14 07:57:18 +00:00
// Before EIP-3529: refunds were capped to gasUsed / 2
2021-05-11 09:54:20 +00:00
st . refundGas ( params . RefundQuotient )
2021-05-02 09:34:19 +00:00
}
2020-12-09 18:24:08 +00:00
}
2021-05-11 09:54:20 +00:00
effectiveTip := st . gasPrice
2022-10-14 12:00:00 +00:00
if rules . IsLondon {
2023-11-29 02:29:16 +00:00
if st . gasFeeCap . Gt ( st . evm . Context . BaseFee ) {
effectiveTip = cmath . Min256 ( st . tip , new ( uint256 . Int ) . Sub ( st . gasFeeCap , st . evm . Context . BaseFee ) )
2022-10-26 11:03:47 +00:00
} else {
effectiveTip = u256 . Num0
}
2021-04-22 17:11:37 +00:00
}
2022-02-21 12:42:23 +00:00
amount := new ( uint256 . Int ) . SetUint64 ( st . gasUsed ( ) )
amount . Mul ( amount , effectiveTip ) // gasUsed * effectiveTip = how much goes to the block producer (miner, validator)
2023-05-01 16:26:24 +00:00
st . state . AddBalance ( coinbase , amount )
2023-10-22 14:23:40 +00:00
if ! msg . IsFree ( ) && rules . IsLondon {
2023-11-29 02:29:16 +00:00
burntContractAddress := st . evm . ChainConfig ( ) . GetBurntContract ( st . evm . Context . BlockNumber )
2023-10-22 14:23:40 +00:00
if burntContractAddress != nil {
2023-11-29 02:29:16 +00:00
burnAmount := new ( uint256 . Int ) . Mul ( new ( uint256 . Int ) . SetUint64 ( st . gasUsed ( ) ) , st . evm . Context . BaseFee )
2023-10-22 14:23:40 +00:00
st . state . AddBalance ( * burntContractAddress , burnAmount )
2023-10-20 19:46:19 +00:00
}
2022-10-21 11:03:38 +00:00
}
2022-02-24 00:03:10 +00:00
if st . isBor {
2022-02-21 12:42:23 +00:00
// Deprecating transfer log and will be removed in future fork. PLEASE DO NOT USE this transfer log going forward. Parameters won't get updated as expected going forward with EIP1559
// add transfer log
2022-02-07 21:30:46 +00:00
output1 := input1 . Clone ( )
output2 := input2 . Clone ( )
AddFeeTransferLog (
st . state ,
msg . From ( ) ,
2023-05-01 16:26:24 +00:00
coinbase ,
2022-02-07 21:30:46 +00:00
amount ,
input1 ,
input2 ,
output1 . Sub ( output1 , amount ) ,
output2 . Add ( output2 , amount ) ,
)
}
2020-04-22 08:25:36 +00:00
return & ExecutionResult {
2023-06-23 09:10:23 +00:00
UsedGas : st . gasUsed ( ) ,
Err : vmerr ,
ReturnData : ret ,
2020-04-22 08:25:36 +00:00
} , nil
2014-07-24 10:04:15 +00:00
}
2014-12-18 20:58:26 +00:00
2021-05-02 09:34:19 +00:00
func ( st * StateTransition ) refundGas ( refundQuotient uint64 ) {
2015-09-02 10:55:11 +00:00
// Apply refund counter, capped to half of the used gas.
2021-05-02 09:34:19 +00:00
refund := st . gasUsed ( ) / refundQuotient
2017-11-13 11:47:27 +00:00
if refund > st . state . GetRefund ( ) {
refund = st . state . GetRefund ( )
}
st . gas += refund
2017-01-04 19:17:24 +00:00
2017-11-13 11:47:27 +00:00
// Return ETH for remaining gas, exchanged at the original rate.
2021-05-25 22:26:25 +00:00
remaining := new ( uint256 . Int ) . Mul ( new ( uint256 . Int ) . SetUint64 ( st . gas ) , st . gasPrice )
2020-06-04 07:43:08 +00:00
st . state . AddBalance ( st . msg . From ( ) , remaining )
2014-12-18 20:58:26 +00:00
2015-09-02 10:55:11 +00:00
// Also return remaining gas to the block gas counter so it is
// available for the next transaction.
2017-11-13 11:47:27 +00:00
st . gp . AddGas ( st . gas )
2014-12-18 20:58:26 +00:00
}
2017-11-13 11:47:27 +00:00
// gasUsed returns the amount of gas used up by the state transition.
func ( st * StateTransition ) gasUsed ( ) uint64 {
return st . initialGas - st . gas
2014-12-18 20:58:26 +00:00
}