diff --git a/packages/binary/marshalutil/marshalutil.bytes.go b/packages/binary/marshalutil/marshalutil.bytes.go
index 22d2580acf9eb3185368cd33d893e1f0d690ade6..0ee36484ac69805bb70ddb22c7b5b5920acf7ae1 100644
--- a/packages/binary/marshalutil/marshalutil.bytes.go
+++ b/packages/binary/marshalutil/marshalutil.bytes.go
@@ -1,13 +1,18 @@
 package marshalutil
 
-func (util *MarshalUtil) WriteBytes(bytes []byte) {
+// WriteBytes appends the given bytes to the internal buffer.
+// It returns the same MarshalUtil so calls can be chained.
+func (util *MarshalUtil) WriteBytes(bytes []byte) *MarshalUtil {
 	writeEndOffset := util.expandWriteCapacity(len(bytes))
 
 	copy(util.bytes[util.writeOffset:writeEndOffset], bytes)
 
 	util.WriteSeek(writeEndOffset)
+
+	return util
 }
 
+// ReadBytes unmarshals the given amount of bytes from the internal read buffer.
 func (util *MarshalUtil) ReadBytes(length int) ([]byte, error) {
 	if length < 0 {
 		length = len(util.bytes) - util.readOffset + length
diff --git a/packages/binary/valuetransfer/address/address.go b/packages/binary/valuetransfer/address/address.go
index 17cfddba141ff76a67a3b25fa992474746ff660d..13e89793906ed7ee166a48977824b312c1a5a00c 100644
--- a/packages/binary/valuetransfer/address/address.go
+++ b/packages/binary/valuetransfer/address/address.go
@@ -1,9 +1,13 @@
 package address
 
 import (
+	"crypto/rand"
+	"fmt"
+
 	"github.com/mr-tron/base58"
 	"golang.org/x/crypto/blake2b"
 
+	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
 	"github.com/iotaledger/goshimmer/packages/binary/signature/ed25119"
 )
 
@@ -13,7 +17,36 @@ type AddressDigest = []byte
 
 type Address [Length]byte
 
-func New(bytes []byte) (address Address) {
+// Random create a random address, which can for example be used in unit tests.
+func Random() (address Address) {
+	// generate a random sequence of bytes
+	addressBytes := make([]byte, Length)
+	if _, err := rand.Read(addressBytes); err != nil {
+		panic(err)
+	}
+
+	// copy the generated bytes into the result
+	copy(address[:], addressBytes)
+
+	return
+}
+
+// FromBase58 creates an address from base58 encoded string.
+func FromBase58(base58String string) (address Address, err error) {
+	// decode string
+	bytes, err := base58.Decode(base58String)
+	if err != nil {
+		return
+	}
+
+	// sanitize input
+	if len(bytes) != Length {
+		err = fmt.Errorf("base58 encoded string does not match the length of an address")
+
+		return
+	}
+
+	// copy bytes to result
 	copy(address[:], bytes)
 
 	return
@@ -28,6 +61,29 @@ func FromED25519PubKey(key ed25119.PublicKey) (address Address) {
 	return
 }
 
+// FromBytes unmarshals an address from a sequence of bytes.
+func FromBytes(bytes []byte) (result Address, err error, consumedBytes int) {
+	// parse the bytes
+	marshalUtil := marshalutil.New(bytes)
+	addressBytes, err := marshalUtil.ReadBytes(Length)
+	if err != nil {
+		return
+	}
+	copy(result[:], addressBytes)
+	consumedBytes = marshalUtil.ReadOffset()
+
+	return
+}
+
+// Parse is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
+func Parse(marshalUtil *marshalutil.MarshalUtil) (Address, error) {
+	if address, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return FromBytes(data) }); err != nil {
+		return Address{}, err
+	} else {
+		return address.(Address), nil
+	}
+}
+
 func (address *Address) GetVersion() AddressVersion {
 	return address[0]
 }
@@ -36,12 +92,14 @@ func (address *Address) GetDigest() AddressDigest {
 	return address[1:]
 }
 
-func (address Address) ToBytes() []byte {
+// Bytes returns a marshaled version of this address.
+func (address Address) Bytes() []byte {
 	return address[:]
 }
 
+// String returns a human readable (base58 encoded) version of the address.
 func (address Address) String() string {
-	return "Address(" + base58.Encode(address.ToBytes()) + ")"
+	return base58.Encode(address.Bytes())
 }
 
 const Length = 33
diff --git a/packages/binary/valuetransfer/coloredbalance/coloredbalance.go b/packages/binary/valuetransfer/coloredbalance/coloredbalance.go
index b0f4d43a072a3130dfa3da1603b87a4e0240b080..e17e8d68aae98a752aca9d82f1303ccb185b5419 100644
--- a/packages/binary/valuetransfer/coloredbalance/coloredbalance.go
+++ b/packages/binary/valuetransfer/coloredbalance/coloredbalance.go
@@ -44,6 +44,15 @@ func FromBytes(bytes []byte) (result *ColoredBalance, err error, consumedBytes i
 	return
 }
 
+// Parse is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
+func Parse(marshalUtil *marshalutil.MarshalUtil) (*ColoredBalance, error) {
+	if address, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return FromBytes(data) }); err != nil {
+		return nil, err
+	} else {
+		return address.(*ColoredBalance), nil
+	}
+}
+
 func (balance *ColoredBalance) Bytes() []byte {
 	marshalUtil := marshalutil.New(color.Length + marshalutil.UINT32_SIZE)
 
@@ -56,3 +65,6 @@ func (balance *ColoredBalance) Bytes() []byte {
 func (balance *ColoredBalance) String() string {
 	return strconv.FormatInt(balance.balance, 10) + " " + balance.color.String()
 }
+
+// Length encodes the length of a marshaled ColoredBalance (the length of the color + 8 bytes for the balance).
+const Length = color.Length + 8
diff --git a/packages/binary/valuetransfer/payload/transfer/id/id.go b/packages/binary/valuetransfer/payload/transfer/id/id.go
index 8036c466ac7ec863bcc680b59441934f9b3ab4ba..22baa614a721dd92c77efb4720cd54821889348a 100644
--- a/packages/binary/valuetransfer/payload/transfer/id/id.go
+++ b/packages/binary/valuetransfer/payload/transfer/id/id.go
@@ -2,6 +2,8 @@ package id
 
 import (
 	"github.com/mr-tron/base58"
+
+	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
 )
 
 type Id [Length]byte
@@ -12,6 +14,29 @@ func New(idBytes []byte) (result Id) {
 	return
 }
 
+// FromBytes unmarshals a transfer id from a sequence of bytes.
+func FromBytes(bytes []byte) (result Id, err error, consumedBytes int) {
+	// parse the bytes
+	marshalUtil := marshalutil.New(bytes)
+	idBytes, err := marshalUtil.ReadBytes(Length)
+	if err != nil {
+		return
+	}
+	copy(result[:], idBytes)
+	consumedBytes = marshalUtil.ReadOffset()
+
+	return
+}
+
+// Parse is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
+func Parse(marshalUtil *marshalutil.MarshalUtil) (Id, error) {
+	if id, err := marshalUtil.Parse(func(data []byte) (interface{}, error, int) { return FromBytes(data) }); err != nil {
+		return Id{}, err
+	} else {
+		return id.(Id), nil
+	}
+}
+
 func (id Id) Bytes() []byte {
 	return id[:]
 }
diff --git a/packages/binary/valuetransfer/payload/transfer/inputs/inputs.go b/packages/binary/valuetransfer/payload/transfer/inputs/inputs.go
index be2c3fa460e3fd2ceac979e31426aeaa5459bad5..1d107dc7a502207db185db142780fdc5dbc854a2 100644
--- a/packages/binary/valuetransfer/payload/transfer/inputs/inputs.go
+++ b/packages/binary/valuetransfer/payload/transfer/inputs/inputs.go
@@ -32,13 +32,12 @@ func FromBytes(bytes []byte) (inputs *Inputs, err error, consumedBytes int) {
 	}
 
 	for i := uint32(0); i < inputCount; i++ {
-		addressBytes, readErr := marshalUtil.ReadBytes(address.Length)
-		if readErr != nil {
-			err = readErr
+		readAddress, addressErr := address.Parse(marshalUtil)
+		if addressErr != nil {
+			err = addressErr
 
 			return
 		}
-		readAddress := address.New(addressBytes)
 
 		transferIdBytes, readErr := marshalUtil.ReadBytes(transferid.Length)
 		if readErr != nil {
diff --git a/packages/binary/valuetransfer/payload/transfer/outputs/outputs.go b/packages/binary/valuetransfer/payload/transfer/outputs/outputs.go
index f39268bc68a6fa284b2b2cd7ffdcac0bb36fc86e..d32956f4fd94d848d6e808f4052ea27b1024ccf6 100644
--- a/packages/binary/valuetransfer/payload/transfer/outputs/outputs.go
+++ b/packages/binary/valuetransfer/payload/transfer/outputs/outputs.go
@@ -45,13 +45,12 @@ func FromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *Outputs,
 	// iterate the corresponding times and collect addresses + their details
 	for i := uint32(0); i < addressCount; i++ {
 		// read address
-		addressBytes, addressErr := marshalUtil.ReadBytes(address.Length)
+		address, addressErr := address.Parse(marshalUtil)
 		if addressErr != nil {
 			err = addressErr
 
 			return
 		}
-		address := address.New(addressBytes)
 
 		// read number of balances in the outputs
 		balanceCount, balanceCountErr := marshalUtil.ReadUint32()
@@ -109,7 +108,7 @@ func (outputs *Outputs) Bytes() []byte {
 
 	marshalUtil.WriteUint32(uint32(outputs.Size()))
 	outputs.ForEach(func(address address.Address, balances []*coloredbalance.ColoredBalance) {
-		marshalUtil.WriteBytes(address.ToBytes())
+		marshalUtil.WriteBytes(address.Bytes())
 		marshalUtil.WriteUint32(uint32(len(balances)))
 
 		for _, balance := range balances {
diff --git a/packages/binary/valuetransfer/tangle/tangle_test.go b/packages/binary/valuetransfer/tangle/tangle_test.go
index b271eaa336291fe77c3c2f527365f45af7d20f5d..ccbbea0ad1f4bb84cb3f36eb20a7422695595524 100644
--- a/packages/binary/valuetransfer/tangle/tangle_test.go
+++ b/packages/binary/valuetransfer/tangle/tangle_test.go
@@ -56,7 +56,7 @@ func TestTangle_AttachPayload(t *testing.T) {
 		),
 
 		outputs.New(map[address.Address][]*coloredbalance.ColoredBalance{
-			address.New([]byte("output_address")): {
+			address.Random(): {
 				coloredbalance.New(color.IOTA, 1337),
 			},
 		}),
diff --git a/packages/binary/valuetransfer/test/payload_test.go b/packages/binary/valuetransfer/test/payload_test.go
index f5e9f9d1dd5c4eab2378087849de3d7a3dd22aba..dcee4c24f36a1c9214723b297144caae70857301 100644
--- a/packages/binary/valuetransfer/test/payload_test.go
+++ b/packages/binary/valuetransfer/test/payload_test.go
@@ -27,13 +27,13 @@ func ExamplePayload() {
 	valueTransfer := transfer.New(
 		// inputs
 		inputs.New(
-			transferoutputid.New(address.New([]byte("input_address1")), transferid.New([]byte("transfer1"))),
-			transferoutputid.New(address.New([]byte("input_address2")), transferid.New([]byte("transfer2"))),
+			transferoutputid.New(address.Random(), transferid.New([]byte("transfer1"))),
+			transferoutputid.New(address.Random(), transferid.New([]byte("transfer2"))),
 		),
 
 		// outputs
 		outputs.New(map[address.Address][]*coloredbalance.ColoredBalance{
-			address.New([]byte("output_address")): {
+			address.Random(): {
 				coloredbalance.New(color.IOTA, 1337),
 			},
 		}),
@@ -89,7 +89,7 @@ func TestPayload(t *testing.T) {
 			),
 
 			outputs.New(map[address.Address][]*coloredbalance.ColoredBalance{
-				address.New([]byte("output_address")): {
+				address.Random(): {
 					coloredbalance.New(color.IOTA, 1337),
 				},
 			}),
diff --git a/packages/binary/valuetransfer/transferoutput/id/id.go b/packages/binary/valuetransfer/transferoutput/id/id.go
index b43b9491f95eb98c78a9e4748891d662e0f64889..b8d9252e1267b0ab99387053ce1d6b76b35bee5f 100644
--- a/packages/binary/valuetransfer/transferoutput/id/id.go
+++ b/packages/binary/valuetransfer/transferoutput/id/id.go
@@ -3,15 +3,15 @@ package id
 import (
 	"github.com/mr-tron/base58"
 
-	address2 "github.com/iotaledger/goshimmer/packages/binary/valuetransfer/address"
-	id2 "github.com/iotaledger/goshimmer/packages/binary/valuetransfer/payload/transfer/id"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfer/address"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfer/payload/transfer/id"
 )
 
 type Id [Length]byte
 
-func New(outputAddress address2.Address, transferId id2.Id) (transferOutputId Id) {
-	copy(transferOutputId[:address2.Length], outputAddress.ToBytes())
-	copy(transferOutputId[address2.Length:], transferId[:])
+func New(outputAddress address.Address, transferId id.Id) (transferOutputId Id) {
+	copy(transferOutputId[:address.Length], outputAddress.Bytes())
+	copy(transferOutputId[address.Length:], transferId[:])
 
 	return
 }
@@ -22,12 +22,14 @@ func FromBytes(bytes []byte) (transferOutputId Id) {
 	return
 }
 
-func (transferOutputId Id) GetAddress() address2.Address {
-	return address2.New(transferOutputId[:address2.Length])
+func (transferOutputId Id) GetAddress() (address address.Address) {
+	copy(address[:], transferOutputId[:])
+
+	return
 }
 
-func (transferOutputId Id) GetTransferId() id2.Id {
-	return id2.New(transferOutputId[address2.Length:])
+func (transferOutputId Id) GetTransferId() id.Id {
+	return id.New(transferOutputId[address.Length:])
 }
 
 func (transferOutputId Id) ToBytes() []byte {
@@ -38,4 +40,4 @@ func (transferOutputId Id) String() string {
 	return "Id(" + base58.Encode(transferOutputId[:]) + ")"
 }
 
-const Length = address2.Length + id2.Length
+const Length = address.Length + id.Length
diff --git a/packages/binary/valuetransfer/transferoutput/transferoutput.go b/packages/binary/valuetransfer/transferoutput/transferoutput.go
new file mode 100644
index 0000000000000000000000000000000000000000..b2808491ba8f9959dfc25e39444d102aaabafd7e
--- /dev/null
+++ b/packages/binary/valuetransfer/transferoutput/transferoutput.go
@@ -0,0 +1,127 @@
+package transferoutput
+
+import (
+	"fmt"
+
+	"github.com/iotaledger/hive.go/objectstorage"
+
+	"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfer/address"
+	"github.com/iotaledger/goshimmer/packages/binary/valuetransfer/coloredbalance"
+	transferId "github.com/iotaledger/goshimmer/packages/binary/valuetransfer/payload/transfer/id"
+)
+
+// TransferOutput represents the output of a transfer and it contains the balances and the identifiers for this output.
+type TransferOutput struct {
+	address    address.Address
+	transferId transferId.Id
+	balances   []*coloredbalance.ColoredBalance
+
+	objectstorage.StorableObjectFlags
+	storageKey []byte
+}
+
+// New creates a transfer output that contains the balances and identifiers of a successful transfer.
+func New(address address.Address, transferId transferId.Id, balances []*coloredbalance.ColoredBalance) *TransferOutput {
+	return &TransferOutput{
+		address:    address,
+		transferId: transferId,
+		balances:   balances,
+
+		storageKey: marshalutil.New().WriteBytes(address.Bytes()).WriteBytes(transferId.Bytes()).Bytes(),
+	}
+}
+
+// FromStorage get's called when we restore a TransferOutput from the storage.
+// In contrast to other database models, it unmarshals some information from the key so we simply store the key before
+// it gets handed over to UnmarshalBinary (by the ObjectStorage).
+func FromStorage(keyBytes []byte) objectstorage.StorableObject {
+	return &TransferOutput{
+		storageKey: marshalutil.New(keyBytes).Bytes(true),
+	}
+}
+
+// Address returns the address that this output belongs to.
+func (transferOutput *TransferOutput) Address() address.Address {
+	return transferOutput.address
+}
+
+// TransferId returns the transfer id, that created this output.
+func (transferOutput *TransferOutput) TransferId() transferId.Id {
+	return transferOutput.transferId
+}
+
+// Balances returns the colored balances (color + balance) that this output contains.
+func (transferOutput *TransferOutput) Balances() []*coloredbalance.ColoredBalance {
+	return transferOutput.balances
+}
+
+// MarshalBinary marshals the balances into a sequence of bytes - the address and transferId are stored inside the key
+// and are ignored here.
+func (transferOutput *TransferOutput) MarshalBinary() (data []byte, err error) {
+	// determine amount of balances in the output
+	balanceCount := len(transferOutput.balances)
+
+	// initialize helper
+	marshalUtil := marshalutil.New(4 + balanceCount*coloredbalance.Length)
+
+	// marshal the amount of balances
+	marshalUtil.WriteUint32(uint32(balanceCount))
+
+	// marshal balances
+	for _, balance := range transferOutput.balances {
+		marshalUtil.WriteBytes(balance.Bytes())
+	}
+
+	return
+}
+
+// UnmarshalBinary restores a TransferOutput from a serialized version in the ObjectStorage with parts of the object
+// being stored in its key rather than the content of the database to reduce storage requirements.
+func (transferOutput *TransferOutput) UnmarshalBinary(data []byte) (err error) {
+	// check if the storageKey has been set
+	if transferOutput.storageKey == nil {
+		return fmt.Errorf("missing storageKey when trying to unmarshal TransferOutput (it contains part of the information)")
+	}
+
+	// parse information from storageKey
+	storageKeyUnmarshaler := marshalutil.New(transferOutput.storageKey)
+	transferOutput.address, err = address.Parse(storageKeyUnmarshaler)
+	if err != nil {
+		return
+	}
+	transferOutput.transferId, err = transferId.Parse(storageKeyUnmarshaler)
+	if err != nil {
+		return
+	}
+
+	// parse information from content bytes
+	contentUnmarshaler := marshalutil.New(data)
+	balanceCount, err := contentUnmarshaler.ReadUint32()
+	if err != nil {
+		return
+	}
+	transferOutput.balances = make([]*coloredbalance.ColoredBalance, balanceCount)
+	for i := uint32(0); i < balanceCount; i++ {
+		transferOutput.balances[i], err = coloredbalance.Parse(contentUnmarshaler)
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+// Update is disabled and panics if it ever gets called - it is required to match StorableObject interface.
+func (transferOutput *TransferOutput) Update(other objectstorage.StorableObject) {
+	panic("this object should never be updated")
+}
+
+// GetStorageKey returns the key that is used to store the object in the database.
+// It is required to match StorableObject interface.
+func (transferOutput *TransferOutput) GetStorageKey() []byte {
+	return transferOutput.storageKey
+}
+
+// define contract (ensure that the struct fulfills the given interface)
+var _ objectstorage.StorableObject = &TransferOutput{}
diff --git a/packages/binary/valuetransfer/transferoutput/transferoutput_test.go b/packages/binary/valuetransfer/transferoutput/transferoutput_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..c7614b3bf67b4d52bd06c6154b100cd2b6385cae
--- /dev/null
+++ b/packages/binary/valuetransfer/transferoutput/transferoutput_test.go
@@ -0,0 +1,9 @@
+package transferoutput
+
+import (
+	"testing"
+)
+
+func TestNew(t *testing.T) {
+
+}