| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2014 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02: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 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02: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 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-04 10:28:02 +01:00
										 |  |  | package core | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-12-04 12:22:19 +01:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	"math" | 
					
						
							| 
									
										
										
										
											2014-07-30 00:31:15 +02:00
										 |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2015-03-09 18:05:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2021-02-25 07:26:57 -07:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							| 
									
										
										
										
											2015-03-23 16:59:09 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/vm" | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-13 13:06:27 +02:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02: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 18:17:12 +08:00
										 |  |  | The state transitioning model does all the necessary work to work out a valid new state root. | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02: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 == | 
					
						
							|  |  |  |   4a) Attempt to run transaction data | 
					
						
							|  |  |  |   4b) If valid, use result as code for the new state object | 
					
						
							|  |  |  | == end == | 
					
						
							|  |  |  | 5) Run Script section | 
					
						
							|  |  |  | 6) Derive new state root | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | type StateTransition struct { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	gp         *GasPool | 
					
						
							|  |  |  | 	msg        Message | 
					
						
							|  |  |  | 	gas        uint64 | 
					
						
							|  |  |  | 	gasPrice   *big.Int | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	initialGas uint64 | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	value      *big.Int | 
					
						
							|  |  |  | 	data       []byte | 
					
						
							|  |  |  | 	state      vm.StateDB | 
					
						
							| 
									
										
										
										
											2017-08-21 08:47:15 +08:00
										 |  |  | 	evm        *vm.EVM | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-17 12:00:29 +01:00
										 |  |  | // Message represents a message sent to a contract. | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | type Message interface { | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	From() common.Address | 
					
						
							| 
									
										
										
										
											2015-03-17 12:00:29 +01:00
										 |  |  | 	To() *common.Address | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	GasPrice() *big.Int | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	Gas() uint64 | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 	Value() *big.Int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Nonce() uint64 | 
					
						
							| 
									
										
										
										
											2016-07-11 11:58:10 +02:00
										 |  |  | 	CheckNonce() bool | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 	Data() []byte | 
					
						
							| 
									
										
										
										
											2021-02-25 07:26:57 -07:00
										 |  |  | 	AccessList() types.AccessList | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-18 13:00:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | // ExecutionResult includes all output after executing given evm | 
					
						
							|  |  |  | // message no matter the execution itself is successful or not. | 
					
						
							|  |  |  | type ExecutionResult struct { | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return common.CopyBytes(result.ReturnData) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return common.CopyBytes(result.ReturnData) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | // IntrinsicGas computes the 'intrinsic gas' for a message with the given data. | 
					
						
							| 
									
										
										
										
											2021-02-25 07:26:57 -07:00
										 |  |  | func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation bool, isHomestead, isEIP2028 bool) (uint64, error) { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	// Set the starting gas for the raw transaction | 
					
						
							|  |  |  | 	var gas uint64 | 
					
						
							| 
									
										
										
										
											2021-02-25 07:26:57 -07:00
										 |  |  | 	if isContractCreation && isHomestead { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		gas = params.TxGasContractCreation | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		gas = params.TxGas | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	// Bump the required gas by the amount of transactional data | 
					
						
							| 
									
										
										
										
											2015-06-25 14:46:44 +02:00
										 |  |  | 	if len(data) > 0 { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		// Zero and non-zero bytes are priced differently | 
					
						
							|  |  |  | 		var nz uint64 | 
					
						
							| 
									
										
										
										
											2015-06-25 14:46:44 +02:00
										 |  |  | 		for _, byt := range data { | 
					
						
							|  |  |  | 			if byt != 0 { | 
					
						
							|  |  |  | 				nz++ | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		// Make sure we don't exceed uint64 for all data combinations | 
					
						
							| 
									
										
										
										
											2019-08-14 20:53:21 +08:00
										 |  |  | 		nonZeroGas := params.TxDataNonZeroGasFrontier | 
					
						
							|  |  |  | 		if isEIP2028 { | 
					
						
							|  |  |  | 			nonZeroGas = params.TxDataNonZeroGasEIP2028 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (math.MaxUint64-gas)/nonZeroGas < nz { | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 			return 0, ErrGasUintOverflow | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-14 20:53:21 +08:00
										 |  |  | 		gas += nz * nonZeroGas | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		z := uint64(len(data)) - nz | 
					
						
							|  |  |  | 		if (math.MaxUint64-gas)/params.TxDataZeroGas < z { | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 			return 0, ErrGasUintOverflow | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		gas += z * params.TxDataZeroGas | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-25 07:26:57 -07:00
										 |  |  | 	if accessList != nil { | 
					
						
							|  |  |  | 		gas += uint64(len(accessList)) * params.TxAccessListAddressGas | 
					
						
							|  |  |  | 		gas += uint64(accessList.StorageKeys()) * params.TxAccessListStorageKeyGas | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	return gas, nil | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02:00
										 |  |  | // NewStateTransition initialises and returns a new state transition object. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition { | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02:00
										 |  |  | 	return &StateTransition{ | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		gp:       gp, | 
					
						
							|  |  |  | 		evm:      evm, | 
					
						
							|  |  |  | 		msg:      msg, | 
					
						
							|  |  |  | 		gasPrice: msg.GasPrice(), | 
					
						
							|  |  |  | 		value:    msg.Value(), | 
					
						
							|  |  |  | 		data:     msg.Data(), | 
					
						
							|  |  |  | 		state:    evm.StateDB, | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02: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. | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) (*ExecutionResult, error) { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	return NewStateTransition(evm, msg, gp).TransitionDb() | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | // to returns the recipient of the message. | 
					
						
							|  |  |  | func (st *StateTransition) to() common.Address { | 
					
						
							|  |  |  | 	if st.msg == nil || st.msg.To() == nil /* contract creation */ { | 
					
						
							|  |  |  | 		return common.Address{} | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	return *st.msg.To() | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | func (st *StateTransition) buyGas() error { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	mgval := new(big.Int).Mul(new(big.Int).SetUint64(st.msg.Gas()), st.gasPrice) | 
					
						
							| 
									
										
										
										
											2020-12-04 12:22:19 +01:00
										 |  |  | 	if have, want := st.state.GetBalance(st.msg.From()), mgval; have.Cmp(want) < 0 { | 
					
						
							|  |  |  | 		return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From().Hex(), have, want) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	if err := st.gp.SubGas(st.msg.Gas()); err != nil { | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	st.gas += st.msg.Gas() | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	st.initialGas = st.msg.Gas() | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	st.state.SubBalance(st.msg.From(), mgval) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | func (st *StateTransition) preCheck() error { | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	// Make sure this transaction's nonce is correct. | 
					
						
							|  |  |  | 	if st.msg.CheckNonce() { | 
					
						
							| 
									
										
										
										
											2020-12-04 12:22:19 +01: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) | 
					
						
							| 
									
										
										
										
											2016-07-11 11:58:10 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 	return st.buyGas() | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | // TransitionDb will transition the state by applying the current message and | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | // returning the evm execution result with following fields. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // - 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 | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // However if any consensus issue encountered, return the error directly with | 
					
						
							|  |  |  | // nil evm execution result. | 
					
						
							|  |  |  | func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { | 
					
						
							|  |  |  | 	// 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check clauses 1-3, buy gas if everything is correct | 
					
						
							|  |  |  | 	if err := st.preCheck(); err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 	msg := st.msg | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	sender := vm.AccountRef(msg.From()) | 
					
						
							| 
									
										
										
										
											2020-11-13 13:42:19 +01:00
										 |  |  | 	homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber) | 
					
						
							|  |  |  | 	istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber) | 
					
						
							| 
									
										
										
										
											2017-05-08 12:09:35 +03:00
										 |  |  | 	contractCreation := msg.To() == nil | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 	// Check clauses 4-5, subtract intrinsic gas if everything is correct | 
					
						
							| 
									
										
										
										
											2021-02-25 07:26:57 -07:00
										 |  |  | 	gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation, homestead, istanbul) | 
					
						
							| 
									
										
										
										
											2018-02-14 21:02:51 +01:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2018-02-14 21:02:51 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 	if st.gas < gas { | 
					
						
							| 
									
										
										
										
											2020-12-04 12:22:19 +01:00
										 |  |  | 		return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gas, gas) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 	st.gas -= gas | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 	// Check clause 6 | 
					
						
							| 
									
										
										
										
											2020-11-13 13:42:19 +01:00
										 |  |  | 	if msg.Value().Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) { | 
					
						
							| 
									
										
										
										
											2020-12-04 12:22:19 +01:00
										 |  |  | 		return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From().Hex()) | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-25 07:26:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Set up the initial access list. | 
					
						
							| 
									
										
										
										
											2021-02-25 09:10:30 +02:00
										 |  |  | 	if st.evm.ChainConfig().IsBerlin(st.evm.Context.BlockNumber) { | 
					
						
							| 
									
										
										
										
											2021-02-25 07:26:57 -07:00
										 |  |  | 		st.state.PrepareAccessList(msg.From(), msg.To(), st.evm.ActivePrecompiles(), msg.AccessList()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 		ret   []byte | 
					
						
							|  |  |  | 		vmerr error // vm errors do not effect consensus and are therefore not assigned to err | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	if contractCreation { | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 		ret, _, st.gas, vmerr = st.evm.Create(sender, st.data, st.gas, st.value) | 
					
						
							| 
									
										
										
										
											2014-07-07 13:59:09 +02:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-03-24 15:23:16 +01:00
										 |  |  | 		// Increment the nonce for the next transaction | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 		st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1) | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 		ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value) | 
					
						
							| 
									
										
										
										
											2015-07-06 11:54:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 	st.refundGas() | 
					
						
							| 
									
										
										
										
											2020-11-13 13:42:19 +01:00
										 |  |  | 	st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice)) | 
					
						
							| 
									
										
										
										
											2014-07-24 12:04:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 16:25:36 +08:00
										 |  |  | 	return &ExecutionResult{ | 
					
						
							|  |  |  | 		UsedGas:    st.gasUsed(), | 
					
						
							|  |  |  | 		Err:        vmerr, | 
					
						
							|  |  |  | 		ReturnData: ret, | 
					
						
							|  |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2014-07-24 12:04:15 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-18 21:58:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | func (st *StateTransition) refundGas() { | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | 	// Apply refund counter, capped to half of the used gas. | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	refund := st.gasUsed() / 2 | 
					
						
							|  |  |  | 	if refund > st.state.GetRefund() { | 
					
						
							|  |  |  | 		refund = st.state.GetRefund() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	st.gas += refund | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	// Return ETH for remaining gas, exchanged at the original rate. | 
					
						
							|  |  |  | 	remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice) | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	st.state.AddBalance(st.msg.From(), remaining) | 
					
						
							| 
									
										
										
										
											2014-12-18 21:58:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | 	// Also return remaining gas to the block gas counter so it is | 
					
						
							|  |  |  | 	// available for the next transaction. | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	st.gp.AddGas(st.gas) | 
					
						
							| 
									
										
										
										
											2014-12-18 21:58:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02: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 21:58:26 +01:00
										 |  |  | } |