diff --git a/vm/address.go b/vm/address.go
index 215f4bc8fa33b1f089160f5582acb29e65aa85dd..e4c33ec808f6ac85f132ad3934220677070b1d84 100644
--- a/vm/address.go
+++ b/vm/address.go
@@ -3,8 +3,8 @@ package vm
 import (
 	"math/big"
 
-	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/crypto"
 )
 
 type Address interface {
@@ -61,15 +61,29 @@ func ripemd160Func(in []byte) []byte {
 	return common.LeftPadBytes(crypto.Ripemd160(in), 32)
 }
 
-func ecrecoverFunc(in []byte) []byte {
-	// In case of an invalid sig. Defaults to return nil
-	defer func() { recover() }()
+const EcRecoverInputLength = 128
 
+func ecrecoverFunc(in []byte) []byte {
+	// "in" is (hash, v, r, s), each 32 bytes
+	// but for ecrecover we want (r, s, v)
+	if len(in) < EcRecoverInputLength {
+		return nil
+	}
 	hash := in[:32]
-	v := common.BigD(in[32:64]).Bytes()[0] - 27
+	// v is only a bit, but comes as 32 bytes from vm. We only need least significant byte
+	encodedV := in[32:64]
+	v := encodedV[31] - 27
+	if !(v == 0 || v == 1) {
+		return nil
+	}
 	sig := append(in[64:], v)
-
-	return common.LeftPadBytes(crypto.Sha3(crypto.Ecrecover(append(hash, sig...))[1:])[12:], 32)
+	pubKey := crypto.Ecrecover(append(hash, sig...))
+	// secp256.go returns either nil or 65 bytes
+	if pubKey == nil || len(pubKey) != 65 {
+		return nil
+	}
+	// the first byte of pubkey is bitcoin heritage
+	return common.LeftPadBytes(crypto.Sha3(pubKey[1:])[12:], 32)
 }
 
 func memCpy(in []byte) []byte {