diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index cca20386f7725b2676e8096f145ff48c01d3276b..4420887e10eb7359e0d377d22ca9253cdbeb2aa3 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -92,98 +92,98 @@
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/account",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/alert",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/blockchain",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/common",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/config",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/consensus",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/db",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/events",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/logger",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/mempool",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/merkle",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/node",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/p2p",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/permission/types",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/rpc",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/state",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/types",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/vm",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/wire",
-			"Comment": "0.1-61-g64bf8ec",
-			"Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b"
+			"Comment": "0.1-63-gb0c1ee2",
+			"Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d"
 		},
 		{
 			"ImportPath": "github.com/tommy351/gin-cors",
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go
index d35c5d8491c779418bcf5e74b1dcc6ca47816d60..7c50d8425882fed2ce634a966b02f87fa7d62aa6 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go
@@ -70,14 +70,14 @@ func NewNode(privValidator *types.PrivValidator) *Node {
 		wire.WriteJSON(genDoc, buf, n, err)
 		stateDB.Set(stypes.GenDocKey, buf.Bytes())
 		if *err != nil {
-			Exit(Fmt("Unable to write gendoc to db: %v", err))
+			Exit(Fmt("Unable to write gendoc to db: %v", *err))
 		}
 	} else {
 		genDocBytes := stateDB.Get(stypes.GenDocKey)
 		err := new(error)
 		wire.ReadJSONPtr(&genDoc, genDocBytes, err)
 		if *err != nil {
-			Exit(Fmt("Unable to read gendoc from db: %v", err))
+			Exit(Fmt("Unable to read gendoc from db: %v", *err))
 		}
 	}
 	// add the chainid to the global config
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go
index fcaf48d95a2c16cf10a2087bf7d2a543a5b15b08..580a3cc023d1451f9d23b92a38c3044cf8bbf6df 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go
@@ -2,6 +2,7 @@ package state
 
 import (
 	"bytes"
+	"encoding/hex"
 	"fmt"
 	"strconv"
 	"testing"
@@ -14,6 +15,7 @@ import (
 	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
+	vm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/vm"
 )
 
 /*
@@ -868,9 +870,9 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### HasBase")
 	// HasBase
-	snativeAddress, data := snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false)
+	snativeAddress, pF, data := snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false)
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		// return value should be true or false as a 32 byte array...
 		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
 			return fmt.Errorf("Expected 1. Got %X", ret)
@@ -880,21 +882,21 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### SetBase")
 	// SetBase
-	snativeAddress, data = snativePermTestInputCALL("set_base", user[3], ptypes.Bond, false)
+	snativeAddress, pF, data = snativePermTestInputCALL("set_base", user[3], ptypes.Bond, false)
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		// return value should be true or false as a 32 byte array...
 		if !IsZeros(ret) {
 			return fmt.Errorf("Expected 0. Got %X", ret)
 		}
 		return nil
 	})
-	snativeAddress, data = snativePermTestInputCALL("set_base", user[3], ptypes.CreateContract, true)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+	snativeAddress, pF, data = snativePermTestInputCALL("set_base", user[3], ptypes.CreateContract, true)
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		// return value should be true or false as a 32 byte array...
 		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
 			return fmt.Errorf("Expected 1. Got %X", ret)
@@ -904,11 +906,11 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### UnsetBase")
 	// UnsetBase
-	snativeAddress, data = snativePermTestInputCALL("unset_base", user[3], ptypes.CreateContract, false)
+	snativeAddress, pF, data = snativePermTestInputCALL("unset_base", user[3], ptypes.CreateContract, false)
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		if !IsZeros(ret) {
 			return fmt.Errorf("Expected 0. Got %X", ret)
 		}
@@ -917,11 +919,11 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### SetGlobal")
 	// SetGlobalPerm
-	snativeAddress, data = snativePermTestInputCALL("set_global", user[3], ptypes.CreateContract, true)
+	snativeAddress, pF, data = snativePermTestInputCALL("set_global", user[3], ptypes.CreateContract, true)
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		// return value should be true or false as a 32 byte array...
 		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
 			return fmt.Errorf("Expected 1. Got %X", ret)
@@ -931,9 +933,9 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### HasRole")
 	// HasRole
-	snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "bumble")
+	snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "bumble")
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
 			return fmt.Errorf("Expected 1. Got %X", ret)
 		}
@@ -942,18 +944,18 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### AddRole")
 	// AddRole
-	snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+	snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		if !IsZeros(ret) {
 			return fmt.Errorf("Expected 0. Got %X", ret)
 		}
 		return nil
 	})
-	snativeAddress, data = snativeRoleTestInputCALL("add_role", user[3], "chuck")
+	snativeAddress, pF, data = snativeRoleTestInputCALL("add_role", user[3], "chuck")
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
 			return fmt.Errorf("Expected 1. Got %X", ret)
 		}
@@ -962,11 +964,11 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### RmRole")
 	// RmRole
-	snativeAddress, data = snativeRoleTestInputCALL("rm_role", user[3], "chuck")
+	snativeAddress, pF, data = snativeRoleTestInputCALL("rm_role", user[3], "chuck")
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
-	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
+	snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
+	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		if !IsZeros(ret) {
 			return fmt.Errorf("Expected 0. Got %X", ret)
 		}
@@ -1087,21 +1089,17 @@ func execTxWaitEvent(t *testing.T, blockCache *BlockCache, tx types.Tx, eventid
 
 // give a contract perms for an snative, call it, it calls the snative, but shouldn't have permission
 func testSNativeCALLExpectFail(t *testing.T, blockCache *BlockCache, doug *acm.Account, snativeAddress, data []byte) {
-	testSNativeCALL(t, false, blockCache, doug, snativeAddress, data, nil)
+	testSNativeCALL(t, false, blockCache, doug, 0, snativeAddress, data, nil)
 }
 
 // give a contract perms for an snative, call it, it calls the snative, ensure the check funciton (f) succeeds
-func testSNativeCALLExpectPass(t *testing.T, blockCache *BlockCache, doug *acm.Account, snativeAddress, data []byte, f func([]byte) error) {
-	testSNativeCALL(t, true, blockCache, doug, snativeAddress, data, f)
+func testSNativeCALLExpectPass(t *testing.T, blockCache *BlockCache, doug *acm.Account, snativePerm ptypes.PermFlag, snativeAddress, data []byte, f func([]byte) error) {
+	testSNativeCALL(t, true, blockCache, doug, snativePerm, snativeAddress, data, f)
 }
 
-func testSNativeCALL(t *testing.T, expectPass bool, blockCache *BlockCache, doug *acm.Account, snativeAddress, data []byte, f func([]byte) error) {
+func testSNativeCALL(t *testing.T, expectPass bool, blockCache *BlockCache, doug *acm.Account, snativePerm ptypes.PermFlag, snativeAddress, data []byte, f func([]byte) error) {
 	if expectPass {
-		perm, err := ptypes.PermStringToFlag(TrimmedString(snativeAddress))
-		if err != nil {
-			t.Fatal(err)
-		}
-		doug.Permissions.Base.Set(perm, true)
+		doug.Permissions.Base.Set(snativePerm, true)
 	}
 	var addr []byte
 	contractCode := callContractCode(snativeAddress)
@@ -1169,8 +1167,18 @@ func boolToWord256(v bool) Word256 {
 	return LeftPadWord256([]byte{vint})
 }
 
-func snativePermTestInputCALL(name string, user *acm.PrivAccount, perm ptypes.PermFlag, val bool) (addr []byte, data []byte) {
-	addr = LeftPadWord256([]byte(name)).Postfix(20)
+func permNameToFuncID(s string) []byte {
+	for k, v := range vm.PermsMap {
+		if s == v.Name {
+			b, _ := hex.DecodeString(k)
+			return b
+		}
+	}
+	panic("didn't find snative function signature!")
+}
+
+func snativePermTestInputCALL(name string, user *acm.PrivAccount, perm ptypes.PermFlag, val bool) (addr []byte, pF ptypes.PermFlag, data []byte) {
+	addr = LeftPadWord256([]byte(vm.PermissionsContract)).Postfix(20)
 	switch name {
 	case "has_base", "unset_base":
 		data = LeftPadBytes(user.Address, 32)
@@ -1183,6 +1191,11 @@ func snativePermTestInputCALL(name string, user *acm.PrivAccount, perm ptypes.Pe
 		data = Uint64ToWord256(uint64(perm)).Bytes()
 		data = append(data, boolToWord256(val).Bytes()...)
 	}
+	data = append(permNameToFuncID(name), data...)
+	var err error
+	if pF, err = ptypes.PermStringToFlag(name); err != nil {
+		panic(Fmt("failed to convert perm string (%s) to flag", name))
+	}
 	return
 }
 
@@ -1200,10 +1213,16 @@ func snativePermTestInputTx(name string, user *acm.PrivAccount, perm ptypes.Perm
 	return
 }
 
-func snativeRoleTestInputCALL(name string, user *acm.PrivAccount, role string) (addr []byte, data []byte) {
-	addr = LeftPadWord256([]byte(name)).Postfix(20)
+func snativeRoleTestInputCALL(name string, user *acm.PrivAccount, role string) (addr []byte, pF ptypes.PermFlag, data []byte) {
+	addr = LeftPadWord256([]byte(vm.PermissionsContract)).Postfix(20)
 	data = LeftPadBytes(user.Address, 32)
 	data = append(data, LeftPadBytes([]byte(role), 32)...)
+	data = append(permNameToFuncID(name), data...)
+
+	var err error
+	if pF, err = ptypes.PermStringToFlag(name); err != nil {
+		panic(Fmt("failed to convert perm string (%s) to flag", name))
+	}
 	return
 }
 
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go
index ee6f9e27c9cee45d37ff30cea28b544fb801af3e..df62c1df4edaab54b033616fff738f844977bc9b 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go
@@ -42,7 +42,7 @@ type PrivValidator struct {
 	LastRound  int               `json:"last_round"`
 	LastStep   int8              `json:"last_step"`
 
-	// NOTE: A safer implemention leaves PrivKey empty and uses a secure key signing service.
+	// PrivKey should be empty if a Signer other than the default is being used.
 	PrivKey acm.PrivKeyEd25519 `json:"priv_key"`
 	signer  Signer
 
@@ -52,6 +52,9 @@ type PrivValidator struct {
 	mtx      sync.Mutex
 }
 
+// XXX: This is used to sign votes.
+// It is the caller's duty to verify the msg before calling Sign,
+// eg. to avoid double signing.
 type Signer interface {
 	Sign(msg []byte) acm.SignatureEd25519
 }
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go
index a9a5c9ee4dee933b043464852a53972c79eb25ff..b497364d7d111a77c1c64cadda65a29ec8adb742 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go
@@ -1,38 +1,98 @@
 package vm
 
 import (
+	"encoding/hex"
 	"fmt"
 
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
 )
 
-// TODO: ABI
 //------------------------------------------------------------------------------------------------
 // Registered SNative contracts
 
+var PermissionsContract = "permissions_contract"
+
 func registerSNativeContracts() {
-	registeredNativeContracts[LeftPadWord256([]byte("has_base"))] = hasBasePerm
-	registeredNativeContracts[LeftPadWord256([]byte("set_base"))] = setBasePerm
-	registeredNativeContracts[LeftPadWord256([]byte("unset_base"))] = unsetBasePerm
-	registeredNativeContracts[LeftPadWord256([]byte("set_global"))] = setGlobalPerm
-	registeredNativeContracts[LeftPadWord256([]byte("has_role"))] = hasRole
-	registeredNativeContracts[LeftPadWord256([]byte("add_role"))] = addRole
-	registeredNativeContracts[LeftPadWord256([]byte("rm_role"))] = rmRole
+	registeredNativeContracts[LeftPadWord256([]byte(PermissionsContract))] = permissionsContract
+
+	/*
+		// we could expose these but we moved permission and args checks into the permissionsContract
+		// so calling them would be unsafe ...
+		registeredNativeContracts[LeftPadWord256([]byte("has_base"))] = has_base
+		registeredNativeContracts[LeftPadWord256([]byte("set_base"))] = set_base
+		registeredNativeContracts[LeftPadWord256([]byte("unset_base"))] = unset_base
+		registeredNativeContracts[LeftPadWord256([]byte("set_global"))] = set_global
+		registeredNativeContracts[LeftPadWord256([]byte("has_role"))] = has_role
+		registeredNativeContracts[LeftPadWord256([]byte("add_role"))] = add_role
+		registeredNativeContracts[LeftPadWord256([]byte("rm_role"))] = rm_role
+	*/
 }
 
 //-----------------------------------------------------------------------------
 // snative are native contracts that can access and modify an account's permissions
 
-// TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?)
+type SNativeFuncDescription struct {
+	Name     string
+	NArgs    int
+	PermFlag ptypes.PermFlag
+	F        NativeContract
+}
+
+/* The solidity interface used to generate the abi function ids below
+contract Permissions {
+	function has_base(address addr, int permFlag) constant returns (bool value) {}
+	function set_base(address addr, int permFlag, bool value) constant returns (bool val) {}
+	function unset_base(address addr, int permFlag) constant returns (int pf) {}
+	function set_global(address addr, int permFlag, bool value) constant returns (int pf) {}
+	function has_role(address addr, string role) constant returns (bool val) {}
+	function add_role(address addr, string role) constant returns (bool added) {}
+	function rm_role(address addr, string role) constant returns (bool removed) {}
+}
+*/
+
+// function identifiers from the solidity abi
+var PermsMap = map[string]SNativeFuncDescription{
+	"054556ac": SNativeFuncDescription{"has_role", 2, ptypes.HasRole, has_role},
+	"180d26f2": SNativeFuncDescription{"unset_base", 2, ptypes.UnsetBase, unset_base},
+	"3a3fcc59": SNativeFuncDescription{"set_global", 2, ptypes.SetGlobal, set_global},
+	"9a1c4141": SNativeFuncDescription{"add_role", 2, ptypes.AddRole, add_role},
+	"9ea53314": SNativeFuncDescription{"set_base", 3, ptypes.SetBase, set_base},
+	"bb37737a": SNativeFuncDescription{"has_base", 2, ptypes.HasBase, has_base},
+	"ded3350a": SNativeFuncDescription{"rm_role", 2, ptypes.RmRole, rm_role},
+}
+
+func permissionsContract(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
+	if len(args) < 4 {
+		return nil, fmt.Errorf("permissionsContract expects at least a 4-byte function identifier")
+	}
+
+	// map solidity abi function id to snative
+	funcIDbytes := args[:4]
+	args = args[4:]
+	funcID := hex.EncodeToString(funcIDbytes)
+	d, ok := PermsMap[funcID]
+	if !ok {
+		return nil, fmt.Errorf("unknown permissionsContract funcID %s", funcID)
+	}
 
-func hasBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	if !HasPermission(appState, caller, ptypes.HasBase) {
-		return nil, ErrInvalidPermission{caller.Address, "has_base"}
+	// check if we have permission to call this function
+	if !HasPermission(appState, caller, d.PermFlag) {
+		return nil, ErrInvalidPermission{caller.Address, d.Name}
 	}
-	if len(args) != 2*32 {
-		return nil, fmt.Errorf("hasBasePerm() takes two arguments (address, permFlag)")
+
+	// ensure there are enough arguments
+	if len(args) != d.NArgs*32 {
+		return nil, fmt.Errorf("%s() takes %d arguments", d.Name)
 	}
+
+	// call the function
+	return d.F(appState, caller, args, gas)
+}
+
+// TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?)
+
+func has_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, permNum := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
@@ -42,23 +102,12 @@ func hasBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (o
 	if !ValidPermN(permN) {
 		return nil, ptypes.ErrInvalidPermission(permN)
 	}
-	var permInt byte
-	if HasPermission(appState, vmAcc, permN) {
-		permInt = 0x1
-	} else {
-		permInt = 0x0
-	}
+	permInt := byteFromBool(HasPermission(appState, vmAcc, permN))
 	dbg.Printf("snative.hasBasePerm(0x%X, %b) = %v\n", addr.Postfix(20), permN, permInt)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func setBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	if !HasPermission(appState, caller, ptypes.SetBase) {
-		return nil, ErrInvalidPermission{caller.Address, "set_base"}
-	}
-	if len(args) != 3*32 {
-		return nil, fmt.Errorf("setBase() takes three arguments (address, permFlag, permission value)")
-	}
+func set_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, permNum, perm := returnThreeArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
@@ -77,13 +126,7 @@ func setBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (o
 	return perm.Bytes(), nil
 }
 
-func unsetBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	if !HasPermission(appState, caller, ptypes.UnsetBase) {
-		return nil, ErrInvalidPermission{caller.Address, "unset_base"}
-	}
-	if len(args) != 2*32 {
-		return nil, fmt.Errorf("unsetBase() takes two arguments (address, permFlag)")
-	}
+func unset_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, permNum := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
@@ -101,13 +144,7 @@ func unsetBasePerm(appState AppState, caller *Account, args []byte, gas *int64)
 	return permNum.Bytes(), nil
 }
 
-func setGlobalPerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	if !HasPermission(appState, caller, ptypes.SetGlobal) {
-		return nil, ErrInvalidPermission{caller.Address, "set_global"}
-	}
-	if len(args) != 2*32 {
-		return nil, fmt.Errorf("setGlobal() takes two arguments (permFlag, permission value)")
-	}
+func set_global(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	permNum, perm := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(ptypes.GlobalPermissionsAddress256)
 	if vmAcc == nil {
@@ -126,72 +163,39 @@ func setGlobalPerm(appState AppState, caller *Account, args []byte, gas *int64)
 	return perm.Bytes(), nil
 }
 
-func hasRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	if !HasPermission(appState, caller, ptypes.HasRole) {
-		return nil, ErrInvalidPermission{caller.Address, "has_role"}
-	}
-	if len(args) != 2*32 {
-		return nil, fmt.Errorf("hasRole() takes two arguments (address, role)")
-	}
+func has_role(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, role := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
 		return nil, fmt.Errorf("Unknown account %X", addr)
 	}
 	roleS := string(role.Bytes())
-	var permInt byte
-	if vmAcc.Permissions.HasRole(roleS) {
-		permInt = 0x1
-	} else {
-		permInt = 0x0
-	}
+	permInt := byteFromBool(vmAcc.Permissions.HasRole(roleS))
 	dbg.Printf("snative.hasRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func addRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	if !HasPermission(appState, caller, ptypes.AddRole) {
-		return nil, ErrInvalidPermission{caller.Address, "add_role"}
-	}
-	if len(args) != 2*32 {
-		return nil, fmt.Errorf("addRole() takes two arguments (address, role)")
-	}
+func add_role(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, role := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
 		return nil, fmt.Errorf("Unknown account %X", addr)
 	}
 	roleS := string(role.Bytes())
-	var permInt byte
-	if vmAcc.Permissions.AddRole(roleS) {
-		permInt = 0x1
-	} else {
-		permInt = 0x0
-	}
+	permInt := byteFromBool(vmAcc.Permissions.AddRole(roleS))
 	appState.UpdateAccount(vmAcc)
 	dbg.Printf("snative.addRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func rmRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	if !HasPermission(appState, caller, ptypes.RmRole) {
-		return nil, ErrInvalidPermission{caller.Address, "rm_role"}
-	}
-	if len(args) != 2*32 {
-		return nil, fmt.Errorf("rmRole() takes two arguments (address, role)")
-	}
+func rm_role(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, role := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
 		return nil, fmt.Errorf("Unknown account %X", addr)
 	}
 	roleS := string(role.Bytes())
-	var permInt byte
-	if vmAcc.Permissions.RmRole(roleS) {
-		permInt = 0x1
-	} else {
-		permInt = 0x0
-	}
+	permInt := byteFromBool(vmAcc.Permissions.RmRole(roleS))
 	appState.UpdateAccount(vmAcc)
 	dbg.Printf("snative.rmRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
@@ -231,3 +235,10 @@ func returnThreeArgs(args []byte) (a Word256, b Word256, c Word256) {
 	copy(c[:], args[64:96])
 	return
 }
+
+func byteFromBool(b bool) byte {
+	if b {
+		return 0x1
+	}
+	return 0x0
+}