diff --git a/Makefile b/Makefile
index 29bbd1a874f96fb7813e15138112d522399992d6..a05fe57e210c74affc132397a405f4cee63813fb 100644
--- a/Makefile
+++ b/Makefile
@@ -73,6 +73,11 @@ hell:
 	go build -o ${REPO}/target/hell ./util/hell/cmd/hell/main.go
 	./target/hell $(filter-out $@,$(MAKECMDGOALS))
 
+# Dumps Solidity interface contracts for SNatives
+.PHONY: snatives
+snatives:
+	@go run ./util/snatives/cmd/main.go
+
 ### Building github.com/eris-ltd/eris-db
 
 # build all targets in github.com/eris-ltd/eris-db
diff --git a/client/rpc/client.go b/client/rpc/client.go
index 77ed13b528cf10853ab790088a456e777ecf910c..72c2002f6f0d43f6805d3149260a1164f354b176 100644
--- a/client/rpc/client.go
+++ b/client/rpc/client.go
@@ -99,19 +99,6 @@ func Name(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, addr,
 	return tx, nil
 }
 
-type PermFunc struct {
-	Name string
-	Args string
-}
-
-var PermsFuncs = []PermFunc{
-	{"set_base", "address, permission flag, value"},
-	{"unset_base", "address, permission flag"},
-	{"set_global", "permission flag, value"},
-	{"add_role", "address, role"},
-	{"rm_role", "address, role"},
-}
-
 func Permissions(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, addrS, nonceS, permFunc string, argsS []string) (*txs.PermissionsTx, error) {
 	pub, _, nonce, err := checkCommon(nodeClient, keyClient, pubkey, addrS, "0", nonceS)
 	if err != nil {
@@ -119,13 +106,13 @@ func Permissions(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey,
 	}
 	var args ptypes.PermArgs
 	switch permFunc {
-	case "set_base":
+	case "setBase":
 		addr, pF, err := decodeAddressPermFlag(argsS[0], argsS[1])
 		if err != nil {
 			return nil, err
 		}
 		if len(argsS) != 3 {
-			return nil, fmt.Errorf("set_base also takes a value (true or false)")
+			return nil, fmt.Errorf("setBase also takes a value (true or false)")
 		}
 		var value bool
 		if argsS[2] == "true" {
@@ -136,13 +123,13 @@ func Permissions(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey,
 			return nil, fmt.Errorf("Unknown value %s", argsS[2])
 		}
 		args = &ptypes.SetBaseArgs{addr, pF, value}
-	case "unset_base":
+	case "unsetBase":
 		addr, pF, err := decodeAddressPermFlag(argsS[0], argsS[1])
 		if err != nil {
 			return nil, err
 		}
 		args = &ptypes.UnsetBaseArgs{addr, pF}
-	case "set_global":
+	case "setGlobal":
 		pF, err := ptypes.PermStringToFlag(argsS[0])
 		if err != nil {
 			return nil, err
@@ -156,13 +143,13 @@ func Permissions(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey,
 			return nil, fmt.Errorf("Unknown value %s", argsS[1])
 		}
 		args = &ptypes.SetGlobalArgs{pF, value}
-	case "add_role":
+	case "addRole":
 		addr, err := hex.DecodeString(argsS[0])
 		if err != nil {
 			return nil, err
 		}
 		args = &ptypes.AddRoleArgs{addr, argsS[1]}
-	case "rm_role":
+	case "removeRole":
 		addr, err := hex.DecodeString(argsS[0])
 		if err != nil {
 			return nil, err
diff --git a/client/rpc/client_test.go b/client/rpc/client_test.go
index 6541bd3f9f3b92b29a3c1c231669afde4350a0a2..0c240a4c0c76e549c993b8cd1a8406946e16543c 100644
--- a/client/rpc/client_test.go
+++ b/client/rpc/client_test.go
@@ -147,7 +147,7 @@ func testPermissions(t *testing.T,
 	nonceString := ""
 
 	_, err := Permissions(nodeClient, keyClient, publicKeyString, addressString,
-		nonceString, "set_base", []string{permAddressString, "root", "true"})
+		nonceString, "setBase", []string{permAddressString, "root", "true"})
 	if err != nil {
 		t.Logf("Error in PermissionsTx: %s", err)
 		t.Fail()
diff --git a/event/event_cache_test.go b/event/event_cache_test.go
index 35ce6d7ed0cbdc45c3b838d831b993fddfbbb42b..041a0650d67e2c57b3a978d0fa8fafcd37cee95e 100644
--- a/event/event_cache_test.go
+++ b/event/event_cache_test.go
@@ -13,7 +13,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-var mockInterval = 10 * time.Millisecond
+var mockInterval = 40 * time.Millisecond
 
 type mockSub struct {
 	subId    string
diff --git a/manager/eris-mint/evm/abi/types.go b/manager/eris-mint/evm/abi/types.go
new file mode 100644
index 0000000000000000000000000000000000000000..2c299e6d10f217f3ca94669d50682316dc0bed29
--- /dev/null
+++ b/manager/eris-mint/evm/abi/types.go
@@ -0,0 +1,27 @@
+package abi
+
+// Ethereum defines types and calling conventions for the ABI
+// (application binary interface) here: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
+// We make a start of representing them here
+
+type Type string
+
+type Arg struct {
+	Name string
+	Type Type
+}
+
+type Return struct {
+	Name string
+	Type Type
+}
+
+const (
+	// We don't need to be exhaustive here, just make what we used strongly typed
+	Address Type = "address"
+	Int     Type = "int"
+	Uint64  Type = "uint64"
+	Bytes32 Type = "bytes32"
+	String  Type = "string"
+	Bool    Type = "bool"
+)
diff --git a/manager/eris-mint/evm/test/fake_app_state.go b/manager/eris-mint/evm/fake_app_state.go
similarity index 97%
rename from manager/eris-mint/evm/test/fake_app_state.go
rename to manager/eris-mint/evm/fake_app_state.go
index 9b7ac96d9143104619c7f13098bfa11043ce9071..d8de25035084a7be4cf26be6d8d9d912d78aeeae 100644
--- a/manager/eris-mint/evm/test/fake_app_state.go
+++ b/manager/eris-mint/evm/fake_app_state.go
@@ -3,7 +3,6 @@ package vm
 import (
 	"fmt"
 
-	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm"
 	"github.com/eris-ltd/eris-db/manager/eris-mint/evm/sha3"
 	. "github.com/eris-ltd/eris-db/word256"
 )
diff --git a/manager/eris-mint/evm/test/log_event_test.go b/manager/eris-mint/evm/log_event_test.go
similarity index 97%
rename from manager/eris-mint/evm/test/log_event_test.go
rename to manager/eris-mint/evm/log_event_test.go
index 34c8ae330300c5f569b075a55f010c6a275de2fc..e85c79fe9ba9353d6734fc509a1b747b41d5eed7 100644
--- a/manager/eris-mint/evm/test/log_event_test.go
+++ b/manager/eris-mint/evm/log_event_test.go
@@ -5,7 +5,6 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm"
 	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
 	"github.com/eris-ltd/eris-db/txs"
 	. "github.com/eris-ltd/eris-db/word256"
diff --git a/manager/eris-mint/evm/native.go b/manager/eris-mint/evm/native.go
index ed4b4f378c93a2a7be83031f59ac6c17c7bc22cd..7470ee32ca5832e9ae2b87d386bc5b50cd83add0 100644
--- a/manager/eris-mint/evm/native.go
+++ b/manager/eris-mint/evm/native.go
@@ -40,6 +40,9 @@ func registerNativeContracts() {
 
 type NativeContract func(appState AppState, caller *Account, input []byte, gas *int64) (output []byte, err error)
 
+const FuncIDLength = 4
+type FuncID [FuncIDLength]byte
+
 /* Removed due to C dependency
 func ecrecoverFunc(appState AppState, caller *Account, input []byte, gas *int64) (output []byte, err error) {
 	// Deduct gas
diff --git a/manager/eris-mint/evm/opcodes/opcodes.go b/manager/eris-mint/evm/opcodes/opcodes.go
index b4205f2fe9633a80643740da942fbc51b1ff5382..bdb3218a1edce49221bdf57fdd5328768abcdff6 100644
--- a/manager/eris-mint/evm/opcodes/opcodes.go
+++ b/manager/eris-mint/evm/opcodes/opcodes.go
@@ -3,6 +3,7 @@ package opcodes
 import (
 	"fmt"
 
+	"github.com/eris-ltd/eris-db/word256"
 	"gopkg.in/fatih/set.v0"
 )
 
@@ -378,6 +379,8 @@ func Bytecode(bytelikes ...interface{}) []byte {
 			if int64(bytes[i]) != b {
 				panic(fmt.Sprintf("The int64 %v does not fit inside a byte", b))
 			}
+		case word256.Word256:
+			return Concat(bytes[:i], b[:], Bytecode(bytelikes[i+1:]...))
 		case []byte:
 			// splice
 			return Concat(bytes[:i], b, Bytecode(bytelikes[i+1:]...))
diff --git a/manager/eris-mint/evm/snative.go b/manager/eris-mint/evm/snative.go
index 0c03827eab16463537c693d07a88e66896bf1491..83edac16891cb3f77beba52ee01affa0e8fe5c34 100644
--- a/manager/eris-mint/evm/snative.go
+++ b/manager/eris-mint/evm/snative.go
@@ -1,105 +1,313 @@
 package vm
 
 import (
-	"encoding/hex"
 	"fmt"
 
 	"github.com/eris-ltd/eris-db/common/sanity"
 	"github.com/eris-ltd/eris-db/manager/eris-mint/evm/sha3"
 	ptypes "github.com/eris-ltd/eris-db/permission/types"
 	. "github.com/eris-ltd/eris-db/word256"
+
+	"strings"
+
+	"github.com/eris-ltd/eris-db/manager/eris-mint/evm/abi"
 )
 
-//------------------------------------------------------------------------------------------------
-// Registered SNative contracts
+//
+// SNative (from 'secure natives') are native (go) contracts that are dispatched
+// based on account permissions and can access and modify an account's permissions
+//
 
-var PermissionsContract = "permissions_contract"
+// Metadata for SNative contract. Acts as a call target from the EVM. Can be
+// used to generate bindings in a smart contract languages.
+type SNativeContractDescription struct {
+	// Comment describing purpose of SNative contract and reason for assembling
+	// the particular functions
+	Comment string
+	// Name of the SNative contract
+	Name          string
+	functionsByID map[FuncID]*SNativeFunctionDescription
+	functions     []*SNativeFunctionDescription
+}
 
-func registerSNativeContracts() {
-	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
-
-type SNativeFuncDescription struct {
-	Name     string
-	NArgs    int
+// Metadata for SNative functions. Act as call targets for the EVM when
+// collected into an SNativeContractDescription. Can be used to generate
+// bindings in a smart contract languages.
+type SNativeFunctionDescription struct {
+	// Comment describing function's purpose, parameters, and return value
+	Comment string
+	// Function name (used to form signature)
+	Name string
+	// Function arguments (used to form signature)
+	Args []abi.Arg
+	// Function return value
+	Return abi.Return
+	// Permissions required to call function
 	PermFlag ptypes.PermFlag
-	F        NativeContract
+	// Native function to which calls will be dispatched when a containing
+	// contract is called with a FuncID matching this NativeContract
+	F NativeContract
 }
 
-/* The solidity interface used to generate the abi function ids below
-contract Permissions {
-	function has_base(address addr, uint64 permFlag) constant returns (bool value) {}
-	function set_base(address addr, uint64 permFlag, bool value) constant returns (bool val) {}
-	function unset_base(address addr, uint64 permFlag) constant returns (uint64 pf) {}
-	function set_global(uint64 permFlag, bool value) constant returns (uint64 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) {}
+func registerSNativeContracts() {
+	for _, contract := range SNativeContracts() {
+		registeredNativeContracts[contract.Address()] = contract.Dispatch
+	}
 }
-*/
 
-// function identifiers from the solidity abi
-var PermsMap = map[string]SNativeFuncDescription{
-	getFuncIdentifiersFromSignature("has_role(address,bytes32)"):    SNativeFuncDescription{"has_role", 2, ptypes.HasRole, has_role},
-	getFuncIdentifiersFromSignature("unset_base(address,uint64)"):   SNativeFuncDescription{"unset_base", 2, ptypes.UnsetBase, unset_base},
-	getFuncIdentifiersFromSignature("set_global(uint64,bool)"):      SNativeFuncDescription{"set_global", 2, ptypes.SetGlobal, set_global},
-	getFuncIdentifiersFromSignature("add_role(address,bytes32)"):    SNativeFuncDescription{"add_role", 2, ptypes.AddRole, add_role},
-	getFuncIdentifiersFromSignature("set_base(address,uint64,bool"): SNativeFuncDescription{"set_base", 3, ptypes.SetBase, set_base},
-	getFuncIdentifiersFromSignature("has_base(address,uint64)"):     SNativeFuncDescription{"has_base", 2, ptypes.HasBase, has_base},
-	getFuncIdentifiersFromSignature("rm_role(address,bytes32)"):     SNativeFuncDescription{"rm_role", 2, ptypes.RmRole, rm_role},
+// Returns a map of all SNative contracts defined indexed by name
+func SNativeContracts() map[string]*SNativeContractDescription {
+	permFlagType := abi.Uint64
+	roleType := abi.Bytes32
+	contracts := []*SNativeContractDescription{
+		NewSNativeContract(`
+		* Interface for managing Secure Native authorizations.
+		* @dev This interface describes the functions exposed by the SNative permissions layer in the Monax blockchain (ErisDB).
+		`,
+			"Permissions",
+			&SNativeFunctionDescription{`
+			* @notice Adds a role to an account
+			* @param _account account address
+			* @param _role role name
+			* @return result whether role was added
+			`,
+				"addRole",
+				[]abi.Arg{
+					arg("_account", abi.Address),
+					arg("_role", roleType),
+				},
+				ret("result", abi.Bool),
+				ptypes.AddRole,
+				addRole},
+
+			&SNativeFunctionDescription{`
+			* @notice Removes a role from an account
+			* @param _account account address
+			* @param _role role name
+			* @return result whether role was removed
+			`,
+				"removeRole",
+				[]abi.Arg{
+					arg("_account", abi.Address),
+					arg("_role", roleType),
+				},
+				ret("result", abi.Bool),
+				ptypes.RmRole,
+				removeRole},
+
+			&SNativeFunctionDescription{`
+			* @notice Indicates whether an account has a role
+			* @param _account account address
+			* @param _role role name
+			* @return result whether account has role
+			`,
+				"hasRole",
+				[]abi.Arg{
+					arg("_account", abi.Address),
+					arg("_role", roleType),
+				},
+				ret("result", abi.Bool),
+				ptypes.HasRole,
+				hasRole},
+
+			&SNativeFunctionDescription{`
+			* @notice Sets the permission flags for an account. Makes them explicitly set (on or off).
+			* @param _account account address
+			* @param _permission the base permissions flags to set for the account
+			* @param _set whether to set or unset the permissions flags at the account level
+			* @return result the effective permissions flags on the account after the call
+			`,
+				"setBase",
+				[]abi.Arg{
+					arg("_account", abi.Address),
+					arg("_permission", permFlagType),
+					arg("_set", abi.Bool),
+				},
+				ret("result", permFlagType),
+				ptypes.SetBase,
+				setBase},
+
+			&SNativeFunctionDescription{`
+			* @notice Unsets the permissions flags for an account. Causes permissions being unset to fall through to global permissions.
+      * @param _account account address
+      * @param _permission the permissions flags to unset for the account
+			* @return result the effective permissions flags on the account after the call
+      `,
+				"unsetBase",
+				[]abi.Arg{
+					arg("_account", abi.Address),
+					arg("_permission", permFlagType)},
+				ret("result", permFlagType),
+				ptypes.UnsetBase,
+				unsetBase},
+
+			&SNativeFunctionDescription{`
+			* @notice Indicates whether an account has a subset of permissions set
+			* @param _account account address
+			* @param _permission the permissions flags (mask) to check whether enabled against base permissions for the account
+			* @return result whether account has the passed permissions flags set
+			`,
+				"hasBase",
+				[]abi.Arg{
+					arg("_account", abi.Address),
+					arg("_permission", permFlagType)},
+				ret("result", permFlagType),
+				ptypes.HasBase,
+				hasBase},
+
+			&SNativeFunctionDescription{`
+			* @notice Sets the global (default) permissions flags for the entire chain
+			* @param _permission the permissions flags to set
+			* @param _set whether to set (or unset) the permissions flags
+			* @return result the global permissions flags after the call
+			`,
+				"setGlobal",
+				[]abi.Arg{
+					arg("_permission", permFlagType),
+					arg("_set", abi.Bool)},
+				ret("result", permFlagType),
+				ptypes.SetGlobal,
+				setGlobal},
+		),
+	}
+
+	contractMap := make(map[string]*SNativeContractDescription, len(contracts))
+	for _, contract := range contracts {
+		contractMap[contract.Name] = contract
+	}
+	return contractMap
 }
 
-func getFuncIdentifiersFromSignature(signature string) string {
-	identifier := sha3.Sha3([]byte(signature))
-	return hex.EncodeToString(identifier[:4])
+// Create a new SNative contract description object by passing a comment, name
+// and a list of member functions descriptions
+func NewSNativeContract(comment, name string,
+	functions ...*SNativeFunctionDescription) *SNativeContractDescription {
+
+	functionsByID := make(map[FuncID]*SNativeFunctionDescription, len(functions))
+	for _, f := range functions {
+		fid := f.ID()
+		otherF, ok := functionsByID[fid]
+		if ok {
+			panic(fmt.Errorf("Function with ID %x already defined: %s", fid,
+				otherF))
+		}
+		functionsByID[fid] = f
+	}
+	return &SNativeContractDescription{
+		Comment:       comment,
+		Name:          name,
+		functionsByID: functionsByID,
+		functions:     functions,
+	}
 }
 
-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")
+// This function is designed to be called from the EVM once a SNative contract
+// has been selected. It is also placed in a registry by registerSNativeContracts
+// So it can be looked up by SNative address
+func (contract *SNativeContractDescription) Dispatch(appState AppState,
+	caller *Account, args []byte, gas *int64) (output []byte, err error) {
+	if len(args) < FuncIDLength {
+		return nil, fmt.Errorf("SNatives dispatch requires a 4-byte function "+
+			"identifier but arguments are only %s bytes long", len(args))
 	}
 
-	// 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)
+	function, err := contract.FunctionByID(firstFourBytes(args))
+	if err != nil {
+		return nil, err
 	}
 
+	remainingArgs := args[FuncIDLength:]
+
 	// check if we have permission to call this function
-	if !HasPermission(appState, caller, d.PermFlag) {
-		return nil, ErrInvalidPermission{caller.Address, d.Name}
+	if !HasPermission(appState, caller, function.PermFlag) {
+		return nil, ErrInvalidPermission{caller.Address, function.Name}
 	}
 
 	// ensure there are enough arguments
-	if len(args) != d.NArgs*32 {
-		return nil, fmt.Errorf("%s() takes %d arguments", d.Name)
+	if len(remainingArgs) != function.NArgs()*Word256Length {
+		return nil, fmt.Errorf("%s() takes %d arguments", function.Name,
+			function.NArgs())
 	}
 
 	// call the function
-	return d.F(appState, caller, args, gas)
+	return function.F(appState, caller, remainingArgs, gas)
 }
 
-// TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?)
+// We define the address of an SNative contact as the simplest possible hash of
+// its canonical name
+func (contract *SNativeContractDescription) Address() Word256 {
+	return LeftPadWord256([]byte(contract.Name))
+}
+
+// Get function by calling identifier FuncID
+func (contract *SNativeContractDescription) FunctionByID(id FuncID) (*SNativeFunctionDescription, error) {
+	f, ok := contract.functionsByID[id]
+	if !ok {
+		return nil,
+			fmt.Errorf("Unknown SNative function with ID %x", id)
+	}
+	return f, nil
+}
+
+// Get function by name
+func (contract *SNativeContractDescription) FunctionByName(name string) (*SNativeFunctionDescription, error) {
+	for _, f := range contract.functions {
+		if f.Name == name {
+			return f, nil
+		}
+	}
+	return nil, fmt.Errorf("Unknown SNative function with name %s", name)
+}
 
-func has_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
+// Get functions in order of declaration
+func (contract *SNativeContractDescription) Functions() []*SNativeFunctionDescription {
+	functions := make([]*SNativeFunctionDescription, len(contract.functions))
+	copy(functions, contract.functions)
+	return functions
+}
+
+//
+// SNative functions
+//
+
+// Get function signature
+func (function *SNativeFunctionDescription) Signature() string {
+	argTypes := make([]string, len(function.Args))
+	for i, arg := range function.Args {
+		argTypes[i] = string(arg.Type)
+	}
+	return fmt.Sprintf("%s(%s)", function.Name,
+		strings.Join(argTypes, ","))
+}
+
+// Get function calling identifier FuncID
+func (function *SNativeFunctionDescription) ID() FuncID {
+	return firstFourBytes(sha3.Sha3([]byte(function.Signature())))
+}
+
+// Get number of function arguments
+func (function *SNativeFunctionDescription) NArgs() int {
+	return len(function.Args)
+}
+
+func arg(name string, abiType abi.Type) abi.Arg {
+	return abi.Arg{
+		Name: name,
+		Type: abiType,
+	}
+}
+
+func ret(name string, abiType abi.Type) abi.Return {
+	return abi.Return{
+		Name: name,
+		Type: abiType,
+	}
+}
+
+// Permission function defintions
+
+// TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?)
+func hasBase(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, permNum := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
@@ -114,8 +322,8 @@ func has_base(appState AppState, caller *Account, args []byte, gas *int64) (outp
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func set_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	addr, permNum, perm := returnThreeArgs(args)
+func setBase(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
+	addr, permNum, permVal := returnThreeArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
 		return nil, fmt.Errorf("Unknown account %X", addr)
@@ -124,16 +332,16 @@ func set_base(appState AppState, caller *Account, args []byte, gas *int64) (outp
 	if !ValidPermN(permN) {
 		return nil, ptypes.ErrInvalidPermission(permN)
 	}
-	permV := !perm.IsZero()
+	permV := !permVal.IsZero()
 	if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
 		return nil, err
 	}
 	appState.UpdateAccount(vmAcc)
 	dbg.Printf("snative.setBasePerm(0x%X, %b, %v)\n", addr.Postfix(20), permN, permV)
-	return perm.Bytes(), nil
+	return effectivePermBytes(vmAcc.Permissions.Base, globalPerms(appState)), nil
 }
 
-func unset_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
+func unsetBase(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, permNum := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
@@ -148,11 +356,11 @@ func unset_base(appState AppState, caller *Account, args []byte, gas *int64) (ou
 	}
 	appState.UpdateAccount(vmAcc)
 	dbg.Printf("snative.unsetBasePerm(0x%X, %b)\n", addr.Postfix(20), permN)
-	return permNum.Bytes(), nil
+	return effectivePermBytes(vmAcc.Permissions.Base, globalPerms(appState)), nil
 }
 
-func set_global(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	permNum, perm := returnTwoArgs(args)
+func setGlobal(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
+	permNum, permVal := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(ptypes.GlobalPermissionsAddress256)
 	if vmAcc == nil {
 		sanity.PanicSanity("cant find the global permissions account")
@@ -161,16 +369,16 @@ func set_global(appState AppState, caller *Account, args []byte, gas *int64) (ou
 	if !ValidPermN(permN) {
 		return nil, ptypes.ErrInvalidPermission(permN)
 	}
-	permV := !perm.IsZero()
+	permV := !permVal.IsZero()
 	if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
 		return nil, err
 	}
 	appState.UpdateAccount(vmAcc)
 	dbg.Printf("snative.setGlobalPerm(%b, %v)\n", permN, permV)
-	return perm.Bytes(), nil
+	return permBytes(vmAcc.Permissions.Base.ResultantPerms()), nil
 }
 
-func has_role(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
+func hasRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, role := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
@@ -182,7 +390,7 @@ func has_role(appState AppState, caller *Account, args []byte, gas *int64) (outp
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func add_role(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
+func addRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, role := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
@@ -195,7 +403,7 @@ func add_role(appState AppState, caller *Account, args []byte, gas *int64) (outp
 	return LeftPadWord256([]byte{permInt}).Bytes(), nil
 }
 
-func rm_role(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
+func removeRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	addr, role := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
@@ -228,6 +436,26 @@ func ValidPermN(n ptypes.PermFlag) bool {
 	return true
 }
 
+// Get the global BasePermissions
+func globalPerms(appState AppState) ptypes.BasePermissions {
+	vmAcc := appState.GetAccount(ptypes.GlobalPermissionsAddress256)
+	if vmAcc == nil {
+		sanity.PanicSanity("cant find the global permissions account")
+	}
+	return vmAcc.Permissions.Base
+}
+
+// Compute the effective permissions from an Account's BasePermissions by
+// taking the bitwise or with the global BasePermissions resultant permissions
+func effectivePermBytes(basePerms ptypes.BasePermissions,
+	globalPerms ptypes.BasePermissions) []byte {
+	return permBytes(basePerms.ResultantPerms() | globalPerms.ResultantPerms())
+}
+
+func permBytes(basePerms ptypes.PermFlag) []byte {
+	return Uint64ToWord256(uint64(basePerms)).Bytes()
+}
+
 // CONTRACT: length has already been checked
 func returnTwoArgs(args []byte) (a Word256, b Word256) {
 	copy(a[:], args[:32])
@@ -249,3 +477,9 @@ func byteFromBool(b bool) byte {
 	}
 	return 0x0
 }
+
+func firstFourBytes(byteSlice []byte) [4]byte {
+	var bs [4]byte
+	copy(bs[:], byteSlice[:4])
+	return bs
+}
diff --git a/manager/eris-mint/evm/snative_test.go b/manager/eris-mint/evm/snative_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..52810efbf15759d72e9f51ed03d69d35c6abe1c0
--- /dev/null
+++ b/manager/eris-mint/evm/snative_test.go
@@ -0,0 +1,135 @@
+package vm
+
+import (
+	"encoding/hex"
+	"testing"
+
+	"strings"
+
+	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
+	ptypes "github.com/eris-ltd/eris-db/permission/types"
+	. "github.com/eris-ltd/eris-db/word256"
+	"github.com/stretchr/testify/assert"
+)
+
+// Compiling the Permissions solidity contract at
+// (generated by with 'make snatives' function) and passing to
+// https://ethereum.github.io/browser-solidity (toggle details to get list)
+// yields:
+// Keep this updated to drive TestPermissionsContractSignatures
+const compiledSigs = `
+a73f7f8a addRole(address,bytes32)
+225b6574 hasBase(address,uint64)
+ac4ab3fb hasRole(address,bytes32)
+6853920e removeRole(address,bytes32)
+dbd4a8ea setBase(address,uint64,bool)
+c4bc7b70 setGlobal(uint64,bool)
+b7d4dc0d unsetBase(address,uint64)
+`
+
+func TestPermissionsContractSignatures(t *testing.T) {
+	contract := SNativeContracts()["Permissions"]
+
+	nFuncs := len(contract.functions)
+
+	sigMap := idToSignatureMap()
+
+	assert.Len(t, sigMap, nFuncs,
+		"Permissions contract defines %s functions so we need %s " +
+				"signatures in compiledSigs",
+		nFuncs, nFuncs)
+
+	for funcID, signature := range sigMap {
+		assertFunctionIDSignature(t, contract, funcID, signature)
+	}
+}
+
+func TestSNativeContractDescription_Dispatch(t *testing.T) {
+	contract := SNativeContracts()["Permissions"]
+	state := newAppState()
+	caller := &Account{
+		Address: addr(1, 1, 1),
+	}
+	grantee := &Account{
+		Address: addr(2, 2, 2),
+	}
+	state.UpdateAccount(grantee)
+
+	function, err := contract.FunctionByName("addRole")
+	if err != nil {
+		t.Fatalf("Could not get function: %s", err)
+	}
+	funcID := function.ID()
+	gas := int64(1000)
+
+	// Should fail since we have no permissions
+	retValue, err := contract.Dispatch(state, caller, Bytecode(funcID[:],
+		grantee.Address, permFlagToWord256(ptypes.CreateAccount)), &gas)
+	assert.Error(t, err)
+	if err != nil {
+		assert.Contains(t, err.Error(), "does not have permission")
+	}
+
+	// Grant all permissions and dispatch should success
+	caller.Permissions = allAccountPermissions()
+	retValue, err = contract.Dispatch(state, caller, Bytecode(funcID[:],
+		grantee.Address, permFlagToWord256(ptypes.CreateAccount)), &gas)
+	assert.NoError(t, err)
+	assert.Equal(t, retValue, LeftPadBytes([]byte{1}, 32))
+}
+
+//
+// Helpers
+//
+func assertFunctionIDSignature(t *testing.T, contract *SNativeContractDescription,
+	funcIDHex string, expectedSignature string) {
+	function, err := contract.FunctionByID(funcIDFromHex(t, funcIDHex))
+	assert.NoError(t, err,
+		"Error retrieving SNativeFunctionDescription with ID %s", funcIDHex)
+	if err == nil {
+		assert.Equal(t, expectedSignature, function.Signature())
+	}
+}
+
+func funcIDFromHex(t *testing.T, hexString string) FuncID {
+	bs, err := hex.DecodeString(hexString)
+	assert.NoError(t, err, "Could not decode hex string '%s'", hexString)
+	if len(bs) != 4 {
+		t.Fatalf("FuncID must be 4 bytes but '%s' is %v bytes", hexString,
+			len(bs))
+	}
+	return firstFourBytes(bs)
+}
+
+func permFlagToWord256(permFlag ptypes.PermFlag) Word256 {
+	return Uint64ToWord256(uint64(permFlag))
+}
+
+func addr(rightBytes ...uint8) Word256 {
+	return LeftPadWord256(rightBytes)
+}
+
+func allAccountPermissions() ptypes.AccountPermissions {
+	return ptypes.AccountPermissions{
+		Base: ptypes.BasePermissions{
+			Perms:  ptypes.AllPermFlags,
+			SetBit: ptypes.AllPermFlags,
+		},
+		Roles: []string{},
+	}
+}
+
+// turns the solidity compiler function summary into a map to drive signature
+// test
+func idToSignatureMap() map[string]string {
+	sigMap := make(map[string]string)
+	lines := strings.Split(compiledSigs, "\n")
+	for _, line := range lines {
+		trimmed := strings.Trim(line, " \t")
+		if trimmed != "" {
+			idSig := strings.Split(trimmed, " ")
+			sigMap[idSig[0]] = idSig[1]
+		}
+	}
+	return sigMap
+}
diff --git a/manager/eris-mint/evm/test/vm_test.go b/manager/eris-mint/evm/vm_test.go
similarity index 99%
rename from manager/eris-mint/evm/test/vm_test.go
rename to manager/eris-mint/evm/vm_test.go
index 248a4377a7a6fd6b328187982ed039373a42df4c..4911965b33aab7b2ee1b752ec3b0994b473b1dfe 100644
--- a/manager/eris-mint/evm/test/vm_test.go
+++ b/manager/eris-mint/evm/vm_test.go
@@ -10,7 +10,6 @@ import (
 
 	"errors"
 
-	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm"
 	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
 	ptypes "github.com/eris-ltd/eris-db/permission/types"
 	"github.com/eris-ltd/eris-db/txs"
diff --git a/manager/eris-mint/state/permissions_test.go b/manager/eris-mint/state/permissions_test.go
index fd4dd421935b6a58b0cdaf592b0f61dbd4849722..73d1ae4fbf85fb38514e6d694bbc93a5c8844019 100644
--- a/manager/eris-mint/state/permissions_test.go
+++ b/manager/eris-mint/state/permissions_test.go
@@ -2,7 +2,6 @@ package state
 
 import (
 	"bytes"
-	"encoding/hex"
 	"fmt"
 	"strconv"
 	"testing"
@@ -29,6 +28,7 @@ func init() {
 var (
 	dbBackend = "memdb"
 	dbDir     = ""
+	permissionsContract = vm.SNativeContracts()["Permissions"]
 )
 
 /*
@@ -885,7 +885,7 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### HasBase")
 	// HasBase
-	snativeAddress, pF, data := snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false)
+	snativeAddress, pF, data := snativePermTestInputCALL("hasBase", user[3], ptypes.Bond, false)
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
 	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		// return value should be true or false as a 32 byte array...
@@ -897,10 +897,10 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### SetBase")
 	// SetBase
-	snativeAddress, pF, data = snativePermTestInputCALL("set_base", user[3], ptypes.Bond, false)
+	snativeAddress, pF, data = snativePermTestInputCALL("setBase", user[3], ptypes.Bond, false)
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
 	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false)
+	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", 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) {
@@ -908,9 +908,9 @@ func TestSNativeCALL(t *testing.T) {
 		}
 		return nil
 	})
-	snativeAddress, pF, data = snativePermTestInputCALL("set_base", user[3], ptypes.CreateContract, true)
+	snativeAddress, pF, data = snativePermTestInputCALL("setBase", 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)
+	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", 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) {
@@ -921,10 +921,10 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### UnsetBase")
 	// UnsetBase
-	snativeAddress, pF, data = snativePermTestInputCALL("unset_base", user[3], ptypes.CreateContract, false)
+	snativeAddress, pF, data = snativePermTestInputCALL("unsetBase", user[3], ptypes.CreateContract, false)
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
 	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
+	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", 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)
@@ -934,10 +934,10 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### SetGlobal")
 	// SetGlobalPerm
-	snativeAddress, pF, data = snativePermTestInputCALL("set_global", user[3], ptypes.CreateContract, true)
+	snativeAddress, pF, data = snativePermTestInputCALL("setGlobal", user[3], ptypes.CreateContract, true)
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
 	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
+	snativeAddress, pF, data = snativePermTestInputCALL("hasBase", 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) {
@@ -948,7 +948,7 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### HasRole")
 	// HasRole
-	snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "bumble")
+	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", user[3], "bumble")
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
 	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error {
 		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
@@ -959,17 +959,17 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### AddRole")
 	// AddRole
-	snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
+	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", 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, pF, data = snativeRoleTestInputCALL("add_role", user[3], "chuck")
+	snativeAddress, pF, data = snativeRoleTestInputCALL("addRole", user[3], "chuck")
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
 	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
+	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", 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)
@@ -979,10 +979,10 @@ func TestSNativeCALL(t *testing.T) {
 
 	fmt.Println("\n#### RmRole")
 	// RmRole
-	snativeAddress, pF, data = snativeRoleTestInputCALL("rm_role", user[3], "chuck")
+	snativeAddress, pF, data = snativeRoleTestInputCALL("removeRole", user[3], "chuck")
 	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
 	testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil })
-	snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
+	snativeAddress, pF, data = snativeRoleTestInputCALL("hasRole", 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)
@@ -1006,14 +1006,14 @@ func TestSNativeTx(t *testing.T) {
 
 	fmt.Println("\n#### SetBase")
 	// SetBase
-	snativeArgs := snativePermTestInputTx("set_base", user[3], ptypes.Bond, false)
+	snativeArgs := snativePermTestInputTx("setBase", user[3], ptypes.Bond, false)
 	testSNativeTxExpectFail(t, blockCache, snativeArgs)
 	testSNativeTxExpectPass(t, blockCache, ptypes.SetBase, snativeArgs)
 	acc := blockCache.GetAccount(user[3].Address)
 	if v, _ := acc.Permissions.Base.Get(ptypes.Bond); v {
 		t.Fatal("expected permission to be set false")
 	}
-	snativeArgs = snativePermTestInputTx("set_base", user[3], ptypes.CreateContract, true)
+	snativeArgs = snativePermTestInputTx("setBase", user[3], ptypes.CreateContract, true)
 	testSNativeTxExpectPass(t, blockCache, ptypes.SetBase, snativeArgs)
 	acc = blockCache.GetAccount(user[3].Address)
 	if v, _ := acc.Permissions.Base.Get(ptypes.CreateContract); !v {
@@ -1022,7 +1022,7 @@ func TestSNativeTx(t *testing.T) {
 
 	fmt.Println("\n#### UnsetBase")
 	// UnsetBase
-	snativeArgs = snativePermTestInputTx("unset_base", user[3], ptypes.CreateContract, false)
+	snativeArgs = snativePermTestInputTx("unsetBase", user[3], ptypes.CreateContract, false)
 	testSNativeTxExpectFail(t, blockCache, snativeArgs)
 	testSNativeTxExpectPass(t, blockCache, ptypes.UnsetBase, snativeArgs)
 	acc = blockCache.GetAccount(user[3].Address)
@@ -1032,7 +1032,7 @@ func TestSNativeTx(t *testing.T) {
 
 	fmt.Println("\n#### SetGlobal")
 	// SetGlobalPerm
-	snativeArgs = snativePermTestInputTx("set_global", user[3], ptypes.CreateContract, true)
+	snativeArgs = snativePermTestInputTx("setGlobal", user[3], ptypes.CreateContract, true)
 	testSNativeTxExpectFail(t, blockCache, snativeArgs)
 	testSNativeTxExpectPass(t, blockCache, ptypes.SetGlobal, snativeArgs)
 	acc = blockCache.GetAccount(ptypes.GlobalPermissionsAddress)
@@ -1042,7 +1042,7 @@ func TestSNativeTx(t *testing.T) {
 
 	fmt.Println("\n#### AddRole")
 	// AddRole
-	snativeArgs = snativeRoleTestInputTx("add_role", user[3], "chuck")
+	snativeArgs = snativeRoleTestInputTx("addRole", user[3], "chuck")
 	testSNativeTxExpectFail(t, blockCache, snativeArgs)
 	testSNativeTxExpectPass(t, blockCache, ptypes.AddRole, snativeArgs)
 	acc = blockCache.GetAccount(user[3].Address)
@@ -1052,7 +1052,7 @@ func TestSNativeTx(t *testing.T) {
 
 	fmt.Println("\n#### RmRole")
 	// RmRole
-	snativeArgs = snativeRoleTestInputTx("rm_role", user[3], "chuck")
+	snativeArgs = snativeRoleTestInputTx("removeRole", user[3], "chuck")
 	testSNativeTxExpectFail(t, blockCache, snativeArgs)
 	testSNativeTxExpectPass(t, blockCache, ptypes.RmRole, snativeArgs)
 	acc = blockCache.GetAccount(user[3].Address)
@@ -1182,27 +1182,26 @@ func boolToWord256(v bool) Word256 {
 	return LeftPadWord256([]byte{vint})
 }
 
-func permNameToFuncID(s string) []byte {
-	for k, v := range vm.PermsMap {
-		if s == v.Name {
-			b, _ := hex.DecodeString(k)
-			return b
-		}
+func permNameToFuncID(name string) []byte {
+  function, err := permissionsContract.FunctionByName(name)
+	if err != nil {
+		panic("didn't find snative function signature!")
 	}
-	panic("didn't find snative function signature!")
+	id := function.ID()
+	return id[:]
 }
 
 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)
+	addr = permissionsContract.Address().Postfix(20)
 	switch name {
-	case "has_base", "unset_base":
+	case "hasBase", "unsetBase":
 		data = LeftPadBytes(user.Address, 32)
 		data = append(data, Uint64ToWord256(uint64(perm)).Bytes()...)
-	case "set_base":
+	case "setBase":
 		data = LeftPadBytes(user.Address, 32)
 		data = append(data, Uint64ToWord256(uint64(perm)).Bytes()...)
 		data = append(data, boolToWord256(val).Bytes()...)
-	case "set_global":
+	case "setGlobal":
 		data = Uint64ToWord256(uint64(perm)).Bytes()
 		data = append(data, boolToWord256(val).Bytes()...)
 	}
@@ -1216,20 +1215,20 @@ func snativePermTestInputCALL(name string, user *acm.PrivAccount, perm ptypes.Pe
 
 func snativePermTestInputTx(name string, user *acm.PrivAccount, perm ptypes.PermFlag, val bool) (snativeArgs ptypes.PermArgs) {
 	switch name {
-	case "has_base":
+	case "hasBase":
 		snativeArgs = &ptypes.HasBaseArgs{user.Address, perm}
-	case "unset_base":
+	case "unsetBase":
 		snativeArgs = &ptypes.UnsetBaseArgs{user.Address, perm}
-	case "set_base":
+	case "setBase":
 		snativeArgs = &ptypes.SetBaseArgs{user.Address, perm, val}
-	case "set_global":
+	case "setGlobal":
 		snativeArgs = &ptypes.SetGlobalArgs{perm, val}
 	}
 	return
 }
 
 func snativeRoleTestInputCALL(name string, user *acm.PrivAccount, role string) (addr []byte, pF ptypes.PermFlag, data []byte) {
-	addr = LeftPadWord256([]byte(vm.PermissionsContract)).Postfix(20)
+	addr = permissionsContract.Address().Postfix(20)
 	data = LeftPadBytes(user.Address, 32)
 	data = append(data, RightPadBytes([]byte(role), 32)...)
 	data = append(permNameToFuncID(name), data...)
@@ -1243,11 +1242,11 @@ func snativeRoleTestInputCALL(name string, user *acm.PrivAccount, role string) (
 
 func snativeRoleTestInputTx(name string, user *acm.PrivAccount, role string) (snativeArgs ptypes.PermArgs) {
 	switch name {
-	case "has_role":
+	case "hasRole":
 		snativeArgs = &ptypes.HasRoleArgs{user.Address, role}
-	case "add_role":
+	case "addRole":
 		snativeArgs = &ptypes.AddRoleArgs{user.Address, role}
-	case "rm_role":
+	case "removeRole":
 		snativeArgs = &ptypes.RmRoleArgs{user.Address, role}
 	}
 	return
diff --git a/manager/eris-mint/state/tx_cache.go b/manager/eris-mint/state/tx_cache.go
index 87ccd91334872dfca4830893a3082d790ca23530..dc322d6685090495b450d06ba01fea42570bda3a 100644
--- a/manager/eris-mint/state/tx_cache.go
+++ b/manager/eris-mint/state/tx_cache.go
@@ -19,6 +19,8 @@ type TxCache struct {
 	storages map[Tuple256]Word256
 }
 
+var _ vm.AppState = &TxCache{}
+
 func NewTxCache(backend *BlockCache) *TxCache {
 	return &TxCache{
 		backend:  backend,
diff --git a/permission/types/permissions.go b/permission/types/permissions.go
index 15706c9f8ca2a2922610522a4075b3f128693465..03ff4b6ba8d8cd2fa893c7cd846b8066bc029bdc 100644
--- a/permission/types/permissions.go
+++ b/permission/types/permissions.go
@@ -112,6 +112,12 @@ func (p *BasePermissions) IsSet(ty PermFlag) bool {
 	return p.SetBit&ty > 0
 }
 
+// Returns the Perms PermFlag masked with SetBit bit field to give the resultant
+// permissions enabled by this BasePermissions
+func (p *BasePermissions) ResultantPerms() PermFlag {
+	return p.Perms & p.SetBit
+}
+
 func (p BasePermissions) String() string {
 	return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit)
 }
@@ -183,19 +189,19 @@ func PermFlagToString(pf PermFlag) (perm string) {
 	case Name:
 		perm = "name"
 	case HasBase:
-		perm = "has_base"
+		perm = "hasBase"
 	case SetBase:
-		perm = "set_base"
+		perm = "setBase"
 	case UnsetBase:
-		perm = "unset_base"
+		perm = "unsetBase"
 	case SetGlobal:
-		perm = "set_global"
+		perm = "setGlobal"
 	case HasRole:
-		perm = "has_role"
+		perm = "hasRole"
 	case AddRole:
-		perm = "add_role"
+		perm = "addRole"
 	case RmRole:
-		perm = "rm_role"
+		perm = "removeRole"
 	default:
 		perm = "#-UNKNOWN-#"
 	}
@@ -218,19 +224,19 @@ func PermStringToFlag(perm string) (pf PermFlag, err error) {
 		pf = Bond
 	case "name":
 		pf = Name
-	case "has_base":
+	case "hasBase":
 		pf = HasBase
-	case "set_base":
+	case "setBase":
 		pf = SetBase
-	case "unset_base":
+	case "unsetBase":
 		pf = UnsetBase
-	case "set_global":
+	case "setGlobal":
 		pf = SetGlobal
-	case "has_role":
+	case "hasRole":
 		pf = HasRole
-	case "add_role":
+	case "addRole":
 		pf = AddRole
-	case "rm_role":
+	case "removeRole":
 		pf = RmRole
 	default:
 		err = fmt.Errorf("Unknown permission %s", perm)
diff --git a/util/snatives/cmd/main.go b/util/snatives/cmd/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..a04bca2c6fabacd937ac194d5cb7afb77383457f
--- /dev/null
+++ b/util/snatives/cmd/main.go
@@ -0,0 +1,29 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/eris-ltd/eris-db/manager/eris-mint/evm"
+	"github.com/eris-ltd/eris-db/util/snatives/templates"
+)
+
+// Dump SNative contracts
+func main() {
+	contracts := vm.SNativeContracts()
+	// Index of next contract
+	i := 1
+	for _, contract := range contracts {
+		solidity, err := templates.NewSolidityContract(contract).Solidity()
+		if err != nil {
+			fmt.Printf("Error generating solidity for contract %s: %s\n",
+				contract.Name, err)
+		}
+		fmt.Println(solidity)
+		if i < len(contracts) {
+			// Two new lines between contracts as per Solidity style guide
+			// (the template gives us 1 trailing new line)
+			fmt.Println()
+		}
+		i++
+	}
+}
diff --git a/util/snatives/templates/indent_writer.go b/util/snatives/templates/indent_writer.go
new file mode 100644
index 0000000000000000000000000000000000000000..d553f435fca31f3ff15ecdc9c4f846be2309e446
--- /dev/null
+++ b/util/snatives/templates/indent_writer.go
@@ -0,0 +1,47 @@
+package templates
+
+import "io"
+
+const newLine = byte('\n')
+
+type indentWriter struct {
+	writer      io.Writer
+	indentLevel uint
+	indentBytes []byte
+	indent      bool
+}
+
+var _ io.Writer = (*indentWriter)(nil)
+
+// indentWriter indents all lines written to it with a specified indent string
+// indented the specified number of indents
+func NewIndentWriter(indentLevel uint, indentString string,
+	writer io.Writer) *indentWriter {
+	return &indentWriter{
+		writer:      writer,
+		indentLevel: indentLevel,
+		indentBytes: []byte(indentString),
+		indent:      true,
+	}
+}
+
+func (iw *indentWriter) Write(p []byte) (int, error) {
+	bs := make([]byte, 0, len(p))
+	for _, b := range p {
+		if iw.indent {
+			for i := uint(0); i < iw.indentLevel; i++ {
+				bs = append(bs, iw.indentBytes...)
+			}
+			iw.indent = false
+		}
+		if b == newLine {
+			iw.indent = true
+		}
+		bs = append(bs, b)
+	}
+	return iw.writer.Write(bs)
+}
+
+func (iw *indentWriter) SetIndent(level uint) {
+	iw.indentLevel = level
+}
diff --git a/util/snatives/templates/solidity_templates.go b/util/snatives/templates/solidity_templates.go
new file mode 100644
index 0000000000000000000000000000000000000000..f4d87f16b566b6f21d2afcb2bd510f9b97574571
--- /dev/null
+++ b/util/snatives/templates/solidity_templates.go
@@ -0,0 +1,133 @@
+package templates
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"text/template"
+
+	"github.com/eris-ltd/eris-db/manager/eris-mint/evm"
+)
+
+const contractTemplateText = `/**
+[[.Comment]]
+* @dev These functions can be accessed as if this contract were deployed at the address [[.Address]]
+*/
+contract [[.Name]] {[[range .Functions]]
+[[.SolidityIndent 1]]
+[[end]]}
+`
+const functionTemplateText = `/**
+[[.Comment]]
+*/
+function [[.Name]]([[.ArgList]]) constant returns ([[.Return.Type]] [[.Return.Name]]);`
+
+// Solidity style guide recommends 4 spaces per indentation level
+// (see: http://solidity.readthedocs.io/en/develop/style-guide.html)
+const indentString = "    "
+
+var contractTemplate *template.Template
+var functionTemplate *template.Template
+
+func init() {
+	var err error
+	functionTemplate, err = template.New("SolidityFunctionTemplate").
+		Delims("[[", "]]").
+		Parse(functionTemplateText)
+	if err != nil {
+		panic(fmt.Errorf("Couldn't parse SNative function template: %s", err))
+	}
+	contractTemplate, err = template.New("SolidityContractTemplate").
+		Delims("[[", "]]").
+		Parse(contractTemplateText)
+	if err != nil {
+		panic(fmt.Errorf("Couldn't parse SNative contract template: %s", err))
+	}
+}
+
+type solidityContract struct {
+	*vm.SNativeContractDescription
+}
+
+type solidityFunction struct {
+	*vm.SNativeFunctionDescription
+}
+
+// Create a templated solidityContract from an SNative contract description
+func NewSolidityContract(contract *vm.SNativeContractDescription) *solidityContract {
+	return &solidityContract{contract}
+}
+
+func (contract *solidityContract) Address() string {
+	return fmt.Sprintf("0x%x",
+		contract.SNativeContractDescription.Address().Postfix(20))
+}
+
+// Generate Solidity code for this SNative contract
+func (contract *solidityContract) Solidity() (string, error) {
+	buf := new(bytes.Buffer)
+	err := contractTemplate.Execute(buf, contract)
+	if err != nil {
+		return "", err
+	}
+	return buf.String(), nil
+}
+
+func (contract *solidityContract) Functions() []*solidityFunction {
+	functions := contract.SNativeContractDescription.Functions()
+	solidityFunctions := make([]*solidityFunction, len(functions))
+	for i, function := range functions {
+		solidityFunctions[i] = NewSolidityFunction(function)
+	}
+	return solidityFunctions
+}
+
+// Create a templated solidityFunction from an SNative function description
+func NewSolidityFunction(function *vm.SNativeFunctionDescription) *solidityFunction {
+	return &solidityFunction{function}
+}
+
+func (function *solidityFunction) ArgList() string {
+	argList := make([]string, len(function.Args))
+	for i, arg := range function.Args {
+		argList[i] = fmt.Sprintf("%s %s", arg.Type, arg.Name)
+	}
+	return strings.Join(argList, ", ")
+}
+
+func (function *solidityFunction) Comment() string {
+	return comment(function.SNativeFunctionDescription.Comment)
+}
+
+func (function *solidityFunction) SolidityIndent(indentLevel uint) (string, error) {
+	return function.solidity(indentLevel)
+}
+
+func (function *solidityFunction) Solidity() (string, error) {
+	return function.solidity(0)
+}
+
+func (function *solidityFunction) solidity(indentLevel uint) (string, error) {
+	buf := new(bytes.Buffer)
+	iw := NewIndentWriter(indentLevel, indentString, buf)
+	err := functionTemplate.Execute(iw, function)
+	if err != nil {
+		return "", err
+	}
+	return buf.String(), nil
+}
+
+func (contract *solidityContract) Comment() string {
+	return comment(contract.SNativeContractDescription.Comment)
+}
+
+func comment(comment string) string {
+	commentLines := make([]string, 0, 5)
+	for _, line := range strings.Split(comment, "\n") {
+		trimLine := strings.TrimLeft(line, " \t\n")
+		if trimLine != "" {
+			commentLines = append(commentLines, trimLine)
+		}
+	}
+	return strings.Join(commentLines, "\n")
+}
diff --git a/util/snatives/templates/solidity_templates_test.go b/util/snatives/templates/solidity_templates_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..d0a68e961c4d212a8aa7b1ec798969c4dd5f16ff
--- /dev/null
+++ b/util/snatives/templates/solidity_templates_test.go
@@ -0,0 +1,30 @@
+package templates
+
+import (
+	"testing"
+	"github.com/stretchr/testify/assert"
+	"fmt"
+	"github.com/eris-ltd/eris-db/manager/eris-mint/evm"
+)
+
+func TestSNativeFuncTemplate(t *testing.T) {
+	contract := vm.SNativeContracts()["Permissions"]
+	function, err := contract.FunctionByName("removeRole")
+	if err != nil {
+		t.Fatal("Couldn't get function")
+	}
+	solidityFunction := NewSolidityFunction(function)
+	solidity, err := solidityFunction.Solidity()
+	assert.NoError(t, err)
+	fmt.Println(solidity)
+}
+
+// This test checks that we can generate the SNative contract interface and
+// prints it to stdout
+func TestSNativeContractTemplate(t *testing.T) {
+	contract := vm.SNativeContracts()["Permissions"]
+	solidityContract := NewSolidityContract(contract)
+	solidity, err := solidityContract.Solidity()
+	assert.NoError(t, err)
+	fmt.Println(solidity)
+}
\ No newline at end of file
diff --git a/word256/word.go b/word256/word.go
index 2537830ebea8f46cb71ecd56d112f94e9aa8df6a..9dfe7a673121bf544b4d3a81e03eb1f94039e548 100644
--- a/word256/word.go
+++ b/word256/word.go
@@ -30,7 +30,8 @@ var (
 	One256  = Word256{1}
 )
 
-type Word256 [32]byte
+const Word256Length = 32
+type Word256 [Word256Length]byte
 
 func (w Word256) String() string        { return string(w[:]) }
 func (w Word256) TrimmedString() string { return TrimmedString(w.Bytes()) }