diff --git a/app/app.go b/app/app.go
index 6c8a9ae..2d61a7a 100644
--- a/app/app.go
+++ b/app/app.go
@@ -91,7 +91,7 @@ func NewChildChain(logger log.Logger, db dbm.DB, traceStore io.Writer, options .
 	)
 
 	app.Router().
-		AddRoute("spend", utxo.NewSpendHandler(app.utxoMapper, app.nextPosition, types.ProtoUTXO))
+		AddRoute("spend", utxo.NewSpendHandler(app.utxoMapper, app.nextPosition))
 
 	app.MountStoresIAVL(app.capKeyMainStore)
 	app.MountStoresIAVL(app.capKeyMetadataStore)
@@ -124,7 +124,7 @@ func (app *ChildChain) initChainer(ctx sdk.Context, req abci.RequestInitChain) a
 	// load the accounts
 	for _, gutxo := range genesisState.UTXOs {
 		utxo := ToUTXO(gutxo)
-		app.utxoMapper.AddUTXO(ctx, utxo)
+		app.utxoMapper.ReceiveUTXO(ctx, utxo)
 	}
 
 	app.validatorAddress = ethcmn.HexToAddress(genesisState.Validator.Address)
@@ -144,14 +144,8 @@ func (app *ChildChain) endBlocker(ctx sdk.Context, req abci.RequestEndBlock) abc
 			Oindex:     0,
 			DepositNum: 0,
 		}
-		utxo := types.BaseUTXO{
-			Address:        app.validatorAddress,
-			InputAddresses: [2]ethcmn.Address{app.validatorAddress, ethcmn.Address{}},
-			Amount:         app.feeAmount,
-			Denom:          types.Denom,
-			Position:       position,
-		}
-		app.utxoMapper.AddUTXO(ctx, &utxo)
+		utxo := utxo.NewUTXO(app.validatorAddress.Bytes(), app.feeAmount, types.Denom, position)
+		app.utxoMapper.ReceiveUTXO(ctx, utxo)
 	}
 
 	// reset txIndex and fee
@@ -188,7 +182,7 @@ func (app *ChildChain) nextPosition(ctx sdk.Context, secondary bool) utxo.Positi
 	return types.NewPlasmaPosition(uint64(ctx.BlockHeight()), app.txIndex-1, 1, 0)
 }
 
-// Unimplemented for now
+// Fee Updater passed into antehandler
 func (app *ChildChain) feeUpdater(output []utxo.Output) sdk.Error {
 	if len(output) != 1 || output[0].Denom != types.Denom {
 		return utxo.ErrInvalidFee(2, "Fee must be paid in Eth")
diff --git a/app/app_test.go b/app/app_test.go
index a64e02e..c1236c5 100644
--- a/app/app_test.go
+++ b/app/app_test.go
@@ -4,6 +4,7 @@ import (
 	"encoding/binary"
 	"fmt"
 	"os"
+	"reflect"
 	"testing"
 
 	"crypto/ecdsa"
@@ -19,6 +20,7 @@ import (
 
 	types "github.com/FourthState/plasma-mvp-sidechain/types"
 	utils "github.com/FourthState/plasma-mvp-sidechain/utils"
+	"github.com/FourthState/plasma-mvp-sidechain/x/utxo"
 	rlp "github.com/ethereum/go-ethereum/rlp"
 )
 
@@ -103,6 +105,15 @@ func CreateConfirmSig(hash []byte, privKey0, privKey1 *ecdsa.PrivateKey, two_inp
 	return confirmSigs
 }
 
+func getInputKeys(mapper utxo.Mapper, inputs ...Input) (res [][]byte) {
+	for _, in := range inputs {
+		if !reflect.DeepEqual(in.addr, common.Address{}) {
+			res = append(res, mapper.ConstructKey(in.addr.Bytes(), in.position))
+		}
+	}
+	return res
+}
+
 // helper for constructing single or double input tx
 func GetTx(msg types.SpendMsg, privKeyA, privKeyB *ecdsa.PrivateKey, two_sigs bool) (tx types.BaseTx) {
 	hash := ethcrypto.Keccak256(msg.GetSignBytes())
@@ -196,12 +207,13 @@ func TestSpendDeposit(t *testing.T) {
 
 	// Retrieve UTXO from context
 	position := types.NewPlasmaPosition(1, 0, 0, 0)
-	utxo := cc.utxoMapper.GetUTXO(ctx, addrB.Bytes(), position)
+	res := cc.utxoMapper.GetUTXO(ctx, addrB.Bytes(), position)
 
-	expected := types.NewBaseUTXO(addrB, [2]common.Address{addrA, common.Address{}}, 100, "", position)
-	expected.TxHash = tmhash.Sum(txBytes)
+	inputKey := cc.utxoMapper.ConstructKey(addrA.Bytes(), types.NewPlasmaPosition(0, 0, 0, 1))
+	txHash := tmhash.Sum(txBytes)
+	expected := utxo.NewUTXOwithInputs(addrB.Bytes(), 100, "Ether", position, txHash, [][]byte{inputKey})
 
-	require.Equal(t, expected, utxo, "UTXO did not get added to store correctly")
+	require.Equal(t, expected, res, "UTXO did not get added to store correctly")
 }
 
 func TestSpendTx(t *testing.T) {
@@ -263,12 +275,12 @@ func TestSpendTx(t *testing.T) {
 
 	// Retrieve UTXO from context
 	position := types.NewPlasmaPosition(5, 0, 0, 0)
-	utxo := cc.utxoMapper.GetUTXO(ctx, addrA.Bytes(), position)
+	actual := cc.utxoMapper.GetUTXO(ctx, addrA.Bytes(), position)
 
-	expected := types.NewBaseUTXO(addrA, [2]common.Address{addrB, common.Address{}}, 100, "", position)
-	expected.TxHash = txHash
+	inputKey := cc.utxoMapper.ConstructKey(addrB.Bytes(), types.NewPlasmaPosition(1, 0, 0, 0))
+	expected := utxo.NewUTXOwithInputs(addrA.Bytes(), 100, "Ether", position, txHash, [][]byte{inputKey})
 
-	require.Equal(t, expected, utxo, "UTXO did not get added to store correctly")
+	require.Equal(t, expected, actual, "UTXO did not get added to store correctly")
 
 }
 
@@ -383,12 +395,10 @@ func TestDifferentTxForms(t *testing.T) {
 			// note: all cases currently have inputs belonging to the previous tx
 			// and therefore we only need to grab the first txhash from the inptus
 			input_utxo := cc.utxoMapper.GetUTXO(ctx, tc.input0.addr.Bytes(), tc.input0.position)
-			baseutxo, _ := input_utxo.(*types.BaseUTXO)
-			txhash := baseutxo.TxHash
 			blknumKey := make([]byte, binary.MaxVarintLen64)
 			binary.PutUvarint(blknumKey, uint64(7+uint64(index-1)))
 			blockhash := cc.metadataMapper.GetMetadata(ctx, blknumKey)
-			hash := tmhash.Sum(append(txhash, blockhash...))
+			hash := tmhash.Sum(append(input_utxo.TxHash, blockhash...))
 
 			msg.Input0ConfirmSigs = CreateConfirmSig(hash, keys[tc.input0.input_index0], keys[input0_index1], tc.input0.input_index1 != -1)
 			msg.Input1ConfirmSigs = CreateConfirmSig(hash, keys[input1_index0], keys[input1_index1], tc.input1.input_index1 != -1)
@@ -403,30 +413,30 @@ func TestDifferentTxForms(t *testing.T) {
 
 		// Retrieve utxo from context
 		position := types.NewPlasmaPosition(uint64(index)+7, 0, 0, 0)
-		utxo := cc.utxoMapper.GetUTXO(ctx, tc.newowner0.Bytes(), position)
+		utxo0 := cc.utxoMapper.GetUTXO(ctx, tc.newowner0.Bytes(), position)
 
-		expected := types.NewBaseUTXO(tc.newowner0, [2]common.Address{msg.Owner0, msg.Owner1}, tc.amount0, "", position)
-		expected.TxHash = tmhash.Sum(txBytes)
+		inputKeys := getInputKeys(cc.utxoMapper, tc.input0, tc.input1)
+		txHash := tmhash.Sum(txBytes)
+		expected := utxo.NewUTXOwithInputs(tc.newowner0.Bytes(), tc.amount0, "Ether", position, txHash, inputKeys)
 
-		require.Equal(t, expected, utxo, fmt.Sprintf("First UTXO did not get added to the utxo store correctly. Failed on test case: %d", index))
+		require.Equal(t, expected, utxo0, fmt.Sprintf("First UTXO did not get added to the utxo store correctly. Failed on test case: %d", index))
 
 		if !utils.ZeroAddress(msg.Newowner1) {
 			position = types.NewPlasmaPosition(uint64(index)+7, 0, 1, 0)
-			utxo = cc.utxoMapper.GetUTXO(ctx, tc.newowner1.Bytes(), position)
+			utxo1 := cc.utxoMapper.GetUTXO(ctx, tc.newowner1.Bytes(), position)
 
-			expected = types.NewBaseUTXO(tc.newowner1, [2]common.Address{msg.Owner0, msg.Owner1}, tc.amount1, "", position)
-			expected.TxHash = tmhash.Sum(txBytes)
+			expected = utxo.NewUTXOwithInputs(tc.newowner1.Bytes(), tc.amount1, "Ether", position, txHash, inputKeys)
 
-			require.Equal(t, expected, utxo, fmt.Sprintf("Second UTXO did not get added to the utxo store correctly. Failed on test case: %d", index))
+			require.Equal(t, expected, utxo1, fmt.Sprintf("Second UTXO did not get added to the utxo store correctly. Failed on test case: %d", index))
 		}
 
 		// Check that inputs were removed
-		utxo = cc.utxoMapper.GetUTXO(ctx, msg.Owner0.Bytes(), tc.input0.position)
-		require.Nil(t, utxo, fmt.Sprintf("first input was not removed from the utxo store. Failed on test case: %d", index))
+		recovered := cc.utxoMapper.GetUTXO(ctx, msg.Owner0.Bytes(), tc.input0.position)
+		require.False(t, recovered.Valid, fmt.Sprintf("first input was not removed from the utxo store. Failed on test case: %d", index))
 
 		if !utils.ZeroAddress(msg.Owner1) {
-			utxo = cc.utxoMapper.GetUTXO(ctx, msg.Owner1.Bytes(), tc.input1.position)
-			require.Nil(t, utxo, fmt.Sprintf("second input was not removed from the utxo store. Failed on test case: %d", index))
+			recovered = cc.utxoMapper.GetUTXO(ctx, msg.Owner1.Bytes(), tc.input1.position)
+			require.False(t, recovered.Valid, fmt.Sprintf("second input was not removed from the utxo store. Failed on test case: %d", index))
 		}
 
 		cc.EndBlock(abci.RequestEndBlock{})
@@ -469,16 +479,17 @@ func TestMultiTxBlocks(t *testing.T) {
 	for i := uint16(0); i < N; i++ {
 		txBytes, _ := rlp.EncodeToBytes(txs[i])
 		position := types.NewPlasmaPosition(1, i, 0, 0)
-		utxo := cc.utxoMapper.GetUTXO(ctx, addrs[i].Bytes(), position)
+		actual := cc.utxoMapper.GetUTXO(ctx, addrs[i].Bytes(), position)
 
-		expected := types.NewBaseUTXO(addrs[i], [2]common.Address{addrs[i], common.Address{}}, 100, "", position)
+		inputKey := cc.utxoMapper.ConstructKey(addrs[i].Bytes(), types.NewPlasmaPosition(0, 0, 0, uint64(i+1)))
+		expected := utxo.NewUTXOwithInputs(addrs[i].Bytes(), 100, "Ether", position, tmhash.Sum(txBytes), [][]byte{inputKey})
 		expected.TxHash = tmhash.Sum(txBytes)
 
-		require.Equal(t, expected, utxo, fmt.Sprintf("UTXO %d did not get added to store correctly", i+1))
+		require.Equal(t, expected, actual, fmt.Sprintf("UTXO %d did not get added to store correctly", i+1))
 
 		position = types.NewPlasmaPosition(0, 0, 0, uint64(i)+1)
-		utxo = cc.utxoMapper.GetUTXO(ctx, addrs[i].Bytes(), position)
-		require.Nil(t, utxo, fmt.Sprintf("deposit %d did not get removed correctly from the utxo store", i+1))
+		deposit := cc.utxoMapper.GetUTXO(ctx, addrs[i].Bytes(), position)
+		require.False(t, deposit.Valid, fmt.Sprintf("deposit %d did not get removed correctly from the utxo store", i+1))
 	}
 
 	cc.EndBlock(abci.RequestEndBlock{})
@@ -514,15 +525,15 @@ func TestMultiTxBlocks(t *testing.T) {
 	// Retrieve and check UTXO from context
 	for i := uint16(0); i < N; i++ {
 		txBytes, _ := rlp.EncodeToBytes(txs[i])
-		utxo := cc.utxoMapper.GetUTXO(ctx, addrs[(i+1)%N].Bytes(), types.NewPlasmaPosition(2, i, 0, 0))
+		actual := cc.utxoMapper.GetUTXO(ctx, addrs[(i+1)%N].Bytes(), types.NewPlasmaPosition(2, i, 0, 0))
 
-		expected := types.NewBaseUTXO(addrs[(i+1)%N], [2]common.Address{addrs[i], common.Address{}}, 100, "", types.NewPlasmaPosition(2, i, 0, 0))
-		expected.TxHash = tmhash.Sum(txBytes)
+		inputKey := cc.utxoMapper.ConstructKey(addrs[i].Bytes(), types.NewPlasmaPosition(1, i, 0, 0))
+		expected := utxo.NewUTXOwithInputs(addrs[(i+1)%N].Bytes(), 100, "Ether", types.NewPlasmaPosition(2, i, 0, 0), tmhash.Sum(txBytes), [][]byte{inputKey})
 
-		require.Equal(t, expected, utxo, fmt.Sprintf("UTXO %d did not get added to store correctly", i+1))
+		require.Equal(t, expected, actual, fmt.Sprintf("UTXO %d did not get added to store correctly", i+1))
 
-		utxo = cc.utxoMapper.GetUTXO(ctx, addrs[i].Bytes(), types.NewPlasmaPosition(1, i, 0, 0))
-		require.Nil(t, utxo, fmt.Sprintf("UTXO %d  did not get removed from the utxo store correctly", i))
+		input := cc.utxoMapper.GetUTXO(ctx, addrs[i].Bytes(), types.NewPlasmaPosition(1, i, 0, 0))
+		require.False(t, input.Valid, fmt.Sprintf("UTXO %d  did not get removed from the utxo store correctly", i))
 	}
 
 }
@@ -584,9 +595,9 @@ func TestFee(t *testing.T) {
 	valUTXO := cc.utxoMapper.GetUTXO(ctx, valAddr.Bytes(), expectedValPosition)
 
 	// Check that users and validators have expected UTXO's
-	require.Equal(t, uint64(90), utxo1.GetAmount(), "UTXO1 does not have expected amount")
-	require.Equal(t, uint64(90), utxo2.GetAmount(), "UTXO2 does not have expected amount")
-	require.Equal(t, uint64(20), valUTXO.GetAmount(), "Validator fees did not get collected into UTXO correctly")
+	require.Equal(t, uint64(90), utxo1.Amount, "UTXO1 does not have expected amount")
+	require.Equal(t, uint64(90), utxo2.Amount, "UTXO2 does not have expected amount")
+	require.Equal(t, uint64(20), valUTXO.Amount, "Validator fees did not get collected into UTXO correctly")
 
 	// Check that validator can spend his fees as if they were a regular UTXO on sidechain
 	valMsg := GenerateSimpleMsg(valAddr, addrs[0], [4]uint64{1, 1<<16 - 1, 0, 0}, 10, 10)
@@ -606,5 +617,5 @@ func TestFee(t *testing.T) {
 
 	// Check that fee Amount gets reset between blocks. feeAmount for block 2 is 10 not 30.
 	feeUTXO2 := cc.utxoMapper.GetUTXO(ctx, valAddr.Bytes(), types.NewPlasmaPosition(2, 1<<16-1, 0, 0))
-	require.Equal(t, uint64(10), feeUTXO2.GetAmount(), "Fee Amount on second block is incorrect")
+	require.Equal(t, uint64(10), feeUTXO2.Amount, "Fee Amount on second block is incorrect")
 }
diff --git a/app/genesis.go b/app/genesis.go
index b5784d8..623e152 100644
--- a/app/genesis.go
+++ b/app/genesis.go
@@ -49,20 +49,15 @@ func ToUTXO(gutxo GenesisUTXO) utxo.UTXO {
 	// Any failed str conversion defaults to 0
 	addr := common.HexToAddress(gutxo.Address)
 	amount, _ := strconv.ParseUint(gutxo.Denom, 10, 64)
-	utxo := &types.BaseUTXO{
-		InputAddresses: [2]common.Address{addr, common.Address{}},
-		Address:        addr,
-		Amount:         amount,
-		Denom:          types.Denom,
-	}
+
 	blkNum, _ := strconv.ParseUint(gutxo.Position[0], 10, 64)
 	txIndex, _ := strconv.ParseUint(gutxo.Position[1], 10, 16)
 	oIndex, _ := strconv.ParseUint(gutxo.Position[2], 10, 8)
 	depNum, _ := strconv.ParseUint(gutxo.Position[3], 10, 64)
 
 	position := types.NewPlasmaPosition(blkNum, uint16(txIndex), uint8(oIndex), depNum)
-	utxo.SetPosition(position)
-	return utxo
+
+	return utxo.NewUTXO(addr.Bytes(), amount, "Ether", position)
 }
 
 var (
diff --git a/auth/ante.go b/auth/ante.go
index 3c0129c..ced59b7 100644
--- a/auth/ante.go
+++ b/auth/ante.go
@@ -125,36 +125,30 @@ func processConfirmSig(
 	res sdk.Result) {
 
 	// Verify utxo exists
-	utxo := utxoMapper.GetUTXO(ctx, addr.Bytes(), &position)
-	if utxo == nil {
+	input := utxoMapper.GetUTXO(ctx, addr.Bytes(), &position)
+	if reflect.DeepEqual(input, utxo.UTXO{}) {
 		return sdk.ErrUnknownRequest(fmt.Sprintf("confirm Sig verification failed: UTXO trying to be spent, does not exist: %v.", position)).Result()
 	}
-	plasmaUTXO, ok := utxo.(*types.BaseUTXO)
-	if !ok {
-		return sdk.ErrInternal("utxo must be of type BaseUTXO").Result()
+	// Get input addresses for input UTXO (grandfather inputs)
+	inputAddresses := input.InputAddresses()
+	if len(inputAddresses) != len(sigs) {
+		return sdk.ErrUnauthorized("Wrong number of confirm sigs").Result()
 	}
-	inputAddresses := plasmaUTXO.GetInputAddresses()
 
-	// Get the block hash
+	// Get the block hash that input was created in
 	blknumKey := make([]byte, binary.MaxVarintLen64)
-	binary.PutUvarint(blknumKey, plasmaUTXO.GetPosition().Get()[0].Uint64())
+	binary.PutUvarint(blknumKey, input.Position.Get()[0].Uint64())
 	blockHash := metadataMapper.GetMetadata(ctx, blknumKey)
 
-	txHash := plasmaUTXO.GetTxHash()
-
-	hash := append(txHash, blockHash...)
+	// Create confirm signature hash
+	hash := append(input.TxHash, blockHash...)
 	confirmHash := tmhash.Sum(hash)
 	signHash := utils.SignHash(confirmHash)
 
-	pubKey0, err0 := ethcrypto.SigToPub(signHash, sigs[0][:])
-	if err0 != nil || !reflect.DeepEqual(ethcrypto.PubkeyToAddress(*pubKey0).Bytes(), inputAddresses[0].Bytes()) {
-		return sdk.ErrUnauthorized("confirm signature 0 verification failed").Result()
-	}
-
-	if utils.ValidAddress(inputAddresses[1]) {
-		pubKey1, err1 := ethcrypto.SigToPub(signHash, sigs[1][:])
-		if err1 != nil || !reflect.DeepEqual(ethcrypto.PubkeyToAddress(*pubKey1).Bytes(), inputAddresses[1].Bytes()) {
-			return sdk.ErrUnauthorized("confirm signature 1 verification failed").Result()
+	for i, sig := range sigs {
+		pubKey, err := ethcrypto.SigToPub(signHash, sig[:])
+		if err != nil || !reflect.DeepEqual(ethcrypto.PubkeyToAddress(*pubKey).Bytes(), inputAddresses[i]) {
+			return sdk.ErrUnauthorized(fmt.Sprintf("confirm signature %d verification failed", i)).Result()
 		}
 	}
 
@@ -164,14 +158,14 @@ func processConfirmSig(
 // Checks that utxo at the position specified exists, matches the address in the SpendMsg
 // and returns the denomination associated with the utxo
 func checkUTXO(ctx sdk.Context, mapper utxo.Mapper, position types.PlasmaPosition, addr common.Address) sdk.Result {
-	utxo := mapper.GetUTXO(ctx, addr.Bytes(), &position)
-	if utxo == nil {
-		return sdk.ErrUnknownRequest(fmt.Sprintf("UTXO trying to be spent, does not exist: %v.", position)).Result()
+	input := mapper.GetUTXO(ctx, addr.Bytes(), &position)
+	if !input.Valid {
+		return sdk.ErrUnknownRequest(fmt.Sprintf("UTXO trying to be spent, is not valid: %v.", position)).Result()
 	}
 
 	// Verify that utxo owner equals input address in the transaction
-	if !reflect.DeepEqual(utxo.GetAddress(), addr.Bytes()) {
-		return sdk.ErrUnauthorized(fmt.Sprintf("signer does not match utxo owner, signer: %X  owner: %X", addr.Bytes(), utxo.GetAddress())).Result()
+	if !reflect.DeepEqual(input.Address, addr.Bytes()) {
+		return sdk.ErrUnauthorized(fmt.Sprintf("signer does not match utxo owner, signer: %X  owner: %X", addr.Bytes(), input.Address)).Result()
 	}
 
 	return sdk.Result{}
diff --git a/auth/ante_test.go b/auth/ante_test.go
index 3401977..6ab165c 100644
--- a/auth/ante_test.go
+++ b/auth/ante_test.go
@@ -71,14 +71,15 @@ func CreateConfirmSig(hash []byte, privKey0, privKey1 *ecdsa.PrivateKey, two_inp
 	signHash := utils.SignHash(hash)
 	confirmSig0Slice, _ := ethcrypto.Sign(signHash, privKey0)
 	copy(confirmSig0[:], confirmSig0Slice)
+	if !two_inputs {
+		return [][65]byte{confirmSig0}
+	}
 
 	var confirmSig1 [65]byte
-	if two_inputs {
-		confirmSig1Slice, _ := ethcrypto.Sign(signHash, privKey1)
-		copy(confirmSig1[:], confirmSig1Slice)
-	}
-	confirmSigs = [][65]byte{confirmSig0, confirmSig1}
-	return confirmSigs
+	confirmSig1Slice, _ := ethcrypto.Sign(signHash, privKey1)
+	copy(confirmSig1[:], confirmSig1Slice)
+
+	return [][65]byte{confirmSig0, confirmSig1}
 }
 
 // helper for constructing single or double input tx
@@ -100,11 +101,11 @@ func GetTx(msg types.SpendMsg, privKey0, privKey1 *ecdsa.PrivateKey, two_sigs bo
 }
 
 // helper for constructing input addresses
-func getInputAddr(addr0, addr1 common.Address, two bool) [2]common.Address {
+func getInputAddr(addr0, addr1 common.Address, two bool) [][]byte {
 	if two {
-		return [2]common.Address{addr0, addr1}
+		return [][]byte{addr0.Bytes(), addr1.Bytes()}
 	} else {
-		return [2]common.Address{addr0, common.Address{}}
+		return [][]byte{addr0.Bytes()}
 	}
 }
 
@@ -117,10 +118,10 @@ func TestNoSigs(t *testing.T) {
 	tx := types.NewBaseTx(msg, emptysigs)
 
 	// Add input UTXOs to mapper
-	utxo1 := types.NewBaseUTXO(msg.Owner0, [2]common.Address{}, 100, types.Denom, types.NewPlasmaPosition(1, 0, 0, 0))
-	utxo2 := types.NewBaseUTXO(msg.Owner0, [2]common.Address{}, 100, types.Denom, types.NewPlasmaPosition(1, 1, 0, 0))
-	mapper.AddUTXO(ctx, utxo1)
-	mapper.AddUTXO(ctx, utxo2)
+	utxo1 := utxo.NewUTXO(msg.Owner0.Bytes(), 100, types.Denom, types.NewPlasmaPosition(1, 0, 0, 0))
+	utxo2 := utxo.NewUTXO(msg.Owner0.Bytes(), 100, types.Denom, types.NewPlasmaPosition(1, 1, 0, 0))
+	mapper.ReceiveUTXO(ctx, utxo1)
+	mapper.ReceiveUTXO(ctx, utxo2)
 
 	handler := NewAnteHandler(mapper, metadataMapper, feeUpdater)
 	_, res, abort := handler(ctx, tx, false)
@@ -142,10 +143,10 @@ func TestNotEnoughSigs(t *testing.T) {
 	tx := types.NewBaseTx(msg, sigs)
 
 	// Add input UTXOs to mapper
-	utxo1 := types.NewBaseUTXO(msg.Owner0, [2]common.Address{}, 100, types.Denom, types.NewPlasmaPosition(1, 0, 0, 0))
-	utxo2 := types.NewBaseUTXO(msg.Owner0, [2]common.Address{}, 100, types.Denom, types.NewPlasmaPosition(1, 1, 0, 0))
-	mapper.AddUTXO(ctx, utxo1)
-	mapper.AddUTXO(ctx, utxo2)
+	utxo1 := utxo.NewUTXO(msg.Owner0.Bytes(), 100, types.Denom, types.NewPlasmaPosition(1, 0, 0, 0))
+	utxo2 := utxo.NewUTXO(msg.Owner0.Bytes(), 100, types.Denom, types.NewPlasmaPosition(1, 1, 0, 0))
+	mapper.ReceiveUTXO(ctx, utxo1)
+	mapper.ReceiveUTXO(ctx, utxo2)
 
 	handler := NewAnteHandler(mapper, metadataMapper, feeUpdater)
 	_, res, abort := handler(ctx, tx, false)
@@ -256,17 +257,15 @@ func TestDifferentCases(t *testing.T) {
 		require.Equal(t, sdk.ToABCICode(sdk.CodespaceType(1), sdk.CodeType(6)), res.Code, res.Log)
 
 		inputAddr := getInputAddr(addrs[tc.input0.input_index0], addrs[input0_index1], tc.input0.input_index1 != -1)
-		utxo0 := types.NewBaseUTXO(tc.input0.addr, inputAddr, 2000, types.Denom, tc.input0.position)
 		txhash0 := tmhash.Sum([]byte("first utxo"))
-		utxo0.TxHash = txhash0
+		utxo0 := utxo.NewUTXOwithInputs(tc.input0.addr.Bytes(), 2000, types.Denom, tc.input0.position, txhash0, inputAddr)
 
-		var utxo1 *types.BaseUTXO
+		var utxo1 utxo.UTXO
 		var txhash1 []byte
 		if tc.input1.owner_index != -1 {
 			txhash1 = tmhash.Sum([]byte("second utxo"))
 			inputAddr = getInputAddr(addrs[input1_index0], addrs[input1_index1], tc.input0.input_index1 != -1)
-			utxo1 = types.NewBaseUTXO(tc.input1.addr, inputAddr, 2000, types.Denom, tc.input1.position)
-			utxo1.TxHash = txhash1
+			utxo1 = utxo.NewUTXOwithInputs(tc.input1.addr.Bytes(), 2000, types.Denom, tc.input1.position, txhash1, inputAddr)
 		}
 
 		blknumKey := make([]byte, binary.MaxVarintLen64)
@@ -275,12 +274,12 @@ func TestDifferentCases(t *testing.T) {
 
 		// for ease of testing, txhash is simplified
 		// app_test tests for correct functionality when setting tx_hash
-		mapper.AddUTXO(ctx, utxo0)
+		mapper.ReceiveUTXO(ctx, utxo0)
 		hash := tmhash.Sum(append(txhash0, blockHash...))
 		msg.Input0ConfirmSigs = CreateConfirmSig(hash, keys[tc.input0.input_index0], keys[input0_index1], tc.input0.input_index1 != -1)
 		if tc.input1.owner_index != -1 {
 			hash = tmhash.Sum(append(txhash1, blockHash...))
-			mapper.AddUTXO(ctx, utxo1)
+			mapper.ReceiveUTXO(ctx, utxo1)
 			msg.Input1ConfirmSigs = CreateConfirmSig(hash, keys[input1_index0], keys[input1_index1], tc.input1.input_index1 != -1)
 		}
 		tx = GetTx(msg, keys[tc.input0.owner_index], keys[owner_index1], tc.input1.owner_index != -1)
diff --git a/client/plasmacli/cmd/balance.go b/client/plasmacli/cmd/balance.go
index 53793eb..20b603f 100644
--- a/client/plasmacli/cmd/balance.go
+++ b/client/plasmacli/cmd/balance.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"github.com/FourthState/plasma-mvp-sidechain/client"
 	"github.com/FourthState/plasma-mvp-sidechain/client/context"
-	"github.com/FourthState/plasma-mvp-sidechain/types"
+	"github.com/FourthState/plasma-mvp-sidechain/x/utxo"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/spf13/cobra"
 )
@@ -30,12 +30,14 @@ var balanceCmd = &cobra.Command{
 		}
 
 		for _, pair := range res {
-			var utxo types.BaseUTXO
-			err := ctx.Codec.UnmarshalBinaryBare(pair.Value, &utxo)
+			var resUTXO utxo.UTXO
+			err := ctx.Codec.UnmarshalBinaryBare(pair.Value, &resUTXO)
 			if err != nil {
 				return err
 			}
-			fmt.Printf("Position: %v \nAmount: %d \n", utxo.Position, utxo.Amount)
+			if resUTXO.Valid {
+				fmt.Printf("Position: %v \nAmount: %d \n", resUTXO.Position, resUTXO.Amount)
+			}
 		}
 
 		return nil
diff --git a/client/plasmacli/cmd/confirmSig.go b/client/plasmacli/cmd/confirmSig.go
index ff37203..2bcf5a4 100644
--- a/client/plasmacli/cmd/confirmSig.go
+++ b/client/plasmacli/cmd/confirmSig.go
@@ -10,8 +10,8 @@ import (
 
 	"github.com/FourthState/plasma-mvp-sidechain/client"
 	"github.com/FourthState/plasma-mvp-sidechain/client/context"
-	"github.com/FourthState/plasma-mvp-sidechain/types"
 	"github.com/FourthState/plasma-mvp-sidechain/utils"
+	"github.com/FourthState/plasma-mvp-sidechain/x/utxo"
 	"github.com/ethereum/go-ethereum/accounts"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/tendermint/tendermint/crypto/tmhash"
@@ -66,18 +66,18 @@ var signCmd = &cobra.Command{
 			return err
 		}
 
-		var utxo types.BaseUTXO
-		err = ctx.Codec.UnmarshalBinaryBare(res, &utxo)
+		var input utxo.UTXO
+		err = ctx.Codec.UnmarshalBinaryBare(res, &input)
 
 		blknumKey := make([]byte, binary.MaxVarintLen64)
-		binary.PutUvarint(blknumKey, utxo.GetPosition().Get()[0].Uint64())
+		binary.PutUvarint(blknumKey, input.Position.Get()[0].Uint64())
 
 		blockhash, err := ctx.QueryStore(blknumKey, ctx.MetadataStore)
 		if err != nil {
 			return err
 		}
 
-		hash := tmhash.Sum(append(utxo.TxHash, blockhash...))
+		hash := tmhash.Sum(append(input.TxHash, blockhash...))
 		signHash := utils.SignHash(hash)
 
 		dir := viper.GetString(FlagHomeDir)
@@ -100,15 +100,10 @@ var signCmd = &cobra.Command{
 
 		sig, err := ks.SignHashWithPassphrase(acct, passphrase, signHash)
 
-		fmt.Printf("\nConfirmation Signature for utxo with\nposition: %v \namount: %d\n", utxo.Position, utxo.Amount)
+		fmt.Printf("\nConfirmation Signature for utxo with\nposition: %v \namount: %d\n", input.Position, input.Amount)
 		fmt.Printf("signature: %x\n", sig)
 
-		inputLen := 1
-		// check number of inputs
-		if !utils.ZeroAddress(utxo.InputAddresses[1]) {
-			inputLen = 2
-		}
-		fmt.Printf("UTXO had %d inputs\n", inputLen)
+		fmt.Printf("UTXO had %d inputs\n", len(input.InputAddresses()))
 		return nil
 	},
 }
diff --git a/client/plasmacli/cmd/info.go b/client/plasmacli/cmd/info.go
index bc3c43f..0cc14ed 100644
--- a/client/plasmacli/cmd/info.go
+++ b/client/plasmacli/cmd/info.go
@@ -1,11 +1,12 @@
 package cmd
 
 import (
+	"encoding/hex"
 	"fmt"
 	"github.com/FourthState/plasma-mvp-sidechain/client"
 	"github.com/FourthState/plasma-mvp-sidechain/client/context"
 	"github.com/FourthState/plasma-mvp-sidechain/types"
-	"github.com/FourthState/plasma-mvp-sidechain/utils"
+	"github.com/FourthState/plasma-mvp-sidechain/x/utxo"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/spf13/cobra"
 )
@@ -18,7 +19,7 @@ func init() {
 
 var infoCmd = &cobra.Command{
 	Use:   "info <address>",
-	Short: "Information on owned utxos ",
+	Short: "Information on owned utxos valid and invalid",
 	RunE: func(cmd *cobra.Command, args []string) error {
 		ctx := context.NewClientContextFromViper()
 
@@ -29,25 +30,40 @@ var infoCmd = &cobra.Command{
 			return err2
 		}
 
-		for _, pair := range res {
-			var utxo types.BaseUTXO
-			err := ctx.Codec.UnmarshalBinaryBare(pair.Value, &utxo)
+		for i, pair := range res {
+			fmt.Printf("Start UTXO %d info:\n", i)
+			var resUTXO utxo.UTXO
+			err := ctx.Codec.UnmarshalBinaryBare(pair.Value, &resUTXO)
 			if err != nil {
 				return err
 			}
-			fmt.Printf("\nPosition: %v \nAmount: %d \nDenomination: %s \n", utxo.Position, utxo.Amount, utxo.GetDenom())
-			inputAddrHelper(utxo)
+			fmt.Printf("\nPosition: %v \nAmount: %d \nDenomination: %s \nValid: %t\n", resUTXO.Position, resUTXO.Amount, resUTXO.Denom, resUTXO.Valid)
+
+			if resUTXO.InputKeys != nil {
+				inputOwners := resUTXO.InputAddresses()
+				inputs := resUTXO.InputPositions(ctx.Codec, types.ProtoPosition)
+				for i, key := range resUTXO.InputKeys {
+					plasmaInput, _ := inputs[i].(*types.PlasmaPosition)
+					fmt.Printf("\nInput Owner %d: %s\nInput Position %d: %v\nInputKey %d in UTXO store: %s\n", i, hex.EncodeToString(inputOwners[i]),
+						i, *plasmaInput, i, hex.EncodeToString(key))
+				}
+			}
+
+			if resUTXO.SpenderKeys != nil {
+				spenders := resUTXO.SpenderAddresses()
+				spenderPositions := resUTXO.SpenderPositions(ctx.Codec, types.ProtoPosition)
+				for i, key := range resUTXO.SpenderKeys {
+					plasmaPosition, _ := spenderPositions[i].(*types.PlasmaPosition)
+					fmt.Printf("\nSpender %d: %s\nSpending Position %d: %v\nSpendKey %d in UTXO store: %s\n", i, hex.EncodeToString(spenders[i]),
+						i, *plasmaPosition, i, hex.EncodeToString(key))
+				}
+			}
+
+			fmt.Printf("End UTXO %d info:\n", i)
 		}
 
+		fmt.Println()
+
 		return nil
 	},
 }
-
-func inputAddrHelper(utxo types.BaseUTXO) {
-	if utxo.Position.DepositNum == 0 {
-		fmt.Printf("First Input Address: %s \n", utxo.InputAddresses[0].Hex())
-		if !utils.ZeroAddress(utxo.InputAddresses[1]) {
-			fmt.Printf("Second Input Address: %s \n", utxo.InputAddresses[1].Hex())
-		}
-	}
-}
diff --git a/client/plasmacli/cmd/prove.go b/client/plasmacli/cmd/prove.go
index a022b31..9296b08 100644
--- a/client/plasmacli/cmd/prove.go
+++ b/client/plasmacli/cmd/prove.go
@@ -5,7 +5,7 @@ import (
 	"fmt"
 	"github.com/FourthState/plasma-mvp-sidechain/client"
 	"github.com/FourthState/plasma-mvp-sidechain/client/context"
-	"github.com/FourthState/plasma-mvp-sidechain/types"
+	"github.com/FourthState/plasma-mvp-sidechain/x/utxo"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/spf13/cobra"
 )
@@ -41,13 +41,13 @@ var proveCmd = &cobra.Command{
 			return err2
 		}
 
-		var utxo types.BaseUTXO
-		err = ctx.Codec.UnmarshalBinaryBare(res, &utxo)
+		var resUTXO utxo.UTXO
+		err = ctx.Codec.UnmarshalBinaryBare(res, &resUTXO)
 		if err != nil {
 			return err
 		}
 
-		result, err := ctx.Client.Tx(utxo.TxHash, true)
+		result, err := ctx.Client.Tx(resUTXO.TxHash, true)
 		if err != nil {
 			return err
 		}
diff --git a/types/utxo.go b/types/utxo.go
index 483bf40..cb75945 100644
--- a/types/utxo.go
+++ b/types/utxo.go
@@ -1,16 +1,10 @@
 package types
 
 import (
-	"errors"
-	"fmt"
 	amino "github.com/tendermint/go-amino"
 
-	utils "github.com/FourthState/plasma-mvp-sidechain/utils"
 	"github.com/FourthState/plasma-mvp-sidechain/x/utxo"
 	sdk "github.com/cosmos/cosmos-sdk/types"
-	"github.com/ethereum/go-ethereum/common"
-
-	"github.com/tendermint/tendermint/crypto/tmhash"
 )
 
 const (
@@ -18,126 +12,9 @@ const (
 	Denom = "Ether"
 )
 
-var _ utxo.UTXO = &BaseUTXO{}
-
-// Implements UTXO interface
-type BaseUTXO struct {
-	InputAddresses [2]common.Address
-	Address        common.Address
-	Amount         uint64
-	Denom          string
-	Position       PlasmaPosition
-	TxHash         []byte
-}
-
-func ProtoUTXO(ctx sdk.Context, msg sdk.Msg) utxo.UTXO {
-	spendmsg, ok := msg.(SpendMsg)
-	if !ok {
-		return nil
-	}
-
-	return &BaseUTXO{
-		InputAddresses: [2]common.Address{spendmsg.Owner0, spendmsg.Owner1},
-		TxHash:         tmhash.Sum(ctx.TxBytes()),
-	}
-}
-
-func NewBaseUTXO(addr common.Address, inputaddr [2]common.Address, amount uint64,
-	denom string, position PlasmaPosition) *BaseUTXO {
-	return &BaseUTXO{
-		InputAddresses: inputaddr,
-		Address:        addr,
-		Amount:         amount,
-		Denom:          denom,
-		Position:       position,
-	}
-}
-
-func (baseutxo BaseUTXO) GetTxHash() []byte {
-	return baseutxo.TxHash
-}
-
-//Implements UTXO
-func (baseutxo BaseUTXO) GetAddress() []byte {
-	return baseutxo.Address.Bytes()
-}
-
-//Implements UTXO
-func (baseutxo *BaseUTXO) SetAddress(addr []byte) error {
-	if !utils.ZeroAddress(baseutxo.Address) {
-		return fmt.Errorf("address already set to: %X", baseutxo.Address)
-	}
-	address := common.BytesToAddress(addr)
-	if utils.ZeroAddress(address) {
-		return fmt.Errorf("invalid address provided: %X", address)
-	}
-	baseutxo.Address = address
-	return nil
-}
-
-//Implements UTXO
-func (baseutxo *BaseUTXO) SetInputAddresses(addrs [2]common.Address) error {
-	if !utils.ZeroAddress(baseutxo.InputAddresses[0]) {
-		return fmt.Errorf("input addresses already set to: %X, %X", baseutxo.InputAddresses[0], baseutxo.InputAddresses[1])
-	}
-	if utils.ZeroAddress(addrs[0]) {
-		return fmt.Errorf("invalid address provided: %X", addrs[0])
-	}
-	baseutxo.InputAddresses = addrs
-	return nil
-}
-
-//Implements UTXO
-func (baseutxo BaseUTXO) GetInputAddresses() [2]common.Address {
-	return baseutxo.InputAddresses
-}
-
-//Implements UTXO
-func (baseutxo BaseUTXO) GetAmount() uint64 {
-	return baseutxo.Amount
-}
-
-//Implements UTXO
-func (baseutxo *BaseUTXO) SetAmount(amount uint64) error {
-	if baseutxo.Amount != 0 {
-		return fmt.Errorf("amount already set to: %d", baseutxo.Amount)
-	}
-	baseutxo.Amount = amount
-	return nil
-}
-
-func (baseutxo BaseUTXO) GetPosition() utxo.Position {
-	return baseutxo.Position
-}
-
-func (baseutxo *BaseUTXO) SetPosition(position utxo.Position) error {
-	if baseutxo.Position.IsValid() {
-		return fmt.Errorf("position already set to: %v", baseutxo.Position)
-	} else if !position.IsValid() {
-		return errors.New("invalid position provided")
-	}
-
-	plasmaposition, ok := position.(PlasmaPosition)
-	if !ok {
-		return errors.New("position must be of type PlasmaPosition")
-	}
-	baseutxo.Position = plasmaposition
-	return nil
-}
-
-func (baseutxo BaseUTXO) GetDenom() string {
-	return Denom
-}
-
-func (baseutxo *BaseUTXO) SetDenom(denom string) error {
-	return nil
-}
-
 //----------------------------------------
 // Position
 
-var _ utxo.Position = &PlasmaPosition{}
-
 type PlasmaPosition struct {
 	Blknum     uint64
 	TxIndex    uint16
@@ -145,6 +22,10 @@ type PlasmaPosition struct {
 	DepositNum uint64
 }
 
+func ProtoPosition() utxo.Position {
+	return &PlasmaPosition{}
+}
+
 func NewPlasmaPosition(blknum uint64, txIndex uint16, oIndex uint8, depositNum uint64) PlasmaPosition {
 	return PlasmaPosition{
 		Blknum:     blknum,
@@ -173,8 +54,7 @@ func (position PlasmaPosition) IsValid() bool {
 //-------------------------------------------------------
 // misc
 func RegisterAmino(cdc *amino.Codec) {
-	cdc.RegisterConcrete(&BaseUTXO{}, "types/BaseUTXO", nil)
-	cdc.RegisterConcrete(&PlasmaPosition{}, "types/PlasmaPosition", nil)
+	cdc.RegisterConcrete(PlasmaPosition{}, "types/PlasmaPosition", nil)
 	cdc.RegisterConcrete(BaseTx{}, "types/BaseTX", nil)
 	cdc.RegisterConcrete(SpendMsg{}, "types/SpendMsg", nil)
 }
diff --git a/types/utxo_test.go b/types/utxo_test.go
deleted file mode 100644
index 57e58fb..0000000
--- a/types/utxo_test.go
+++ /dev/null
@@ -1,98 +0,0 @@
-package types
-
-import (
-	"fmt"
-	"github.com/stretchr/testify/require"
-	"testing"
-
-	"github.com/FourthState/plasma-mvp-sidechain/utils"
-	"github.com/ethereum/go-ethereum/common"
-	ethcrypto "github.com/ethereum/go-ethereum/crypto"
-)
-
-// return a base utxo with nothing set, along with two addresses
-func GetBareUTXO() (utxo *BaseUTXO, addrA, addrB common.Address) {
-	privKeyA, _ := ethcrypto.GenerateKey()
-	privKeyB, _ := ethcrypto.GenerateKey()
-	addrA = utils.PrivKeyToAddress(privKeyA)
-	addrB = utils.PrivKeyToAddress(privKeyB)
-	return &BaseUTXO{}, addrA, addrB
-}
-
-// Basic tests checking methods for BaseUTXO
-func TestGetSetAddress(t *testing.T) {
-	utxo, addrA, addrB := GetBareUTXO()
-
-	// try to set address to another blank address
-	err := utxo.SetAddress(common.Address{}.Bytes())
-	require.Error(t, err)
-
-	// set address to addrB
-	err = utxo.SetAddress(addrB.Bytes())
-	require.NoError(t, err)
-
-	// try to set address to addrA (currently set to addrB)
-	err = utxo.SetAddress(addrA.Bytes())
-	require.Error(t, err)
-
-	// check get method
-	addr := utxo.GetAddress()
-	require.Equal(t, addr, addrB.Bytes(), fmt.Sprintf("BaseUTXO GetAddress() method returned the wrong address: %s", addr))
-}
-
-// Test GetInputAddresses() and SetInputAddresses
-func TestInputAddresses(t *testing.T) {
-	utxo, addrA, addrB := GetBareUTXO()
-
-	// try to set input address to blank addresses
-	err := utxo.SetInputAddresses([2]common.Address{common.Address{}, common.Address{}})
-	require.Error(t, err)
-
-	// set input addresses to addrA, addrA
-	err = utxo.SetInputAddresses([2]common.Address{addrA, addrA})
-	require.NoError(t, err)
-
-	// try to set input address to addrB
-	err = utxo.SetInputAddresses([2]common.Address{addrB, common.Address{}})
-	require.Error(t, err)
-
-	// check get method
-	addrs := utxo.GetInputAddresses()
-	require.Equal(t, addrs, [2]common.Address{addrA, addrA})
-}
-
-// Test GetAmount() and SetAmount()
-func TestAmount(t *testing.T) {
-	utxo := NewBaseUTXO(common.Address{}, [2]common.Address{common.Address{}, common.Address{}}, 100, "ether", PlasmaPosition{})
-
-	// try to set denom when it already has a value
-	err := utxo.SetAmount(100000000)
-	require.Error(t, err)
-
-	// check get method
-	amount := utxo.GetAmount()
-	require.Equal(t, amount, uint64(100), "the wrong amount was returned by GetAmount()")
-}
-
-// Test GetPosition() and SetPosition()
-func TestPosition(t *testing.T) {
-	utxo := BaseUTXO{}
-	position := NewPlasmaPosition(0, uint16(0), uint8(0), 0)
-
-	// try to set position to incorrect position 0, 0, 0, 0
-	err := utxo.SetPosition(position)
-	require.Error(t, err)
-
-	// set position
-	position = NewPlasmaPosition(5, uint16(12), uint8(1), 0)
-	err = utxo.SetPosition(position)
-	require.NoError(t, err)
-
-	// try to set to different position
-	position = NewPlasmaPosition(1, uint16(23), uint8(1), 0)
-	err = utxo.SetPosition(position)
-	require.Error(t, err)
-
-	// check get method
-	require.Equal(t, utxo.GetPosition(), NewPlasmaPosition(5, uint16(12), uint8(1), 0), "the wrong position was returned")
-}
diff --git a/x/utxo/handler.go b/x/utxo/handler.go
index 4573fe8..32515c5 100644
--- a/x/utxo/handler.go
+++ b/x/utxo/handler.go
@@ -2,6 +2,7 @@ package utxo
 
 import (
 	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/tendermint/tendermint/crypto/tmhash"
 )
 
 // Return the next position for handler to store newly created UTXOs
@@ -9,25 +10,27 @@ import (
 // If false, NextPosition will increment position to accomadate outputs for a new transaction
 type NextPosition func(ctx sdk.Context, secondary bool) Position
 
-// Proto function to create application's UTXO implementation and fill with some proto-information
-type ProtoUTXO func(sdk.Context, sdk.Msg) UTXO
-
 // User-defined fee update function
 type FeeUpdater func([]Output) sdk.Error
 
 // Handler handles spends of arbitrary utxo implementation
-func NewSpendHandler(um Mapper, nextPos NextPosition, proto ProtoUTXO) sdk.Handler {
+func NewSpendHandler(um Mapper, nextPos NextPosition) sdk.Handler {
 	return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
 		spendMsg, ok := msg.(SpendMsg)
 		if !ok {
 			panic("Msg does not implement SpendMsg")
 		}
 
-		// Delete inputs from store
-		for _, i := range spendMsg.Inputs() {
-			um.DeleteUTXO(ctx, i.Owner, i.Position)
+		var inputKeys [][]byte
+		inputs := spendMsg.Inputs()
+		for _, in := range inputs {
+			inKey := um.ConstructKey(in.Owner, in.Position)
+			inputKeys = append(inputKeys, inKey)
 		}
 
+		txHash := tmhash.Sum(ctx.TxBytes())
+
+		var spenderKeys [][]byte
 		// Add outputs from store
 		for i, o := range spendMsg.Outputs() {
 			var next Position
@@ -36,12 +39,17 @@ func NewSpendHandler(um Mapper, nextPos NextPosition, proto ProtoUTXO) sdk.Handl
 			} else {
 				next = nextPos(ctx, true)
 			}
-			utxo := proto(ctx, msg)
-			utxo.SetPosition(next)
-			utxo.SetAddress(o.Owner)
-			utxo.SetDenom(o.Denom)
-			utxo.SetAmount(o.Amount)
-			um.AddUTXO(ctx, utxo)
+			spenderKeys = append(spenderKeys, um.ConstructKey(o.Owner, next))
+			utxo := NewUTXOwithInputs(o.Owner, o.Amount, o.Denom, next, txHash, inputKeys)
+			um.ReceiveUTXO(ctx, utxo)
+		}
+
+		// Spend inputs from store
+		for _, i := range spendMsg.Inputs() {
+			err := um.SpendUTXO(ctx, i.Owner, i.Position, spenderKeys)
+			if err != nil {
+				return err.Result()
+			}
 		}
 
 		return sdk.Result{}
@@ -61,7 +69,7 @@ func AnteHelper(ctx sdk.Context, um Mapper, tx sdk.Tx, simulate bool, feeUpdater
 	totalInput := map[string]uint64{}
 	for _, i := range spendMsg.Inputs() {
 		utxo := um.GetUTXO(ctx, i.Owner, i.Position)
-		totalInput[utxo.GetDenom()] += utxo.GetAmount()
+		totalInput[utxo.Denom] += utxo.Amount
 	}
 
 	// Add up all outputs and fee
diff --git a/x/utxo/handler_test.go b/x/utxo/handler_test.go
index 845afff..f9793e2 100644
--- a/x/utxo/handler_test.go
+++ b/x/utxo/handler_test.go
@@ -103,30 +103,35 @@ func TestHandleSpendMessage(t *testing.T) {
 		ms, capKey, _ := SetupMultiStore()
 
 		cdc := MakeCodec()
-		cdc.RegisterConcrete(&testUTXO{}, "x/utxo/testUTXO", nil)
+		cdc.RegisterConcrete(&UTXO{}, "x/utxo/UTXO", nil)
 		cdc.RegisterConcrete(&testPosition{}, "x/utxo/testPosition", nil)
 		mapper := NewBaseMapper(capKey, cdc)
 		app := testApp{0, 0}
-		handler := NewSpendHandler(mapper, app.testNextPosition, testProtoUTXO)
+		handler := NewSpendHandler(mapper, app.testNextPosition)
 
 		ctx := sdk.NewContext(ms, abci.Header{Height: 6}, false, log.NewNopLogger())
 		var inputs []Input
 		var outputs []Output
+		var inputKeys [][]byte
+		var spenderKeys [][]byte
 
 		// Add utxo's that will be spent
 		for i := 0; i < tc.inputNum; i++ {
 			position := newTestPosition([]uint64{5, uint64(i), 0})
-			utxo := newTestUTXO(addrs[i].Bytes(), 100, position)
-			mapper.AddUTXO(ctx, utxo)
+			utxo := NewUTXO(addrs[i].Bytes(), 100, "testEther", position)
+			mapper.ReceiveUTXO(ctx, utxo)
 
 			utxo = mapper.GetUTXO(ctx, addrs[i].Bytes(), position)
 			require.NotNil(t, utxo)
 
 			inputs = append(inputs, Input{addrs[i].Bytes(), position})
+			inputKeys = append(inputKeys, mapper.ConstructKey(addrs[i].Bytes(), position))
 		}
 
 		for i := 0; i < tc.outputNum; i++ {
 			outputs = append(outputs, Output{addrs[(i+1)%len].Bytes(), "Ether", uint64((100 * tc.inputNum) / tc.outputNum)})
+			position := newTestPosition([]uint64{6, 0, uint64(i)})
+			spenderKeys = append(spenderKeys, mapper.ConstructKey(addrs[(i+1)%len].Bytes(), position))
 		}
 
 		// Create spend msg
@@ -141,9 +146,10 @@ func TestHandleSpendMessage(t *testing.T) {
 
 		// Delete inputs
 		for _, in := range msg.Inputs() {
-			mapper.DeleteUTXO(ctx, in.Owner, in.Position)
 			utxo := mapper.GetUTXO(ctx, in.Owner, in.Position)
-			require.Nil(t, utxo)
+			require.NotNil(t, utxo)
+			require.False(t, utxo.Valid, "Spent UTXO not valid")
+			require.Equal(t, spenderKeys, utxo.SpenderKeys, "Spender keys not set properly for inputs")
 		}
 
 		// Check that outputs were created and are valid
@@ -153,12 +159,10 @@ func TestHandleSpendMessage(t *testing.T) {
 			utxo := mapper.GetUTXO(ctx, o.Owner, position)
 			require.NotNil(t, utxo, fmt.Sprintf("test case %d, output %d", index, i))
 
-			require.Equal(t, uint64((tc.inputNum*100)/tc.outputNum), utxo.GetAmount())
-			require.EqualValues(t, addrs[(i+1)%len].Bytes(), utxo.GetAddress())
-
-			mapper.DeleteUTXO(ctx, o.Owner, position)
-			utxo = mapper.GetUTXO(ctx, o.Owner, position)
-			require.Nil(t, utxo)
+			require.Equal(t, uint64((tc.inputNum*100)/tc.outputNum), utxo.Amount)
+			require.EqualValues(t, addrs[(i+1)%len].Bytes(), utxo.Address)
+			require.True(t, utxo.Valid, "Output UTXO is not valid")
+			require.Equal(t, inputKeys, utxo.InputKeys, "Input keys for new outputs not set properly")
 		}
 	}
 }
diff --git a/x/utxo/mapper.go b/x/utxo/mapper.go
index 4bc3d93..3b3a791 100644
--- a/x/utxo/mapper.go
+++ b/x/utxo/mapper.go
@@ -9,16 +9,17 @@ import (
 // retrieved from the context.
 type Mapper interface {
 	GetUTXO(ctx sdk.Context, addr []byte, position Position) UTXO
-	GetUTXOsForAddress(ctx sdk.Context, addr []byte) []UTXO
-	AddUTXO(ctx sdk.Context, utxo UTXO)
-	DeleteUTXO(ctx sdk.Context, addr []byte, position Position)
+	ConstructKey(addr []byte, position Position) []byte
+	ReceiveUTXO(sdk.Context, UTXO)
+	ValidateUTXO(sdk.Context, UTXO) sdk.Error
+	InvalidateUTXO(sdk.Context, UTXO)
+	SpendUTXO(ctx sdk.Context, addr []byte, position Position, spenderKeys [][]byte) sdk.Error
 }
 
 // Maps Address+Position to UTXO
 // Uses go-amino encoding/decoding library
 // Implements Mapper
 type baseMapper struct {
-
 	// The contextKey used to access the store from the Context.
 	contextKey sdk.StoreKey
 
@@ -31,60 +32,71 @@ func NewBaseMapper(contextKey sdk.StoreKey, cdc *amino.Codec) Mapper {
 		contextKey: contextKey,
 		cdc:        cdc,
 	}
-
 }
 
 // Returns the UTXO corresponding to the address + go amino encoded Position struct
 // Returns nil if no UTXO exists at that position
 func (um baseMapper) GetUTXO(ctx sdk.Context, addr []byte, position Position) UTXO {
 	store := ctx.KVStore(um.contextKey)
-	key := um.constructKey(addr, position)
+	key := um.ConstructKey(addr, position)
 	bz := store.Get(key)
 
 	if bz == nil {
-		return nil
+		return UTXO{}
 	}
 
 	utxo := um.decodeUTXO(bz)
 	return utxo
 }
 
-// Returns all the UTXOs owned by an address.
-// Returns empty slice if no UTXO exists for the address.
-func (um baseMapper) GetUTXOsForAddress(ctx sdk.Context, addr []byte) []UTXO {
+// Receives the UTXO to the mapper
+func (um baseMapper) ReceiveUTXO(ctx sdk.Context, utxo UTXO) {
 	store := ctx.KVStore(um.contextKey)
-	iterator := sdk.KVStorePrefixIterator(store, addr)
-	utxos := make([]UTXO, 0)
-
-	for ; iterator.Valid(); iterator.Next() {
-		utxo := um.decodeUTXO(iterator.Value())
-		utxos = append(utxos, utxo)
-	}
-	iterator.Close()
 
-	return utxos
+	key := utxo.StoreKey(um.cdc)
+	bz := um.encodeUTXO(utxo)
+	store.Set(key, bz)
 }
 
-// Adds the UTXO to the mapper
-func (um baseMapper) AddUTXO(ctx sdk.Context, utxo UTXO) {
-	position := utxo.GetPosition()
-	address := utxo.GetAddress()
+// Spend UTXO corresponding to address + position from mapping
+func (um baseMapper) SpendUTXO(ctx sdk.Context, addr []byte, position Position, spenderKeys [][]byte) sdk.Error {
 	store := ctx.KVStore(um.contextKey)
+	key := um.ConstructKey(addr, position)
+	utxo := um.GetUTXO(ctx, addr, position)
+	if !utxo.Valid {
+		return sdk.ErrUnauthorized("UTXO is not valid for spend")
+	}
+	utxo.Valid = false
+	utxo.SpenderKeys = spenderKeys
+	encodedUTXO := um.encodeUTXO(utxo)
+	store.Set(key, encodedUTXO)
+	return nil
+}
 
-	key := um.constructKey(address, position)
-	bz := um.encodeUTXO(utxo)
-	store.Set(key, bz)
+// Validates UTXO only if it not spent already
+func (um baseMapper) ValidateUTXO(ctx sdk.Context, utxo UTXO) sdk.Error {
+	store := ctx.KVStore(um.contextKey)
+	key := utxo.StoreKey(um.cdc)
+	if utxo.SpenderKeys != nil {
+		return sdk.ErrUnauthorized("Cannot validate spent UTXO")
+	}
+	utxo.Valid = true
+	encodedUTXO := um.encodeUTXO(utxo)
+	store.Set(key, encodedUTXO)
+	return nil
 }
 
-// Deletes UTXO corresponding to address + position from mapping
-func (um baseMapper) DeleteUTXO(ctx sdk.Context, addr []byte, position Position) {
+// Invalidates UTXO
+func (um baseMapper) InvalidateUTXO(ctx sdk.Context, utxo UTXO) {
 	store := ctx.KVStore(um.contextKey)
-	key := um.constructKey(addr, position)
-	store.Delete(key)
+	key := utxo.StoreKey(um.cdc)
+	utxo.Valid = false
+	encodedUTXO := um.encodeUTXO(utxo)
+	store.Set(key, encodedUTXO)
 }
 
 // (<address> + <encoded position>) forms the unique key that maps to an UTXO.
-func (um baseMapper) constructKey(address []byte, position Position) []byte {
+func (um baseMapper) ConstructKey(address []byte, position Position) []byte {
 	posBytes, err := um.cdc.MarshalBinaryBare(position)
 	if err != nil {
 		panic(err)
diff --git a/x/utxo/mapper_test.go b/x/utxo/mapper_test.go
index 5de727c..83023fd 100644
--- a/x/utxo/mapper_test.go
+++ b/x/utxo/mapper_test.go
@@ -1,8 +1,6 @@
 package utxo
 
 import (
-	"errors"
-	"fmt"
 	"github.com/stretchr/testify/require"
 	"testing"
 
@@ -23,8 +21,8 @@ type testPosition struct {
 	OutputIndex uint8
 }
 
-func testProtoUTXO(ctx sdk.Context, msg sdk.Msg) UTXO {
-	return &testUTXO{}
+func testProtoPosition() Position {
+	return &testPosition{}
 }
 
 func newTestPosition(newPos []uint64) testPosition {
@@ -46,89 +44,19 @@ func (pos testPosition) IsValid() bool {
 	return true
 }
 
-var _ UTXO = &testUTXO{}
-
-type testUTXO struct {
-	Owner    []byte
-	Amount   uint64
-	Denom    string
-	Position testPosition
-}
-
-func newTestUTXO(owner []byte, amount uint64, position testPosition) UTXO {
-	return &testUTXO{
-		Owner:    owner,
-		Amount:   amount,
-		Denom:    "Ether",
-		Position: position,
-	}
-}
-
-func (utxo testUTXO) GetAddress() []byte {
-	return utxo.Owner
-}
-
-func (utxo *testUTXO) SetAddress(address []byte) error {
-	if utxo.Owner != nil {
-		return errors.New("Owner already set")
-	}
-	utxo.Owner = address
-	return nil
-}
-
-func (utxo testUTXO) GetAmount() uint64 {
-	return utxo.Amount
-}
-
-func (utxo *testUTXO) SetAmount(amount uint64) error {
-	if utxo.Amount != 0 {
-		return errors.New("Owner already set")
-	}
-	utxo.Amount = amount
-	return nil
-}
-
-func (utxo testUTXO) GetDenom() string {
-	return utxo.Denom
-}
-
-func (utxo *testUTXO) SetDenom(denom string) error {
-	if utxo.Denom != "" {
-		return errors.New("Owner already set")
-	}
-	utxo.Denom = denom
-	return nil
-}
-
-func (utxo testUTXO) GetPosition() Position {
-	return utxo.Position
-}
-
-func (utxo *testUTXO) SetPosition(pos Position) error {
-
-	position, ok := pos.(testPosition)
-	if !ok {
-		fmt.Println("ah")
-		return errors.New("position setting err")
-	}
-	utxo.Position = position
-	return nil
-}
-
 /*
-	Basic test of Get, Add, Delete
+	Basic test of Get, Receive, Spend
 	Creates a valid UTXO and adds it to the uxto mapping.
 	Checks to make sure UTXO isn't nil after adding to mapping.
 	Then deletes the UTXO from the mapping
 */
 
-func TestUTXOGetAddDelete(t *testing.T) {
+func TestUTXOGetReceiveSpend(t *testing.T) {
 	ms, capKey, _ := SetupMultiStore()
 
 	ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger())
 	cdc := MakeCodec()
-	cdc.RegisterConcrete(&testUTXO{}, "x/utxo/testUTXO", nil)
-	cdc.RegisterConcrete(&testPosition{}, "x/utxo/testPosition", nil)
+	cdc.RegisterConcrete(testPosition{}, "x/utxo/testPosition", nil)
 	mapper := NewBaseMapper(capKey, cdc)
 
 	priv, _ := ethcrypto.GenerateKey()
@@ -136,20 +64,21 @@ func TestUTXOGetAddDelete(t *testing.T) {
 
 	position := newTestPosition([]uint64{1, 0, 0})
 
-	utxo := newTestUTXO(addr.Bytes(), 100, position)
+	utxo := NewUTXO(addr.Bytes(), 100, "testEther", position)
 
-	require.NotNil(t, utxo)
-	require.Equal(t, addr.Bytes(), utxo.GetAddress())
-	require.EqualValues(t, position, utxo.GetPosition())
+	require.Equal(t, addr.Bytes(), utxo.Address)
+	require.EqualValues(t, position, utxo.Position)
 
-	mapper.AddUTXO(ctx, utxo)
+	mapper.ReceiveUTXO(ctx, utxo)
 
-	utxo = mapper.GetUTXO(ctx, addr.Bytes(), position)
-	require.NotNil(t, utxo)
+	received := mapper.GetUTXO(ctx, addr.Bytes(), position)
+	require.True(t, received.Valid, "output UTXO is not valid")
+	require.Equal(t, utxo, received, "not equal after receive")
 
-	mapper.DeleteUTXO(ctx, addr.Bytes(), position)
+	mapper.SpendUTXO(ctx, addr.Bytes(), position, [][]byte{[]byte("spenderKey")})
 	utxo = mapper.GetUTXO(ctx, addr.Bytes(), position)
-	require.Nil(t, utxo)
+	require.False(t, utxo.Valid, "Spent UTXO is still valid")
+	require.Equal(t, utxo.SpenderKeys, [][]byte{[]byte("spenderKey")})
 }
 
 /*
@@ -163,8 +92,7 @@ func TestMultiUTXOAddDeleteSameBlock(t *testing.T) {
 
 	ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger())
 	cdc := MakeCodec()
-	cdc.RegisterConcrete(&testUTXO{}, "x/utxo/testUTXO", nil)
-	cdc.RegisterConcrete(&testPosition{}, "x/utxo/testPosition", nil)
+	cdc.RegisterConcrete(testPosition{}, "x/utxo/testPosition", nil)
 	mapper := NewBaseMapper(capKey, cdc)
 
 	priv, _ := ethcrypto.GenerateKey()
@@ -172,21 +100,21 @@ func TestMultiUTXOAddDeleteSameBlock(t *testing.T) {
 
 	for i := 0; i < 20; i++ {
 		position := newTestPosition([]uint64{uint64(i%4) + 1, uint64(i / 4), 0})
-		utxo := newTestUTXO(addr.Bytes(), 100, position)
-		mapper.AddUTXO(ctx, utxo)
+		utxo := NewUTXO(addr.Bytes(), 100, "testEther", position)
+		mapper.ReceiveUTXO(ctx, utxo)
 
 		utxo = mapper.GetUTXO(ctx, addr.Bytes(), position)
-		require.NotNil(t, utxo)
+		require.True(t, utxo.Valid, "Received UTXO is not valid")
 	}
 
 	for i := 0; i < 20; i++ {
 		position := newTestPosition([]uint64{uint64(i%4) + 1, uint64(i / 4), 0})
 
 		utxo := mapper.GetUTXO(ctx, addr.Bytes(), position)
-		require.NotNil(t, utxo)
-		mapper.DeleteUTXO(ctx, addr.Bytes(), position)
+		mapper.SpendUTXO(ctx, addr.Bytes(), position, [][]byte{[]byte("spenderKey")})
 		utxo = mapper.GetUTXO(ctx, addr.Bytes(), position)
-		require.Nil(t, utxo)
+		require.False(t, utxo.Valid, "Spent UTXO is still valid")
+		require.Equal(t, utxo.SpenderKeys, [][]byte{[]byte("spenderKey")})
 	}
 
 }
@@ -197,8 +125,7 @@ func TestInvalidAddress(t *testing.T) {
 	ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger())
 
 	cdc := MakeCodec()
-	cdc.RegisterConcrete(&testUTXO{}, "x/utxo/testUTXO", nil)
-	cdc.RegisterConcrete(&testPosition{}, "x/utxo/testPosition", nil)
+	cdc.RegisterConcrete(testPosition{}, "x/utxo/testPosition", nil)
 	mapper := NewBaseMapper(capKey, cdc)
 
 	priv0, _ := ethcrypto.GenerateKey()
@@ -209,82 +136,88 @@ func TestInvalidAddress(t *testing.T) {
 
 	position := newTestPosition([]uint64{1, 0, 0})
 
-	utxo := newTestUTXO(addr0.Bytes(), 100, position)
+	utxo := NewUTXO(addr0.Bytes(), 100, "testEther", position)
 
-	require.NotNil(t, utxo)
-	require.Equal(t, addr0.Bytes(), utxo.GetAddress())
-	require.EqualValues(t, position, utxo.GetPosition())
+	require.Equal(t, addr0.Bytes(), utxo.Address)
+	require.EqualValues(t, position, utxo.Position)
 
-	mapper.AddUTXO(ctx, utxo)
+	mapper.ReceiveUTXO(ctx, utxo)
 
 	// GetUTXO with correct position but wrong address
 	utxo = mapper.GetUTXO(ctx, addr1.Bytes(), position)
-	require.Nil(t, utxo)
+	require.Equal(t, utxo, UTXO{}, "Valid UTXO in wrong location")
 
 	utxo = mapper.GetUTXO(ctx, addr0.Bytes(), position)
-	require.NotNil(t, utxo)
 
-	// DeleteUTXO with correct position but wrong address
-	mapper.DeleteUTXO(ctx, addr1.Bytes(), position)
+	// SpendUTXO with correct position but wrong address
+	mapper.SpendUTXO(ctx, addr1.Bytes(), position, [][]byte{[]byte("spenderKey")})
 	utxo = mapper.GetUTXO(ctx, addr0.Bytes(), position)
-	require.NotNil(t, utxo)
+	require.True(t, utxo.Valid, "UTXO invalid after invalid spend")
+	require.Nil(t, utxo.SpenderKeys, "UTXO has spenderKeys set after invalid spend")
 
-	mapper.DeleteUTXO(ctx, addr0.Bytes(), position)
+	mapper.SpendUTXO(ctx, addr0.Bytes(), position, [][]byte{[]byte("spenderKey")})
 	utxo = mapper.GetUTXO(ctx, addr0.Bytes(), position)
-	require.Nil(t, utxo)
+	require.False(t, utxo.Valid, "UTXO still valid after valid spend")
+	require.Equal(t, utxo.SpenderKeys, [][]byte{[]byte("spenderKey")}, "UTXO doesn't have spenderKeys set after valid spend")
 }
 
-/*
-	Test getting all UTXOs for an Address.
-*/
-
-func TestGetUTXOsForAddress(t *testing.T) {
+func TestSpendInvalidUTXO(t *testing.T) {
 	ms, capKey, _ := SetupMultiStore()
 
 	ctx := sdk.NewContext(ms, abci.Header{}, false, log.NewNopLogger())
+	cdc := MakeCodec()
+	cdc.RegisterConcrete(testPosition{}, "x/utxo/testPosition", nil)
+	mapper := NewBaseMapper(capKey, cdc)
+
+	priv, _ := ethcrypto.GenerateKey()
+	addr := utils.PrivKeyToAddress(priv)
+
+	position := newTestPosition([]uint64{1, 0, 0})
+
+	utxo := NewUTXO(addr.Bytes(), 100, "testEther", position)
+
+	require.True(t, utxo.Valid, "UTXO is not valid on creation")
+
+	mapper.InvalidateUTXO(ctx, utxo)
+
+	err := mapper.SpendUTXO(ctx, addr.Bytes(), position, [][]byte{[]byte("spenderKey")})
+
+	utxo = mapper.GetUTXO(ctx, addr.Bytes(), position)
+	require.NotNil(t, err, "Allowed invalid UTXO to be spent")
+	require.Nil(t, utxo.SpenderKeys, "UTXO mutated after invalid spend")
+
+	mapper.ValidateUTXO(ctx, utxo)
+	err = mapper.SpendUTXO(ctx, addr.Bytes(), position, [][]byte{[]byte("spenderKey")})
+
+	utxo = mapper.GetUTXO(ctx, addr.Bytes(), position)
+	require.Nil(t, err, "Spend of valid UTXO errorred")
+	require.False(t, utxo.Valid, "Spent UTXO is still valid")
+	require.Equal(t, utxo.SpenderKeys, [][]byte{[]byte("spenderKey")}, "UTXO doesn't have spenderKeys set after valid spend")
+}
+
+func TestUTXOMethods(t *testing.T) {
+	_, capKey, _ := SetupMultiStore()
 
 	cdc := MakeCodec()
-	cdc.RegisterConcrete(&testUTXO{}, "x/utxo/testUTXO", nil)
-	cdc.RegisterConcrete(&testPosition{}, "x/utxo/testPosition", nil)
+	cdc.RegisterConcrete(testPosition{}, "x/utxo/testPosition", nil)
 	mapper := NewBaseMapper(capKey, cdc)
 
-	privA, _ := ethcrypto.GenerateKey()
-	addrA := utils.PrivKeyToAddress(privA)
-
-	privB, _ := ethcrypto.GenerateKey()
-	addrB := utils.PrivKeyToAddress(privB)
-
-	privC, _ := ethcrypto.GenerateKey()
-	addrC := utils.PrivKeyToAddress(privC)
-
-	positionB0 := newTestPosition([]uint64{1, 0, 0})
-	positionB1 := newTestPosition([]uint64{2, 1, 0})
-	positionB2 := newTestPosition([]uint64{3, 2, 1})
-
-	utxo0 := newTestUTXO(addrB.Bytes(), 100, positionB0)
-	utxo1 := newTestUTXO(addrB.Bytes(), 200, positionB1)
-	utxo2 := newTestUTXO(addrB.Bytes(), 300, positionB2)
-
-	mapper.AddUTXO(ctx, utxo0)
-	mapper.AddUTXO(ctx, utxo1)
-	mapper.AddUTXO(ctx, utxo2)
-
-	utxosForAddressB := mapper.GetUTXOsForAddress(ctx, addrB.Bytes())
-	require.NotNil(t, utxosForAddressB)
-	require.Equal(t, 3, len(utxosForAddressB))
-	require.Equal(t, utxo0, utxosForAddressB[0])
-	require.Equal(t, utxo1, utxosForAddressB[1])
-	require.Equal(t, utxo2, utxosForAddressB[2])
-
-	positionC0 := newTestPosition([]uint64{2, 3, 0})
-	utxo3 := newTestUTXO(addrC.Bytes(), 300, positionC0)
-	mapper.AddUTXO(ctx, utxo3)
-	utxosForAddressC := mapper.GetUTXOsForAddress(ctx, addrC.Bytes())
-	require.NotNil(t, utxosForAddressC)
-	require.Equal(t, 1, len(utxosForAddressC))
-	require.Equal(t, utxo3, utxosForAddressC[0])
-
-	// check returns empty slice if no UTXOs exist for address
-	utxosForAddressA := mapper.GetUTXOsForAddress(ctx, addrA.Bytes())
-	require.Empty(t, utxosForAddressA)
+	addr1 := []byte("12345")
+	addr2 := []byte("13579")
+	addr3 := []byte("67890")
+
+	outputPos1 := testPosition{7, 8, 9}
+	outputPos2 := testPosition{3, 4, 5}
+
+	outputKey1 := mapper.ConstructKey(addr1, outputPos1)
+	outputKey2 := mapper.ConstructKey(addr2, outputPos2)
+
+	testUTXO := NewUTXO(addr3, 100, "Ether", testPosition{0, 1, 2})
+	testUTXO.SpenderKeys = [][]byte{outputKey1, outputKey2}
+
+	addrs := testUTXO.SpenderAddresses()
+	require.Equal(t, [][]byte{addr1, addr2}, addrs, "Spender addresses are not correct")
+
+	positions := testUTXO.SpenderPositions(cdc, testProtoPosition)
+	require.Equal(t, []Position{&outputPos1, &outputPos2}, positions, "Spender position not correct")
 }
diff --git a/x/utxo/types.go b/x/utxo/types.go
index da69a01..f48ce20 100644
--- a/x/utxo/types.go
+++ b/x/utxo/types.go
@@ -2,24 +2,103 @@ package utxo
 
 import (
 	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/tendermint/go-amino"
 )
 
 // UTXO is a standard unspent transaction output
-type UTXO interface {
-	// Address that owns UTXO
-	GetAddress() []byte
-	SetAddress([]byte) error // errors if already set
+// When spent, it becomes invalid and spender keys are filled in
+type UTXO struct {
+	InputKeys   [][]byte // Keys in store for input UTXOs that created this output
+	Address     []byte
+	Amount      uint64
+	Denom       string
+	Valid       bool
+	Position    Position
+	TxHash      []byte   // transaction that created this UTXO
+	SpenderKeys [][]byte // Keys in store for UTXOs that spent this output
+}
+
+func NewUTXO(owner []byte, amount uint64, denom string, position Position) UTXO {
+	return UTXO{
+		Address:  owner,
+		Amount:   amount,
+		Denom:    denom,
+		Position: position,
+		Valid:    true,
+	}
+}
+
+func NewUTXOwithInputs(owner []byte, amount uint64, denom string, position Position, txHash []byte, inputKeys [][]byte) UTXO {
+	return UTXO{
+		InputKeys: inputKeys,
+		Address:   owner,
+		Amount:    amount,
+		Denom:     denom,
+		Position:  position,
+		Valid:     true,
+		TxHash:    txHash,
+	}
+}
+
+func (utxo UTXO) StoreKey(cdc *amino.Codec) []byte {
+	encPos := cdc.MustMarshalBinaryBare(utxo.Position)
+	return append(utxo.Address, encPos...)
+}
+
+// Recovers InputAddresses from Input keys.
+// Assumes all addresses on-chain have same length
+func (utxo UTXO) InputAddresses() [][]byte {
+	var addresses [][]byte
+	addrLen := len(utxo.Address)
+	for _, key := range utxo.InputKeys {
+		addresses = append(addresses, key[:addrLen])
+	}
+	return addresses
+}
 
-	GetAmount() uint64
-	SetAmount(uint64) error // errors if already set
+// Recovers InputPositions from Input keys.
+// Assumes all addresses on-chain have same length
+func (utxo UTXO) InputPositions(cdc *amino.Codec, proto ProtoPosition) []Position {
+	var inputs []Position
+	addrLen := len(utxo.Address)
+	for _, key := range utxo.InputKeys {
+		encodedPos := key[addrLen:]
+		pos := proto()
+		cdc.MustUnmarshalBinaryBare(encodedPos, pos)
+		inputs = append(inputs, pos)
+	}
+	return inputs
+}
 
-	GetDenom() string
-	SetDenom(string) error // errors if already set
+// Recovers Spender Addresses from Spender keys.
+// Assumes all addresses on-chain have same length
+func (utxo UTXO) SpenderAddresses() [][]byte {
+	var addresses [][]byte
+	addrLen := len(utxo.Address)
+	for _, key := range utxo.SpenderKeys {
+		addresses = append(addresses, key[:addrLen])
+	}
+	return addresses
+}
 
-	GetPosition() Position
-	SetPosition(Position) error // errors if already set
+// Recovers Spender Positions from Spender keys.
+// Assumes all addresses on-chain have same length
+func (utxo UTXO) SpenderPositions(cdc *amino.Codec, proto ProtoPosition) []Position {
+	var spenders []Position
+	addrLen := len(utxo.Address)
+	for _, key := range utxo.SpenderKeys {
+		encodedPos := key[addrLen:]
+		pos := proto()
+		cdc.MustUnmarshalBinaryBare(encodedPos, pos)
+		spenders = append(spenders, pos)
+	}
+	return spenders
 }
 
+// Create a prototype Position.
+// Must return pointer to struct implementing Position
+type ProtoPosition func() Position
+
 // Positions must be unqiue or a collision may result when using mapper.go
 type Position interface {
 	// Position is a uint slice
diff --git a/x/utxo/utils.go b/x/utxo/utils.go
index b4b2a3d..df67e15 100644
--- a/x/utxo/utils.go
+++ b/x/utxo/utils.go
@@ -28,5 +28,4 @@ func MakeCodec() *amino.Codec {
 
 func RegisterAmino(cdc *amino.Codec) {
 	cdc.RegisterInterface((*Position)(nil), nil)
-	cdc.RegisterInterface((*UTXO)(nil), nil)
 }