diff --git a/core/vm/evm.go b/core/vm/evm.go
index d47b0093889db726d39119646f9dc65759392a98..030f0c789cde040ee367cbb82cf336b97fe24cd8 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -44,7 +44,7 @@ type (
 func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) {
 	if contract.CodeAddr != nil {
 		precompiles := PrecompiledContractsHomestead
-		if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
+		if evm.chainRules.IsByzantium {
 			precompiles = PrecompiledContractsByzantium
 		}
 		if p := precompiles[*contract.CodeAddr]; p != nil {
@@ -203,10 +203,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
 	)
 	if !evm.StateDB.Exist(addr) {
 		precompiles := PrecompiledContractsHomestead
-		if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
+		if evm.chainRules.IsByzantium {
 			precompiles = PrecompiledContractsByzantium
 		}
-		if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
+		if precompiles[addr] == nil && evm.chainRules.IsEIP158 && value.Sign() == 0 {
 			// Calling a non existing account, don't do anything, but ping the tracer
 			if evm.vmConfig.Debug && evm.depth == 0 {
 				evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
@@ -394,7 +394,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
 	// Create a new account on the state
 	snapshot := evm.StateDB.Snapshot()
 	evm.StateDB.CreateAccount(address)
-	if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
+	if evm.chainRules.IsEIP158 {
 		evm.StateDB.SetNonce(address, 1)
 	}
 	evm.Transfer(evm.StateDB, caller.Address(), address, value)
@@ -416,7 +416,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
 	ret, err := run(evm, contract, nil, false)
 
 	// check whether the max code size has been exceeded
-	maxCodeSizeExceeded := evm.ChainConfig().IsEIP158(evm.BlockNumber) && len(ret) > params.MaxCodeSize
+	maxCodeSizeExceeded := evm.chainRules.IsEIP158 && 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
@@ -433,7 +433,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
 	// 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)) {
+	if maxCodeSizeExceeded || (err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas)) {
 		evm.StateDB.RevertToSnapshot(snapshot)
 		if err != errExecutionReverted {
 			contract.UseGas(contract.Gas)
diff --git a/core/vm/gas.go b/core/vm/gas.go
index 022a84f243c94ad706ca92d914bc57a6d32e010e..bd8b4f1042fa8b85d33811a31b0656f3952d5867 100644
--- a/core/vm/gas.go
+++ b/core/vm/gas.go
@@ -18,8 +18,6 @@ package vm
 
 import (
 	"math/big"
-
-	"github.com/ethereum/go-ethereum/params"
 )
 
 // Gas costs
@@ -34,10 +32,10 @@ const (
 
 // calcGas returns the actual gas cost of the call.
 //
-// The cost of gas was changed during the homestead price change HF. To allow for EIP150
-// to be implemented. The returned gas is gas - base * 63 / 64.
-func callGas(gasTable params.GasTable, availableGas, base uint64, callCost *big.Int) (uint64, error) {
-	if gasTable.CreateBySuicide > 0 {
+// The cost of gas was changed during the homestead price change HF.
+// As part of EIP 150 (TangerineWhistle), the returned gas is gas - base * 63 / 64.
+func callGas(isEip150 bool, availableGas, base uint64, callCost *big.Int) (uint64, error) {
+	if isEip150 {
 		availableGas = availableGas - base
 		gas := availableGas - availableGas/64
 		// If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index 8270300ba71dcd16ee6d18d532e7fc85438533b5..b2999fdea7f45e965fbd06787789c8cfd81309fe 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -53,59 +53,45 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
 	return 0, nil
 }
 
-func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	gas, err := memoryGasCost(mem, memorySize)
-	if err != nil {
-		return 0, err
-	}
-
-	var overflow bool
-	if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
-		return 0, errGasUintOverflow
-	}
-
-	words, overflow := bigUint64(stack.Back(2))
-	if overflow {
-		return 0, errGasUintOverflow
-	}
+// memoryCopierGas creates the gas functions for the following opcodes, and takes
+// the stack position of the operand which determines the size of the data to copy
+// as argument:
+// CALLDATACOPY (stack position 2)
+// CODECOPY (stack position 2)
+// EXTCODECOPY (stack poition 3)
+// RETURNDATACOPY (stack position 2)
+func memoryCopierGas(stackpos int) gasFunc {
+	return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+		// Gas for expanding the memory
+		gas, err := memoryGasCost(mem, memorySize)
+		if err != nil {
+			return 0, err
+		}
+		// And gas for copying data, charged per word at param.CopyGas
+		words, overflow := bigUint64(stack.Back(stackpos))
+		if overflow {
+			return 0, errGasUintOverflow
+		}
 
-	if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow {
-		return 0, errGasUintOverflow
-	}
+		if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow {
+			return 0, errGasUintOverflow
+		}
 
-	if gas, overflow = math.SafeAdd(gas, words); overflow {
-		return 0, errGasUintOverflow
+		if gas, overflow = math.SafeAdd(gas, words); overflow {
+			return 0, errGasUintOverflow
+		}
+		return gas, nil
 	}
-	return gas, nil
 }
 
-func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	gas, err := memoryGasCost(mem, memorySize)
-	if err != nil {
-		return 0, err
-	}
-
-	var overflow bool
-	if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
-		return 0, errGasUintOverflow
-	}
-
-	words, overflow := bigUint64(stack.Back(2))
-	if overflow {
-		return 0, errGasUintOverflow
-	}
-
-	if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow {
-		return 0, errGasUintOverflow
-	}
-
-	if gas, overflow = math.SafeAdd(gas, words); overflow {
-		return 0, errGasUintOverflow
-	}
-	return gas, nil
-}
+var (
+	gasCallDataCopy   = memoryCopierGas(2)
+	gasCodeCopy       = memoryCopierGas(2)
+	gasExtCodeCopy    = memoryCopierGas(3)
+	gasReturnDataCopy = memoryCopierGas(2)
+)
 
-func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
 	var (
 		y, x    = stack.Back(1), stack.Back(0)
 		current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x))
@@ -175,7 +161,7 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
 }
 
 func makeGasLog(n uint64) gasFunc {
-	return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+	return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
 		requestedSize, overflow := bigUint64(stack.Back(1))
 		if overflow {
 			return 0, errGasUintOverflow
@@ -204,17 +190,11 @@ func makeGasLog(n uint64) gasFunc {
 	}
 }
 
-func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	var overflow bool
+func gasSha3(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
 	gas, err := memoryGasCost(mem, memorySize)
 	if err != nil {
 		return 0, err
 	}
-
-	if gas, overflow = math.SafeAdd(gas, params.Sha3Gas); overflow {
-		return 0, errGasUintOverflow
-	}
-
 	wordGas, overflow := bigUint64(stack.Back(1))
 	if overflow {
 		return 0, errGasUintOverflow
@@ -228,117 +208,27 @@ func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
 	return gas, nil
 }
 
-func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	gas, err := memoryGasCost(mem, memorySize)
-	if err != nil {
-		return 0, err
-	}
-
-	var overflow bool
-	if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
-		return 0, errGasUintOverflow
-	}
-
-	wordGas, overflow := bigUint64(stack.Back(2))
-	if overflow {
-		return 0, errGasUintOverflow
-	}
-	if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow {
-		return 0, errGasUintOverflow
-	}
-	if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
-		return 0, errGasUintOverflow
-	}
-	return gas, nil
-}
-
-func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	gas, err := memoryGasCost(mem, memorySize)
-	if err != nil {
-		return 0, err
-	}
-
-	var overflow bool
-	if gas, overflow = math.SafeAdd(gas, gt.ExtcodeCopy); overflow {
-		return 0, errGasUintOverflow
-	}
-
-	wordGas, overflow := bigUint64(stack.Back(3))
-	if overflow {
-		return 0, errGasUintOverflow
-	}
-
-	if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow {
-		return 0, errGasUintOverflow
-	}
-
-	if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
-		return 0, errGasUintOverflow
-	}
-	return gas, nil
-}
-
-func gasExtCodeHash(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	return gt.ExtcodeHash, nil
-}
-
-func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	var overflow bool
-	gas, err := memoryGasCost(mem, memorySize)
-	if err != nil {
-		return 0, errGasUintOverflow
-	}
-	if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
-		return 0, errGasUintOverflow
-	}
-	return gas, nil
-}
-
-func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	var overflow bool
-	gas, err := memoryGasCost(mem, memorySize)
-	if err != nil {
-		return 0, errGasUintOverflow
-	}
-	if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
-		return 0, errGasUintOverflow
-	}
-	return gas, nil
-}
-
-func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	var overflow bool
-	gas, err := memoryGasCost(mem, memorySize)
-	if err != nil {
-		return 0, errGasUintOverflow
-	}
-	if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow {
-		return 0, errGasUintOverflow
-	}
-	return gas, nil
+// pureMemoryGascost is used by several operations, which aside from their
+// static cost have a dynamic cost which is solely based on the memory
+// expansion
+func pureMemoryGascost(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+	return memoryGasCost(mem, memorySize)
 }
 
-func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	var overflow bool
-	gas, err := memoryGasCost(mem, memorySize)
-	if err != nil {
-		return 0, err
-	}
-	if gas, overflow = math.SafeAdd(gas, params.CreateGas); overflow {
-		return 0, errGasUintOverflow
-	}
-	return gas, nil
-}
+var (
+	gasReturn  = pureMemoryGascost
+	gasRevert  = pureMemoryGascost
+	gasMLoad   = pureMemoryGascost
+	gasMStore8 = pureMemoryGascost
+	gasMStore  = pureMemoryGascost
+	gasCreate  = pureMemoryGascost
+)
 
-func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	var overflow bool
+func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
 	gas, err := memoryGasCost(mem, memorySize)
 	if err != nil {
 		return 0, err
 	}
-	if gas, overflow = math.SafeAdd(gas, params.Create2Gas); overflow {
-		return 0, errGasUintOverflow
-	}
 	wordGas, overflow := bigUint64(stack.Back(2))
 	if overflow {
 		return 0, errGasUintOverflow
@@ -349,27 +239,27 @@ func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
 	if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
 		return 0, errGasUintOverflow
 	}
-
 	return gas, nil
 }
 
-func gasBalance(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	return gt.Balance, nil
-}
-
-func gasExtCodeSize(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	return gt.ExtcodeSize, nil
-}
+func gasExpFrontier(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+	expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8)
 
-func gasSLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	return gt.SLoad, nil
+	var (
+		gas      = expByteLen * params.ExpByteFrontier // no overflow check required. Max is 256 * ExpByte gas
+		overflow bool
+	)
+	if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow {
+		return 0, errGasUintOverflow
+	}
+	return gas, nil
 }
 
-func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasExpEIP158(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
 	expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8)
 
 	var (
-		gas      = expByteLen * gt.ExpByte // no overflow check required. Max is 256 * ExpByte gas
+		gas      = expByteLen * params.ExpByteEIP158 // no overflow check required. Max is 256 * ExpByte gas
 		overflow bool
 	)
 	if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow {
@@ -378,14 +268,13 @@ func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
 	return gas, nil
 }
 
-func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
 	var (
-		gas            = gt.Calls
+		gas            uint64
 		transfersValue = stack.Back(2).Sign() != 0
 		address        = common.BigToAddress(stack.Back(1))
-		eip158         = evm.ChainConfig().IsEIP158(evm.BlockNumber)
 	)
-	if eip158 {
+	if evm.chainRules.IsEIP158 {
 		if transfersValue && evm.StateDB.Empty(address) {
 			gas += params.CallNewAccountGas
 		}
@@ -404,7 +293,7 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
 		return 0, errGasUintOverflow
 	}
 
-	evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0))
+	evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0))
 	if err != nil {
 		return 0, err
 	}
@@ -414,21 +303,22 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
 	return gas, nil
 }
 
-func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	gas := gt.Calls
-	if stack.Back(2).Sign() != 0 {
-		gas += params.CallValueTransferGas
-	}
+func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
 	memoryGas, err := memoryGasCost(mem, memorySize)
 	if err != nil {
 		return 0, err
 	}
-	var overflow bool
+	var (
+		gas      uint64
+		overflow bool
+	)
+	if stack.Back(2).Sign() != 0 {
+		gas += params.CallValueTransferGas
+	}
 	if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
 		return 0, errGasUintOverflow
 	}
-
-	evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0))
+	evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0))
 	if err != nil {
 		return 0, err
 	}
@@ -438,76 +328,57 @@ func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
 	return gas, nil
 }
 
-func gasReturn(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
-	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:
-	if evm.ChainConfig().IsEIP150(evm.BlockNumber) {
-		gas = gt.Suicide
-		var (
-			address = common.BigToAddress(stack.Back(0))
-			eip158  = evm.ChainConfig().IsEIP158(evm.BlockNumber)
-		)
-
-		if eip158 {
-			// if empty and transfers value
-			if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
-				gas += gt.CreateBySuicide
-			}
-		} else if !evm.StateDB.Exist(address) {
-			gas += gt.CreateBySuicide
-		}
-	}
-
-	if !evm.StateDB.HasSuicided(contract.Address()) {
-		evm.StateDB.AddRefund(params.SuicideRefundGas)
-	}
-	return gas, nil
-}
-
-func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
 	gas, err := memoryGasCost(mem, memorySize)
 	if err != nil {
 		return 0, err
 	}
-	var overflow bool
-	if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow {
-		return 0, errGasUintOverflow
-	}
-
-	evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0))
+	evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0))
 	if err != nil {
 		return 0, err
 	}
+	var overflow bool
 	if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
 		return 0, errGasUintOverflow
 	}
 	return gas, nil
 }
 
-func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
 	gas, err := memoryGasCost(mem, memorySize)
 	if err != nil {
 		return 0, err
 	}
-	var overflow bool
-	if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow {
-		return 0, errGasUintOverflow
-	}
-
-	evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0))
+	evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0))
 	if err != nil {
 		return 0, err
 	}
+	var overflow bool
 	if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
 		return 0, errGasUintOverflow
 	}
 	return gas, nil
 }
+
+func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+	var gas uint64
+	// EIP150 homestead gas reprice fork:
+	if evm.chainRules.IsEIP150 {
+		gas = params.SelfdestructGasEIP150
+		var address = common.BigToAddress(stack.Back(0))
+
+		if evm.chainRules.IsEIP158 {
+			// if empty and transfers value
+			if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
+				gas += params.CreateBySelfdestructGas
+			}
+		} else if !evm.StateDB.Exist(address) {
+			gas += params.CreateBySelfdestructGas
+		}
+	}
+
+	if !evm.StateDB.HasSuicided(contract.Address()) {
+		evm.StateDB.AddRefund(params.SelfdestructRefundGas)
+	}
+	return gas, nil
+}
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 2a062d7e772f805397a869daf3a9b1d9c42d5290..7b6909c9279aaf2f7252edd50689da3aa46b3b61 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -694,7 +694,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
 		input        = memory.Get(offset.Int64(), size.Int64())
 		gas          = contract.Gas
 	)
-	if interpreter.evm.ChainConfig().IsEIP150(interpreter.evm.BlockNumber) {
+	if interpreter.evm.chainRules.IsEIP150 {
 		gas -= gas / 64
 	}
 
@@ -704,7 +704,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
 	// homestead we must check for CodeStoreOutOfGasError (homestead only
 	// rule) and treat as an error, if the ruleset is frontier we must
 	// ignore this error and pretend the operation was successful.
-	if interpreter.evm.ChainConfig().IsHomestead(interpreter.evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas {
+	if interpreter.evm.chainRules.IsHomestead && suberr == ErrCodeStoreOutOfGas {
 		stack.push(interpreter.intPool.getZero())
 	} else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
 		stack.push(interpreter.intPool.getZero())
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index 989f85f5d31b9b6762c8544a954094a87a960c35..18081ec4c9a4921180e309bf896143aca1b28908 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -23,7 +23,6 @@ import (
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/common/math"
-	"github.com/ethereum/go-ethereum/params"
 )
 
 // Config are the configuration options for the Interpreter
@@ -71,9 +70,8 @@ type keccakState interface {
 
 // EVMInterpreter represents an EVM interpreter
 type EVMInterpreter struct {
-	evm      *EVM
-	cfg      Config
-	gasTable params.GasTable
+	evm *EVM
+	cfg Config
 
 	intPool *intPool
 
@@ -91,11 +89,15 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
 	// we'll set the default jump table.
 	if !cfg.JumpTable[STOP].valid {
 		switch {
-		case evm.ChainConfig().IsConstantinople(evm.BlockNumber):
+		case evm.chainRules.IsConstantinople:
 			cfg.JumpTable = constantinopleInstructionSet
-		case evm.ChainConfig().IsByzantium(evm.BlockNumber):
+		case evm.chainRules.IsByzantium:
 			cfg.JumpTable = byzantiumInstructionSet
-		case evm.ChainConfig().IsHomestead(evm.BlockNumber):
+		case evm.chainRules.IsEIP158:
+			cfg.JumpTable = spuriousDragonInstructionSet
+		case evm.chainRules.IsEIP150:
+			cfg.JumpTable = tangerineWhistleInstructionSet
+		case evm.chainRules.IsHomestead:
 			cfg.JumpTable = homesteadInstructionSet
 		default:
 			cfg.JumpTable = frontierInstructionSet
@@ -103,9 +105,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
 	}
 
 	return &EVMInterpreter{
-		evm:      evm,
-		cfg:      cfg,
-		gasTable: evm.ChainConfig().GasTable(evm.BlockNumber),
+		evm: evm,
+		cfg: cfg,
 	}
 }
 
@@ -210,6 +211,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
 			}
 		}
 		// Static portion of gas
+		cost = operation.constantGas // For tracing
 		if !contract.UseGas(operation.constantGas) {
 			return nil, ErrOutOfGas
 		}
@@ -234,8 +236,10 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
 		// consume the gas and return an error if not enough gas is available.
 		// cost is explicitly set so that the capture state defer method can get the proper cost
 		if operation.dynamicGas != nil {
-			cost, err = operation.dynamicGas(in.gasTable, in.evm, contract, stack, mem, memorySize)
-			if err != nil || !contract.UseGas(cost) {
+			var dynamicCost uint64
+			dynamicCost, err = operation.dynamicGas(in.evm, contract, stack, mem, memorySize)
+			cost += dynamicCost // total cost, for debug tracing
+			if err != nil || !contract.UseGas(dynamicCost) {
 				return nil, ErrOutOfGas
 			}
 		}
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index 425436f9e50f134d489c4b774aa0a7bfe77ff474..a14f3fd9802c672d21bbe12da8bfb78d1363c37a 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -24,7 +24,7 @@ import (
 
 type (
 	executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
-	gasFunc       func(params.GasTable, *EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
+	gasFunc       func(*EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
 	// memorySizeFunc returns the required size, and whether the operation overflowed a uint64
 	memorySizeFunc func(*Stack) (size uint64, overflow bool)
 )
@@ -54,10 +54,12 @@ type operation struct {
 }
 
 var (
-	frontierInstructionSet       = newFrontierInstructionSet()
-	homesteadInstructionSet      = newHomesteadInstructionSet()
-	byzantiumInstructionSet      = newByzantiumInstructionSet()
-	constantinopleInstructionSet = newConstantinopleInstructionSet()
+	frontierInstructionSet         = newFrontierInstructionSet()
+	homesteadInstructionSet        = newHomesteadInstructionSet()
+	tangerineWhistleInstructionSet = newTangerineWhistleInstructionSet()
+	spuriousDragonInstructionSet   = newSpuriousDragonInstructionSet()
+	byzantiumInstructionSet        = newByzantiumInstructionSet()
+	constantinopleInstructionSet   = newConstantinopleInstructionSet()
 )
 
 // NewConstantinopleInstructionSet returns the frontier, homestead
@@ -87,21 +89,22 @@ func newConstantinopleInstructionSet() [256]operation {
 		valid:       true,
 	}
 	instructionSet[EXTCODEHASH] = operation{
-		execute:    opExtCodeHash,
-		dynamicGas: gasExtCodeHash,
-		minStack:   minStack(1, 1),
-		maxStack:   maxStack(1, 1),
-		valid:      true,
+		execute:     opExtCodeHash,
+		constantGas: params.ExtcodeHashGas,
+		minStack:    minStack(1, 1),
+		maxStack:    maxStack(1, 1),
+		valid:       true,
 	}
 	instructionSet[CREATE2] = operation{
-		execute:    opCreate2,
-		dynamicGas: gasCreate2,
-		minStack:   minStack(4, 1),
-		maxStack:   maxStack(4, 1),
-		memorySize: memoryCreate2,
-		valid:      true,
-		writes:     true,
-		returns:    true,
+		execute:     opCreate2,
+		constantGas: params.Create2Gas,
+		dynamicGas:  gasCreate2,
+		minStack:    minStack(4, 1),
+		maxStack:    maxStack(4, 1),
+		memorySize:  memoryCreate2,
+		valid:       true,
+		writes:      true,
+		returns:     true,
 	}
 	return instructionSet
 }
@@ -110,15 +113,16 @@ func newConstantinopleInstructionSet() [256]operation {
 // byzantium instructions.
 func newByzantiumInstructionSet() [256]operation {
 	// instructions that can be executed during the homestead phase.
-	instructionSet := newHomesteadInstructionSet()
+	instructionSet := newSpuriousDragonInstructionSet()
 	instructionSet[STATICCALL] = operation{
-		execute:    opStaticCall,
-		dynamicGas: gasStaticCall,
-		minStack:   minStack(6, 1),
-		maxStack:   maxStack(6, 1),
-		memorySize: memoryStaticCall,
-		valid:      true,
-		returns:    true,
+		execute:     opStaticCall,
+		constantGas: params.CallGasEIP150,
+		dynamicGas:  gasStaticCall,
+		minStack:    minStack(6, 1),
+		maxStack:    maxStack(6, 1),
+		memorySize:  memoryStaticCall,
+		valid:       true,
+		returns:     true,
 	}
 	instructionSet[RETURNDATASIZE] = operation{
 		execute:     opReturnDataSize,
@@ -128,12 +132,13 @@ func newByzantiumInstructionSet() [256]operation {
 		valid:       true,
 	}
 	instructionSet[RETURNDATACOPY] = operation{
-		execute:    opReturnDataCopy,
-		dynamicGas: gasReturnDataCopy,
-		minStack:   minStack(3, 0),
-		maxStack:   maxStack(3, 0),
-		memorySize: memoryReturnDataCopy,
-		valid:      true,
+		execute:     opReturnDataCopy,
+		constantGas: GasFastestStep,
+		dynamicGas:  gasReturnDataCopy,
+		minStack:    minStack(3, 0),
+		maxStack:    maxStack(3, 0),
+		memorySize:  memoryReturnDataCopy,
+		valid:       true,
 	}
 	instructionSet[REVERT] = operation{
 		execute:    opRevert,
@@ -148,18 +153,40 @@ func newByzantiumInstructionSet() [256]operation {
 	return instructionSet
 }
 
+// EIP 158 a.k.a Spurious Dragon
+func newSpuriousDragonInstructionSet() [256]operation {
+	instructionSet := newTangerineWhistleInstructionSet()
+	instructionSet[EXP].dynamicGas = gasExpEIP158
+	return instructionSet
+
+}
+
+// EIP 150 a.k.a Tangerine Whistle
+func newTangerineWhistleInstructionSet() [256]operation {
+	instructionSet := newHomesteadInstructionSet()
+	instructionSet[BALANCE].constantGas = params.BalanceGasEIP150
+	instructionSet[EXTCODESIZE].constantGas = params.ExtcodeSizeGasEIP150
+	instructionSet[SLOAD].constantGas = params.SloadGasEIP150
+	instructionSet[EXTCODECOPY].constantGas = params.ExtcodeCopyBaseEIP150
+	instructionSet[CALL].constantGas = params.CallGasEIP150
+	instructionSet[CALLCODE].constantGas = params.CallGasEIP150
+	instructionSet[DELEGATECALL].constantGas = params.CallGasEIP150
+	return instructionSet
+}
+
 // NewHomesteadInstructionSet returns the frontier and homestead
 // instructions that can be executed during the homestead phase.
 func newHomesteadInstructionSet() [256]operation {
 	instructionSet := newFrontierInstructionSet()
 	instructionSet[DELEGATECALL] = operation{
-		execute:    opDelegateCall,
-		dynamicGas: gasDelegateCall,
-		minStack:   minStack(6, 1),
-		maxStack:   maxStack(6, 1),
-		memorySize: memoryDelegateCall,
-		valid:      true,
-		returns:    true,
+		execute:     opDelegateCall,
+		dynamicGas:  gasDelegateCall,
+		constantGas: params.CallGasFrontier,
+		minStack:    minStack(6, 1),
+		maxStack:    maxStack(6, 1),
+		memorySize:  memoryDelegateCall,
+		valid:       true,
+		returns:     true,
 	}
 	return instructionSet
 }
@@ -241,7 +268,7 @@ func newFrontierInstructionSet() [256]operation {
 		},
 		EXP: {
 			execute:    opExp,
-			dynamicGas: gasExp,
+			dynamicGas: gasExpFrontier,
 			minStack:   minStack(2, 1),
 			maxStack:   maxStack(2, 1),
 			valid:      true,
@@ -331,12 +358,13 @@ func newFrontierInstructionSet() [256]operation {
 			valid:       true,
 		},
 		SHA3: {
-			execute:    opSha3,
-			dynamicGas: gasSha3,
-			minStack:   minStack(2, 1),
-			maxStack:   maxStack(2, 1),
-			memorySize: memorySha3,
-			valid:      true,
+			execute:     opSha3,
+			constantGas: params.Sha3Gas,
+			dynamicGas:  gasSha3,
+			minStack:    minStack(2, 1),
+			maxStack:    maxStack(2, 1),
+			memorySize:  memorySha3,
+			valid:       true,
 		},
 		ADDRESS: {
 			execute:     opAddress,
@@ -346,11 +374,11 @@ func newFrontierInstructionSet() [256]operation {
 			valid:       true,
 		},
 		BALANCE: {
-			execute:    opBalance,
-			dynamicGas: gasBalance,
-			minStack:   minStack(1, 1),
-			maxStack:   maxStack(1, 1),
-			valid:      true,
+			execute:     opBalance,
+			constantGas: params.BalanceGasFrontier,
+			minStack:    minStack(1, 1),
+			maxStack:    maxStack(1, 1),
+			valid:       true,
 		},
 		ORIGIN: {
 			execute:     opOrigin,
@@ -388,12 +416,13 @@ func newFrontierInstructionSet() [256]operation {
 			valid:       true,
 		},
 		CALLDATACOPY: {
-			execute:    opCallDataCopy,
-			dynamicGas: gasCallDataCopy,
-			minStack:   minStack(3, 0),
-			maxStack:   maxStack(3, 0),
-			memorySize: memoryCallDataCopy,
-			valid:      true,
+			execute:     opCallDataCopy,
+			constantGas: GasFastestStep,
+			dynamicGas:  gasCallDataCopy,
+			minStack:    minStack(3, 0),
+			maxStack:    maxStack(3, 0),
+			memorySize:  memoryCallDataCopy,
+			valid:       true,
 		},
 		CODESIZE: {
 			execute:     opCodeSize,
@@ -403,12 +432,13 @@ func newFrontierInstructionSet() [256]operation {
 			valid:       true,
 		},
 		CODECOPY: {
-			execute:    opCodeCopy,
-			dynamicGas: gasCodeCopy,
-			minStack:   minStack(3, 0),
-			maxStack:   maxStack(3, 0),
-			memorySize: memoryCodeCopy,
-			valid:      true,
+			execute:     opCodeCopy,
+			constantGas: GasFastestStep,
+			dynamicGas:  gasCodeCopy,
+			minStack:    minStack(3, 0),
+			maxStack:    maxStack(3, 0),
+			memorySize:  memoryCodeCopy,
+			valid:       true,
 		},
 		GASPRICE: {
 			execute:     opGasprice,
@@ -418,19 +448,20 @@ func newFrontierInstructionSet() [256]operation {
 			valid:       true,
 		},
 		EXTCODESIZE: {
-			execute:    opExtCodeSize,
-			dynamicGas: gasExtCodeSize,
-			minStack:   minStack(1, 1),
-			maxStack:   maxStack(1, 1),
-			valid:      true,
+			execute:     opExtCodeSize,
+			constantGas: params.ExtcodeSizeGasFrontier,
+			minStack:    minStack(1, 1),
+			maxStack:    maxStack(1, 1),
+			valid:       true,
 		},
 		EXTCODECOPY: {
-			execute:    opExtCodeCopy,
-			dynamicGas: gasExtCodeCopy,
-			minStack:   minStack(4, 0),
-			maxStack:   maxStack(4, 0),
-			memorySize: memoryExtCodeCopy,
-			valid:      true,
+			execute:     opExtCodeCopy,
+			constantGas: params.ExtcodeCopyBaseFrontier,
+			dynamicGas:  gasExtCodeCopy,
+			minStack:    minStack(4, 0),
+			maxStack:    maxStack(4, 0),
+			memorySize:  memoryExtCodeCopy,
+			valid:       true,
 		},
 		BLOCKHASH: {
 			execute:     opBlockhash,
@@ -482,36 +513,39 @@ func newFrontierInstructionSet() [256]operation {
 			valid:       true,
 		},
 		MLOAD: {
-			execute:    opMload,
-			dynamicGas: gasMLoad,
-			minStack:   minStack(1, 1),
-			maxStack:   maxStack(1, 1),
-			memorySize: memoryMLoad,
-			valid:      true,
+			execute:     opMload,
+			constantGas: GasFastestStep,
+			dynamicGas:  gasMLoad,
+			minStack:    minStack(1, 1),
+			maxStack:    maxStack(1, 1),
+			memorySize:  memoryMLoad,
+			valid:       true,
 		},
 		MSTORE: {
-			execute:    opMstore,
-			dynamicGas: gasMStore,
-			minStack:   minStack(2, 0),
-			maxStack:   maxStack(2, 0),
-			memorySize: memoryMStore,
-			valid:      true,
+			execute:     opMstore,
+			constantGas: GasFastestStep,
+			dynamicGas:  gasMStore,
+			minStack:    minStack(2, 0),
+			maxStack:    maxStack(2, 0),
+			memorySize:  memoryMStore,
+			valid:       true,
 		},
 		MSTORE8: {
-			execute:    opMstore8,
-			dynamicGas: gasMStore8,
-			memorySize: memoryMStore8,
-			minStack:   minStack(2, 0),
-			maxStack:   maxStack(2, 0),
+			execute:     opMstore8,
+			constantGas: GasFastestStep,
+			dynamicGas:  gasMStore8,
+			memorySize:  memoryMStore8,
+			minStack:    minStack(2, 0),
+			maxStack:    maxStack(2, 0),
 
 			valid: true,
 		},
 		SLOAD: {
-			execute:    opSload,
-			dynamicGas: gasSLoad,
-			minStack:   minStack(1, 1),
-			maxStack:   maxStack(1, 1),
-			valid:      true,
+			execute:     opSload,
+			constantGas: params.SloadGasFrontier,
+			minStack:    minStack(1, 1),
+			maxStack:    maxStack(1, 1),
+			valid:       true,
 		},
 		SSTORE: {
 			execute:    opSstore,
@@ -1059,32 +1093,35 @@ func newFrontierInstructionSet() [256]operation {
 			writes:     true,
 		},
 		CREATE: {
-			execute:    opCreate,
-			dynamicGas: gasCreate,
-			minStack:   minStack(3, 1),
-			maxStack:   maxStack(3, 1),
-			memorySize: memoryCreate,
-			valid:      true,
-			writes:     true,
-			returns:    true,
+			execute:     opCreate,
+			constantGas: params.CreateGas,
+			dynamicGas:  gasCreate,
+			minStack:    minStack(3, 1),
+			maxStack:    maxStack(3, 1),
+			memorySize:  memoryCreate,
+			valid:       true,
+			writes:      true,
+			returns:     true,
 		},
 		CALL: {
-			execute:    opCall,
-			dynamicGas: gasCall,
-			minStack:   minStack(7, 1),
-			maxStack:   maxStack(7, 1),
-			memorySize: memoryCall,
-			valid:      true,
-			returns:    true,
+			execute:     opCall,
+			constantGas: params.CallGasFrontier,
+			dynamicGas:  gasCall,
+			minStack:    minStack(7, 1),
+			maxStack:    maxStack(7, 1),
+			memorySize:  memoryCall,
+			valid:       true,
+			returns:     true,
 		},
 		CALLCODE: {
-			execute:    opCallCode,
-			dynamicGas: gasCallCode,
-			minStack:   minStack(7, 1),
-			maxStack:   maxStack(7, 1),
-			memorySize: memoryCall,
-			valid:      true,
-			returns:    true,
+			execute:     opCallCode,
+			constantGas: params.CallGasFrontier,
+			dynamicGas:  gasCallCode,
+			minStack:    minStack(7, 1),
+			maxStack:    maxStack(7, 1),
+			memorySize:  memoryCall,
+			valid:       true,
+			returns:     true,
 		},
 		RETURN: {
 			execute:    opReturn,
@@ -1097,7 +1134,7 @@ func newFrontierInstructionSet() [256]operation {
 		},
 		SELFDESTRUCT: {
 			execute:    opSuicide,
-			dynamicGas: gasSuicide,
+			dynamicGas: gasSelfdestruct,
 			minStack:   minStack(1, 0),
 			maxStack:   maxStack(1, 0),
 			halts:      true,
diff --git a/params/config.go b/params/config.go
index 2c7be848a7dfeeae725dced94f9b3ff4d6c15a09..8c40b797dc58c73ab8e9a74de0b39d0599167c8e 100644
--- a/params/config.go
+++ b/params/config.go
@@ -386,25 +386,6 @@ func (c *ChainConfig) IsEWASM(num *big.Int) bool {
 	return isForked(c.EWASMBlock, num)
 }
 
-// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
-//
-// The returned GasTable's fields shouldn't, under any circumstances, be changed.
-func (c *ChainConfig) GasTable(num *big.Int) GasTable {
-	if num == nil {
-		return GasTableHomestead
-	}
-	switch {
-	case c.IsConstantinople(num):
-		return GasTableConstantinople
-	case c.IsEIP158(num):
-		return GasTableEIP158
-	case c.IsEIP150(num):
-		return GasTableEIP150
-	default:
-		return GasTableHomestead
-	}
-}
-
 // CheckCompatible checks whether scheduled fork transitions have been imported
 // with a mismatching chain configuration.
 func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError {
diff --git a/params/gas_table.go b/params/gas_table.go
deleted file mode 100644
index 6c4a38269cda01966a983c62a136d4c3c4a24869..0000000000000000000000000000000000000000
--- a/params/gas_table.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// 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.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-package params
-
-// GasTable organizes gas prices for different ethereum phases.
-type GasTable struct {
-	ExtcodeSize uint64
-	ExtcodeCopy uint64
-	ExtcodeHash uint64
-	Balance     uint64
-	SLoad       uint64
-	Calls       uint64
-	Suicide     uint64
-
-	ExpByte uint64
-
-	// CreateBySuicide occurs when the
-	// refunded account is one that does
-	// not exist. This logic is similar
-	// to call. May be left nil. Nil means
-	// not charged.
-	CreateBySuicide uint64
-}
-
-// Variables containing gas prices for different ethereum phases.
-var (
-	// GasTableHomestead contain the gas prices for
-	// the homestead phase.
-	GasTableHomestead = GasTable{
-		ExtcodeSize: 20,
-		ExtcodeCopy: 20,
-		Balance:     20,
-		SLoad:       50,
-		Calls:       40,
-		Suicide:     0,
-		ExpByte:     10,
-	}
-
-	// GasTableEIP150 contain the gas re-prices for
-	// the EIP150 phase.
-	GasTableEIP150 = GasTable{
-		ExtcodeSize: 700,
-		ExtcodeCopy: 700,
-		Balance:     400,
-		SLoad:       200,
-		Calls:       700,
-		Suicide:     5000,
-		ExpByte:     10,
-
-		CreateBySuicide: 25000,
-	}
-	// GasTableEIP158 contain the gas re-prices for
-	// the EIP155/EIP158 phase.
-	GasTableEIP158 = GasTable{
-		ExtcodeSize: 700,
-		ExtcodeCopy: 700,
-		Balance:     400,
-		SLoad:       200,
-		Calls:       700,
-		Suicide:     5000,
-		ExpByte:     50,
-
-		CreateBySuicide: 25000,
-	}
-	// GasTableConstantinople contain the gas re-prices for
-	// the constantinople phase.
-	GasTableConstantinople = GasTable{
-		ExtcodeSize: 700,
-		ExtcodeCopy: 700,
-		ExtcodeHash: 400,
-		Balance:     400,
-		SLoad:       200,
-		Calls:       700,
-		Suicide:     5000,
-		ExpByte:     50,
-
-		CreateBySuicide: 25000,
-	}
-)
diff --git a/params/protocol_params.go b/params/protocol_params.go
index 14750f6a1a346afa850309f9b94d9780b991ed04..01dc197affe9850e8c4966504c201d417e67b523 100644
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
@@ -52,22 +52,48 @@ const (
 	NetSstoreResetRefund      uint64 = 4800  // Once per SSTORE operation for resetting to the original non-zero value
 	NetSstoreResetClearRefund uint64 = 19800 // Once per SSTORE operation for resetting to the original zero value
 
-	JumpdestGas      uint64 = 1     // Once per JUMPDEST operation.
-	EpochDuration    uint64 = 30000 // Duration between proof-of-work epochs.
-	CallGas          uint64 = 40    // Once per CALL operation & message call transaction.
-	CreateDataGas    uint64 = 200   //
-	CallCreateDepth  uint64 = 1024  // Maximum depth of call/create stack.
-	ExpGas           uint64 = 10    // Once per EXP instruction
-	LogGas           uint64 = 375   // Per LOG* operation.
-	CopyGas          uint64 = 3     //
-	StackLimit       uint64 = 1024  // Maximum size of VM stack allowed.
-	TierStepGas      uint64 = 0     // Once per operation, for a selection of them.
-	LogTopicGas      uint64 = 375   // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
-	CreateGas        uint64 = 32000 // Once per CREATE operation & contract-creation transaction.
-	Create2Gas       uint64 = 32000 // Once per CREATE2 operation
-	SuicideRefundGas uint64 = 24000 // Refunded following a suicide operation.
-	MemoryGas        uint64 = 3     // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
-	TxDataNonZeroGas uint64 = 68    // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
+	JumpdestGas   uint64 = 1     // Once per JUMPDEST operation.
+	EpochDuration uint64 = 30000 // Duration between proof-of-work epochs.
+
+	CreateDataGas         uint64 = 200   //
+	CallCreateDepth       uint64 = 1024  // Maximum depth of call/create stack.
+	ExpGas                uint64 = 10    // Once per EXP instruction
+	LogGas                uint64 = 375   // Per LOG* operation.
+	CopyGas               uint64 = 3     //
+	StackLimit            uint64 = 1024  // Maximum size of VM stack allowed.
+	TierStepGas           uint64 = 0     // Once per operation, for a selection of them.
+	LogTopicGas           uint64 = 375   // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
+	CreateGas             uint64 = 32000 // Once per CREATE operation & contract-creation transaction.
+	Create2Gas            uint64 = 32000 // Once per CREATE2 operation
+	SelfdestructRefundGas uint64 = 24000 // Refunded following a selfdestruct operation.
+	MemoryGas             uint64 = 3     // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
+	TxDataNonZeroGas      uint64 = 68    // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
+
+	// These have been changed during the course of the chain
+	CallGasFrontier        uint64 = 40  // Once per CALL operation & message call transaction.
+	CallGasEIP150          uint64 = 700 // Static portion of gas for CALL-derivates after EIP 150 (Tangerine)
+	BalanceGasFrontier     uint64 = 20  // The cost of a BALANCE operation
+	BalanceGasEIP150       uint64 = 400 // The cost of a BALANCE operation after Tangerine
+	ExtcodeSizeGasFrontier uint64 = 20  // Cost of EXTCODESIZE before EIP 150 (Tangerine)
+	ExtcodeSizeGasEIP150   uint64 = 700 // Cost of EXTCODESIZE after EIP 150 (Tangerine)
+	SloadGasFrontier       uint64 = 50
+	SloadGasEIP150         uint64 = 200
+	ExtcodeHashGas         uint64 = 400  // Cost of EXTCODEHASH (introduced in Constantinople)
+	SelfdestructGasEIP150  uint64 = 5000 // Cost of SELFDESTRUCT post EIP 150 (Tangerine)
+
+	// EXP has a dynamic portion depending on the size of the exponent
+	ExpByteFrontier uint64 = 10 // was set to 10 in Frontier
+	ExpByteEIP158   uint64 = 50 // was raised to 50 during Eip158 (Spurious Dragon)
+
+	// Extcodecopy has a dynamic AND a static cost. This represents only the
+	// static portion of the gas. It was changed during EIP 150 (Tangerine)
+	ExtcodeCopyBaseFrontier uint64 = 20
+	ExtcodeCopyBaseEIP150   uint64 = 700
+
+	// CreateBySelfdestructGas is used when the refunded account is one that does
+	// not exist. This logic is similar to call.
+	// Introduced in Tangerine Whistle (Eip 150)
+	CreateBySelfdestructGas uint64 = 25000
 
 	MaxCodeSize = 24576 // Maximum bytecode to permit for a contract