diff --git a/common/math/big.go b/common/math/big.go
index fd0174b366f5b3ec2dc11951e98050de4628f60b..78727865032a6c05701c36904c32bacbf21978ae 100644
--- a/common/math/big.go
+++ b/common/math/big.go
@@ -130,6 +130,34 @@ func PaddedBigBytes(bigint *big.Int, n int) []byte {
 	return ret
 }
 
+// bigEndianByteAt returns the byte at position n,
+// in Big-Endian encoding
+// So n==0 returns the least significant byte
+func bigEndianByteAt(bigint *big.Int, n int) byte {
+	words := bigint.Bits()
+	// Check word-bucket the byte will reside in
+	i := n / wordBytes
+	if i >= len(words) {
+		return byte(0)
+	}
+	word := words[i]
+	// Offset of the byte
+	shift := 8 * uint(n%wordBytes)
+
+	return byte(word >> shift)
+}
+
+// Byte returns the byte at position n,
+// with the supplied padlength in Little-Endian encoding.
+// n==0 returns the MSB
+// Example: bigint '5', padlength 32, n=31 => 5
+func Byte(bigint *big.Int, padlength, n int) byte {
+	if n >= padlength {
+		return byte(0)
+	}
+	return bigEndianByteAt(bigint, padlength-1-n)
+}
+
 // ReadBits encodes the absolute value of bigint as big-endian bytes. Callers must ensure
 // that buf has enough space. If buf is too short the result will be incomplete.
 func ReadBits(bigint *big.Int, buf []byte) {
diff --git a/common/math/big_test.go b/common/math/big_test.go
index e789bd18e1381b32d2df87ecd4ad0b07967e7cea..be9810dc8cf54de243b90dd741ca283dfba8cc3a 100644
--- a/common/math/big_test.go
+++ b/common/math/big_test.go
@@ -21,6 +21,8 @@ import (
 	"encoding/hex"
 	"math/big"
 	"testing"
+
+	"github.com/ethereum/go-ethereum/common"
 )
 
 func TestHexOrDecimal256(t *testing.T) {
@@ -133,8 +135,44 @@ func TestPaddedBigBytes(t *testing.T) {
 	}
 }
 
-func BenchmarkPaddedBigBytes(b *testing.B) {
+func BenchmarkPaddedBigBytesLargePadding(b *testing.B) {
 	bigint := MustParseBig256("123456789123456789123456789123456789")
+	for i := 0; i < b.N; i++ {
+		PaddedBigBytes(bigint, 200)
+	}
+}
+
+func BenchmarkPaddedBigBytesSmallPadding(b *testing.B) {
+	bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
+	for i := 0; i < b.N; i++ {
+		PaddedBigBytes(bigint, 5)
+	}
+}
+
+func BenchmarkPaddedBigBytesSmallOnePadding(b *testing.B) {
+	bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
+	for i := 0; i < b.N; i++ {
+		PaddedBigBytes(bigint, 32)
+	}
+}
+
+func BenchmarkByteAtBrandNew(b *testing.B) {
+	bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
+	for i := 0; i < b.N; i++ {
+		bigEndianByteAt(bigint, 15)
+	}
+}
+
+func BenchmarkByteAt(b *testing.B) {
+	bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
+	for i := 0; i < b.N; i++ {
+		bigEndianByteAt(bigint, 15)
+	}
+}
+
+func BenchmarkByteAtOld(b *testing.B) {
+
+	bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
 	for i := 0; i < b.N; i++ {
 		PaddedBigBytes(bigint, 32)
 	}
@@ -174,6 +212,65 @@ func TestU256(t *testing.T) {
 	}
 }
 
+func TestBigEndianByteAt(t *testing.T) {
+	tests := []struct {
+		x   string
+		y   int
+		exp byte
+	}{
+		{"00", 0, 0x00},
+		{"01", 1, 0x00},
+		{"00", 1, 0x00},
+		{"01", 0, 0x01},
+		{"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x30},
+		{"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x20},
+		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0xAB},
+		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00},
+		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 500, 0x00},
+	}
+	for _, test := range tests {
+		v := new(big.Int).SetBytes(common.Hex2Bytes(test.x))
+		actual := bigEndianByteAt(v, test.y)
+		if actual != test.exp {
+			t.Fatalf("Expected  [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual)
+		}
+
+	}
+}
+func TestLittleEndianByteAt(t *testing.T) {
+	tests := []struct {
+		x   string
+		y   int
+		exp byte
+	}{
+		{"00", 0, 0x00},
+		{"01", 1, 0x00},
+		{"00", 1, 0x00},
+		{"01", 0, 0x00},
+		{"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x00},
+		{"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x00},
+		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0x00},
+		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00},
+		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 0, 0xAB},
+		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 1, 0xCD},
+		{"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 0, 0x00},
+		{"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 1, 0xCD},
+		{"0000000000000000000000000000000000000000000000000000000000102030", 31, 0x30},
+		{"0000000000000000000000000000000000000000000000000000000000102030", 30, 0x20},
+		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 32, 0x0},
+		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 31, 0xFF},
+		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0xFFFF, 0x0},
+	}
+	for _, test := range tests {
+		v := new(big.Int).SetBytes(common.Hex2Bytes(test.x))
+		actual := Byte(v, 32, test.y)
+		if actual != test.exp {
+			t.Fatalf("Expected  [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual)
+		}
+
+	}
+}
+
 func TestS256(t *testing.T) {
 	tests := []struct{ x, y *big.Int }{
 		{x: big.NewInt(0), y: big.NewInt(0)},
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 42f1781d8878ad6a4a836db8063cdaf46b921230..f5164fcdd43e98496265d4ef4ce92b5f0b40c0ff 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -256,15 +256,14 @@ func opXor(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac
 }
 
 func opByte(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
-	th, val := stack.pop(), stack.pop()
-	if th.Cmp(big.NewInt(32)) < 0 {
-		byte := evm.interpreter.intPool.get().SetInt64(int64(math.PaddedBigBytes(val, 32)[th.Int64()]))
-		stack.push(byte)
+	th, val := stack.pop(), stack.peek()
+	if th.Cmp(common.Big32) < 0 {
+		b := math.Byte(val, 32, int(th.Int64()))
+		val.SetUint64(uint64(b))
 	} else {
-		stack.push(new(big.Int))
+		val.SetUint64(0)
 	}
-
-	evm.interpreter.intPool.put(th, val)
+	evm.interpreter.intPool.put(th)
 	return nil, nil
 }
 func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..ae428aeabaa00dc8376a2932077f50f2b992fe43
--- /dev/null
+++ b/core/vm/instructions_test.go
@@ -0,0 +1,42 @@
+package vm
+
+import (
+	"math/big"
+	"testing"
+
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/params"
+)
+
+func TestByteOp(t *testing.T) {
+	var (
+		env   = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
+		stack = newstack()
+	)
+	tests := []struct {
+		v        string
+		th       uint64
+		expected *big.Int
+	}{
+		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 0, big.NewInt(0xAB)},
+		{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 1, big.NewInt(0xCD)},
+		{"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 0, big.NewInt(0x00)},
+		{"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 1, big.NewInt(0xCD)},
+		{"0000000000000000000000000000000000000000000000000000000000102030", 31, big.NewInt(0x30)},
+		{"0000000000000000000000000000000000000000000000000000000000102030", 30, big.NewInt(0x20)},
+		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 32, big.NewInt(0x0)},
+		{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0xFFFFFFFFFFFFFFFF, big.NewInt(0x0)},
+	}
+	pc := uint64(0)
+	for _, test := range tests {
+		val := new(big.Int).SetBytes(common.Hex2Bytes(test.v))
+		th := new(big.Int).SetUint64(test.th)
+		stack.push(val)
+		stack.push(th)
+		opByte(&pc, env, nil, nil, stack)
+		actual := stack.pop()
+		if actual.Cmp(test.expected) != 0 {
+			t.Fatalf("Expected  [%v] %v:th byte to be %v, was %v.", test.v, test.th, test.expected, actual)
+		}
+	}
+}