| 
									
										
										
										
											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-10-18 13:31:20 +02:00
										 |  |  | package vm | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	"sync/atomic" | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2016-10-08 00:23:45 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | type ( | 
					
						
							|  |  |  | 	CanTransferFunc func(StateDB, common.Address, *big.Int) bool | 
					
						
							|  |  |  | 	TransferFunc    func(StateDB, common.Address, common.Address, *big.Int) | 
					
						
							|  |  |  | 	// GetHashFunc returns the nth block hash in the blockchain | 
					
						
							|  |  |  | 	// and is used by the BLOCKHASH EVM op code. | 
					
						
							|  |  |  | 	GetHashFunc func(uint64) common.Hash | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter. | 
					
						
							|  |  |  | func run(evm *EVM, snapshot int, contract *Contract, input []byte) ([]byte, error) { | 
					
						
							|  |  |  | 	if contract.CodeAddr != nil { | 
					
						
							|  |  |  | 		precompiledContracts := PrecompiledContracts | 
					
						
							|  |  |  | 		if p := precompiledContracts[*contract.CodeAddr]; p != nil { | 
					
						
							|  |  |  | 			return RunPrecompiledContract(p, input, contract) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return evm.interpreter.Run(snapshot, contract, input) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Context provides the EVM with auxiliary information. Once provided | 
					
						
							|  |  |  | // it shouldn't be modified. | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | type Context struct { | 
					
						
							|  |  |  | 	// CanTransfer returns whether the account contains | 
					
						
							|  |  |  | 	// sufficient ether to transfer the value | 
					
						
							|  |  |  | 	CanTransfer CanTransferFunc | 
					
						
							|  |  |  | 	// Transfer transfers ether from one account to the other | 
					
						
							|  |  |  | 	Transfer TransferFunc | 
					
						
							|  |  |  | 	// GetHash returns the hash corresponding to n | 
					
						
							|  |  |  | 	GetHash GetHashFunc | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Message information | 
					
						
							|  |  |  | 	Origin   common.Address // Provides information for ORIGIN | 
					
						
							|  |  |  | 	GasPrice *big.Int       // Provides information for GASPRICE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Block information | 
					
						
							|  |  |  | 	Coinbase    common.Address // Provides information for COINBASE | 
					
						
							|  |  |  | 	GasLimit    *big.Int       // Provides information for GASLIMIT | 
					
						
							|  |  |  | 	BlockNumber *big.Int       // Provides information for NUMBER | 
					
						
							|  |  |  | 	Time        *big.Int       // Provides information for TIME | 
					
						
							|  |  |  | 	Difficulty  *big.Int       // Provides information for DIFFICULTY | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | // EVM is the Ethereum Virtual Machine base object and provides | 
					
						
							|  |  |  | // the necessary tools to run a contract on the given state with | 
					
						
							|  |  |  | // the provided context. It should be noted that any error | 
					
						
							|  |  |  | // generated through any of the calls should be considered a | 
					
						
							|  |  |  | // revert-state-and-consume-all-gas operation, no checks on | 
					
						
							|  |  |  | // specific errors should ever be performed. The interpreter makes | 
					
						
							|  |  |  | // sure that any errors generated are to be considered faulty code. | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | // The EVM should never be reused and is not thread safe. | 
					
						
							|  |  |  | type EVM struct { | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// Context provides auxiliary blockchain related information | 
					
						
							|  |  |  | 	Context | 
					
						
							|  |  |  | 	// StateDB gives access to the underlying state | 
					
						
							|  |  |  | 	StateDB StateDB | 
					
						
							|  |  |  | 	// Depth is the current call stack | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	depth int | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// chainConfig contains information about the current chain | 
					
						
							|  |  |  | 	chainConfig *params.ChainConfig | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | 	// chain rules contains the chain rules for the current epoch | 
					
						
							|  |  |  | 	chainRules params.Rules | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	// virtual machine configuration options used to initialise the | 
					
						
							|  |  |  | 	// evm. | 
					
						
							|  |  |  | 	vmConfig Config | 
					
						
							|  |  |  | 	// global (to this context) ethereum virtual machine | 
					
						
							|  |  |  | 	// used throughout the execution of the tx. | 
					
						
							|  |  |  | 	interpreter *Interpreter | 
					
						
							|  |  |  | 	// abort is used to abort the EVM calling operations | 
					
						
							|  |  |  | 	// NOTE: must be set atomically | 
					
						
							|  |  |  | 	abort int32 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | // NewEVM retutrns a new EVM evmironment. The returned EVM is not thread safe | 
					
						
							|  |  |  | // and should only ever be used *once*. | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM { | 
					
						
							|  |  |  | 	evm := &EVM{ | 
					
						
							|  |  |  | 		Context:     ctx, | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 		StateDB:     statedb, | 
					
						
							|  |  |  | 		vmConfig:    vmConfig, | 
					
						
							|  |  |  | 		chainConfig: chainConfig, | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | 		chainRules:  chainConfig.Rules(ctx.BlockNumber), | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	evm.interpreter = NewInterpreter(evm, vmConfig) | 
					
						
							|  |  |  | 	return evm | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | // Cancel cancels any running EVM operation. This may be called concurrently and | 
					
						
							|  |  |  | // it's safe to be called multiple times. | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | func (evm *EVM) Cancel() { | 
					
						
							|  |  |  | 	atomic.StoreInt32(&evm.abort, 1) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-06 19:44:35 +02:00
										 |  |  | // Call executes the contract associated with the addr with the given input as parameters. It also handles any | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | // necessary value transfer required and takes the necessary steps to create accounts and reverses the state in | 
					
						
							|  |  |  | // case of an execution error or failed value transfer. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if evm.vmConfig.NoRecursion && evm.depth > 0 { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, gas, nil | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Depth check execution. Fail if we're trying to execute above the | 
					
						
							|  |  |  | 	// limit. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	if evm.depth > int(params.CallCreateDepth) { | 
					
						
							|  |  |  | 		return nil, gas, ErrDepth | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, gas, ErrInsufficientBalance | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 		to       = AccountRef(addr) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		snapshot = evm.StateDB.Snapshot() | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if !evm.StateDB.Exist(addr) { | 
					
						
							| 
									
										
										
										
											2017-02-28 15:09:11 +01:00
										 |  |  | 		if PrecompiledContracts[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 			return nil, gas, nil | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 		evm.StateDB.CreateAccount(addr) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// initialise a new contract and set the code that is to be used by the | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	// E The contract is a scoped evmironment for this execution context | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// only. | 
					
						
							|  |  |  | 	contract := NewContract(caller, to, value, gas) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | 	ret, err = run(evm, snapshot, contract, input) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// When an error was returned by the EVM or when setting the creation code | 
					
						
							|  |  |  | 	// above we revert to the snapshot and consume any gas remaining. Additionally | 
					
						
							|  |  |  | 	// when we're in homestead this also counts for code storage gas errors. | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		contract.UseGas(contract.Gas) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		evm.StateDB.RevertToSnapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	return ret, contract.Gas, err | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-06 19:44:35 +02:00
										 |  |  | // CallCode executes the contract associated with the addr with the given input as parameters. It also handles any | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | // necessary value transfer required and takes the necessary steps to create accounts and reverses the state in | 
					
						
							|  |  |  | // case of an execution error or failed value transfer. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // CallCode differs from Call in the sense that it executes the given address' code with the caller as context. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if evm.vmConfig.NoRecursion && evm.depth > 0 { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, gas, nil | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Depth check execution. Fail if we're trying to execute above the | 
					
						
							|  |  |  | 	// limit. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	if evm.depth > int(params.CallCreateDepth) { | 
					
						
							|  |  |  | 		return nil, gas, ErrDepth | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, gas, ErrInsufficientBalance | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		snapshot = evm.StateDB.Snapshot() | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 		to       = AccountRef(caller.Address()) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	) | 
					
						
							|  |  |  | 	// initialise a new contract and set the code that is to be used by the | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	// E The contract is a scoped evmironment for this execution context | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// only. | 
					
						
							|  |  |  | 	contract := NewContract(caller, to, value, gas) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | 	ret, err = run(evm, snapshot, contract, input) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		contract.UseGas(contract.Gas) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		evm.StateDB.RevertToSnapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	return ret, contract.Gas, err | 
					
						
							| 
									
										
										
										
											2016-02-03 23:46:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-06 19:44:35 +02:00
										 |  |  | // DelegateCall executes the contract associated with the addr with the given input as parameters. | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | // It reverses the state in case of an execution error. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // DelegateCall differs from CallCode in the sense that it executes the given address' code with the caller as context | 
					
						
							|  |  |  | // and the caller is set to the caller of the caller. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if evm.vmConfig.NoRecursion && evm.depth > 0 { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, gas, nil | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// Depth check execution. Fail if we're trying to execute above the | 
					
						
							|  |  |  | 	// limit. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	if evm.depth > int(params.CallCreateDepth) { | 
					
						
							|  |  |  | 		return nil, gas, ErrDepth | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		snapshot = evm.StateDB.Snapshot() | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 		to       = AccountRef(caller.Address()) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// Iinitialise a new contract and make initialise the delegate values | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 	contract := NewContract(caller, to, nil, gas).AsDelegate() | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | 	ret, err = run(evm, snapshot, contract, input) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		contract.UseGas(contract.Gas) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		evm.StateDB.RevertToSnapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-10-05 22:22:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	return ret, contract.Gas, err | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | // Create creates a new contract using code as deployment code. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if evm.vmConfig.NoRecursion && evm.depth > 0 { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, common.Address{}, gas, nil | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Depth check execution. Fail if we're trying to execute above the | 
					
						
							|  |  |  | 	// limit. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	if evm.depth > int(params.CallCreateDepth) { | 
					
						
							|  |  |  | 		return nil, common.Address{}, gas, ErrDepth | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, common.Address{}, gas, ErrInsufficientBalance | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create a new account on the state | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	nonce := evm.StateDB.GetNonce(caller.Address()) | 
					
						
							|  |  |  | 	evm.StateDB.SetNonce(caller.Address(), nonce+1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	snapshot := evm.StateDB.Snapshot() | 
					
						
							|  |  |  | 	contractAddr = crypto.CreateAddress(caller.Address(), nonce) | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 	evm.StateDB.CreateAccount(contractAddr) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if evm.ChainConfig().IsEIP158(evm.BlockNumber) { | 
					
						
							|  |  |  | 		evm.StateDB.SetNonce(contractAddr, 1) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 	evm.Transfer(evm.StateDB, caller.Address(), contractAddr, value) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// initialise a new contract and set the code that is to be used by the | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	// E The contract is a scoped evmironment for this execution context | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// only. | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 	contract := NewContract(caller, AccountRef(contractAddr), value, gas) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | 	ret, err = run(evm, snapshot, contract, nil) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// check whether the max code size has been exceeded | 
					
						
							|  |  |  | 	maxCodeSizeExceeded := len(ret) > params.MaxCodeSize | 
					
						
							|  |  |  | 	// if the contract creation ran successfully and no errors were returned | 
					
						
							|  |  |  | 	// calculate the gas required to store the code. If the code could not | 
					
						
							|  |  |  | 	// be stored due to not enough gas set an error and let it be handled | 
					
						
							|  |  |  | 	// by the error checking condition below. | 
					
						
							|  |  |  | 	if err == nil && !maxCodeSizeExceeded { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		createDataGas := uint64(len(ret)) * params.CreateDataGas | 
					
						
							|  |  |  | 		if contract.UseGas(createDataGas) { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 			evm.StateDB.SetCode(contractAddr, ret) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 			err = ErrCodeStoreOutOfGas | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// When an error was returned by the EVM or when setting the creation code | 
					
						
							|  |  |  | 	// above we revert to the snapshot and consume any gas remaining. Additionally | 
					
						
							|  |  |  | 	// when we're in homestead this also counts for code storage gas errors. | 
					
						
							|  |  |  | 	if maxCodeSizeExceeded || | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		(err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) { | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | 		contract.UseGas(contract.Gas) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		evm.StateDB.RevertToSnapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// If the vm returned with an error the return value should be set to nil. | 
					
						
							|  |  |  | 	// This isn't consensus critical but merely to for behaviour reasons such as | 
					
						
							|  |  |  | 	// tests, RPC calls, etc. | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		ret = nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	return ret, contractAddr, contract.Gas, err | 
					
						
							| 
									
										
										
										
											2014-10-22 15:22:21 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | // ChainConfig returns the evmironment's chain configuration | 
					
						
							|  |  |  | func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | // Interpreter returns the EVM interpreter | 
					
						
							|  |  |  | func (evm *EVM) Interpreter() *Interpreter { return evm.interpreter } |