diff --git a/Makefile b/Makefile
index 53fd84ee4616b39e8191b8ed818f02e83f8981d2..a05fe57e210c74affc132397a405f4cee63813fb 100644
--- a/Makefile
+++ b/Makefile
@@ -76,7 +76,7 @@ hell:
 # Dumps Solidity interface contracts for SNatives
 .PHONY: snatives
 snatives:
-	@go run ./util/snatives/main.go
+	@go run ./util/snatives/cmd/main.go
 
 ### Building github.com/eris-ltd/eris-db
 
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/snative.go b/manager/eris-mint/evm/snative.go
index c74acc4d05657f01d2d49fedd3fdc51c1d9017be..20463dc8db6a9b4855be874d722bcd9570baea3b 100644
--- a/manager/eris-mint/evm/snative.go
+++ b/manager/eris-mint/evm/snative.go
@@ -8,8 +8,8 @@ import (
 	ptypes "github.com/eris-ltd/eris-db/permission/types"
 	. "github.com/eris-ltd/eris-db/word256"
 
-	"bytes"
 	"strings"
+	"github.com/eris-ltd/eris-db/manager/eris-mint/evm/abi"
 )
 
 //------------------------------------------------------------------------------------------------
@@ -18,40 +18,18 @@ import (
 type SNativeContractDescription struct {
 	Comment   string
 	Name      string
-	functions map[FuncID]SNativeFuncDescription
+	functions map[FuncID]*SNativeFunctionDescription
 }
 
-type SNativeFuncDescription struct {
+type SNativeFunctionDescription struct {
 	Comment  string
 	Name     string
-	Args     []SolidityArg
-	Return   SolidityReturn
+	Args     []abi.Arg
+	Return   abi.Return
 	PermFlag ptypes.PermFlag
 	F        NativeContract
 }
 
-type SolidityType string
-
-type SolidityArg struct {
-	Name string
-	Type SolidityType
-}
-
-type SolidityReturn struct {
-	Name string
-	Type SolidityType
-}
-
-const (
-	// We don't need to be exhaustive here, just make what we used strongly typed
-	SolidityAddress SolidityType = "address"
-	SolidityInt     SolidityType = "int"
-	SolidityUint64  SolidityType = "uint64"
-	SolidityBytes32 SolidityType = "bytes32"
-	SolidityString  SolidityType = "string"
-	SolidityBool    SolidityType = "bool"
-)
-
 func registerSNativeContracts() {
 	for _, contract := range SNativeContracts() {
 		registeredNativeContracts[contract.Address()] = contract.Dispatch
@@ -59,121 +37,122 @@ func registerSNativeContracts() {
 }
 
 // Returns a map of all SNative contracts defined indexed by name
-func SNativeContracts() map[string]SNativeContractDescription {
-	permFlagType := SolidityUint64
-	roleType := SolidityBytes32
-	contracts := []SNativeContractDescription{
+func SNativeContracts() map[string]*SNativeContractDescription {
+	permFlagType := abi.Uint64
+	roleType := abi.Bytes32
+	contracts := []*SNativeContractDescription{
 		NewSNativeContract(`
 		* Interface for managing Secure Native authorizations.
-		* @dev This Solidity interface describes the functions exposed by the SNative permissions layer in the Monax blockchain (ErisDB).
+		* @dev This interface describes the functions exposed by the SNative permissions layer in the Monax blockchain (ErisDB).
 		`,
 			"permissions_contract",
-			SNativeFuncDescription{`
+			&SNativeFunctionDescription{`
 			* @notice Adds a role to an account
-			* @param _account account
-			* @param _role role
+			* @param _account account address
+			* @param _role role name
 			* @return result whether role was added
 			`,
 				"add_role",
-				[]SolidityArg{
-					arg("_account", SolidityAddress),
+				[]abi.Arg{
+					arg("_account", abi.Address),
 					arg("_role", roleType),
 				},
-				ret("result", SolidityBool),
+				ret("result", abi.Bool),
 				ptypes.AddRole,
 				add_role},
 
-			SNativeFuncDescription{`
+			&SNativeFunctionDescription{`
 			* @notice Indicates whether an account has a role
-			* @param _account account
-			* @param _role role
+			* @param _account account address
+			* @param _role role name
 			* @return result whether account has role
 			`,
 				"has_role",
-				[]SolidityArg{
-					arg("_account", SolidityAddress),
+				[]abi.Arg{
+					arg("_account", abi.Address),
 					arg("_role", roleType),
 				},
-				ret("result", SolidityBool),
+				ret("result", abi.Bool),
 				ptypes.HasRole,
 				has_role},
 
-			SNativeFuncDescription{`
+			&SNativeFunctionDescription{`
 			* @notice Removes a role from an account
-			* @param _account account
-			* @param _role role
+			* @param _account account address
+			* @param _role role name
 			* @return result whether role was removed
 			`,
 				"rm_role",
-				[]SolidityArg{
-					arg("_account", SolidityAddress),
+				[]abi.Arg{
+					arg("_account", abi.Address),
 					arg("_role", roleType),
 				},
-				ret("result", SolidityBool),
+				ret("result", abi.Bool),
 				ptypes.RmRole,
 				rm_role},
 
-			SNativeFuncDescription{`
-			* @notice Sets a base authorization for an account
-			* @param _account account
-			* @param _authorization base authorization
-			* @param _value value of base authorization
-			* @return result value passed in
+			&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 resultant permissions flags on the account after the call
 			`,
 				"set_base",
-				[]SolidityArg{
-					arg("_account", SolidityAddress),
-					arg("_authorization", permFlagType),
-					arg("_value", permFlagType)},
-				ret("result", SolidityBool),
+				[]abi.Arg{
+					arg("_account", abi.Address),
+					arg("_permission", permFlagType),
+					arg("_set", abi.Bool),
+				},
+				ret("result", permFlagType),
 				ptypes.SetBase,
 				set_base},
 
-			SNativeFuncDescription{`
-			* @notice Indicates whether an account has a base authorization
-			* @param _account account
-			* @param _authorization base authorization
-			* @return result whether account has base authorization set
+			&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
 			`,
 				"has_base",
-				[]SolidityArg{
-					arg("_account", SolidityAddress),
-					arg("_authorization", permFlagType)},
-				ret("result", SolidityBool),
+				[]abi.Arg{
+					arg("_account", abi.Address),
+					arg("_permission", permFlagType)},
+				ret("result", permFlagType),
 				ptypes.HasBase,
 				has_base},
 
-			SNativeFuncDescription{`
-			* @notice Sets a base authorization for an account to the global (default) value of the base authorization
-      * @param _account account
-      * @param _authorization base authorization
-      * @return authorization base authorization passed in
+			&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 resultant permissions flags on the account after the call
       `,
 				"unset_base",
-				[]SolidityArg{
-					arg("_account", SolidityAddress),
-					arg("_authorization", permFlagType)},
-				ret("authorization", permFlagType),
+				[]abi.Arg{
+					arg("_account", abi.Address),
+					arg("_permission", permFlagType)},
+				ret("result", permFlagType),
 				ptypes.UnsetBase,
 				unset_base},
 
-			SNativeFuncDescription{`
-			* @notice Sets global (default) value for a base authorization
-			* @param _authorization base authorization
-			* @param _value value of base authorization
-			* @return authorization base authorization passed in
+			&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 resultant permissions flags on the account after the call
 			`,
 				"set_global",
-				[]SolidityArg{
-					arg("_authorization", permFlagType),
-					arg("_value", permFlagType)},
-				ret("authorization", permFlagType),
+				[]abi.Arg{
+					arg("_permission", permFlagType),
+					arg("_set", abi.Bool)},
+				ret("result", permFlagType),
 				ptypes.SetGlobal,
 				set_global},
 		),
 	}
 
-	contractMap := make(map[string]SNativeContractDescription, len(contracts))
+	contractMap := make(map[string]*SNativeContractDescription, len(contracts))
 	for _, contract := range contracts {
 		contractMap[contract.Name] = contract
 	}
@@ -183,8 +162,8 @@ func SNativeContracts() map[string]SNativeContractDescription {
 //-----------------------------------------------------------------------------
 // snative are native contracts that can access and modify an account's permissions
 
-func NewSNativeContract(comment, name string, functions ...SNativeFuncDescription) SNativeContractDescription {
-	fs := make(map[FuncID]SNativeFuncDescription, len(functions))
+func NewSNativeContract(comment, name string, functions ...*SNativeFunctionDescription) *SNativeContractDescription {
+	fs := make(map[FuncID]*SNativeFunctionDescription, len(functions))
 	for _, f := range functions {
 		fid := f.ID()
 		otherF, ok := fs[fid]
@@ -194,7 +173,7 @@ func NewSNativeContract(comment, name string, functions ...SNativeFuncDescriptio
 		}
 		fs[fid] = f
 	}
-	return SNativeContractDescription{
+	return &SNativeContractDescription{
 		Comment:   comment,
 		Name:      name,
 		functions: fs,
@@ -207,25 +186,25 @@ func NewSNativeContract(comment, name string, functions ...SNativeFuncDescriptio
 func (contract *SNativeContractDescription) Dispatch(appState AppState,
 	caller *Account, args []byte, gas *int64) (output []byte, err error) {
 	if len(args) < FuncIDLength {
-		return Zero256.Bytes(), fmt.Errorf("SNatives dispatch requires a 4-byte function "+
+		return nil, fmt.Errorf("SNatives dispatch requires a 4-byte function "+
 			"identifier but arguments are only %s bytes long", len(args))
 	}
 
 	function, err := contract.FunctionByID(firstFourBytes(args))
 	if err != nil {
-		return Zero256.Bytes(), err
+		return nil, err
 	}
 
 	remainingArgs := args[FuncIDLength:]
 
 	// check if we have permission to call this function
 	if !HasPermission(appState, caller, function.PermFlag) {
-		return Zero256.Bytes(), ErrInvalidPermission{caller.Address, function.Name}
+		return nil, ErrInvalidPermission{caller.Address, function.Name}
 	}
 
 	// ensure there are enough arguments
 	if len(remainingArgs) != function.NArgs()*Word256Length {
-		return Zero256.Bytes(), fmt.Errorf("%s() takes %d arguments", function.Name,
+		return nil, fmt.Errorf("%s() takes %d arguments", function.Name,
 			function.NArgs())
 	}
 
@@ -233,54 +212,42 @@ func (contract *SNativeContractDescription) Dispatch(appState AppState,
 	return function.F(appState, caller, remainingArgs, gas)
 }
 
+// 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))
 }
 
-func (contract *SNativeContractDescription) FunctionByID(id FuncID) (*SNativeFuncDescription, error) {
+func (contract *SNativeContractDescription) FunctionByID(id FuncID) (*SNativeFunctionDescription, error) {
 	f, ok := contract.functions[id]
 	if !ok {
 		return nil,
 			fmt.Errorf("Unknown SNative function with ID %x", id)
 	}
-	return &f, nil
+	return f, nil
 }
 
-func (contract *SNativeContractDescription) FunctionByName(name string) (*SNativeFuncDescription, error) {
+func (contract *SNativeContractDescription) FunctionByName(name string) (*SNativeFunctionDescription, error) {
 	for _, f := range contract.functions {
 		if f.Name == name {
-			return &f, nil
+			return f, nil
 		}
 	}
 	return nil, fmt.Errorf("Unknown SNative function with name %s", name)
 }
 
-func (contract *SNativeContractDescription) Functions() []SNativeFuncDescription {
-	fs := make([]SNativeFuncDescription, 0, len(contract.functions))
+func (contract *SNativeContractDescription) Functions() []*SNativeFunctionDescription {
+	fs := make([]*SNativeFunctionDescription, 0, len(contract.functions))
 	for _, f := range contract.functions {
 		fs = append(fs, f)
 	}
 	return fs
 }
 
-func (contract *SNativeContractDescription) SolidityComment() string {
-	return solidityComment(contract.Comment)
-}
-
-// Generate solidity code for this SNative contract
-func (contract *SNativeContractDescription) Solidity() (string, error) {
-	buf := new(bytes.Buffer)
-	err := snativeContractTemplate.Execute(buf, contract)
-	if err != nil {
-		return "", err
-	}
-	return buf.String(), nil
-}
-
 //
 // SNative functions
 //
-func (function *SNativeFuncDescription) Signature() string {
+func (function *SNativeFunctionDescription) Signature() string {
 	argTypes := make([]string, len(function.Args))
 	for i, arg := range function.Args {
 		argTypes[i] = string(arg.Type)
@@ -289,57 +256,25 @@ func (function *SNativeFuncDescription) Signature() string {
 		strings.Join(argTypes, ","))
 }
 
-func (function *SNativeFuncDescription) ID() FuncID {
+func (function *SNativeFunctionDescription) ID() FuncID {
 	return firstFourBytes(sha3.Sha3([]byte(function.Signature())))
 }
 
-func (function *SNativeFuncDescription) NArgs() int {
+func (function *SNativeFunctionDescription) NArgs() int {
 	return len(function.Args)
 }
 
-func (function *SNativeFuncDescription) SolidityArgList() 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 *SNativeFuncDescription) SolidityComment() string {
-	return solidityComment(function.Comment)
-}
-
-func (function *SNativeFuncDescription) Solidity() (string, error) {
-	buf := new(bytes.Buffer)
-	err := snativeFuncTemplate.Execute(buf, function)
-	if err != nil {
-		return "", err
-	}
-	return buf.String(), nil
-}
-
-func solidityComment(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")
-}
-
-func arg(name string, solidityType SolidityType) SolidityArg {
-	return SolidityArg{
+func arg(name string, abiType abi.Type) abi.Arg {
+	return abi.Arg{
 		Name: name,
-		Type: solidityType,
+		Type: abiType,
 	}
 }
 
-func ret(name string, solidityType SolidityType) SolidityReturn {
-	return SolidityReturn{
+func ret(name string, abiType abi.Type) abi.Return {
+	return abi.Return{
 		Name: name,
-		Type: solidityType,
+		Type: abiType,
 	}
 }
 
@@ -362,7 +297,7 @@ func has_base(appState AppState, caller *Account, args []byte, gas *int64) (outp
 }
 
 func set_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	addr, permNum, perm := returnThreeArgs(args)
+	addr, permNum, permVal := returnThreeArgs(args)
 	vmAcc := appState.GetAccount(addr)
 	if vmAcc == nil {
 		return nil, fmt.Errorf("Unknown account %X", addr)
@@ -371,13 +306,13 @@ 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 resultantPermBytes(vmAcc.Permissions.Base), nil
 }
 
 func unset_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
@@ -395,11 +330,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 resultantPermBytes(vmAcc.Permissions.Base), nil
 }
 
 func set_global(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
-	permNum, perm := returnTwoArgs(args)
+	permNum, permVal := returnTwoArgs(args)
 	vmAcc := appState.GetAccount(ptypes.GlobalPermissionsAddress256)
 	if vmAcc == nil {
 		sanity.PanicSanity("cant find the global permissions account")
@@ -408,13 +343,13 @@ 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 resultantPermBytes(vmAcc.Permissions.Base), nil
 }
 
 func has_role(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
@@ -475,6 +410,10 @@ func ValidPermN(n ptypes.PermFlag) bool {
 	return true
 }
 
+func resultantPermBytes(basePerms ptypes.BasePermissions) []byte {
+	return Uint64ToWord256(uint64(basePerms.ResultantPerms())).Bytes()
+}
+
 // CONTRACT: length has already been checked
 func returnTwoArgs(args []byte) (a Word256, b Word256) {
 	copy(a[:], args[:32])
diff --git a/manager/eris-mint/evm/snative_templates.go b/manager/eris-mint/evm/snative_templates.go
deleted file mode 100644
index dc47388e2dc515693743148e2d53e4c844ca1532..0000000000000000000000000000000000000000
--- a/manager/eris-mint/evm/snative_templates.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package vm
-
-import (
-	"text/template"
-	"fmt"
-)
-
-const snativeContractTemplateText=`/**
-{{.SolidityComment}}
-*/
-contract {{.Name}} {
-{{range .Functions}}
-{{.Solidity}}
-{{end}}
-}
-`
-const snativeFuncTemplateText=`/**
-{{.SolidityComment}}
-*/
-function {{.Name}}({{.SolidityArgList}}) constant returns ({{.Return.Type}} {{.Return.Name}});`
-
-var snativeContractTemplate *template.Template
-var snativeFuncTemplate *template.Template
-
-func init() {
-	var err error
-	snativeFuncTemplate, err = template.New("snativeFuncTemplate").
-	Parse(snativeFuncTemplateText)
-	if err != nil {
-		panic(fmt.Errorf("Couldn't parse SNative function template: %s", err))
-	}
-	snativeContractTemplate, err = template.New("snativeFuncTemplate").
-			Parse(snativeContractTemplateText)
-	if err != nil {
-		panic(fmt.Errorf("Couldn't parse SNative contract template: %s", err))
-	}
-}
\ No newline at end of file
diff --git a/manager/eris-mint/evm/snative_test.go b/manager/eris-mint/evm/snative_test.go
index 5738d6180dd23a504a4b0edff5f0a65b97c7e42e..5677e20b73ed8ab4202086e89a863631dc801786 100644
--- a/manager/eris-mint/evm/snative_test.go
+++ b/manager/eris-mint/evm/snative_test.go
@@ -6,7 +6,6 @@ import (
 
 	. "github.com/eris-ltd/eris-db/word256"
 	"github.com/stretchr/testify/assert"
-	"fmt"
 	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
 	ptypes "github.com/eris-ltd/eris-db/permission/types"
 )
@@ -20,8 +19,8 @@ Functions
 744f5998 has_base(address,uint64)
 e8145855 has_role(address,bytes32)
 28fd0194 rm_role(address,bytes32)
-3f0ebb30 set_base(address,uint64,uint64)
-d54a562d set_global(uint64,uint64)
+c2174d8f set_base(address,uint64,bool)
+85f1522b set_global(uint64,bool)
 73448c99 unset_base(address,uint64)
 
 */
@@ -41,11 +40,11 @@ func TestPermissionsContractSignatures(t *testing.T) {
 	assertFunctionIDSignature(t, contract, "28fd0194",
 		"rm_role(address,bytes32)")
 
-	assertFunctionIDSignature(t, contract, "3f0ebb30",
-		"set_base(address,uint64,uint64)")
+	assertFunctionIDSignature(t, contract, "c2174d8f",
+		"set_base(address,uint64,bool)")
 
-	assertFunctionIDSignature(t, contract, "d54a562d",
-		"set_global(uint64,uint64)")
+	assertFunctionIDSignature(t, contract, "85f1522b",
+		"set_global(uint64,bool)")
 
 	assertFunctionIDSignature(t, contract, "73448c99",
 		"unset_base(address,uint64)")
@@ -83,30 +82,10 @@ func TestSNativeContractDescription_Dispatch(t *testing.T) {
 	assert.Equal(t, retValue, LeftPadBytes([]byte{1},32))
 }
 
-func TestSNativeFuncTemplate(t *testing.T) {
-	contract := SNativeContracts()["permissions_contract"]
-	function, err := contract.FunctionByName("rm_role")
-	if err != nil {
-		t.Fatal("Couldn't get function")
-	}
-	solidity, err := function.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 := SNativeContracts()["permissions_contract"]
-	solidity, err := contract.Solidity()
-	assert.NoError(t, err)
-	fmt.Println(solidity)
-}
-
 //
 // Helpers
 //
-func assertFunctionIDSignature(t *testing.T, contract SNativeContractDescription,
+func assertFunctionIDSignature(t *testing.T, contract *SNativeContractDescription,
 	funcIDHex string, expectedSignature string) {
 	function, err := contract.FunctionByID(funcIDFromHex(t, funcIDHex))
 	assert.NoError(t, err,
diff --git a/permission/types/permissions.go b/permission/types/permissions.go
index 15706c9f8ca2a2922610522a4075b3f128693465..bd6cd9ad24e6d474cb97b4291368f0ab4ab5876c 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)
 }
diff --git a/util/snatives/main.go b/util/snatives/cmd/main.go
similarity index 71%
rename from util/snatives/main.go
rename to util/snatives/cmd/main.go
index e15d26ffca708a58e9744235e8cc02ae25b83d1c..5b1f6b49938e17bb27e986c7dc8aef6f20d8f4da 100644
--- a/util/snatives/main.go
+++ b/util/snatives/cmd/main.go
@@ -4,12 +4,13 @@ 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() {
 	for _, contract := range vm.SNativeContracts() {
-		solidity, err := contract.Solidity()
+		solidity, err := templates.NewSolidityContract(contract).Solidity()
 		if err != nil {
 			fmt.Printf("Error generating solidity for contract %s: %s\n",
 				contract.Name, err)
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..f98f15e5b182848d0e3d1f7d9247d3768c13668e
--- /dev/null
+++ b/util/snatives/templates/solidity_templates.go
@@ -0,0 +1,125 @@
+package templates
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"text/template"
+
+	"github.com/eris-ltd/eris-db/manager/eris-mint/evm"
+)
+
+const contractTemplateText = `/**
+[[.Comment]]
+*/
+contract [[.Name]] {[[range .Functions]]
+[[.SolidityIndent 1]]
+[[end]]}
+`
+const functionTemplateText = `/**
+[[.Comment]]
+*/
+function [[.Name]]([[.ArgList]]) constant returns ([[.Return.Type]] [[.Return.Name]]);`
+
+const indentString = "\t"
+
+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}
+}
+
+// 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..ffc92b026a5c9ec034814c108c020a3db80ec370
--- /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_contract"]
+	function, err := contract.FunctionByName("rm_role")
+	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_contract"]
+	solidityContract := NewSolidityContract(contract)
+	solidity, err := solidityContract.Solidity()
+	assert.NoError(t, err)
+	fmt.Println(solidity)
+}
\ No newline at end of file