aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/instructions.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm/instructions.go')
-rw-r--r--core/vm/instructions.go60
1 files changed, 60 insertions, 0 deletions
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 1ec13ba35..122fc21e4 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -496,6 +496,38 @@ func opExtCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, sta
return nil, nil
}
+// opExtCodeHash returns the code hash of a specified account.
+// There are several cases when the function is called, while we can relay everything
+// to `state.GetCodeHash` function to ensure the correctness.
+// (1) Caller tries to get the code hash of a normal contract account, state
+// should return the relative code hash and set it as the result.
+//
+// (2) Caller tries to get the code hash of a non-existent account, state should
+// return common.Hash{} and zero will be set as the result.
+//
+// (3) Caller tries to get the code hash for an account without contract code,
+// state should return emptyCodeHash(0xc5d246...) as the result.
+//
+// (4) Caller tries to get the code hash of a precompiled account, the result
+// should be zero or emptyCodeHash.
+//
+// It is worth noting that in order to avoid unnecessary create and clean,
+// all precompile accounts on mainnet have been transferred 1 wei, so the return
+// here should be emptyCodeHash.
+// If the precompile account is not transferred any amount on a private or
+// customized chain, the return value will be zero.
+//
+// (5) Caller tries to get the code hash for an account which is marked as suicided
+// in the current transaction, the code hash of this account should be returned.
+//
+// (6) Caller tries to get the code hash for an account which is marked as deleted,
+// this account should be regarded as a non-existent account and zero should be returned.
+func opExtCodeHash(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+ slot := stack.peek()
+ slot.SetBytes(evm.StateDB.GetCodeHash(common.BigToAddress(slot)).Bytes())
+ return nil, nil
+}
+
func opGasprice(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
stack.push(evm.interpreter.intPool.get().Set(evm.GasPrice))
return nil, nil
@@ -665,6 +697,34 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
return nil, nil
}
+func opCreate2(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+ var (
+ endowment = stack.pop()
+ offset, size = stack.pop(), stack.pop()
+ salt = stack.pop()
+ input = memory.Get(offset.Int64(), size.Int64())
+ gas = contract.Gas
+ )
+
+ // Apply EIP150
+ gas -= gas / 64
+ contract.UseGas(gas)
+ res, addr, returnGas, suberr := evm.Create2(contract, input, gas, endowment, salt)
+ // Push item on the stack based on the returned error.
+ if suberr != nil {
+ stack.push(evm.interpreter.intPool.getZero())
+ } else {
+ stack.push(addr.Big())
+ }
+ contract.Gas += returnGas
+ evm.interpreter.intPool.put(endowment, offset, size, salt)
+
+ if suberr == errExecutionReverted {
+ return res, nil
+ }
+ return nil, nil
+}
+
func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// Pop gas. The actual gas in in evm.callGasTemp.
evm.interpreter.intPool.put(stack.pop())