diff --git a/binary/integer.go b/binary/integer.go
index f865148400b866d4b071f469c934d1fb297c2f7b..a00c07054502952f50408eba9a4bf8d000c654ba 100644
--- a/binary/integer.go
+++ b/binary/integer.go
@@ -17,10 +17,14 @@ package binary
 import (
 	"encoding/binary"
 	"math"
+	"math/big"
 	"sort"
 )
 
-const Uint64TopBitMask = 1 << 63
+var big1 = big.NewInt(1)
+var tt256 = new(big.Int).Lsh(big1, 256)
+var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big1, 256), big1)
+var tt255 = new(big.Int).Lsh(big1, 255)
 
 // Sort for []uint64
 
@@ -75,3 +79,42 @@ func GetInt64BE(src []byte) int64 {
 func IsUint64SumOverflow(a, b uint64) bool {
 	return math.MaxUint64-a < b
 }
+
+//
+
+// Converts a possibly negative big int x into a positive big int encoding a twos complement representation of x
+// truncated to 32 bytes
+func U256(x *big.Int) *big.Int {
+	// Note that the And operation induces big.Int to hold a positive representation of a negative number
+	return new(big.Int).And(x, tt256m1)
+}
+
+// Interprets a positive big.Int as a 256-bit two's complement signed integer
+func S256(x *big.Int) *big.Int {
+	// Sign bit not set, value is its positive self
+	if x.Cmp(tt255) < 0 {
+		return x
+	} else {
+		// negative value is represented
+		return new(big.Int).Sub(x, tt256)
+	}
+}
+
+// Treats the positive big int x as if it contains an embedded a back + 1 byte signed integer in its least significant
+// bits and extends that sign
+func SignExtend(back uint64, x *big.Int) *big.Int {
+	// we assume x contains a signed integer of back + 1 bytes width
+	// most significant bit of the back'th byte,
+	signBit := back*8 + 7
+	// single bit set at sign bit position
+	mask := new(big.Int).Lsh(big1, uint(signBit))
+	// all bits below sign bit set to 1 all above (including sign bit) set to 0
+	mask.Sub(mask, big1)
+	if x.Bit(int(signBit)) == 1 {
+		// Number represented is negative - set all bits above sign bit (including sign bit)
+		return x.Or(x, mask.Not(mask))
+	} else {
+		// Number represented is positive - clear all bits above sign bit (including sign bit)
+		return x.And(x, mask)
+	}
+}
diff --git a/binary/integer_test.go b/binary/integer_test.go
index e530c5a7bb6b312fb2e8777796889b1629cb4a45..c0c1533fecac2e81eb73a754eab919e6c505af04 100644
--- a/binary/integer_test.go
+++ b/binary/integer_test.go
@@ -2,9 +2,16 @@ package binary
 
 import (
 	"math"
+	"math/big"
 	"testing"
 
+	"strconv"
+	"strings"
+
+	"fmt"
+
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func TestIsUint64SumOverflow(t *testing.T) {
@@ -17,3 +24,154 @@ func TestIsUint64SumOverflow(t *testing.T) {
 	assert.True(t, IsUint64SumOverflow(a+b, 1))
 	assert.True(t, IsUint64SumOverflow(a+1, b+1))
 }
+
+func zero() *big.Int {
+	return new(big.Int)
+}
+
+var big2E255 = zero().Lsh(big1, 255)
+var big2E256 = zero().Lsh(big1, 256)
+var big2E257 = zero().Lsh(big1, 257)
+
+func TestU256(t *testing.T) {
+	expected := big2E255
+	encoded := U256(expected)
+	assertBigIntEqual(t, expected, encoded, "Top bit set big int is fixed point")
+
+	expected = zero()
+	encoded = U256(big2E256)
+	assertBigIntEqual(t, expected, encoded, "Ceiling bit is exact overflow")
+
+	expected = zero().Sub(big2E256, big1)
+	encoded = U256(expected)
+	assertBigIntEqual(t, expected, encoded, "Max unsigned big int is fixed point")
+
+	expected = big1
+	encoded = U256(zero().Add(big2E256, big1))
+	assertBigIntEqual(t, expected, encoded, "Overflow by one")
+
+	expected = big2E255
+	encoded = U256(zero().Add(big2E256, big2E255))
+	assertBigIntEqual(t, expected, encoded, "Overflow by doubling")
+
+	negative := big.NewInt(-234)
+	assert.Equal(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16",
+		fmt.Sprintf("%X", U256(negative).Bytes()), "byte representation is twos complement")
+
+	expected, ok := zero().SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16", 16)
+	require.True(t, ok)
+	assertBigIntEqual(t, expected, U256(negative), "Bytes representation should be twos complement")
+
+	expected = zero()
+	encoded = U256(zero().Neg(big2E256))
+	assertBigIntEqual(t, expected, encoded, "Floor bit is overflow")
+
+	expected = big2E255
+	encoded = zero().Neg(big2E255)
+	encoded = U256(encoded)
+	assertBigIntEqual(t, expected, encoded, "2**255 is Self complement")
+
+	expected = zero().Add(big2E255, big1)
+	encoded = zero().Neg(big2E255)
+	encoded = encoded.Add(encoded, big1)
+	encoded = U256(encoded)
+	assertBigIntEqual(t, expected, encoded, "")
+}
+
+func TestS256(t *testing.T) {
+	expected := zero().Neg(big2E255)
+	signed := S256(big2E255)
+	assertBigIntEqual(t, expected, signed, "Should be negative")
+
+	expected = zero().Sub(big2E255, big1)
+	signed = S256(expected)
+	assertBigIntEqual(t, expected, signed, "Maximum twos complement positive is fixed point")
+
+	expected = zero()
+	signed = S256(expected)
+	assertBigIntEqual(t, expected, signed, "Twos complement of zero is fixed poount")
+
+	// Technically undefined but let's not let that stop us
+	expected = zero().Sub(big2E257, big2E256)
+	signed = S256(big2E257)
+	assertBigIntEqual(t, expected, signed, "Out of twos complement bounds")
+}
+
+func TestSignExtend(t *testing.T) {
+	assertSignExtend(t, 16, 0,
+		"0000 0000 1001 0000",
+		"1111 1111 1001 0000")
+
+	assertSignExtend(t, 16, 1,
+		"1001 0000",
+		"1001 0000")
+
+	assertSignExtend(t, 32, 2,
+		"0000 0000 1000 0000 1101 0011 1001 0000",
+		"1111 1111 1000 0000 1101 0011 1001 0000")
+
+	assertSignExtend(t, 32, 2,
+		"0000 0000 0000 0000 1101 0011 1001 0000",
+		"0000 0000 0000 0000 1101 0011 1001 0000")
+
+	// Here we have a stray bit set in the 4th most significant byte that gets wiped out
+	assertSignExtend(t, 32, 2,
+		"0001 0000 0000 0000 1101 0011 1001 0000",
+		"0000 0000 0000 0000 1101 0011 1001 0000")
+	assertSignExtend(t, 32, 2,
+		"0001 0000 1000 0000 1101 0011 1001 0000",
+		"1111 1111 1000 0000 1101 0011 1001 0000")
+
+	assertSignExtend(t, 32, 3,
+		"0001 0000 1000 0000 1101 0011 1001 0000",
+		"0001 0000 1000 0000 1101 0011 1001 0000")
+
+	assertSignExtend(t, 32, 3,
+		"1001 0000 1000 0000 1101 0011 1001 0000",
+		"1001 0000 1000 0000 1101 0011 1001 0000")
+
+	assertSignExtend(t, 64, 3,
+		"0000 0000 0000 0000 0000 0000 0000 0000 1001 0000 1000 0000 1101 0011 1001 0000",
+		"1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 1000 0000 1101 0011 1001 0000")
+
+	assertSignExtend(t, 64, 3,
+		"0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 1000 0000 1101 0011 1001 0000",
+		"0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 1000 0000 1101 0011 1001 0000")
+}
+
+func assertSignExtend(t *testing.T, bitSize int, bytesBack uint64, inputString, expectedString string) bool {
+	input := intFromString(t, bitSize, inputString)
+	expected := intFromString(t, bitSize, expectedString)
+	//actual := SignExtend(big.NewInt(bytesBack), big.NewInt(int64(input)))
+	actual := SignExtend(bytesBack, big.NewInt(int64(input)))
+	var ret bool
+	switch bitSize {
+	case 8:
+		ret = assert.Equal(t, uint8(expected), uint8(actual.Int64()))
+	case 16:
+		ret = assert.Equal(t, uint16(expected), uint16(actual.Int64()))
+	case 32:
+		ret = assert.Equal(t, uint32(expected), uint32(actual.Int64()))
+	case 64:
+		ret = assert.Equal(t, uint64(expected), uint64(actual.Int64()))
+	default:
+		t.Fatalf("Cannot test SignExtend for non-Go-native bit size %v", bitSize)
+		return false
+	}
+	if !ret {
+
+	}
+	return ret
+}
+
+func assertBigIntEqual(t *testing.T, expected, actual *big.Int, messages ...string) bool {
+	return assert.True(t, expected.Cmp(actual) == 0, fmt.Sprintf("%s - not equal:\n%v (expected)\n%v (actual)",
+		strings.Join(messages, " "), expected, actual))
+}
+
+func intFromString(t *testing.T, bitSize int, binStrings ...string) uint64 {
+	binaryString := strings.Replace(strings.Join(binStrings, ""), " ", "", -1)
+	i, err := strconv.ParseUint(binaryString, 2, bitSize)
+	require.NoError(t, err)
+	return i
+}
diff --git a/binary/word256.go b/binary/word256.go
index 6d11fe9aa27538f0ea21b4f94b8183edcfb4f13b..02a90581f9c297f49c9fe08369755efa82694b3f 100644
--- a/binary/word256.go
+++ b/binary/word256.go
@@ -16,16 +16,19 @@ package binary
 
 import (
 	"bytes"
+	"math/big"
 	"sort"
 )
 
 var (
 	Zero256 = Word256{}
-	One256  = Word256{1}
+	One256  = LeftPadWord256([]byte{1})
 )
 
 const Word256Length = 32
 
+var BigWord256Length = big.NewInt(Word256Length)
+
 var trimCutSet = string([]byte{0})
 
 type Word256 [Word256Length]byte
diff --git a/binary/word256_test.go b/binary/word256_test.go
index 055d39109e6e3cdbc249948b2071837ba3a9c87d..78aaeb596829d9d7f9a073fd5402d2e067a4ab74 100644
--- a/binary/word256_test.go
+++ b/binary/word256_test.go
@@ -37,3 +37,7 @@ func TestLeftPadWord256(t *testing.T) {
 		},
 		LeftPadWord256([]byte{1, 2, 3}))
 }
+
+func TestOne256(t *testing.T) {
+	assert.Equal(t, Int64ToWord256(1), One256)
+}
diff --git a/execution/evm/common.go b/execution/evm/common.go
deleted file mode 100644
index e8fb7444c8afcfa69e387323a654c4c2bb5f90ae..0000000000000000000000000000000000000000
--- a/execution/evm/common.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 Monax Industries Limited
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package evm
-
-import (
-	"math/big"
-)
-
-// To256
-//
-// "cast" the big int to a 256 big int (i.e., limit to)
-var tt256 = new(big.Int).Lsh(big.NewInt(1), 256)
-var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1))
-var tt255 = new(big.Int).Lsh(big.NewInt(1), 255)
-
-func U256(x *big.Int) *big.Int {
-	x.And(x, tt256m1)
-	return x
-}
-
-func S256(x *big.Int) *big.Int {
-	if x.Cmp(tt255) < 0 {
-		return x
-	} else {
-		// We don't want to modify x, ever
-		return new(big.Int).Sub(x, tt256)
-	}
-}
diff --git a/execution/evm/memory.go b/execution/evm/memory.go
index 6eb8456cbbd6e861ba56993a8819622e178bd3da..126686146fcee28cb9ae5e964296daf874dbc211 100644
--- a/execution/evm/memory.go
+++ b/execution/evm/memory.go
@@ -3,6 +3,7 @@ package evm
 import (
 	"fmt"
 	"math"
+	"math/big"
 )
 
 const (
@@ -16,7 +17,7 @@ const (
 // unlikely to make a lot of difference.
 var zeroBlock []byte = make([]byte, 32)
 
-// Interface for a bounded linear memory indexed by a single int64 parameter
+// Interface for a bounded linear memory indexed by a single *big.Int parameter
 // for each byte in the memory.
 type Memory interface {
 	// Read a value from the memory store starting at offset
@@ -26,20 +27,23 @@ type Memory interface {
 	//
 	// The value returned should be copy of any underlying memory, not a reference
 	// to the underlying store.
-	Read(offset, length int64) ([]byte, error)
+	Read(offset, length *big.Int) ([]byte, error)
 	// Write a value to the memory starting at offset (the index of the first byte
 	// written will equal offset). The value is provided as bytes to be written
 	// consecutively to the memory store. Return an error if the memory cannot be
 	// written or allocated.
-	Write(offset int64, value []byte) error
+	Write(offset *big.Int, value []byte) error
 	// Returns the current capacity of the memory. For dynamically allocating
 	// memory this capacity can be used as a write offset that is guaranteed to be
 	// unused. Solidity in particular makes this assumption when using MSIZE to
 	// get the current allocated memory.
-	Capacity() int64
+	Capacity() *big.Int
 }
 
-func NewDynamicMemory(initialCapacity, maximumCapacity int64) Memory {
+// Get a new DynamicMemory (note that although we take a maximumCapacity of uint64 we currently
+// limit the maximum to int32 at runtime because we are using a single slice which we cannot guarantee
+// to be indexable above int32 or all validators
+func NewDynamicMemory(initialCapacity, maximumCapacity uint64) Memory {
 	return &dynamicMemory{
 		slice:           make([]byte, initialCapacity),
 		maximumCapacity: maximumCapacity,
@@ -54,10 +58,22 @@ func DefaultDynamicMemoryProvider() Memory {
 // array allocation via a backing slice
 type dynamicMemory struct {
 	slice           []byte
-	maximumCapacity int64
+	maximumCapacity uint64
 }
 
-func (mem *dynamicMemory) Read(offset, length int64) ([]byte, error) {
+func (mem *dynamicMemory) Read(offset, length *big.Int) ([]byte, error) {
+	// Ensures positive and not too wide
+	if !offset.IsUint64() {
+		return nil, fmt.Errorf("offset %v does not fit inside an unsigned 64-bit integer", offset)
+	}
+	// Ensures positive and not too wide
+	if !length.IsUint64() {
+		return nil, fmt.Errorf("length %v does not fit inside an unsigned 64-bit integer", offset)
+	}
+	return mem.read(offset.Uint64(), length.Uint64())
+}
+
+func (mem *dynamicMemory) read(offset, length uint64) ([]byte, error) {
 	capacity := offset + length
 	err := mem.ensureCapacity(capacity)
 	if err != nil {
@@ -68,8 +84,16 @@ func (mem *dynamicMemory) Read(offset, length int64) ([]byte, error) {
 	return value, nil
 }
 
-func (mem *dynamicMemory) Write(offset int64, value []byte) error {
-	capacity := offset + int64(len(value))
+func (mem *dynamicMemory) Write(offset *big.Int, value []byte) error {
+	// Ensures positive and not too wide
+	if !offset.IsUint64() {
+		return fmt.Errorf("offset %v does not fit inside an unsigned 64-bit integer", offset)
+	}
+	return mem.write(offset.Uint64(), value)
+}
+
+func (mem *dynamicMemory) write(offset uint64, value []byte) error {
+	capacity := offset + uint64(len(value))
 	err := mem.ensureCapacity(capacity)
 	if err != nil {
 		return err
@@ -78,18 +102,21 @@ func (mem *dynamicMemory) Write(offset int64, value []byte) error {
 	return nil
 }
 
-func (mem *dynamicMemory) Capacity() int64 {
-	return int64(len(mem.slice))
+func (mem *dynamicMemory) Capacity() *big.Int {
+	return big.NewInt(int64(len(mem.slice)))
 }
 
 // Ensures the current memory store can hold newCapacity. Will only grow the
 // memory (will not shrink).
-func (mem *dynamicMemory) ensureCapacity(newCapacity int64) error {
+func (mem *dynamicMemory) ensureCapacity(newCapacity uint64) error {
+	// Maximum length of a slice that allocates memory is the same as the native int max size
+	// We could rethink this limit, but we don't want different validators to disagree on
+	// transaction validity so we pick the lowest common denominator
 	if newCapacity > math.MaxInt32 {
 		// If we ever did want more than an int32 of space then we would need to
 		// maintain multiple pages of memory
 		return fmt.Errorf("cannot address memory beyond a maximum index "+
-			"of Int32 type (%v bytes)", math.MaxInt32)
+			"with int32 width (%v bytes)", math.MaxInt32)
 	}
 	newCapacityInt := int(newCapacity)
 	// We're already big enough so return
diff --git a/execution/evm/memory_test.go b/execution/evm/memory_test.go
index 923cdda45d6a83c5532f523d3c360e655457ab55..c60a858339f25a2874b75c5751e14fb48e5cd7e4 100644
--- a/execution/evm/memory_test.go
+++ b/execution/evm/memory_test.go
@@ -3,14 +3,16 @@ package evm
 import (
 	"testing"
 
+	"math/big"
+
 	"github.com/stretchr/testify/assert"
 )
 
 // Test static memory allocation with maximum == initial capacity - memory should not grow
 func TestDynamicMemory_StaticAllocation(t *testing.T) {
 	mem := NewDynamicMemory(4, 4).(*dynamicMemory)
-	mem.Write(0, []byte{1})
-	mem.Write(1, []byte{0, 0, 1})
+	mem.Write(big.NewInt(0), []byte{1})
+	mem.Write(big.NewInt(1), []byte{0, 0, 1})
 	assert.Equal(t, []byte{1, 0, 0, 1}, mem.slice)
 	assert.Equal(t, 4, cap(mem.slice), "Slice capacity should not grow")
 }
@@ -18,31 +20,31 @@ func TestDynamicMemory_StaticAllocation(t *testing.T) {
 // Test reading beyond the current capacity - memory should grow
 func TestDynamicMemory_ReadAhead(t *testing.T) {
 	mem := NewDynamicMemory(4, 8).(*dynamicMemory)
-	value, err := mem.Read(2, 4)
+	value, err := mem.Read(big.NewInt(2), big.NewInt(4))
 	assert.NoError(t, err)
 	// Value should be size requested
 	assert.Equal(t, []byte{0, 0, 0, 0}, value)
 	// Slice should have grown to that plus offset
 	assert.Equal(t, []byte{0, 0, 0, 0, 0, 0}, mem.slice)
 
-	value, err = mem.Read(2, 6)
+	value, err = mem.Read(big.NewInt(2), big.NewInt(6))
 	assert.NoError(t, err)
 	assert.Equal(t, []byte{0, 0, 0, 0, 0, 0}, value)
 	assert.Equal(t, []byte{0, 0, 0, 0, 0, 0, 0, 0}, mem.slice)
 
 	// Check cannot read out of bounds
-	_, err = mem.Read(2, 7)
+	_, err = mem.Read(big.NewInt(2), big.NewInt(7))
 	assert.Error(t, err)
 }
 
 // Test writing beyond the current capacity - memory should grow
 func TestDynamicMemory_WriteAhead(t *testing.T) {
 	mem := NewDynamicMemory(4, 8).(*dynamicMemory)
-	err := mem.Write(4, []byte{1, 2, 3, 4})
+	err := mem.Write(big.NewInt(4), []byte{1, 2, 3, 4})
 	assert.NoError(t, err)
 	assert.Equal(t, []byte{0, 0, 0, 0, 1, 2, 3, 4}, mem.slice)
 
-	err = mem.Write(4, []byte{1, 2, 3, 4, 5})
+	err = mem.Write(big.NewInt(4), []byte{1, 2, 3, 4, 5})
 	assert.Error(t, err)
 }
 
@@ -56,21 +58,21 @@ to describe: his sensation of a few hours before on Grattan Bridge, for
 example. If he could get back again into that mood....`)
 
 	// Write the bytes
-	offset := 0x1000000
-	err := mem.Write(int64(offset), bytesToWrite)
+	offset := big.NewInt(0x1000000)
+	err := mem.Write(offset, bytesToWrite)
 	assert.NoError(t, err)
-	assert.Equal(t, append(make([]byte, offset), bytesToWrite...), mem.slice)
-	assert.Equal(t, offset+len(bytesToWrite), len(mem.slice))
+	assert.Equal(t, append(make([]byte, offset.Uint64()), bytesToWrite...), mem.slice)
+	assert.Equal(t, offset.Uint64()+uint64(len(bytesToWrite)), uint64(len(mem.slice)))
 
 	// Read them back
-	value, err := mem.Read(int64(offset), int64(len(bytesToWrite)))
+	value, err := mem.Read(offset, big.NewInt(int64(len(bytesToWrite))))
 	assert.NoError(t, err)
 	assert.Equal(t, bytesToWrite, value)
 }
 
 func TestDynamicMemory_ZeroInitialMemory(t *testing.T) {
 	mem := NewDynamicMemory(0, 16).(*dynamicMemory)
-	err := mem.Write(4, []byte{1, 2, 3, 4})
+	err := mem.Write(big.NewInt(4), []byte{1, 2, 3, 4})
 	assert.NoError(t, err)
 	assert.Equal(t, []byte{0, 0, 0, 0, 1, 2, 3, 4}, mem.slice)
 }
@@ -78,15 +80,15 @@ func TestDynamicMemory_ZeroInitialMemory(t *testing.T) {
 func TestDynamicMemory_Capacity(t *testing.T) {
 	mem := NewDynamicMemory(1, 0x10000000).(*dynamicMemory)
 
-	assert.Equal(t, int64(1), mem.Capacity())
+	assert.Equal(t, big.NewInt(1), mem.Capacity())
 
-	capacity := int64(1234)
-	err := mem.ensureCapacity(capacity)
+	capacity := big.NewInt(1234)
+	err := mem.ensureCapacity(capacity.Uint64())
 	assert.NoError(t, err)
 	assert.Equal(t, capacity, mem.Capacity())
 
-	capacity = int64(123456789)
-	err = mem.ensureCapacity(capacity)
+	capacity = big.NewInt(123456789)
+	err = mem.ensureCapacity(capacity.Uint64())
 	assert.NoError(t, err)
 	assert.Equal(t, capacity, mem.Capacity())
 
diff --git a/execution/evm/stack.go b/execution/evm/stack.go
index 0d8a8f3fae56d01205a82656ec9d0670b1719cd5..2db8018355dab6635a48dcd246254d79780f01f5 100644
--- a/execution/evm/stack.go
+++ b/execution/evm/stack.go
@@ -17,6 +17,8 @@ package evm
 import (
 	"fmt"
 
+	"math/big"
+
 	. "github.com/hyperledger/burrow/binary"
 )
 
@@ -78,6 +80,15 @@ func (st *Stack) PushU64(i uint64) {
 	st.Push(Uint64ToWord256(i))
 }
 
+// Pushes the bigInt as a Word256 encoding negative values in 32-byte twos complement and returns the encoded result
+func (st *Stack) PushBigInt(bigInt *big.Int) Word256 {
+	word := LeftPadWord256(U256(bigInt).Bytes())
+	st.Push(word)
+	return word
+}
+
+// Pops
+
 func (st *Stack) Pop() Word256 {
 	st.useGas(GasStackOp)
 	if st.ptr == 0 {
@@ -102,6 +113,15 @@ func (st *Stack) PopU64() uint64 {
 	return Uint64FromWord256(d)
 }
 
+func (st *Stack) PopBigIntSigned() *big.Int {
+	return S256(st.PopBigInt())
+}
+
+func (st *Stack) PopBigInt() *big.Int {
+	d := st.Pop()
+	return new(big.Int).SetBytes(d[:])
+}
+
 func (st *Stack) Len() int {
 	return st.ptr
 }
diff --git a/execution/evm/vm.go b/execution/evm/vm.go
index f20efce78f68c56e32abba9b1650a67f81866b1b..fe1f51cbfde5783612babd698940888874609e0a 100644
--- a/execution/evm/vm.go
+++ b/execution/evm/vm.go
@@ -18,7 +18,6 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
-	"math/big"
 
 	acm "github.com/hyperledger/burrow/account"
 	. "github.com/hyperledger/burrow/binary"
@@ -220,202 +219,147 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 		switch op {
 
 		case ADD: // 0x01
-			x, y := stack.Pop(), stack.Pop()
-			xb := new(big.Int).SetBytes(x[:])
-			yb := new(big.Int).SetBytes(y[:])
-			sum := new(big.Int).Add(xb, yb)
-			res := LeftPadWord256(U256(sum).Bytes())
-			stack.Push(res)
-			vm.Debugf(" %v + %v = %v (%X)\n", xb, yb, sum, res)
+			x, y := stack.PopBigInt(), stack.PopBigInt()
+			sum := x.Add(x, y)
+			res := stack.PushBigInt(sum)
+			vm.Debugf(" %v + %v = %v (%X)\n", x, y, sum, res)
 
 		case MUL: // 0x02
-			x, y := stack.Pop(), stack.Pop()
-			xb := new(big.Int).SetBytes(x[:])
-			yb := new(big.Int).SetBytes(y[:])
-			prod := new(big.Int).Mul(xb, yb)
-			res := LeftPadWord256(U256(prod).Bytes())
-			stack.Push(res)
-			vm.Debugf(" %v * %v = %v (%X)\n", xb, yb, prod, res)
+			x, y := stack.PopBigInt(), stack.PopBigInt()
+			prod := x.Mul(x, y)
+			res := stack.PushBigInt(prod)
+			vm.Debugf(" %v * %v = %v (%X)\n", x, y, prod, res)
 
 		case SUB: // 0x03
-			x, y := stack.Pop(), stack.Pop()
-			xb := new(big.Int).SetBytes(x[:])
-			yb := new(big.Int).SetBytes(y[:])
-			diff := new(big.Int).Sub(xb, yb)
-			res := LeftPadWord256(U256(diff).Bytes())
-			stack.Push(res)
-			vm.Debugf(" %v - %v = %v (%X)\n", xb, yb, diff, res)
+			x, y := stack.PopBigInt(), stack.PopBigInt()
+			diff := x.Sub(x, y)
+			res := stack.PushBigInt(diff)
+			vm.Debugf(" %v - %v = %v (%X)\n", x, y, diff, res)
 
 		case DIV: // 0x04
-			x, y := stack.Pop(), stack.Pop()
-			if y.IsZero() {
+			x, y := stack.PopBigInt(), stack.PopBigInt()
+			if y.Sign() == 0 {
 				stack.Push(Zero256)
 				vm.Debugf(" %x / %x = %v\n", x, y, 0)
 			} else {
-				xb := new(big.Int).SetBytes(x[:])
-				yb := new(big.Int).SetBytes(y[:])
-				div := new(big.Int).Div(xb, yb)
-				res := LeftPadWord256(U256(div).Bytes())
-				stack.Push(res)
-				vm.Debugf(" %v / %v = %v (%X)\n", xb, yb, div, res)
+				div := x.Div(x, y)
+				res := stack.PushBigInt(div)
+				vm.Debugf(" %v / %v = %v (%X)\n", x, y, div, res)
 			}
 
 		case SDIV: // 0x05
-			x, y := stack.Pop(), stack.Pop()
-			if y.IsZero() {
+			x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned()
+			if y.Sign() == 0 {
 				stack.Push(Zero256)
 				vm.Debugf(" %x / %x = %v\n", x, y, 0)
 			} else {
-				xb := S256(new(big.Int).SetBytes(x[:]))
-				yb := S256(new(big.Int).SetBytes(y[:]))
-				div := new(big.Int).Div(xb, yb)
-				res := LeftPadWord256(U256(div).Bytes())
-				stack.Push(res)
-				vm.Debugf(" %v / %v = %v (%X)\n", xb, yb, div, res)
+				div := x.Div(x, y)
+				res := stack.PushBigInt(div)
+				vm.Debugf(" %v / %v = %v (%X)\n", x, y, div, res)
 			}
 
 		case MOD: // 0x06
-			x, y := stack.Pop(), stack.Pop()
-			if y.IsZero() {
+			x, y := stack.PopBigInt(), stack.PopBigInt()
+			if y.Sign() == 0 {
 				stack.Push(Zero256)
 				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
-				xb := new(big.Int).SetBytes(x[:])
-				yb := new(big.Int).SetBytes(y[:])
-				mod := new(big.Int).Mod(xb, yb)
-				res := LeftPadWord256(U256(mod).Bytes())
-				stack.Push(res)
-				vm.Debugf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
+				mod := x.Mod(x, y)
+				res := stack.PushBigInt(mod)
+				vm.Debugf(" %v %% %v = %v (%X)\n", x, y, mod, res)
 			}
 
 		case SMOD: // 0x07
-			x, y := stack.Pop(), stack.Pop()
-			if y.IsZero() {
+			x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned()
+			if y.Sign() == 0 {
 				stack.Push(Zero256)
 				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
-				xb := S256(new(big.Int).SetBytes(x[:]))
-				yb := S256(new(big.Int).SetBytes(y[:]))
-				mod := new(big.Int).Mod(xb, yb)
-				res := LeftPadWord256(U256(mod).Bytes())
-				stack.Push(res)
-				vm.Debugf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
+				mod := x.Mod(x, y)
+				res := stack.PushBigInt(mod)
+				vm.Debugf(" %v %% %v = %v (%X)\n", x, y, mod, res)
 			}
 
 		case ADDMOD: // 0x08
-			x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
-			if z.IsZero() {
+			x, y, z := stack.PopBigInt(), stack.PopBigInt(), stack.PopBigInt()
+			if z.Sign() == 0 {
 				stack.Push(Zero256)
 				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
-				xb := new(big.Int).SetBytes(x[:])
-				yb := new(big.Int).SetBytes(y[:])
-				zb := new(big.Int).SetBytes(z[:])
-				add := new(big.Int).Add(xb, yb)
-				mod := new(big.Int).Mod(add, zb)
-				res := LeftPadWord256(U256(mod).Bytes())
-				stack.Push(res)
-				vm.Debugf(" %v + %v %% %v = %v (%X)\n",
-					xb, yb, zb, mod, res)
+				add := x.Add(x, y)
+				mod := add.Mod(add, z)
+				res := stack.PushBigInt(mod)
+				vm.Debugf(" %v + %v %% %v = %v (%X)\n", x, y, z, mod, res)
 			}
 
 		case MULMOD: // 0x09
-			x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
-			if z.IsZero() {
+			x, y, z := stack.PopBigInt(), stack.PopBigInt(), stack.PopBigInt()
+			if z.Sign() == 0 {
 				stack.Push(Zero256)
 				vm.Debugf(" %v %% %v = %v\n", x, y, 0)
 			} else {
-				xb := new(big.Int).SetBytes(x[:])
-				yb := new(big.Int).SetBytes(y[:])
-				zb := new(big.Int).SetBytes(z[:])
-				mul := new(big.Int).Mul(xb, yb)
-				mod := new(big.Int).Mod(mul, zb)
-				res := LeftPadWord256(U256(mod).Bytes())
-				stack.Push(res)
-				vm.Debugf(" %v * %v %% %v = %v (%X)\n",
-					xb, yb, zb, mod, res)
+				mul := x.Mul(x, y)
+				mod := mul.Mod(mul, z)
+				res := stack.PushBigInt(mod)
+				vm.Debugf(" %v * %v %% %v = %v (%X)\n", x, y, z, mod, res)
 			}
 
 		case EXP: // 0x0A
-			x, y := stack.Pop(), stack.Pop()
-			xb := new(big.Int).SetBytes(x[:])
-			yb := new(big.Int).SetBytes(y[:])
-			pow := new(big.Int).Exp(xb, yb, big.NewInt(0))
-			res := LeftPadWord256(U256(pow).Bytes())
-			stack.Push(res)
-			vm.Debugf(" %v ** %v = %v (%X)\n", xb, yb, pow, res)
+			x, y := stack.PopBigInt(), stack.PopBigInt()
+			pow := x.Exp(x, y, nil)
+			res := stack.PushBigInt(pow)
+			vm.Debugf(" %v ** %v = %v (%X)\n", x, y, pow, res)
 
 		case SIGNEXTEND: // 0x0B
-			back := stack.Pop()
-			backb := new(big.Int).SetBytes(back[:])
-			if backb.Cmp(big.NewInt(31)) < 0 {
-				bit := uint(backb.Uint64()*8 + 7)
-				num := stack.Pop()
-				numb := new(big.Int).SetBytes(num[:])
-				mask := new(big.Int).Lsh(big.NewInt(1), bit)
-				mask.Sub(mask, big.NewInt(1))
-				if numb.Bit(int(bit)) == 1 {
-					numb.Or(numb, mask.Not(mask))
-				} else {
-					numb.Add(numb, mask)
-				}
-				res := LeftPadWord256(U256(numb).Bytes())
-				vm.Debugf(" = %v (%X)", numb, res)
-				stack.Push(res)
+			back := stack.PopU64()
+			if back < Word256Length-1 {
+				stack.PushBigInt(SignExtend(back, stack.PopBigInt()))
 			}
 
 		case LT: // 0x10
-			x, y := stack.Pop(), stack.Pop()
-			xb := new(big.Int).SetBytes(x[:])
-			yb := new(big.Int).SetBytes(y[:])
-			if xb.Cmp(yb) < 0 {
-				stack.Push64(1)
-				vm.Debugf(" %v < %v = %v\n", xb, yb, 1)
+			x, y := stack.PopBigInt(), stack.PopBigInt()
+			if x.Cmp(y) < 0 {
+				stack.Push(One256)
+				vm.Debugf(" %v < %v = %v\n", x, y, 1)
 			} else {
 				stack.Push(Zero256)
-				vm.Debugf(" %v < %v = %v\n", xb, yb, 0)
+				vm.Debugf(" %v < %v = %v\n", x, y, 0)
 			}
 
 		case GT: // 0x11
-			x, y := stack.Pop(), stack.Pop()
-			xb := new(big.Int).SetBytes(x[:])
-			yb := new(big.Int).SetBytes(y[:])
-			if xb.Cmp(yb) > 0 {
-				stack.Push64(1)
-				vm.Debugf(" %v > %v = %v\n", xb, yb, 1)
+			x, y := stack.PopBigInt(), stack.PopBigInt()
+			if x.Cmp(y) > 0 {
+				stack.Push(One256)
+				vm.Debugf(" %v > %v = %v\n", x, y, 1)
 			} else {
 				stack.Push(Zero256)
-				vm.Debugf(" %v > %v = %v\n", xb, yb, 0)
+				vm.Debugf(" %v > %v = %v\n", x, y, 0)
 			}
 
 		case SLT: // 0x12
-			x, y := stack.Pop(), stack.Pop()
-			xb := S256(new(big.Int).SetBytes(x[:]))
-			yb := S256(new(big.Int).SetBytes(y[:]))
-			if xb.Cmp(yb) < 0 {
-				stack.Push64(1)
-				vm.Debugf(" %v < %v = %v\n", xb, yb, 1)
+			x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned()
+			if x.Cmp(y) < 0 {
+				stack.Push(One256)
+				vm.Debugf(" %v < %v = %v\n", x, y, 1)
 			} else {
 				stack.Push(Zero256)
-				vm.Debugf(" %v < %v = %v\n", xb, yb, 0)
+				vm.Debugf(" %v < %v = %v\n", x, y, 0)
 			}
 
 		case SGT: // 0x13
-			x, y := stack.Pop(), stack.Pop()
-			xb := S256(new(big.Int).SetBytes(x[:]))
-			yb := S256(new(big.Int).SetBytes(y[:]))
-			if xb.Cmp(yb) > 0 {
-				stack.Push64(1)
-				vm.Debugf(" %v > %v = %v\n", xb, yb, 1)
+			x, y := stack.PopBigIntSigned(), stack.PopBigIntSigned()
+			if x.Cmp(y) > 0 {
+				stack.Push(One256)
+				vm.Debugf(" %v > %v = %v\n", x, y, 1)
 			} else {
 				stack.Push(Zero256)
-				vm.Debugf(" %v > %v = %v\n", xb, yb, 0)
+				vm.Debugf(" %v > %v = %v\n", x, y, 0)
 			}
 
 		case EQ: // 0x14
 			x, y := stack.Pop(), stack.Pop()
 			if bytes.Equal(x[:], y[:]) {
-				stack.Push64(1)
+				stack.Push(One256)
 				vm.Debugf(" %X == %X = %v\n", x, y, 1)
 			} else {
 				stack.Push(Zero256)
@@ -425,7 +369,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 		case ISZERO: // 0x15
 			x := stack.Pop()
 			if x.IsZero() {
-				stack.Push64(1)
+				stack.Push(One256)
 				vm.Debugf(" %X == 0 = %v\n", x, 1)
 			} else {
 				stack.Push(Zero256)
@@ -481,7 +425,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			if useGasNegative(gas, GasSha3, &err) {
 				return nil, err
 			}
-			offset, size := stack.Pop64(), stack.Pop64()
+			offset, size := stack.PopBigInt(), stack.PopBigInt()
 			data, memErr := memory.Read(offset, size)
 			if memErr != nil {
 				vm.Debugf(" => Memory err: %s", memErr)
@@ -538,7 +482,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf(" => %d\n", len(input))
 
 		case CALLDATACOPY: // 0x37
-			memOff := stack.Pop64()
+			memOff := stack.PopBigInt()
 			inputOff := stack.Pop64()
 			length := stack.Pop64()
 			data, ok := subslice(input, inputOff, length)
@@ -558,7 +502,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf(" => %d\n", l)
 
 		case CODECOPY: // 0x39
-			memOff := stack.Pop64()
+			memOff := stack.PopBigInt()
 			codeOff := stack.Pop64()
 			length := stack.Pop64()
 			data, ok := subslice(code, codeOff, length)
@@ -614,7 +558,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				return nil, firstErr(err, ErrUnknownAddress)
 			}
 			code := acc.Code()
-			memOff := stack.Pop64()
+			memOff := stack.PopBigInt()
 			codeOff := stack.Pop64()
 			length := stack.Pop64()
 			data, ok := subslice(code, codeOff, length)
@@ -655,8 +599,8 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf(" => 0x%X\n", popped)
 
 		case MLOAD: // 0x51
-			offset := stack.Pop64()
-			data, memErr := memory.Read(offset, 32)
+			offset := stack.PopBigInt()
+			data, memErr := memory.Read(offset, BigWord256Length)
 			if memErr != nil {
 				vm.Debugf(" => Memory err: %s", memErr)
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
@@ -665,7 +609,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf(" => 0x%X @ 0x%X\n", data, offset)
 
 		case MSTORE: // 0x52
-			offset, data := stack.Pop64(), stack.Pop()
+			offset, data := stack.PopBigInt(), stack.Pop()
 			memErr := memory.Write(offset, data.Bytes())
 			if memErr != nil {
 				vm.Debugf(" => Memory err: %s", memErr)
@@ -674,7 +618,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf(" => 0x%X @ 0x%X\n", data, offset)
 
 		case MSTORE8: // 0x53
-			offset, val := stack.Pop64(), byte(stack.Pop64()&0xFF)
+			offset, val := stack.PopBigInt(), byte(stack.Pop64()&0xFF)
 			memErr := memory.Write(offset, []byte{val})
 			if memErr != nil {
 				vm.Debugf(" => Memory err: %s", memErr)
@@ -726,7 +670,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			// free memory to be allocated for it if a subsequent MSTORE is made to
 			// this offset.
 			capacity := memory.Capacity()
-			stack.Push64(capacity)
+			stack.PushBigInt(capacity)
 			vm.Debugf(" => 0x%X\n", capacity)
 
 		case GAS: // 0x5A
@@ -763,7 +707,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 		case LOG0, LOG1, LOG2, LOG3, LOG4:
 			n := int(op - LOG0)
 			topics := make([]Word256, n)
-			offset, size := stack.Pop64(), stack.Pop64()
+			offset, size := stack.PopBigInt(), stack.PopBigInt()
 			for i := 0; i < n; i++ {
 				topics[i] = stack.Pop()
 			}
@@ -789,7 +733,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 				return nil, ErrPermission{"create_contract"}
 			}
 			contractValue := stack.PopU64()
-			offset, size := stack.Pop64(), stack.Pop64()
+			offset, size := stack.PopBigInt(), stack.PopBigInt()
 			input, memErr := memory.Read(offset, size)
 			if memErr != nil {
 				vm.Debugf(" => Memory err: %s", memErr)
@@ -829,8 +773,8 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			if op != DELEGATECALL {
 				value = stack.PopU64()
 			}
-			inOffset, inSize := stack.Pop64(), stack.Pop64()   // inputs
-			retOffset, retSize := stack.Pop64(), stack.Pop64() // outputs
+			inOffset, inSize := stack.PopBigInt(), stack.PopBigInt() // inputs
+			retOffset, retSize := stack.PopBigInt(), stack.Pop64()   // outputs
 			vm.Debugf(" => %X\n", addr)
 
 			// Get the arguments from the memory
@@ -924,7 +868,7 @@ func (vm *VM) call(caller, callee acm.MutableAccount, code, input []byte, value
 			vm.Debugf("resume %s (%v)\n", callee.Address(), gas)
 
 		case RETURN: // 0xF3
-			offset, size := stack.Pop64(), stack.Pop64()
+			offset, size := stack.PopBigInt(), stack.PopBigInt()
 			output, memErr := memory.Read(offset, size)
 			if memErr != nil {
 				vm.Debugf(" => Memory err: %s", memErr)
diff --git a/execution/execution.go b/execution/execution.go
index 09fd8c9f15dbc18be3d668c1c97cfa90df4a1092..caff450fc61c4264a01a164b4dd2f21a25d2bdcf 100644
--- a/execution/execution.go
+++ b/execution/execution.go
@@ -150,8 +150,14 @@ func (exe *executor) Reset() error {
 
 // If the tx is invalid, an error will be returned.
 // Unlike ExecBlock(), state will not be altered.
-func (exe *executor) Execute(tx txs.Tx) error {
+func (exe *executor) Execute(tx txs.Tx) (err error) {
+	defer func() {
+		if r := recover(); r != nil {
+			err = fmt.Errorf("recovered from panic in executor.Execute(%s): %v", tx.String(), r)
+		}
+	}()
 	logger := logging.WithScope(exe.logger, "executor.Execute(tx txs.Tx)")
+	logging.TraceMsg(logger, "Executing transaction", "tx", tx.String())
 	// TODO: do something with fees
 	fees := uint64(0)
 
@@ -301,7 +307,6 @@ func (exe *executor) Execute(tx txs.Tx) error {
 
 		// The logic in runCall MUST NOT return.
 		if exe.runCall {
-
 			// VM call variables
 			var (
 				gas     uint64             = tx.GasLimit
@@ -329,11 +334,11 @@ func (exe *executor) Execute(tx txs.Tx) error {
 				// that will take your fees
 				if outAcc == nil {
 					logging.InfoMsg(logger, "Call to address that does not exist",
-						"caller_address", inAcc.Address,
+						"caller_address", inAcc.Address(),
 						"callee_address", tx.Address)
 				} else {
 					logging.InfoMsg(logger, "Call to address that holds no code",
-						"caller_address", inAcc.Address,
+						"caller_address", inAcc.Address(),
 						"callee_address", tx.Address)
 				}
 				err = txs.ErrTxInvalidAddress
@@ -344,16 +349,17 @@ func (exe *executor) Execute(tx txs.Tx) error {
 			if createContract {
 				// We already checked for permission
 				callee = evm.DeriveNewAccount(caller, permission.GlobalAccountPermissions(exe.state))
-				logging.TraceMsg(logger, "Created new contract",
-					"contract_address", callee.Address,
-					"contract_code", callee.Code)
 				code = tx.Data
+				logging.TraceMsg(logger, "Creating new contract",
+					"contract_address", callee.Address(),
+					"init_code", code)
 			} else {
 				callee = acm.AsMutableAccount(outAcc)
-				logging.TraceMsg(logger, "Calling existing contract",
-					"contract_address", callee.Address,
-					"contract_code", callee.Code)
 				code = callee.Code()
+				logging.TraceMsg(logger, "Calling existing contract",
+					"contract_address", callee.Address(),
+					"input", tx.Data,
+					"contract_code", code)
 			}
 			logger.Trace("callee", callee.Address().String())
 
diff --git a/logging/config/filter_test.go b/logging/config/filter_test.go
index 5e847acbbbec6f5510a5daf224acf361585519ce..9602fa71e5a41bdaeef8c7c703f0b7ca4265a099 100644
--- a/logging/config/filter_test.go
+++ b/logging/config/filter_test.go
@@ -115,5 +115,21 @@ func TestIncludeAnyFilterPredicate(t *testing.T) {
 	assert.False(t, fp([]interface{}{"Foo", "bar", "Shoes", 3427}))
 	assert.False(t, fp([]interface{}{"Foo", "bar", "Shoes", 42, "Bosh", "Bish"}))
 	assert.False(t, fp([]interface{}{"Food", 0.2, "Shoes", 42}))
+}
+
+func TestKeyOnlyPredicate(t *testing.T) {
 
+	fc := &FilterConfig{
+		FilterMode: IncludeWhenAnyMatches,
+		Predicates: []*KeyValuePredicateConfig{
+			{
+				KeyRegex: "Bosh",
+			},
+		},
+	}
+	fp, err := BuildFilterPredicate(fc)
+	assert.NoError(t, err)
+	assert.True(t, fp([]interface{}{"Foo", "bar", "Shoes", 3427}))
+	assert.False(t, fp([]interface{}{"Foo", "bar", "Shoes", 42, "Bosh", "Bish"}))
+	assert.True(t, fp([]interface{}{"Food", 0.2, "Shoes", 42}))
 }
diff --git a/logging/lifecycle/lifecycle.go b/logging/lifecycle/lifecycle.go
index 8d9428fd1b39e5141a2fb0d1429c864f28d29c27..e68a26021c129b918d8ea1b3d142d6fe441e6341 100644
--- a/logging/lifecycle/lifecycle.go
+++ b/logging/lifecycle/lifecycle.go
@@ -57,9 +57,7 @@ func NewLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (types.Info
 	go func() {
 		err := <-errCh.Out()
 		if err != nil {
-			logger.Info("logging_error", err,
-				"logging_config", loggingConfig.RootTOMLString(),
-				"logger", fmt.Sprintf("%#v", logger))
+			fmt.Printf("Logging error: %v", err)
 		}
 	}()
 
diff --git a/txs/tx.go b/txs/tx.go
index 2d35e77620d8fbc043fd09dba182e37afe85e74f..c24018d44e02d716854810bd155b13af73a81f71 100644
--- a/txs/tx.go
+++ b/txs/tx.go
@@ -101,6 +101,7 @@ type (
 	// TODO: replace with sum-type struct like ResultEvent
 	Tx interface {
 		WriteSignBytes(chainID string, w io.Writer, n *int, err *error)
+		String() string
 	}
 
 	Wrapper struct {