|
|
@ -91,29 +91,40 @@ type EVM struct { |
|
|
|
// Context provides auxiliary blockchain related information
|
|
|
|
// Context provides auxiliary blockchain related information
|
|
|
|
Context BlockContext |
|
|
|
Context BlockContext |
|
|
|
TxContext |
|
|
|
TxContext |
|
|
|
|
|
|
|
|
|
|
|
// StateDB gives access to the underlying state
|
|
|
|
// StateDB gives access to the underlying state
|
|
|
|
StateDB StateDB |
|
|
|
StateDB StateDB |
|
|
|
// Depth is the current call stack
|
|
|
|
|
|
|
|
|
|
|
|
// depth is the current call stack
|
|
|
|
depth int |
|
|
|
depth int |
|
|
|
|
|
|
|
|
|
|
|
// chainConfig contains information about the current chain
|
|
|
|
// chainConfig contains information about the current chain
|
|
|
|
chainConfig *params.ChainConfig |
|
|
|
chainConfig *params.ChainConfig |
|
|
|
|
|
|
|
|
|
|
|
// chain rules contains the chain rules for the current epoch
|
|
|
|
// chain rules contains the chain rules for the current epoch
|
|
|
|
chainRules params.Rules |
|
|
|
chainRules params.Rules |
|
|
|
// virtual machine configuration options used to initialise the
|
|
|
|
|
|
|
|
// evm.
|
|
|
|
// virtual machine configuration options used to initialise the evm
|
|
|
|
Config Config |
|
|
|
Config Config |
|
|
|
// global (to this context) ethereum virtual machine
|
|
|
|
|
|
|
|
// used throughout the execution of the tx.
|
|
|
|
// global (to this context) ethereum virtual machine used throughout
|
|
|
|
|
|
|
|
// the execution of the tx
|
|
|
|
interpreter *EVMInterpreter |
|
|
|
interpreter *EVMInterpreter |
|
|
|
|
|
|
|
|
|
|
|
// abort is used to abort the EVM calling operations
|
|
|
|
// abort is used to abort the EVM calling operations
|
|
|
|
abort atomic.Bool |
|
|
|
abort atomic.Bool |
|
|
|
|
|
|
|
|
|
|
|
// callGasTemp holds the gas available for the current call. This is needed because the
|
|
|
|
// callGasTemp holds the gas available for the current call. This is needed because the
|
|
|
|
// available gas is calculated in gasCall* according to the 63/64 rule and later
|
|
|
|
// available gas is calculated in gasCall* according to the 63/64 rule and later
|
|
|
|
// applied in opCall*.
|
|
|
|
// applied in opCall*.
|
|
|
|
callGasTemp uint64 |
|
|
|
callGasTemp uint64 |
|
|
|
|
|
|
|
|
|
|
|
// precompiles holds the precompiled contracts for the current epoch
|
|
|
|
// precompiles holds the precompiled contracts for the current epoch
|
|
|
|
precompiles map[common.Address]PrecompiledContract |
|
|
|
precompiles map[common.Address]PrecompiledContract |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// jumpDests is the aggregated result of JUMPDEST analysis made through
|
|
|
|
|
|
|
|
// the life cycle of EVM.
|
|
|
|
|
|
|
|
jumpDests map[common.Hash]bitvec |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// NewEVM constructs an EVM instance with the supplied block context, state
|
|
|
|
// NewEVM constructs an EVM instance with the supplied block context, state
|
|
|
@ -127,6 +138,7 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon |
|
|
|
Config: config, |
|
|
|
Config: config, |
|
|
|
chainConfig: chainConfig, |
|
|
|
chainConfig: chainConfig, |
|
|
|
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), |
|
|
|
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), |
|
|
|
|
|
|
|
jumpDests: make(map[common.Hash]bitvec), |
|
|
|
} |
|
|
|
} |
|
|
|
evm.precompiles = activePrecompiledContracts(evm.chainRules) |
|
|
|
evm.precompiles = activePrecompiledContracts(evm.chainRules) |
|
|
|
evm.interpreter = NewEVMInterpreter(evm) |
|
|
|
evm.interpreter = NewEVMInterpreter(evm) |
|
|
@ -169,10 +181,10 @@ func (evm *EVM) Interpreter() *EVMInterpreter { |
|
|
|
// parameters. It also handles any necessary value transfer required and takes
|
|
|
|
// parameters. It also handles any necessary value transfer required and takes
|
|
|
|
// the necessary steps to create accounts and reverses the state in case of an
|
|
|
|
// the necessary steps to create accounts and reverses the state in case of an
|
|
|
|
// execution error or failed value transfer.
|
|
|
|
// execution error or failed value transfer.
|
|
|
|
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
// Capture the tracer start/end events in debug mode
|
|
|
|
// Capture the tracer start/end events in debug mode
|
|
|
|
if evm.Config.Tracer != nil { |
|
|
|
if evm.Config.Tracer != nil { |
|
|
|
evm.captureBegin(evm.depth, CALL, caller.Address(), addr, input, gas, value.ToBig()) |
|
|
|
evm.captureBegin(evm.depth, CALL, caller, addr, input, gas, value.ToBig()) |
|
|
|
defer func(startGas uint64) { |
|
|
|
defer func(startGas uint64) { |
|
|
|
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) |
|
|
|
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) |
|
|
|
}(gas) |
|
|
|
}(gas) |
|
|
@ -182,7 +194,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas |
|
|
|
return nil, gas, ErrDepth |
|
|
|
return nil, gas, ErrDepth |
|
|
|
} |
|
|
|
} |
|
|
|
// Fail if we're trying to transfer more than the available balance
|
|
|
|
// Fail if we're trying to transfer more than the available balance
|
|
|
|
if !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { |
|
|
|
if !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller, value) { |
|
|
|
return nil, gas, ErrInsufficientBalance |
|
|
|
return nil, gas, ErrInsufficientBalance |
|
|
|
} |
|
|
|
} |
|
|
|
snapshot := evm.StateDB.Snapshot() |
|
|
|
snapshot := evm.StateDB.Snapshot() |
|
|
@ -205,22 +217,19 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas |
|
|
|
} |
|
|
|
} |
|
|
|
evm.StateDB.CreateAccount(addr) |
|
|
|
evm.StateDB.CreateAccount(addr) |
|
|
|
} |
|
|
|
} |
|
|
|
evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value) |
|
|
|
evm.Context.Transfer(evm.StateDB, caller, addr, value) |
|
|
|
|
|
|
|
|
|
|
|
if isPrecompile { |
|
|
|
if isPrecompile { |
|
|
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) |
|
|
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
|
|
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
|
|
|
// The contract is a scoped environment for this execution context only.
|
|
|
|
|
|
|
|
code := evm.resolveCode(addr) |
|
|
|
code := evm.resolveCode(addr) |
|
|
|
if len(code) == 0 { |
|
|
|
if len(code) == 0 { |
|
|
|
ret, err = nil, nil // gas is unchanged
|
|
|
|
ret, err = nil, nil // gas is unchanged
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
addrCopy := addr |
|
|
|
// The contract is a scoped environment for this execution context only.
|
|
|
|
// If the account has no code, we can abort here
|
|
|
|
contract := NewContract(caller, addr, value, gas, evm.jumpDests) |
|
|
|
// The depth-check is already done, and precompiles handled above
|
|
|
|
contract.SetCallCode(evm.resolveCodeHash(addr), code) |
|
|
|
contract := NewContract(caller, AccountRef(addrCopy), value, gas) |
|
|
|
|
|
|
|
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), code) |
|
|
|
|
|
|
|
ret, err = evm.interpreter.Run(contract, input, false) |
|
|
|
ret, err = evm.interpreter.Run(contract, input, false) |
|
|
|
gas = contract.Gas |
|
|
|
gas = contract.Gas |
|
|
|
} |
|
|
|
} |
|
|
@ -251,10 +260,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas |
|
|
|
//
|
|
|
|
//
|
|
|
|
// CallCode differs from Call in the sense that it executes the given address'
|
|
|
|
// CallCode differs from Call in the sense that it executes the given address'
|
|
|
|
// code with the caller as context.
|
|
|
|
// code with the caller as context.
|
|
|
|
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
// Invoke tracer hooks that signal entering/exiting a call frame
|
|
|
|
// Invoke tracer hooks that signal entering/exiting a call frame
|
|
|
|
if evm.Config.Tracer != nil { |
|
|
|
if evm.Config.Tracer != nil { |
|
|
|
evm.captureBegin(evm.depth, CALLCODE, caller.Address(), addr, input, gas, value.ToBig()) |
|
|
|
evm.captureBegin(evm.depth, CALLCODE, caller, addr, input, gas, value.ToBig()) |
|
|
|
defer func(startGas uint64) { |
|
|
|
defer func(startGas uint64) { |
|
|
|
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) |
|
|
|
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) |
|
|
|
}(gas) |
|
|
|
}(gas) |
|
|
@ -267,7 +276,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, |
|
|
|
// Note although it's noop to transfer X ether to caller itself. But
|
|
|
|
// Note although it's noop to transfer X ether to caller itself. But
|
|
|
|
// if caller doesn't have enough balance, it would be an error to allow
|
|
|
|
// if caller doesn't have enough balance, it would be an error to allow
|
|
|
|
// over-charging itself. So the check here is necessary.
|
|
|
|
// over-charging itself. So the check here is necessary.
|
|
|
|
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { |
|
|
|
if !evm.Context.CanTransfer(evm.StateDB, caller, value) { |
|
|
|
return nil, gas, ErrInsufficientBalance |
|
|
|
return nil, gas, ErrInsufficientBalance |
|
|
|
} |
|
|
|
} |
|
|
|
var snapshot = evm.StateDB.Snapshot() |
|
|
|
var snapshot = evm.StateDB.Snapshot() |
|
|
@ -276,11 +285,10 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, |
|
|
|
if p, isPrecompile := evm.precompile(addr); isPrecompile { |
|
|
|
if p, isPrecompile := evm.precompile(addr); isPrecompile { |
|
|
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) |
|
|
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
addrCopy := addr |
|
|
|
|
|
|
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
|
|
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
|
|
|
// The contract is a scoped environment for this execution context only.
|
|
|
|
// The contract is a scoped environment for this execution context only.
|
|
|
|
contract := NewContract(caller, AccountRef(caller.Address()), value, gas) |
|
|
|
contract := NewContract(caller, caller, value, gas, evm.jumpDests) |
|
|
|
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) |
|
|
|
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr)) |
|
|
|
ret, err = evm.interpreter.Run(contract, input, false) |
|
|
|
ret, err = evm.interpreter.Run(contract, input, false) |
|
|
|
gas = contract.Gas |
|
|
|
gas = contract.Gas |
|
|
|
} |
|
|
|
} |
|
|
@ -290,7 +298,6 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, |
|
|
|
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { |
|
|
|
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { |
|
|
|
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) |
|
|
|
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gas = 0 |
|
|
|
gas = 0 |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -302,14 +309,11 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, |
|
|
|
//
|
|
|
|
//
|
|
|
|
// DelegateCall differs from CallCode in the sense that it executes the given address'
|
|
|
|
// 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.
|
|
|
|
// code with the caller as context and the caller is set to the caller of the caller.
|
|
|
|
func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
// Invoke tracer hooks that signal entering/exiting a call frame
|
|
|
|
// Invoke tracer hooks that signal entering/exiting a call frame
|
|
|
|
if evm.Config.Tracer != nil { |
|
|
|
if evm.Config.Tracer != nil { |
|
|
|
// NOTE: caller must, at all times be a contract. It should never happen
|
|
|
|
|
|
|
|
// that caller is something other than a Contract.
|
|
|
|
|
|
|
|
parent := caller.(*Contract) |
|
|
|
|
|
|
|
// DELEGATECALL inherits value from parent call
|
|
|
|
// DELEGATECALL inherits value from parent call
|
|
|
|
evm.captureBegin(evm.depth, DELEGATECALL, caller.Address(), addr, input, gas, parent.value.ToBig()) |
|
|
|
evm.captureBegin(evm.depth, DELEGATECALL, caller, addr, input, gas, value.ToBig()) |
|
|
|
defer func(startGas uint64) { |
|
|
|
defer func(startGas uint64) { |
|
|
|
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) |
|
|
|
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) |
|
|
|
}(gas) |
|
|
|
}(gas) |
|
|
@ -324,10 +328,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by |
|
|
|
if p, isPrecompile := evm.precompile(addr); isPrecompile { |
|
|
|
if p, isPrecompile := evm.precompile(addr); isPrecompile { |
|
|
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) |
|
|
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
addrCopy := addr |
|
|
|
|
|
|
|
// Initialise a new contract and make initialise the delegate values
|
|
|
|
// Initialise a new contract and make initialise the delegate values
|
|
|
|
contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() |
|
|
|
//
|
|
|
|
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) |
|
|
|
// Note: The value refers to the original value from the parent call.
|
|
|
|
|
|
|
|
contract := NewContract(originCaller, caller, value, gas, evm.jumpDests) |
|
|
|
|
|
|
|
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr)) |
|
|
|
ret, err = evm.interpreter.Run(contract, input, false) |
|
|
|
ret, err = evm.interpreter.Run(contract, input, false) |
|
|
|
gas = contract.Gas |
|
|
|
gas = contract.Gas |
|
|
|
} |
|
|
|
} |
|
|
@ -347,10 +352,10 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by |
|
|
|
// as parameters while disallowing any modifications to the state during the call.
|
|
|
|
// as parameters while disallowing any modifications to the state during the call.
|
|
|
|
// Opcodes that attempt to perform such modifications will result in exceptions
|
|
|
|
// Opcodes that attempt to perform such modifications will result in exceptions
|
|
|
|
// instead of performing the modifications.
|
|
|
|
// instead of performing the modifications.
|
|
|
|
func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
// Invoke tracer hooks that signal entering/exiting a call frame
|
|
|
|
// Invoke tracer hooks that signal entering/exiting a call frame
|
|
|
|
if evm.Config.Tracer != nil { |
|
|
|
if evm.Config.Tracer != nil { |
|
|
|
evm.captureBegin(evm.depth, STATICCALL, caller.Address(), addr, input, gas, nil) |
|
|
|
evm.captureBegin(evm.depth, STATICCALL, caller, addr, input, gas, nil) |
|
|
|
defer func(startGas uint64) { |
|
|
|
defer func(startGas uint64) { |
|
|
|
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) |
|
|
|
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) |
|
|
|
}(gas) |
|
|
|
}(gas) |
|
|
@ -375,14 +380,11 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte |
|
|
|
if p, isPrecompile := evm.precompile(addr); isPrecompile { |
|
|
|
if p, isPrecompile := evm.precompile(addr); isPrecompile { |
|
|
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) |
|
|
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// At this point, we use a copy of address. If we don't, the go compiler will
|
|
|
|
|
|
|
|
// leak the 'contract' to the outer scope, and make allocation for 'contract'
|
|
|
|
|
|
|
|
// even if the actual execution ends on RunPrecompiled above.
|
|
|
|
|
|
|
|
addrCopy := addr |
|
|
|
|
|
|
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
|
|
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
|
|
|
// The contract is a scoped environment for this execution context only.
|
|
|
|
// The contract is a scoped environment for this execution context only.
|
|
|
|
contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas) |
|
|
|
contract := NewContract(caller, addr, new(uint256.Int), gas, evm.jumpDests) |
|
|
|
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) |
|
|
|
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr)) |
|
|
|
|
|
|
|
|
|
|
|
// When an error was returned by the EVM or when setting the creation code
|
|
|
|
// 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
|
|
|
|
// 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.
|
|
|
|
// when we're in Homestead this also counts for code storage gas errors.
|
|
|
@ -415,9 +417,9 @@ func (c *codeAndHash) Hash() common.Hash { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// create creates a new contract using code as deployment code.
|
|
|
|
// create creates a new contract using code as deployment code.
|
|
|
|
func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *uint256.Int, address common.Address, typ OpCode) (ret []byte, createAddress common.Address, leftOverGas uint64, err error) { |
|
|
|
func (evm *EVM) create(caller common.Address, codeAndHash *codeAndHash, gas uint64, value *uint256.Int, address common.Address, typ OpCode) (ret []byte, createAddress common.Address, leftOverGas uint64, err error) { |
|
|
|
if evm.Config.Tracer != nil { |
|
|
|
if evm.Config.Tracer != nil { |
|
|
|
evm.captureBegin(evm.depth, typ, caller.Address(), address, codeAndHash.code, gas, value.ToBig()) |
|
|
|
evm.captureBegin(evm.depth, typ, caller, address, codeAndHash.code, gas, value.ToBig()) |
|
|
|
defer func(startGas uint64) { |
|
|
|
defer func(startGas uint64) { |
|
|
|
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) |
|
|
|
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) |
|
|
|
}(gas) |
|
|
|
}(gas) |
|
|
@ -427,14 +429,14 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, |
|
|
|
if evm.depth > int(params.CallCreateDepth) { |
|
|
|
if evm.depth > int(params.CallCreateDepth) { |
|
|
|
return nil, common.Address{}, gas, ErrDepth |
|
|
|
return nil, common.Address{}, gas, ErrDepth |
|
|
|
} |
|
|
|
} |
|
|
|
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { |
|
|
|
if !evm.Context.CanTransfer(evm.StateDB, caller, value) { |
|
|
|
return nil, common.Address{}, gas, ErrInsufficientBalance |
|
|
|
return nil, common.Address{}, gas, ErrInsufficientBalance |
|
|
|
} |
|
|
|
} |
|
|
|
nonce := evm.StateDB.GetNonce(caller.Address()) |
|
|
|
nonce := evm.StateDB.GetNonce(caller) |
|
|
|
if nonce+1 < nonce { |
|
|
|
if nonce+1 < nonce { |
|
|
|
return nil, common.Address{}, gas, ErrNonceUintOverflow |
|
|
|
return nil, common.Address{}, gas, ErrNonceUintOverflow |
|
|
|
} |
|
|
|
} |
|
|
|
evm.StateDB.SetNonce(caller.Address(), nonce+1) |
|
|
|
evm.StateDB.SetNonce(caller, nonce+1) |
|
|
|
|
|
|
|
|
|
|
|
// Charge the contract creation init gas in verkle mode
|
|
|
|
// Charge the contract creation init gas in verkle mode
|
|
|
|
if evm.chainRules.IsEIP4762 { |
|
|
|
if evm.chainRules.IsEIP4762 { |
|
|
@ -495,12 +497,12 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, |
|
|
|
} |
|
|
|
} |
|
|
|
gas = gas - statelessGas |
|
|
|
gas = gas - statelessGas |
|
|
|
} |
|
|
|
} |
|
|
|
evm.Context.Transfer(evm.StateDB, caller.Address(), address, value) |
|
|
|
evm.Context.Transfer(evm.StateDB, caller, address, value) |
|
|
|
|
|
|
|
|
|
|
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
|
|
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
|
|
|
// The contract is a scoped environment for this execution context only.
|
|
|
|
// The contract is a scoped environment for this execution context only.
|
|
|
|
contract := NewContract(caller, AccountRef(address), value, gas) |
|
|
|
contract := NewContract(caller, address, value, gas, evm.jumpDests) |
|
|
|
contract.SetCodeOptionalHash(&address, codeAndHash) |
|
|
|
contract.SetCodeOptionalHash(codeAndHash) |
|
|
|
contract.IsDeployment = true |
|
|
|
contract.IsDeployment = true |
|
|
|
|
|
|
|
|
|
|
|
ret, err = evm.initNewContract(contract, address, value) |
|
|
|
ret, err = evm.initNewContract(contract, address, value) |
|
|
@ -547,8 +549,8 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address, valu |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Create creates a new contract using code as deployment code.
|
|
|
|
// Create creates a new contract using code as deployment code.
|
|
|
|
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { |
|
|
|
func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { |
|
|
|
contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) |
|
|
|
contractAddr = crypto.CreateAddress(caller, evm.StateDB.GetNonce(caller)) |
|
|
|
return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE) |
|
|
|
return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -556,9 +558,9 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint2 |
|
|
|
//
|
|
|
|
//
|
|
|
|
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
|
|
|
|
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
|
|
|
|
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
|
|
|
|
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
|
|
|
|
func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { |
|
|
|
func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { |
|
|
|
codeAndHash := &codeAndHash{code: code} |
|
|
|
codeAndHash := &codeAndHash{code: code} |
|
|
|
contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes()) |
|
|
|
contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), codeAndHash.Hash().Bytes()) |
|
|
|
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2) |
|
|
|
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|