diff --git a/core/vm/evm.go b/core/vm/evm.go
index 448acd469d15f8722ef034ed7849704b35cb7b3d..8d654c666ea2f61565f073e9f1c8cc49b43ca6e6 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -168,8 +168,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
 	// 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)
 		evm.StateDB.RevertToSnapshot(snapshot)
+		if err != errExecutionReverted {
+			contract.UseGas(contract.Gas)
+		}
 	}
 	return ret, contract.Gas, err
 }
@@ -207,10 +209,11 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
 
 	ret, err = run(evm, snapshot, contract, input)
 	if err != nil {
-		contract.UseGas(contract.Gas)
 		evm.StateDB.RevertToSnapshot(snapshot)
+		if err != errExecutionReverted {
+			contract.UseGas(contract.Gas)
+		}
 	}
-
 	return ret, contract.Gas, err
 }
 
@@ -239,10 +242,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
 
 	ret, err = run(evm, snapshot, contract, input)
 	if err != nil {
-		contract.UseGas(contract.Gas)
 		evm.StateDB.RevertToSnapshot(snapshot)
+		if err != errExecutionReverted {
+			contract.UseGas(contract.Gas)
+		}
 	}
-
 	return ret, contract.Gas, err
 }
 
@@ -281,8 +285,10 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
 	// when we're in Homestead this also counts for code storage gas errors.
 	ret, err = run(evm, snapshot, contract, input)
 	if err != nil {
-		contract.UseGas(contract.Gas)
 		evm.StateDB.RevertToSnapshot(snapshot)
+		if err != errExecutionReverted {
+			contract.UseGas(contract.Gas)
+		}
 	}
 	return ret, contract.Gas, err
 }
@@ -339,18 +345,12 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
 	// 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 ||
-		(err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
-		contract.UseGas(contract.Gas)
+	if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
 		evm.StateDB.RevertToSnapshot(snapshot)
+		if err != errExecutionReverted {
+			contract.UseGas(contract.Gas)
+		}
 	}
-	// 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
-	}
-
 	return ret, contractAddr, contract.Gas, err
 }
 
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index a6346bd806e1a596fdd284121f3e7569b7d53b71..3b0698ce9e992432ab7542da84ed78bf399dbffa 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -396,6 +396,10 @@ func gasReturn(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
 	return memoryGasCost(mem, memorySize)
 }
 
+func gasRevert(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+	return memoryGasCost(mem, memorySize)
+}
+
 func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
 	var gas uint64
 	// EIP150 homestead gas reprice fork:
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index b3b7310dd45d2ef3f288fdd9ca53b17d4629b5c2..ece4d2229ab10f6bdc5125bdbf0d459953017d84 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -32,6 +32,7 @@ var (
 	bigZero                  = new(big.Int)
 	errWriteProtection       = errors.New("evm: write protection")
 	errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
+	errExecutionReverted     = errors.New("evm: execution reverted")
 )
 
 func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
@@ -579,7 +580,7 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
 	}
 
 	contract.UseGas(gas)
-	_, addr, returnGas, suberr := evm.Create(contract, input, gas, value)
+	res, addr, returnGas, suberr := evm.Create(contract, input, gas, value)
 	// Push item on the stack based on the returned error. If the ruleset is
 	// homestead we must check for CodeStoreOutOfGasError (homestead only
 	// rule) and treat as an error, if the ruleset is frontier we must
@@ -592,9 +593,11 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
 		stack.push(addr.Big())
 	}
 	contract.Gas += returnGas
-
 	evm.interpreter.intPool.put(value, offset, size)
 
+	if suberr == errExecutionReverted {
+		return res, nil
+	}
 	return nil, nil
 }
 
@@ -622,7 +625,8 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
 		stack.push(new(big.Int))
 	} else {
 		stack.push(big.NewInt(1))
-
+	}
+	if err == nil || err == errExecutionReverted {
 		memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
 	}
 	contract.Gas += returnGas
@@ -653,10 +657,10 @@ func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
 	ret, returnGas, err := evm.CallCode(contract, address, args, gas, value)
 	if err != nil {
 		stack.push(new(big.Int))
-
 	} else {
 		stack.push(big.NewInt(1))
-
+	}
+	if err == nil || err == errExecutionReverted {
 		memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
 	}
 	contract.Gas += returnGas
@@ -676,6 +680,8 @@ func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st
 		stack.push(new(big.Int))
 	} else {
 		stack.push(big.NewInt(1))
+	}
+	if err == nil || err == errExecutionReverted {
 		memory.Set(outOffset.Uint64(), outSize.Uint64(), ret)
 	}
 	contract.Gas += returnGas
@@ -704,7 +710,8 @@ func opStaticCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac
 		stack.push(new(big.Int))
 	} else {
 		stack.push(big.NewInt(1))
-
+	}
+	if err == nil || err == errExecutionReverted {
 		memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
 	}
 	contract.Gas += returnGas
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index 23f930e9133a44f4428f85ae4db2e01e47698f8e..0466bf085cf6f14e54f24a7e9bb6db9103dc991e 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -209,24 +209,22 @@ func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret
 		if verifyPool {
 			verifyIntegerPool(in.intPool)
 		}
-		// checks whether the operation should revert state.
-		if operation.reverts {
-			in.evm.StateDB.RevertToSnapshot(snapshot)
+		// if the operation clears the return data (e.g. it has returning data)
+		// set the last return to the result of the operation.
+		if operation.returns {
+			in.returnData = res
 		}
 
 		switch {
 		case err != nil:
 			return nil, err
+		case operation.reverts:
+			return res, errExecutionReverted
 		case operation.halts:
 			return res, nil
 		case !operation.jumps:
 			pc++
 		}
-		// if the operation clears the return data (e.g. it has returning data)
-		// set the last return to the result of the operation.
-		if operation.returns {
-			in.returnData = res
-		}
 	}
 	return nil, nil
 }
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index 2d7697e9c1efcbe7bd6db873bbf1f1f5bfe489a7..f0a922912fd1d6194e0eb15ca4bbdd96be4a0702 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -41,20 +41,13 @@ type operation struct {
 	validateStack stackValidationFunc
 	// memorySize returns the memory size required for the operation
 	memorySize memorySizeFunc
-	// halts indicates whether the operation shoult halt further execution
-	// and return
-	halts bool
-	// jumps indicates whether operation made a jump. This prevents the program
-	// counter from further incrementing.
-	jumps bool
-	// writes determines whether this a state modifying operation
-	writes bool
-	// valid is used to check whether the retrieved operation is valid and known
-	valid bool
-	// reverts determined whether the operation reverts state
-	reverts bool
-	// returns determines whether the opertions sets the return data
-	returns bool
+
+	halts   bool // indicates whether the operation shoult halt further execution
+	jumps   bool // indicates whether the program counter should not increment
+	writes  bool // determines whether this a state modifying operation
+	valid   bool // indication whether the retrieved operation is valid and known
+	reverts bool // determines whether the operation reverts state (implicitly halts)
+	returns bool // determines whether the opertions sets the return data content
 }
 
 var (
@@ -91,10 +84,12 @@ func NewMetropolisInstructionSet() [256]operation {
 	}
 	instructionSet[REVERT] = operation{
 		execute:       opRevert,
-		gasCost:       constGasFunc(GasFastestStep),
+		gasCost:       gasRevert,
 		validateStack: makeStackFunc(2, 0),
+		memorySize:    memoryRevert,
 		valid:         true,
 		reverts:       true,
+		returns:       true,
 	}
 	return instructionSet
 }
diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go
index f1b671adcf9d78578c14eb595305a542baa471c6..bec0235bcc8977569c6f33f1dac8ad1dbb93294f 100644
--- a/core/vm/memory_table.go
+++ b/core/vm/memory_table.go
@@ -89,6 +89,10 @@ func memoryReturn(stack *Stack) *big.Int {
 	return calcMemSize(stack.Back(0), stack.Back(1))
 }
 
+func memoryRevert(stack *Stack) *big.Int {
+	return calcMemSize(stack.Back(0), stack.Back(1))
+}
+
 func memoryLog(stack *Stack) *big.Int {
 	mSize, mStart := stack.Back(1), stack.Back(0)
 	return calcMemSize(mStart, mSize)