diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index de3a7232263616767d8cd0e8a18af75eeab55de4..608d4a9ec6ae9753121f63b499fa49157b51d2d9 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -19,7 +19,7 @@ jobs:
 
       - name: Pull additional Docker images
         run: |
-          docker pull angelocapossele/drand:1.1.1
+          docker pull angelocapossele/drand:1.1.3
           docker pull gaiaadm/pumba:0.7.2
           docker pull gaiadocker/iproute2:latest
 
@@ -54,7 +54,7 @@ jobs:
 
       - name: Pull additional Docker images
         run: |
-          docker pull angelocapossele/drand:1.1.1
+          docker pull angelocapossele/drand:1.1.3
           docker pull gaiaadm/pumba:0.7.2
           docker pull gaiadocker/iproute2:latest
 
@@ -88,7 +88,7 @@ jobs:
 
       - name: Pull additional Docker images
         run: |
-          docker pull angelocapossele/drand:1.1.1
+          docker pull angelocapossele/drand:1.1.3
           docker pull gaiaadm/pumba:0.7.2
           docker pull gaiadocker/iproute2:latest
 
@@ -123,7 +123,7 @@ jobs:
 
       - name: Pull additional Docker images
         run: |
-          docker pull angelocapossele/drand:1.1.1
+          docker pull angelocapossele/drand:1.1.3
           docker pull gaiaadm/pumba:0.7.2
           docker pull gaiadocker/iproute2:latest
 
@@ -159,7 +159,7 @@ jobs:
 
       - name: Pull additional Docker images
         run: |
-          docker pull angelocapossele/drand:1.1.1
+          docker pull angelocapossele/drand:1.1.3
           docker pull gaiaadm/pumba:0.7.2
           docker pull gaiadocker/iproute2:latest
 
@@ -195,7 +195,7 @@ jobs:
 
       - name: Pull additional Docker images
         run: |
-          docker pull angelocapossele/drand:1.1.1
+          docker pull angelocapossele/drand:1.1.3
           docker pull gaiaadm/pumba:latest
           docker pull gaiadocker/iproute2:latest
 
@@ -229,7 +229,7 @@ jobs:
 
       - name: Pull additional Docker images
         run: |
-          docker pull angelocapossele/drand:1.1.1
+          docker pull angelocapossele/drand:1.1.3
           docker pull gaiaadm/pumba:latest
           docker pull gaiadocker/iproute2:latest
 
@@ -263,7 +263,7 @@ jobs:
 
       - name: Pull additional Docker images
         run: |
-          docker pull angelocapossele/drand:1.1.1
+          docker pull angelocapossele/drand:1.1.3
           docker pull gaiaadm/pumba:latest
           docker pull gaiadocker/iproute2:latest
 
diff --git a/dapps/faucet/packages/payload/payload.go b/dapps/faucet/packages/payload/payload.go
index 6e6e0a9659008a420acdfd077f04447a3c0c9a61..a949f043ade356dac8521ab71f974895af4ab9e8 100644
--- a/dapps/faucet/packages/payload/payload.go
+++ b/dapps/faucet/packages/payload/payload.go
@@ -50,31 +50,22 @@ func New(addr address.Address, powTarget int) (*Payload, error) {
 }
 
 func init() {
-	payload.RegisterType(Type, ObjectName, GenericPayloadUnmarshalerFactory(Type))
+	payload.RegisterType(Type, ObjectName, PayloadUnmarshaler)
 }
 
 // FromBytes parses the marshaled version of a Payload into an object.
 // It either returns a new Payload or fills an optionally provided Payload with the parsed information.
-func FromBytes(bytes []byte, optionalTargetObject ...*Payload) (result *Payload, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Payload{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to FromBytes")
-	}
-
+func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) {
 	// initialize helper
 	marshalUtil := marshalutil.New(bytes)
 
 	// read data
-	result.payloadType, err = marshalUtil.ReadUint32()
-	if err != nil {
+	result = &Payload{}
+	if _, err = marshalUtil.ReadUint32(); err != nil {
 		return
 	}
-	if _, err = marshalUtil.ReadUint32(); err != nil {
+	result.payloadType, err = marshalUtil.ReadUint32()
+	if err != nil {
 		return
 	}
 	addr, err := marshalUtil.ReadBytes(address.Length)
@@ -113,8 +104,8 @@ func (faucetPayload *Payload) Bytes() []byte {
 	marshalUtil := marshalutil.New()
 
 	// marshal the payload specific information
-	marshalUtil.WriteUint32(faucetPayload.Type())
 	marshalUtil.WriteUint32(uint32(address.Length + pow.NonceBytes))
+	marshalUtil.WriteUint32(faucetPayload.Type())
 	marshalUtil.WriteBytes(faucetPayload.address.Bytes())
 	marshalUtil.WriteUint64(faucetPayload.nonce)
 
@@ -122,13 +113,6 @@ func (faucetPayload *Payload) Bytes() []byte {
 	return marshalUtil.Bytes()
 }
 
-// Unmarshal unmarshals a given slice of bytes and fills the object.
-func (faucetPayload *Payload) Unmarshal(data []byte) (err error) {
-	_, _, err = FromBytes(data, faucetPayload)
-
-	return
-}
-
 // String returns a human readable version of faucet payload (for debug purposes).
 func (faucetPayload *Payload) String() string {
 	return stringify.Struct("FaucetPayload",
@@ -136,16 +120,11 @@ func (faucetPayload *Payload) String() string {
 	)
 }
 
-// GenericPayloadUnmarshalerFactory sets the generic unmarshaler.
-func GenericPayloadUnmarshalerFactory(payloadType payload.Type) payload.Unmarshaler {
-	return func(data []byte) (payload payload.Payload, err error) {
-		payload = &Payload{
-			payloadType: payloadType,
-		}
-		err = payload.Unmarshal(data)
+// PayloadUnmarshaler sets the generic unmarshaler.
+func PayloadUnmarshaler(data []byte) (payload payload.Payload, err error) {
+	payload, _, err = FromBytes(data)
 
-		return
-	}
+	return
 }
 
 // IsFaucetReq checks if the message is faucet payload.
diff --git a/dapps/networkdelay/object.go b/dapps/networkdelay/object.go
index 40e45947dddddc662c292e6ec006e59920731f86..99464032fcc1de789379f205f3d1f4e1a1847bf7 100644
--- a/dapps/networkdelay/object.go
+++ b/dapps/networkdelay/object.go
@@ -41,26 +41,16 @@ func NewObject(id ID, sentTime int64) *Object {
 
 // FromBytes parses the marshaled version of an Object into a Go object.
 // It either returns a new Object or fills an optionally provided Object with the parsed information.
-func FromBytes(bytes []byte, optionalTargetObject ...*Object) (result *Object, consumedBytes int, err error) {
+func FromBytes(bytes []byte) (result *Object, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = Parse(marshalUtil, optionalTargetObject...)
+	result, err = Parse(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
 // Parse unmarshals an Object using the given marshalUtil (for easier marshaling/unmarshaling).
-func Parse(marshalUtil *marshalutil.MarshalUtil, optionalTarget ...*Object) (result *Object, err error) {
-	// determine the target that will hold the unmarshaled information
-	switch len(optionalTarget) {
-	case 0:
-		result = &Object{}
-	case 1:
-		result = optionalTarget[0]
-	default:
-		panic("too many arguments in call to FromBytes")
-	}
-
+func Parse(marshalUtil *marshalutil.MarshalUtil) (result *Object, err error) {
 	// read information that are required to identify the object from the outside
 	if _, err = marshalUtil.ReadUint32(); err != nil {
 		return
@@ -70,6 +60,7 @@ func Parse(marshalUtil *marshalutil.MarshalUtil, optionalTarget ...*Object) (res
 	}
 
 	// parse id
+	result = &Object{}
 	id, err := marshalUtil.ReadBytes(32)
 	if err != nil {
 		return
@@ -114,8 +105,8 @@ func (o *Object) Bytes() (bytes []byte) {
 	marshalUtil := marshalutil.New(marshalutil.UINT32_SIZE + marshalutil.UINT32_SIZE + objectLength)
 
 	// marshal the payload specific information
-	marshalUtil.WriteUint32(Type)
 	marshalUtil.WriteUint32(uint32(objectLength))
+	marshalUtil.WriteUint32(Type)
 	marshalUtil.WriteBytes(o.id[:])
 	marshalUtil.WriteInt64(o.sentTime)
 
@@ -142,17 +133,9 @@ func (o *Object) Type() payload.Type {
 	return Type
 }
 
-// Unmarshal unmarshals the payload from the given bytes.
-func (o *Object) Unmarshal(data []byte) (err error) {
-	_, _, err = FromBytes(data, o)
-
-	return
-}
-
 func init() {
 	payload.RegisterType(Type, ObjectName, func(data []byte) (payload payload.Payload, err error) {
-		payload = &Object{}
-		err = payload.Unmarshal(data)
+		payload, _, err = FromBytes(data)
 
 		return
 	})
diff --git a/dapps/valuetransfers/packages/branchmanager/branch.go b/dapps/valuetransfers/packages/branchmanager/branch.go
index 7ccf9b0cc161bb01d44dabd323af3d212a8530de..1fce39bf6944f1e5a581ab6c13499fd277011bc3 100644
--- a/dapps/valuetransfers/packages/branchmanager/branch.go
+++ b/dapps/valuetransfers/packages/branchmanager/branch.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"sync"
 
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 	"github.com/iotaledger/hive.go/stringify"
@@ -43,54 +44,62 @@ func NewBranch(id BranchID, parentBranches []BranchID) *Branch {
 	}
 }
 
-// BranchFromStorageKey is a factory method that creates a new Branch instance from a storage key of the objectstorage.
-// It is used by the objectstorage, to create new instances of this entity.
-func BranchFromStorageKey(key []byte, optionalTargetObject ...*Branch) (result *Branch, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Branch{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to BranchFromStorageKey")
-	}
-
-	// parse information
-	marshalUtil := marshalutil.New(key)
-	result.id, err = ParseBranchID(marshalUtil)
-	if err != nil {
-		return
-	}
+// BranchFromBytes unmarshals a Branch from a sequence of bytes.
+func BranchFromBytes(bytes []byte) (result *Branch, consumedBytes int, err error) {
+	marshalUtil := marshalutil.New(bytes)
+	result, err = ParseBranch(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
-// BranchFromBytes unmarshals a Branch from a sequence of bytes.
-func BranchFromBytes(bytes []byte, optionalTargetObject ...*Branch) (result *Branch, consumedBytes int, err error) {
-	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseBranch(marshalUtil, optionalTargetObject...)
-	consumedBytes = marshalUtil.ReadOffset()
+// BranchFromObjectStorage is a factory method that creates a new Branch instance from the ObjectStorage.
+func BranchFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	if result, _, err = BranchFromBytes(byteutils.ConcatBytes(key, data)); err != nil {
+		return
+	}
 
 	return
 }
 
 // ParseBranch unmarshals a Branch using the given marshalUtil (for easier marshaling/unmarshaling).
-func ParseBranch(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*Branch) (result *Branch, err error) {
-	parsedObject, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return BranchFromStorageKey(data, optionalTargetObject...)
-	})
+func ParseBranch(marshalUtil *marshalutil.MarshalUtil) (result *Branch, err error) {
+	result = &Branch{}
+
+	if result.id, err = ParseBranchID(marshalUtil); err != nil {
+		return
+	}
+	result.preferred, err = marshalUtil.ReadBool()
 	if err != nil {
 		return
 	}
-
-	result = parsedObject.(*Branch)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	result.liked, err = marshalUtil.ReadBool()
+	if err != nil {
+		return
+	}
+	result.finalized, err = marshalUtil.ReadBool()
+	if err != nil {
+		return
+	}
+	result.confirmed, err = marshalUtil.ReadBool()
+	if err != nil {
+		return
+	}
+	result.rejected, err = marshalUtil.ReadBool()
+	if err != nil {
+		return
+	}
+	parentBranchCount, err := marshalUtil.ReadUint32()
+	if err != nil {
 		return
-	})
+	}
+	result.parentBranches = make([]BranchID, parentBranchCount)
+	for i := uint32(0); i < parentBranchCount; i++ {
+		result.parentBranches[i], err = ParseBranchID(marshalUtil)
+		if err != nil {
+			return
+		}
+	}
 
 	return
 }
@@ -403,45 +412,6 @@ func (branch *Branch) ObjectStorageValue() []byte {
 	return marshalUtil.Bytes()
 }
 
-// UnmarshalObjectStorageValue unmarshals the bytes that are stored in the value of the objectstorage.
-func (branch *Branch) UnmarshalObjectStorageValue(valueBytes []byte) (consumedBytes int, err error) {
-	marshalUtil := marshalutil.New(valueBytes)
-	branch.preferred, err = marshalUtil.ReadBool()
-	if err != nil {
-		return
-	}
-	branch.liked, err = marshalUtil.ReadBool()
-	if err != nil {
-		return
-	}
-	branch.finalized, err = marshalUtil.ReadBool()
-	if err != nil {
-		return
-	}
-	branch.confirmed, err = marshalUtil.ReadBool()
-	if err != nil {
-		return
-	}
-	branch.rejected, err = marshalUtil.ReadBool()
-	if err != nil {
-		return
-	}
-	parentBranchCount, err := marshalUtil.ReadUint32()
-	if err != nil {
-		return
-	}
-	branch.parentBranches = make([]BranchID, parentBranchCount)
-	for i := uint32(0); i < parentBranchCount; i++ {
-		branch.parentBranches[i], err = ParseBranchID(marshalUtil)
-		if err != nil {
-			return
-		}
-	}
-	consumedBytes = marshalUtil.ReadOffset()
-
-	return
-}
-
 // CachedBranch is a wrapper for the generic CachedObject returned by the objectstorage, that overrides the accessor
 // methods, with a type-casted one.
 type CachedBranch struct {
diff --git a/dapps/valuetransfers/packages/branchmanager/branchmanager.go b/dapps/valuetransfers/packages/branchmanager/branchmanager.go
index 3e58994b5abebb8d20cdafe5505dd348e1d8a30f..80cbd55d33a8b5d3eb2dbee0731066845bdc6c34 100644
--- a/dapps/valuetransfers/packages/branchmanager/branchmanager.go
+++ b/dapps/valuetransfers/packages/branchmanager/branchmanager.go
@@ -43,10 +43,10 @@ func New(store kvstore.KVStore) (branchManager *BranchManager) {
 	osFactory := objectstorage.NewFactory(store, storageprefix.ValueTransfers)
 
 	branchManager = &BranchManager{
-		branchStorage:         osFactory.New(osBranch, osBranchFactory, osBranchOptions...),
-		childBranchStorage:    osFactory.New(osChildBranch, osChildBranchFactory, osChildBranchOptions...),
-		conflictStorage:       osFactory.New(osConflict, osConflictFactory, osConflictOptions...),
-		conflictMemberStorage: osFactory.New(osConflictMember, osConflictMemberFactory, osConflictMemberOptions...),
+		branchStorage:         osFactory.New(osBranch, BranchFromObjectStorage, osBranchOptions...),
+		childBranchStorage:    osFactory.New(osChildBranch, ChildBranchFromObjectStorage, osChildBranchOptions...),
+		conflictStorage:       osFactory.New(osConflict, ConflictFromObjectStorage, osConflictOptions...),
+		conflictMemberStorage: osFactory.New(osConflictMember, ConflictMemberFromObjectStorage, osConflictMemberOptions...),
 		Events:                newEvents(),
 	}
 	branchManager.init()
diff --git a/dapps/valuetransfers/packages/branchmanager/child_branch.go b/dapps/valuetransfers/packages/branchmanager/child_branch.go
index 10c1bfbf00cd146e93b31a3c7235d905e964d608..4f4d0504947f3717e82aa79be97a90bd3be0240c 100644
--- a/dapps/valuetransfers/packages/branchmanager/child_branch.go
+++ b/dapps/valuetransfers/packages/branchmanager/child_branch.go
@@ -1,6 +1,7 @@
 package branchmanager
 
 import (
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 )
@@ -24,57 +25,34 @@ func NewChildBranch(parentID BranchID, childID BranchID) *ChildBranch {
 }
 
 // ChildBranchFromBytes unmarshals a ChildBranch from a sequence of bytes.
-func ChildBranchFromBytes(bytes []byte, optionalTargetObject ...*ChildBranch) (result *ChildBranch, consumedBytes int, err error) {
+func ChildBranchFromBytes(bytes []byte) (result *ChildBranch, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseChildBranch(marshalUtil, optionalTargetObject...)
+	result, err = ParseChildBranch(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
-// ChildBranchFromStorageKey is a factory method that creates a new ChildBranch instance from a storage key of the
+// ChildBranchFromObjectStorage is a factory method that creates a new ChildBranch instance from a storage key of the
 // objectstorage. It is used by the objectstorage, to create new instances of this entity.
-func ChildBranchFromStorageKey(key []byte, optionalTargetObject ...*ChildBranch) (result *ChildBranch, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &ChildBranch{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to ChildBranchFromStorageKey")
-	}
-
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(key)
-	if result.parentID, err = ParseBranchID(marshalUtil); err != nil {
+func ChildBranchFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	if result, _, err = ChildBranchFromBytes(byteutils.ConcatBytes(key, data)); err != nil {
 		return
 	}
-	if result.childID, err = ParseBranchID(marshalUtil); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
 // ParseChildBranch unmarshals a ChildBranch using the given marshalUtil (for easier marshaling/unmarshaling).
-func ParseChildBranch(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*ChildBranch) (result *ChildBranch, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return ChildBranchFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
+func ParseChildBranch(marshalUtil *marshalutil.MarshalUtil) (result *ChildBranch, err error) {
+	result = &ChildBranch{}
 
+	if result.parentID, err = ParseBranchID(marshalUtil); err != nil {
 		return
 	}
-
-	result = parsedObject.(*ChildBranch)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.childID, err = ParseBranchID(marshalUtil); err != nil {
 		return
-	})
+	}
 
 	return
 }
@@ -89,6 +67,11 @@ func (childBranch *ChildBranch) ChildID() BranchID {
 	return childBranch.childID
 }
 
+// Bytes returns a marshaled version of this ChildBranch.
+func (childBranch *ChildBranch) Bytes() []byte {
+	return childBranch.ObjectStorageKey()
+}
+
 // ObjectStorageKey returns the bytes that are used a key when storing the Branch in an objectstorage.
 func (childBranch ChildBranch) ObjectStorageKey() []byte {
 	return marshalutil.New(ConflictIDLength + BranchIDLength).
@@ -103,12 +86,6 @@ func (childBranch ChildBranch) ObjectStorageValue() []byte {
 	return nil
 }
 
-// UnmarshalObjectStorageValue returns the bytes that represent all remaining information (not stored in the key) of a
-// marshaled Branch.
-func (childBranch ChildBranch) UnmarshalObjectStorageValue([]byte) (consumedBytes int, err error) {
-	return
-}
-
 // Update is disabled but needs to be implemented to be compatible with the objectstorage.
 func (childBranch ChildBranch) Update(objectstorage.StorableObject) {
 	panic("updates are disabled - use the setters")
diff --git a/dapps/valuetransfers/packages/branchmanager/conflict.go b/dapps/valuetransfers/packages/branchmanager/conflict.go
index f717aea91778b64868a59141ff562d45765226d0..304c78fcd57df73d49af443488e5146f352e7c5d 100644
--- a/dapps/valuetransfers/packages/branchmanager/conflict.go
+++ b/dapps/valuetransfers/packages/branchmanager/conflict.go
@@ -3,6 +3,7 @@ package branchmanager
 import (
 	"sync"
 
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 	"github.com/iotaledger/hive.go/stringify"
@@ -26,54 +27,33 @@ func NewConflict(id ConflictID) *Conflict {
 }
 
 // ConflictFromBytes unmarshals a Conflict from a sequence of bytes.
-func ConflictFromBytes(bytes []byte, optionalTargetObject ...*Conflict) (result *Conflict, consumedBytes int, err error) {
+func ConflictFromBytes(bytes []byte) (result *Conflict, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseConflict(marshalUtil, optionalTargetObject...)
+	result, err = ParseConflict(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
-// ConflictFromStorageKey is a factory method that creates a new Conflict instance from a storage key of the
-// objectstorage. It is used by the objectstorage, to create new instances of this entity.
-func ConflictFromStorageKey(key []byte, optionalTargetObject ...*Conflict) (result *Conflict, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Conflict{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to ConflictFromStorageKey")
-	}
-
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(key)
-	if result.id, err = ParseConflictID(marshalUtil); err != nil {
+// ConflictFromObjectStorage is a factory method that creates a new Conflict instance from the ObjectStorage.
+func ConflictFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	if result, _, err = ConflictFromBytes(byteutils.ConcatBytes(key, data)); err != nil {
 		return
 	}
-	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
 // ParseConflict unmarshals a Conflict using the given marshalUtil (for easier marshaling/unmarshaling).
-func ParseConflict(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*Conflict) (result *Conflict, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return ConflictFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
+func ParseConflict(marshalUtil *marshalutil.MarshalUtil) (result *Conflict, err error) {
+	result = &Conflict{}
 
+	if result.id, err = ParseConflictID(marshalUtil); err != nil {
 		return
 	}
-
-	result = parsedObject.(*Conflict)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.memberCount, err = marshalUtil.ReadUint32(); err != nil {
 		return
-	})
+	}
 
 	return
 }
@@ -126,10 +106,7 @@ func (conflict *Conflict) DecreaseMemberCount(optionalDelta ...int) (newMemberCo
 
 // Bytes returns a marshaled version of this Conflict.
 func (conflict *Conflict) Bytes() []byte {
-	return marshalutil.New().
-		WriteBytes(conflict.ObjectStorageKey()).
-		WriteBytes(conflict.ObjectStorageValue()).
-		Bytes()
+	return byteutils.ConcatBytes(conflict.ObjectStorageKey(), conflict.ObjectStorageValue())
 }
 
 // String returns a human readable version of this Conflict (for debug purposes).
@@ -153,18 +130,6 @@ func (conflict *Conflict) ObjectStorageValue() []byte {
 		Bytes()
 }
 
-// UnmarshalObjectStorageValue unmarshals the bytes that are stored in the value of the objectstorage.
-func (conflict *Conflict) UnmarshalObjectStorageValue(valueBytes []byte) (consumedBytes int, err error) {
-	marshalUtil := marshalutil.New(valueBytes)
-	conflict.memberCount, err = marshalUtil.ReadUint32()
-	if err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
-
-	return
-}
-
 // Update is disabled but needs to be implemented to be compatible with the objectstorage.
 func (conflict *Conflict) Update(other objectstorage.StorableObject) {
 	panic("updates are disabled - use the setters")
diff --git a/dapps/valuetransfers/packages/branchmanager/conflict_member.go b/dapps/valuetransfers/packages/branchmanager/conflict_member.go
index 4d7fb663a03e17d478860a88f7e66a5d0b31e827..9e4e45b03c1b408eaef3d65cade392d52b06785e 100644
--- a/dapps/valuetransfers/packages/branchmanager/conflict_member.go
+++ b/dapps/valuetransfers/packages/branchmanager/conflict_member.go
@@ -24,57 +24,32 @@ func NewConflictMember(conflictID ConflictID, branchID BranchID) *ConflictMember
 }
 
 // ConflictMemberFromBytes unmarshals a ConflictMember from a sequence of bytes.
-func ConflictMemberFromBytes(bytes []byte, optionalTargetObject ...*ConflictMember) (result *ConflictMember, consumedBytes int, err error) {
+func ConflictMemberFromBytes(bytes []byte) (result *ConflictMember, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseConflictMember(marshalUtil, optionalTargetObject...)
+	result, err = ParseConflictMember(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
-// ConflictMemberFromStorageKey is a factory method that creates a new ConflictMember instance from a storage key of the
+// ConflictMemberFromObjectStorage is a factory method that creates a new ConflictMember instance from a storage key of the
 // objectstorage. It is used by the objectstorage, to create new instances of this entity.
-func ConflictMemberFromStorageKey(key []byte, optionalTargetObject ...*ConflictMember) (result *ConflictMember, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &ConflictMember{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to ConflictMemberFromStorageKey")
-	}
-
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(key)
-	if result.conflictID, err = ParseConflictID(marshalUtil); err != nil {
-		return
-	}
-	if result.branchID, err = ParseBranchID(marshalUtil); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
+func ConflictMemberFromObjectStorage(key []byte, _ []byte) (result objectstorage.StorableObject, err error) {
+	result, _, err = ConflictMemberFromBytes(key)
 
 	return
 }
 
 // ParseConflictMember unmarshals a ConflictMember using the given marshalUtil (for easier marshaling/unmarshaling).
-func ParseConflictMember(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*ConflictMember) (result *ConflictMember, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return ConflictMemberFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
+func ParseConflictMember(marshalUtil *marshalutil.MarshalUtil) (result *ConflictMember, err error) {
+	result = &ConflictMember{}
 
+	if result.conflictID, err = ParseConflictID(marshalUtil); err != nil {
 		return
 	}
-
-	result = parsedObject.(*ConflictMember)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.branchID, err = ParseBranchID(marshalUtil); err != nil {
 		return
-	})
+	}
 
 	return
 }
@@ -103,12 +78,6 @@ func (conflictMember ConflictMember) ObjectStorageValue() []byte {
 	return nil
 }
 
-// UnmarshalObjectStorageValue returns the bytes that represent all remaining information (not stored in the key) of a
-// marshaled Branch.
-func (conflictMember ConflictMember) UnmarshalObjectStorageValue([]byte) (consumedBytes int, err error) {
-	return
-}
-
 // Update is disabled but needs to be implemented to be compatible with the objectstorage.
 func (conflictMember ConflictMember) Update(other objectstorage.StorableObject) {
 	panic("updates are disabled - use the setters")
diff --git a/dapps/valuetransfers/packages/branchmanager/objectstorage.go b/dapps/valuetransfers/packages/branchmanager/objectstorage.go
index 21cb4d20fba2c40625f3c2864b38c5c4fdbedcb1..bec990418c29bd272deafe79f5ca45b3b36d557c 100644
--- a/dapps/valuetransfers/packages/branchmanager/objectstorage.go
+++ b/dapps/valuetransfers/packages/branchmanager/objectstorage.go
@@ -47,19 +47,3 @@ var (
 		osLeakDetectionOption,
 	}
 )
-
-func osBranchFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return BranchFromStorageKey(key)
-}
-
-func osChildBranchFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return ChildBranchFromStorageKey(key)
-}
-
-func osConflictFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return ConflictFromStorageKey(key)
-}
-
-func osConflictMemberFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return ConflictMemberFromStorageKey(key)
-}
diff --git a/dapps/valuetransfers/packages/payload/payload.go b/dapps/valuetransfers/packages/payload/payload.go
index 118b5b842f2eb28e88c71c8d514a44c0ad12d6c6..4b4c0c0c50d73e49cbd99bd203896b30ac5ce690 100644
--- a/dapps/valuetransfers/packages/payload/payload.go
+++ b/dapps/valuetransfers/packages/payload/payload.go
@@ -1,6 +1,7 @@
 package payload
 
 import (
+	"fmt"
 	"sync"
 
 	"github.com/iotaledger/hive.go/marshalutil"
@@ -43,58 +44,72 @@ func New(parent1PayloadID, parent2PayloadID ID, valueTransfer *transaction.Trans
 
 // FromBytes parses the marshaled version of a Payload into an object.
 // It either returns a new Payload or fills an optionally provided Payload with the parsed information.
-func FromBytes(bytes []byte, optionalTargetObject ...*Payload) (result *Payload, consumedBytes int, err error) {
+func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = Parse(marshalUtil, optionalTargetObject...)
+	result, err = Parse(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
-// FromStorageKey is a factory method that creates a new Payload instance from a storage key of the objectstorage.
-// It is used by the objectstorage, to create new instances of this entity.
-func FromStorageKey(key []byte, optionalTargetObject ...*Payload) (result *Payload, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Payload{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to MissingPayloadFromStorageKey")
+// FromObjectStorage is a factory method that creates a new Payload from the ObjectStorage.
+func FromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	// parse the message
+	parsedPayload, err := Parse(marshalutil.New(data))
+	if err != nil {
+		return
 	}
 
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(key)
-	payloadID, idErr := ParseID(marshalUtil)
-	if idErr != nil {
-		err = idErr
-
+	// parse the ID from they key
+	payloadID, err := ParseID(marshalutil.New(key))
+	if err != nil {
 		return
 	}
-	result.id = &payloadID
-	consumedBytes = marshalUtil.ReadOffset()
+	parsedPayload.id = &payloadID
+
+	// assign result
+	result = parsedPayload
 
 	return
 }
 
 // Parse unmarshals a Payload using the given marshalUtil (for easier marshaling/unmarshaling).
-func Parse(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*Payload) (result *Payload, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Payload{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to Parse")
+func Parse(marshalUtil *marshalutil.MarshalUtil) (result *Payload, err error) {
+	// determine read offset before starting to parse
+	readOffsetStart := marshalUtil.ReadOffset()
+
+	// read information that are required to identify the payload from the outside
+	_, err = marshalUtil.ReadUint32()
+	if err != nil {
+		return
+	}
+	_, err = marshalUtil.ReadUint32()
+	if err != nil {
+		return
 	}
 
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
+	// parse parent1 payload id
+	result = &Payload{}
+	if result.parent1PayloadID, err = ParseID(marshalUtil); err != nil {
+		return
+	}
+	if result.parent2PayloadID, err = ParseID(marshalUtil); err != nil {
+		return
+	}
+	if result.transaction, err = transaction.Parse(marshalUtil); err != nil {
+		return
+	}
+
+	// retrieve the number of bytes we processed
+	readOffsetEnd := marshalUtil.ReadOffset()
+
+	// store marshaled version as a copy
+	result.bytes, err = marshalUtil.ReadBytes(readOffsetEnd-readOffsetStart, readOffsetStart)
+	if err != nil {
+		err = fmt.Errorf("error trying to copy raw source bytes: %w", err)
 
 		return
-	})
+	}
 
 	return
 }
@@ -201,8 +216,8 @@ func (payload *Payload) ObjectStorageValue() (bytes []byte) {
 	// marshal fields
 	payloadLength := IDLength + IDLength + len(transferBytes)
 	marshalUtil := marshalutil.New(marshalutil.UINT32_SIZE + marshalutil.UINT32_SIZE + payloadLength)
-	marshalUtil.WriteUint32(Type)
 	marshalUtil.WriteUint32(uint32(payloadLength))
+	marshalUtil.WriteUint32(Type)
 	marshalUtil.WriteBytes(payload.parent1PayloadID.Bytes())
 	marshalUtil.WriteBytes(payload.parent2PayloadID.Bytes())
 	marshalUtil.WriteBytes(transferBytes)
@@ -214,48 +229,6 @@ func (payload *Payload) ObjectStorageValue() (bytes []byte) {
 	return
 }
 
-// UnmarshalObjectStorageValue unmarshals the bytes that are stored in the value of the objectstorage.
-func (payload *Payload) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	marshalUtil := marshalutil.New(data)
-
-	// read information that are required to identify the payload from the outside
-	_, err = marshalUtil.ReadUint32()
-	if err != nil {
-		return
-	}
-	_, err = marshalUtil.ReadUint32()
-	if err != nil {
-		return
-	}
-
-	// parse parent1 payload id
-	if payload.parent1PayloadID, err = ParseID(marshalUtil); err != nil {
-		return
-	}
-	if payload.parent2PayloadID, err = ParseID(marshalUtil); err != nil {
-		return
-	}
-	if payload.transaction, err = transaction.Parse(marshalUtil); err != nil {
-		return
-	}
-
-	// return the number of bytes we processed
-	consumedBytes = marshalUtil.ReadOffset()
-
-	// store bytes, so we don't have to marshal manually
-	payload.bytes = make([]byte, consumedBytes)
-	copy(payload.bytes, data[:consumedBytes])
-
-	return
-}
-
-// Unmarshal unmarshals a given slice of bytes and fills the object with the.
-func (payload *Payload) Unmarshal(data []byte) (err error) {
-	_, _, err = FromBytes(data, payload)
-
-	return
-}
-
 func init() {
 	payload.RegisterType(Type, ObjectName, func(data []byte) (payload payload.Payload, err error) {
 		payload, _, err = FromBytes(data)
diff --git a/dapps/valuetransfers/packages/tangle/attachment.go b/dapps/valuetransfers/packages/tangle/attachment.go
index e7b41335b57948f0f9eb57bd1585d4831e1a1f69..7fa2b81a3c6828541262984077fb6064e0816366 100644
--- a/dapps/valuetransfers/packages/tangle/attachment.go
+++ b/dapps/valuetransfers/packages/tangle/attachment.go
@@ -3,6 +3,7 @@ package tangle
 import (
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 	"github.com/iotaledger/hive.go/stringify"
@@ -15,8 +16,6 @@ type Attachment struct {
 
 	transactionID transaction.ID
 	payloadID     payload.ID
-
-	storageKey []byte
 }
 
 // NewAttachment creates an attachment object with the given information.
@@ -24,68 +23,36 @@ func NewAttachment(transactionID transaction.ID, payloadID payload.ID) *Attachme
 	return &Attachment{
 		transactionID: transactionID,
 		payloadID:     payloadID,
-
-		storageKey: marshalutil.New(AttachmentLength).
-			WriteBytes(transactionID.Bytes()).
-			WriteBytes(payloadID.Bytes()).
-			Bytes(),
 	}
 }
 
 // AttachmentFromBytes unmarshals an Attachment from a sequence of bytes - it either creates a new object or fills the
 // optionally provided one with the parsed information.
-func AttachmentFromBytes(bytes []byte, optionalTargetObject ...*Attachment) (result *Attachment, consumedBytes int, err error) {
+func AttachmentFromBytes(bytes []byte) (result *Attachment, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseAttachment(marshalUtil, optionalTargetObject...)
+	result, err = ParseAttachment(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
 // ParseAttachment is a wrapper for simplified unmarshaling of Attachments from a byte stream using the marshalUtil package.
-func ParseAttachment(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*Attachment) (result *Attachment, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return AttachmentFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
-
+func ParseAttachment(marshalUtil *marshalutil.MarshalUtil) (result *Attachment, err error) {
+	result = &Attachment{}
+	if result.transactionID, err = transaction.ParseID(marshalUtil); err != nil {
 		return
 	}
-
-	result = parsedObject.(*Attachment)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.payloadID, err = payload.ParseID(marshalUtil); err != nil {
 		return
-	})
+	}
 
 	return
 }
 
-// AttachmentFromStorageKey gets called when we restore an Attachment from the storage - it parses the key bytes and
+// AttachmentFromObjectStorage gets called when we restore an Attachment from the storage - it parses the key bytes and
 // returns the new object.
-func AttachmentFromStorageKey(key []byte, optionalTargetObject ...*Attachment) (result *Attachment, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Attachment{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to AttachmentFromStorageKey")
-	}
-
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(key)
-	if result.transactionID, err = transaction.ParseID(marshalUtil); err != nil {
-		return
-	}
-	if result.payloadID, err = payload.ParseID(marshalUtil); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
-	result.storageKey = marshalutil.New(key[:consumedBytes]).Bytes(true)
+func AttachmentFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	result, _, err = AttachmentFromBytes(byteutils.ConcatBytes(key, data))
 
 	return
 }
@@ -115,7 +82,7 @@ func (attachment *Attachment) String() string {
 
 // ObjectStorageKey returns the key that is used to store the object in the database.
 func (attachment *Attachment) ObjectStorageKey() []byte {
-	return attachment.storageKey
+	return byteutils.ConcatBytes(attachment.transactionID.Bytes(), attachment.payloadID.Bytes())
 }
 
 // ObjectStorageValue marshals the "content part" of an Attachment to a sequence of bytes. Since all of the information
@@ -124,12 +91,6 @@ func (attachment *Attachment) ObjectStorageValue() (data []byte) {
 	return
 }
 
-// UnmarshalObjectStorageValue unmarshals the "content part" of an Attachment from a sequence of bytes. Since all of the information
-// for this object are stored in its key, this method does nothing and is only required to conform with the interface.
-func (attachment *Attachment) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	return
-}
-
 // Update is disabled - updates are supposed to happen through the setters (if existing).
 func (attachment *Attachment) Update(other objectstorage.StorableObject) {
 	panic("update forbidden")
diff --git a/dapps/valuetransfers/packages/tangle/consumer.go b/dapps/valuetransfers/packages/tangle/consumer.go
index 1fdcacb63ae9f3bc7cef6438973bb7e3adf83f79..2afc4099fd18d17aae4dd2fedab6b7b78911828a 100644
--- a/dapps/valuetransfers/packages/tangle/consumer.go
+++ b/dapps/valuetransfers/packages/tangle/consumer.go
@@ -3,6 +3,7 @@ package tangle
 import (
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 	"github.com/iotaledger/hive.go/stringify"
@@ -18,8 +19,6 @@ type Consumer struct {
 
 	consumedInput transaction.OutputID
 	transactionID transaction.ID
-
-	storageKey []byte
 }
 
 // NewConsumer creates a Consumer object with the given information.
@@ -27,68 +26,37 @@ func NewConsumer(consumedInput transaction.OutputID, transactionID transaction.I
 	return &Consumer{
 		consumedInput: consumedInput,
 		transactionID: transactionID,
-
-		storageKey: marshalutil.New(ConsumerLength).
-			WriteBytes(consumedInput.Bytes()).
-			WriteBytes(transactionID.Bytes()).
-			Bytes(),
 	}
 }
 
 // ConsumerFromBytes unmarshals a Consumer from a sequence of bytes - it either creates a new object or fills the
 // optionally provided one with the parsed information.
-func ConsumerFromBytes(bytes []byte, optionalTargetObject ...*Consumer) (result *Consumer, consumedBytes int, err error) {
+func ConsumerFromBytes(bytes []byte) (result *Consumer, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseConsumer(marshalUtil, optionalTargetObject...)
+	result, err = ParseConsumer(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
 // ParseConsumer unmarshals a Consumer using the given marshalUtil (for easier marshaling/unmarshaling).
-func ParseConsumer(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*Consumer) (result *Consumer, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return ConsumerFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
+func ParseConsumer(marshalUtil *marshalutil.MarshalUtil) (result *Consumer, err error) {
+	result = &Consumer{}
 
+	if result.consumedInput, err = transaction.ParseOutputID(marshalUtil); err != nil {
 		return
 	}
-
-	result = parsedObject.(*Consumer)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.transactionID, err = transaction.ParseID(marshalUtil); err != nil {
 		return
-	})
+	}
 
 	return
 }
 
-// ConsumerFromStorageKey is a factory method that creates a new Consumer instance from a storage key of the
+// ConsumerFromObjectStorage is a factory method that creates a new Consumer instance from a storage key of the
 // objectstorage. It is used by the objectstorage, to create new instances of this entity.
-func ConsumerFromStorageKey(key []byte, optionalTargetObject ...*Consumer) (result *Consumer, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Consumer{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to ConsumerFromStorageKey")
-	}
-
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(key)
-	if result.consumedInput, err = transaction.ParseOutputID(marshalUtil); err != nil {
-		return
-	}
-	if result.transactionID, err = transaction.ParseID(marshalUtil); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
-	result.storageKey = marshalutil.New(key[:consumedBytes]).Bytes(true)
+func ConsumerFromObjectStorage(key []byte, _ []byte) (result objectstorage.StorableObject, err error) {
+	result, _, err = ConsumerFromBytes(key)
 
 	return
 }
@@ -118,7 +86,7 @@ func (consumer *Consumer) String() string {
 
 // ObjectStorageKey returns the key that is used to store the object in the database.
 func (consumer *Consumer) ObjectStorageKey() []byte {
-	return consumer.storageKey
+	return byteutils.ConcatBytes(consumer.consumedInput.Bytes(), consumer.transactionID.Bytes())
 }
 
 // ObjectStorageValue marshals the "content part" of an Consumer to a sequence of bytes. Since all of the information for
@@ -127,12 +95,6 @@ func (consumer *Consumer) ObjectStorageValue() (data []byte) {
 	return
 }
 
-// UnmarshalObjectStorageValue unmarshals the "content part" of a Consumer from a sequence of bytes. Since all of the information
-// for this object are stored in its key, this method does nothing and is only required to conform with the interface.
-func (consumer *Consumer) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	return
-}
-
 // Update is disabled - updates are supposed to happen through the setters (if existing).
 func (consumer *Consumer) Update(other objectstorage.StorableObject) {
 	panic("update forbidden")
diff --git a/dapps/valuetransfers/packages/tangle/missingpayload.go b/dapps/valuetransfers/packages/tangle/missingpayload.go
index ebad334e58f6a8c47183ff3d069ed2b3518afa18..075b88b1a0dd693dea2376f70a8590c0f96ac842 100644
--- a/dapps/valuetransfers/packages/tangle/missingpayload.go
+++ b/dapps/valuetransfers/packages/tangle/missingpayload.go
@@ -4,6 +4,7 @@ import (
 	"time"
 
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload"
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 )
@@ -27,54 +28,32 @@ func NewMissingPayload(payloadID payload.ID) *MissingPayload {
 
 // MissingPayloadFromBytes unmarshals an entry for a missing value transfer payload from a sequence of bytes.
 // It either creates a new entry or fills the optionally provided one with the parsed information.
-func MissingPayloadFromBytes(bytes []byte, optionalTargetObject ...*MissingPayload) (result *MissingPayload, consumedBytes int, err error) {
+func MissingPayloadFromBytes(bytes []byte) (result *MissingPayload, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseMissingPayload(marshalUtil, optionalTargetObject...)
+	result, err = ParseMissingPayload(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
 // ParseMissingPayload unmarshals a MissingPayload using the given marshalUtil (for easier marshaling/unmarshaling).
-func ParseMissingPayload(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*MissingPayload) (result *MissingPayload, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return MissingPayloadFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
+func ParseMissingPayload(marshalUtil *marshalutil.MarshalUtil) (result *MissingPayload, err error) {
+	result = &MissingPayload{}
 
+	if result.payloadID, err = payload.ParseID(marshalUtil); err != nil {
 		return
 	}
-
-	result = parsedObject.(*MissingPayload)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.missingSince, err = marshalUtil.ReadTime(); err != nil {
 		return
-	})
+	}
 
 	return
 }
 
-// MissingPayloadFromStorageKey gets called when we restore an entry for a missing value transfer payload from the storage. The bytes and
+// MissingPayloadFromObjectStorage gets called when we restore an entry for a missing value transfer payload from the storage. The bytes and
 // the content will be unmarshaled by an external caller using the binary.ObjectStorageValue interface.
-func MissingPayloadFromStorageKey(key []byte, optionalTargetObject ...*MissingPayload) (result *MissingPayload, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &MissingPayload{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to MissingPayloadFromStorageKey")
-	}
-
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(key)
-	if result.payloadID, err = payload.ParseID(marshalUtil); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
+func MissingPayloadFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	result, _, err = MissingPayloadFromBytes(byteutils.ConcatBytes(key, data))
 
 	return
 }
@@ -91,10 +70,7 @@ func (missingPayload *MissingPayload) MissingSince() time.Time {
 
 // Bytes marshals the missing payload into a sequence of bytes.
 func (missingPayload *MissingPayload) Bytes() []byte {
-	return marshalutil.New(payload.IDLength + marshalutil.TIME_SIZE).
-		WriteBytes(missingPayload.ObjectStorageKey()).
-		WriteBytes(missingPayload.ObjectStorageValue()).
-		Bytes()
+	return byteutils.ConcatBytes(missingPayload.ObjectStorageKey(), missingPayload.ObjectStorageValue())
 }
 
 // Update is disabled and panics if it ever gets called - updates are supposed to happen through the setters.
@@ -116,16 +92,5 @@ func (missingPayload *MissingPayload) ObjectStorageValue() (data []byte) {
 		Bytes()
 }
 
-// UnmarshalObjectStorageValue is required to match the encoding.BinaryUnmarshaler interface.
-func (missingPayload *MissingPayload) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	marshalUtil := marshalutil.New(data)
-	if missingPayload.missingSince, err = marshalUtil.ReadTime(); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
-
-	return
-}
-
 // Interface contract: make compiler warn if the interface is not implemented correctly.
 var _ objectstorage.StorableObject = &MissingPayload{}
diff --git a/dapps/valuetransfers/packages/tangle/objectstorage.go b/dapps/valuetransfers/packages/tangle/objectstorage.go
index 593d041c9831e6a58e6810c7530905b2523c2cdb..294a24d5741b4a1a8a1fd0ca427c2c5e551f13fb 100644
--- a/dapps/valuetransfers/packages/tangle/objectstorage.go
+++ b/dapps/valuetransfers/packages/tangle/objectstorage.go
@@ -3,8 +3,6 @@ package tangle
 import (
 	"time"
 
-	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload"
-	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
 	"github.com/iotaledger/hive.go/objectstorage"
 )
 
@@ -32,39 +30,3 @@ var (
 		MaxConsumerHoldTime:   10 * time.Second,
 	})
 )
-
-func osPayloadFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return payload.FromStorageKey(key)
-}
-
-func osPayloadMetadataFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return PayloadMetadataFromStorageKey(key)
-}
-
-func osMissingPayloadFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return MissingPayloadFromStorageKey(key)
-}
-
-func osPayloadApproverFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return PayloadApproverFromStorageKey(key)
-}
-
-func osTransactionFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return transaction.FromStorageKey(key)
-}
-
-func osTransactionMetadataFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return TransactionMetadataFromStorageKey(key)
-}
-
-func osAttachmentFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return AttachmentFromStorageKey(key)
-}
-
-func osOutputFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return OutputFromStorageKey(key)
-}
-
-func osConsumerFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return ConsumerFromStorageKey(key)
-}
diff --git a/dapps/valuetransfers/packages/tangle/output.go b/dapps/valuetransfers/packages/tangle/output.go
index 4421454ee8b13ef90b3c5302f16121c7e45ec146..dd1f4c4b3cdff90efc619c0c49ef01fd2952ec2d 100644
--- a/dapps/valuetransfers/packages/tangle/output.go
+++ b/dapps/valuetransfers/packages/tangle/output.go
@@ -8,6 +8,7 @@ import (
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/branchmanager"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 	"github.com/iotaledger/hive.go/stringify"
@@ -43,7 +44,6 @@ type Output struct {
 	rejectedMutex           sync.RWMutex
 
 	objectstorage.StorableObjectFlags
-	storageKey []byte
 }
 
 // NewOutput creates an Output that contains the balances and identifiers of a Transaction.
@@ -55,68 +55,81 @@ func NewOutput(address address.Address, transactionID transaction.ID, branchID b
 		solid:              false,
 		solidificationTime: time.Time{},
 		balances:           balances,
-
-		storageKey: marshalutil.New().WriteBytes(address.Bytes()).WriteBytes(transactionID.Bytes()).Bytes(),
 	}
 }
 
 // OutputFromBytes unmarshals an Output object from a sequence of bytes.
 // It either creates a new object or fills the optionally provided object with the parsed information.
-func OutputFromBytes(bytes []byte, optionalTargetObject ...*Output) (result *Output, consumedBytes int, err error) {
+func OutputFromBytes(bytes []byte) (result *Output, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseOutput(marshalUtil, optionalTargetObject...)
+	result, err = ParseOutput(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
 // ParseOutput unmarshals an Output using the given marshalUtil (for easier marshaling/unmarshaling).
-func ParseOutput(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*Output) (result *Output, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return OutputFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
+func ParseOutput(marshalUtil *marshalutil.MarshalUtil) (result *Output, err error) {
+	result = &Output{}
 
+	if result.address, err = address.Parse(marshalUtil); err != nil {
 		return
 	}
-
-	result = parsedObject.(*Output)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.transactionID, err = transaction.ParseID(marshalUtil); err != nil {
 		return
-	})
-
-	return
-}
-
-// OutputFromStorageKey get's called when we restore a Output 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 UnmarshalObjectStorageValue (by the ObjectStorage).
-func OutputFromStorageKey(keyBytes []byte, optionalTargetObject ...*Output) (result *Output, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Output{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to OutputFromStorageKey")
-	}
-
-	// parse information
-	marshalUtil := marshalutil.New(keyBytes)
-	result.address, err = address.Parse(marshalUtil)
+	}
+	if result.branchID, err = branchmanager.ParseBranchID(marshalUtil); err != nil {
+		return
+	}
+	if result.solid, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.solidificationTime, err = marshalUtil.ReadTime(); err != nil {
+		return
+	}
+	if result.firstConsumer, err = transaction.ParseID(marshalUtil); err != nil {
+		return
+	}
+	consumerCount, err := marshalUtil.ReadUint32()
 	if err != nil {
 		return
 	}
-	result.transactionID, err = transaction.ParseID(marshalUtil)
+	if result.preferred, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.finalized, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.liked, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.confirmed, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.rejected, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	result.consumerCount = int(consumerCount)
+	balanceCount, err := marshalUtil.ReadUint32()
 	if err != nil {
 		return
 	}
-	result.storageKey = marshalutil.New(keyBytes[:transaction.OutputIDLength]).Bytes(true)
-	consumedBytes = marshalUtil.ReadOffset()
+	result.balances = make([]*balance.Balance, balanceCount)
+	for i := uint32(0); i < balanceCount; i++ {
+		result.balances[i], err = balance.Parse(marshalUtil)
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+// OutputFromObjectStorage get's called when we restore a Output 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 UnmarshalObjectStorageValue (by the ObjectStorage).
+func OutputFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	result, _, err = OutputFromBytes(byteutils.ConcatBytes(key, data))
 
 	return
 }
@@ -407,19 +420,13 @@ func (output *Output) Balances() []*balance.Balance {
 
 // Bytes marshals the object into a sequence of bytes.
 func (output *Output) Bytes() []byte {
-	return marshalutil.New().
-		WriteBytes(output.ObjectStorageKey()).
-		WriteBytes(output.ObjectStorageValue()).
-		Bytes()
+	return byteutils.ConcatBytes(output.ObjectStorageKey(), output.ObjectStorageValue())
 }
 
 // ObjectStorageKey returns the key that is used to store the object in the database.
 // It is required to match StorableObject interface.
 func (output *Output) ObjectStorageKey() []byte {
-	return marshalutil.New(transaction.OutputIDLength).
-		WriteBytes(output.address.Bytes()).
-		WriteBytes(output.transactionID.Bytes()).
-		Bytes()
+	return byteutils.ConcatBytes(output.address.Bytes(), output.transactionID.Bytes())
 }
 
 // ObjectStorageValue marshals the balances into a sequence of bytes - the address and transaction id are stored inside the key
@@ -449,58 +456,6 @@ func (output *Output) ObjectStorageValue() []byte {
 	return marshalUtil.Bytes()
 }
 
-// UnmarshalObjectStorageValue restores a Output 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 (output *Output) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	marshalUtil := marshalutil.New(data)
-	if output.branchID, err = branchmanager.ParseBranchID(marshalUtil); err != nil {
-		return
-	}
-	if output.solid, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if output.solidificationTime, err = marshalUtil.ReadTime(); err != nil {
-		return
-	}
-	if output.firstConsumer, err = transaction.ParseID(marshalUtil); err != nil {
-		return
-	}
-	consumerCount, err := marshalUtil.ReadUint32()
-	if err != nil {
-		return
-	}
-	if output.preferred, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if output.finalized, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if output.liked, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if output.confirmed, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if output.rejected, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	output.consumerCount = int(consumerCount)
-	balanceCount, err := marshalUtil.ReadUint32()
-	if err != nil {
-		return
-	}
-	output.balances = make([]*balance.Balance, balanceCount)
-	for i := uint32(0); i < balanceCount; i++ {
-		output.balances[i], err = balance.Parse(marshalUtil)
-		if err != nil {
-			return
-		}
-	}
-	consumedBytes = marshalUtil.ReadOffset()
-
-	return
-}
-
 // Update is disabled and panics if it ever gets called - it is required to match StorableObject interface.
 func (output *Output) Update(other objectstorage.StorableObject) {
 	panic("this object should never be updated")
diff --git a/dapps/valuetransfers/packages/tangle/payloadapprover.go b/dapps/valuetransfers/packages/tangle/payloadapprover.go
index 7646395d36d3fe3231ec8159e9ecb0257a39e248..e5f0973a82b0c03fa78551d24d0f418a2c0596d1 100644
--- a/dapps/valuetransfers/packages/tangle/payloadapprover.go
+++ b/dapps/valuetransfers/packages/tangle/payloadapprover.go
@@ -2,6 +2,7 @@ package tangle
 
 import (
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload"
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 )
@@ -12,78 +13,45 @@ import (
 type PayloadApprover struct {
 	objectstorage.StorableObjectFlags
 
-	storageKey          []byte
 	referencedPayloadID payload.ID
 	approvingPayloadID  payload.ID
 }
 
 // NewPayloadApprover creates an approver object that encodes a single relation between an approved and an approving payload.
 func NewPayloadApprover(referencedPayload payload.ID, approvingPayload payload.ID) *PayloadApprover {
-	marshalUtil := marshalutil.New(payload.IDLength + payload.IDLength)
-	marshalUtil.WriteBytes(referencedPayload.Bytes())
-	marshalUtil.WriteBytes(approvingPayload.Bytes())
-
 	return &PayloadApprover{
 		referencedPayloadID: referencedPayload,
 		approvingPayloadID:  approvingPayload,
-		storageKey:          marshalUtil.Bytes(),
 	}
 }
 
 // PayloadApproverFromBytes unmarshals a PayloadApprover from a sequence of bytes.
-func PayloadApproverFromBytes(bytes []byte, optionalTargetObject ...*PayloadApprover) (result *PayloadApprover, consumedBytes int, err error) {
+func PayloadApproverFromBytes(bytes []byte) (result *PayloadApprover, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParsePayloadApprover(marshalUtil, optionalTargetObject...)
+	result, err = ParsePayloadApprover(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
 // ParsePayloadApprover unmarshals a PayloadApprover using the given marshalUtil (for easier marshaling/unmarshaling).
-func ParsePayloadApprover(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*PayloadApprover) (result *PayloadApprover, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return PayloadApproverFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
-
+func ParsePayloadApprover(marshalUtil *marshalutil.MarshalUtil) (result *PayloadApprover, err error) {
+	result = &PayloadApprover{}
+	if result.referencedPayloadID, err = payload.ParseID(marshalUtil); err != nil {
 		return
 	}
-
-	result = parsedObject.(*PayloadApprover)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.approvingPayloadID, err = payload.ParseID(marshalUtil); err != nil {
 		return
-	})
+	}
 
 	return
 }
 
-// PayloadApproverFromStorageKey get's called when we restore transaction metadata from the storage.
+// PayloadApproverFromObjectStorage get's called when we restore transaction metadata from the storage.
 // In contrast to other database models, it unmarshals the information from the key and does not use the UnmarshalObjectStorageValue
 // method.
-func PayloadApproverFromStorageKey(key []byte, optionalTargetObject ...*PayloadApprover) (result *PayloadApprover, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &PayloadApprover{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to PayloadApproverFromStorageKey")
-	}
-
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(key)
-	if result.referencedPayloadID, err = payload.ParseID(marshalUtil); err != nil {
-		return
-	}
-	if result.approvingPayloadID, err = payload.ParseID(marshalUtil); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
-	result.storageKey = marshalutil.New(key[:consumedBytes]).Bytes(true)
+func PayloadApproverFromObjectStorage(key []byte, _ []byte) (result objectstorage.StorableObject, err error) {
+	result, _, err = PayloadMetadataFromBytes(key)
 
 	return
 }
@@ -96,7 +64,7 @@ func (payloadApprover *PayloadApprover) ApprovingPayloadID() payload.ID {
 // ObjectStorageKey returns the key that is used to store the object in the database.
 // It is required to match StorableObject interface.
 func (payloadApprover *PayloadApprover) ObjectStorageKey() []byte {
-	return payloadApprover.storageKey
+	return byteutils.ConcatBytes(payloadApprover.referencedPayloadID.Bytes(), payloadApprover.approvingPayloadID.Bytes())
 }
 
 // ObjectStorageValue is implemented to conform with the StorableObject interface, but it does not really do anything,
@@ -105,12 +73,6 @@ func (payloadApprover *PayloadApprover) ObjectStorageValue() (data []byte) {
 	return
 }
 
-// UnmarshalObjectStorageValue is implemented to conform with the StorableObject interface, but it does not really do
-// anything, since all of the information about an approver are stored in the "key".
-func (payloadApprover *PayloadApprover) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	return
-}
-
 // Update is disabled and panics if it ever gets called - updates are supposed to happen through the setters.
 // It is required to match StorableObject interface.
 func (payloadApprover *PayloadApprover) Update(other objectstorage.StorableObject) {
diff --git a/dapps/valuetransfers/packages/tangle/payloadmetadata.go b/dapps/valuetransfers/packages/tangle/payloadmetadata.go
index be575207930db9ff5107719e43e1c623400dace3..dc7b1fb86366b3f8b034c0e6a710f9f7a0c90f2e 100644
--- a/dapps/valuetransfers/packages/tangle/payloadmetadata.go
+++ b/dapps/valuetransfers/packages/tangle/payloadmetadata.go
@@ -4,6 +4,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 	"github.com/iotaledger/hive.go/stringify"
@@ -42,54 +43,46 @@ func NewPayloadMetadata(payloadID payload.ID) *PayloadMetadata {
 
 // PayloadMetadataFromBytes unmarshals a container with the metadata of a value transfer payload from a sequence of bytes.
 // It either creates a new container or fills the optionally provided container with the parsed information.
-func PayloadMetadataFromBytes(bytes []byte, optionalTargetObject ...*PayloadMetadata) (result *PayloadMetadata, consumedBytes int, err error) {
+func PayloadMetadataFromBytes(bytes []byte) (result *PayloadMetadata, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParsePayloadMetadata(marshalUtil, optionalTargetObject...)
+	result, err = ParsePayloadMetadata(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
 // ParsePayloadMetadata is a wrapper for simplified unmarshaling in a byte stream using the marshalUtil package.
-func ParsePayloadMetadata(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*PayloadMetadata) (result *PayloadMetadata, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return PayloadMetadataFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
-
+func ParsePayloadMetadata(marshalUtil *marshalutil.MarshalUtil) (result *PayloadMetadata, err error) {
+	result = &PayloadMetadata{}
+	if result.payloadID, err = payload.ParseID(marshalUtil); err != nil {
 		return
 	}
-
-	result = parsedObject.(*PayloadMetadata)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.solidificationTime, err = marshalUtil.ReadTime(); err != nil {
 		return
-	})
+	}
+	if result.solid, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.liked, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.confirmed, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.rejected, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.branchID, err = branchmanager.ParseBranchID(marshalUtil); err != nil {
+		return
+	}
 
 	return
 }
 
-// PayloadMetadataFromStorageKey gets called when we restore transaction metadata from the storage. The bytes and the content will be
+// PayloadMetadataFromObjectStorage gets called when we restore transaction metadata from the storage. The bytes and the content will be
 // unmarshaled by an external caller using the binary.ObjectStorageValue interface.
-func PayloadMetadataFromStorageKey(id []byte, optionalTargetObject ...*PayloadMetadata) (result *PayloadMetadata, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &PayloadMetadata{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to PayloadMetadataFromStorageKey")
-	}
-
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(id)
-	if result.payloadID, err = payload.ParseID(marshalUtil); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
+func PayloadMetadataFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	result, _, err = PayloadMetadataFromBytes(byteutils.ConcatBytes(key, data))
 
 	return
 }
@@ -275,10 +268,7 @@ func (payloadMetadata *PayloadMetadata) setBranchID(branchID branchmanager.Branc
 
 // Bytes marshals the metadata into a sequence of bytes.
 func (payloadMetadata *PayloadMetadata) Bytes() []byte {
-	return marshalutil.New(payload.IDLength + marshalutil.TIME_SIZE + 2*marshalutil.BOOL_SIZE + branchmanager.BranchIDLength).
-		WriteBytes(payloadMetadata.ObjectStorageKey()).
-		WriteBytes(payloadMetadata.ObjectStorageValue()).
-		Bytes()
+	return byteutils.ConcatBytes(payloadMetadata.ObjectStorageKey(), payloadMetadata.ObjectStorageValue())
 }
 
 // String creates a human readable version of the metadata (for debug purposes).
@@ -314,32 +304,6 @@ func (payloadMetadata *PayloadMetadata) ObjectStorageValue() []byte {
 		Bytes()
 }
 
-// UnmarshalObjectStorageValue is required to match the encoding.BinaryUnmarshaler interface.
-func (payloadMetadata *PayloadMetadata) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	marshalUtil := marshalutil.New(data)
-	if payloadMetadata.solidificationTime, err = marshalUtil.ReadTime(); err != nil {
-		return
-	}
-	if payloadMetadata.solid, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if payloadMetadata.liked, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if payloadMetadata.confirmed, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if payloadMetadata.rejected, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if payloadMetadata.branchID, err = branchmanager.ParseBranchID(marshalUtil); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
-
-	return
-}
-
 // CachedPayloadMetadata is a wrapper for the object storage, that takes care of type casting the managed objects.
 // Since go does not have generics (yet), the object storage works based on the generic "interface{}" type, which means
 // that we have to regularly type cast the returned objects, to match the expected type. To reduce the burden of
diff --git a/dapps/valuetransfers/packages/tangle/signature_filter_test.go b/dapps/valuetransfers/packages/tangle/signature_filter_test.go
index e664d062b3893bcb3f9d3d101a3f087e31564111..c8640ad5d295d75bafde03f6c1f88f4c2f5a94c3 100644
--- a/dapps/valuetransfers/packages/tangle/signature_filter_test.go
+++ b/dapps/valuetransfers/packages/tangle/signature_filter_test.go
@@ -87,7 +87,7 @@ func TestSignatureFilter(t *testing.T) {
 		marshalUtil := marshalutil.New(messagePayload.NewData([]byte("test")).Bytes())
 
 		// set the type to be a value payload
-		marshalUtil.WriteSeek(0)
+		marshalUtil.WriteSeek(4)
 		marshalUtil.WriteUint32(valuePayload.Type)
 
 		// parse modified bytes back into a payload object
diff --git a/dapps/valuetransfers/packages/tangle/tangle.go b/dapps/valuetransfers/packages/tangle/tangle.go
index 52007a6be3c999ba580975a34c28a58c95bd2be9..c9d79d8e79fedf3f2c4f31072552cae741740be5 100644
--- a/dapps/valuetransfers/packages/tangle/tangle.go
+++ b/dapps/valuetransfers/packages/tangle/tangle.go
@@ -48,15 +48,15 @@ func New(store kvstore.KVStore) (tangle *Tangle) {
 	tangle = &Tangle{
 		branchManager: branchmanager.New(store),
 
-		payloadStorage:             osFactory.New(osPayload, osPayloadFactory, objectstorage.CacheTime(cacheTime)),
-		payloadMetadataStorage:     osFactory.New(osPayloadMetadata, osPayloadMetadataFactory, objectstorage.CacheTime(cacheTime)),
-		missingPayloadStorage:      osFactory.New(osMissingPayload, osMissingPayloadFactory, objectstorage.CacheTime(cacheTime)),
-		approverStorage:            osFactory.New(osApprover, osPayloadApproverFactory, objectstorage.CacheTime(cacheTime), objectstorage.PartitionKey(payload.IDLength, payload.IDLength), objectstorage.KeysOnly(true)),
-		transactionStorage:         osFactory.New(osTransaction, osTransactionFactory, objectstorage.CacheTime(cacheTime), osLeakDetectionOption),
-		transactionMetadataStorage: osFactory.New(osTransactionMetadata, osTransactionMetadataFactory, objectstorage.CacheTime(cacheTime), osLeakDetectionOption),
-		attachmentStorage:          osFactory.New(osAttachment, osAttachmentFactory, objectstorage.CacheTime(cacheTime), objectstorage.PartitionKey(transaction.IDLength, payload.IDLength), osLeakDetectionOption),
-		outputStorage:              osFactory.New(osOutput, osOutputFactory, OutputKeyPartitions, objectstorage.CacheTime(cacheTime), osLeakDetectionOption),
-		consumerStorage:            osFactory.New(osConsumer, osConsumerFactory, ConsumerPartitionKeys, objectstorage.CacheTime(cacheTime), osLeakDetectionOption),
+		payloadStorage:             osFactory.New(osPayload, payload.FromObjectStorage, objectstorage.CacheTime(cacheTime)),
+		payloadMetadataStorage:     osFactory.New(osPayloadMetadata, PayloadMetadataFromObjectStorage, objectstorage.CacheTime(cacheTime)),
+		missingPayloadStorage:      osFactory.New(osMissingPayload, MissingPayloadFromObjectStorage, objectstorage.CacheTime(cacheTime)),
+		approverStorage:            osFactory.New(osApprover, PayloadApproverFromObjectStorage, objectstorage.CacheTime(cacheTime), objectstorage.PartitionKey(payload.IDLength, payload.IDLength), objectstorage.KeysOnly(true)),
+		transactionStorage:         osFactory.New(osTransaction, transaction.FromObjectStorage, objectstorage.CacheTime(cacheTime), osLeakDetectionOption),
+		transactionMetadataStorage: osFactory.New(osTransactionMetadata, TransactionMetadataFromObjectStorage, objectstorage.CacheTime(cacheTime), osLeakDetectionOption),
+		attachmentStorage:          osFactory.New(osAttachment, AttachmentFromObjectStorage, objectstorage.CacheTime(cacheTime), objectstorage.PartitionKey(transaction.IDLength, payload.IDLength), osLeakDetectionOption),
+		outputStorage:              osFactory.New(osOutput, OutputFromObjectStorage, OutputKeyPartitions, objectstorage.CacheTime(cacheTime), osLeakDetectionOption),
+		consumerStorage:            osFactory.New(osConsumer, ConsumerFromObjectStorage, ConsumerPartitionKeys, objectstorage.CacheTime(cacheTime), osLeakDetectionOption),
 
 		Events: newEvents(),
 	}
diff --git a/dapps/valuetransfers/packages/tangle/transactionmetadata.go b/dapps/valuetransfers/packages/tangle/transactionmetadata.go
index 753e70593a2e141c092ff2553a31e340d386c3ee..f3e966bbb3e03a377c52dee586350023045ef2ed 100644
--- a/dapps/valuetransfers/packages/tangle/transactionmetadata.go
+++ b/dapps/valuetransfers/packages/tangle/transactionmetadata.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/branchmanager"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 	"github.com/iotaledger/hive.go/stringify"
@@ -46,56 +47,57 @@ func NewTransactionMetadata(id transaction.ID) *TransactionMetadata {
 
 // TransactionMetadataFromBytes unmarshals a TransactionMetadata object from a sequence of bytes.
 // It either creates a new object or fills the optionally provided object with the parsed information.
-func TransactionMetadataFromBytes(bytes []byte, optionalTargetObject ...*TransactionMetadata) (result *TransactionMetadata, consumedBytes int, err error) {
+func TransactionMetadataFromBytes(bytes []byte) (result *TransactionMetadata, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseTransactionMetadata(marshalUtil, optionalTargetObject...)
+	result, err = ParseTransactionMetadata(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
-// TransactionMetadataFromStorageKey get's called when we restore TransactionMetadata from the storage.
+// TransactionMetadataFromObjectStorage get's called when we restore TransactionMetadata 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 UnmarshalObjectStorageValue (by the ObjectStorage).
-func TransactionMetadataFromStorageKey(keyBytes []byte, optionalTargetObject ...*TransactionMetadata) (result *TransactionMetadata, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &TransactionMetadata{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to TransactionMetadataFromStorageKey")
-	}
-
-	// parse information
-	marshalUtil := marshalutil.New(keyBytes)
-	result.id, err = transaction.ParseID(marshalUtil)
-	if err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
+func TransactionMetadataFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	result, _, err = TransactionMetadataFromBytes(byteutils.ConcatBytes(key, data))
 
 	return
 }
 
 // ParseTransactionMetadata is a wrapper for simplified unmarshaling of TransactionMetadata objects from a byte stream using the marshalUtil package.
-func ParseTransactionMetadata(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*TransactionMetadata) (result *TransactionMetadata, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return TransactionMetadataFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
+func ParseTransactionMetadata(marshalUtil *marshalutil.MarshalUtil) (result *TransactionMetadata, err error) {
+	result = &TransactionMetadata{}
 
+	if result.id, err = transaction.ParseID(marshalUtil); err != nil {
 		return
 	}
-
-	result = parsedObject.(*TransactionMetadata)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.branchID, err = branchmanager.ParseBranchID(marshalUtil); err != nil {
 		return
-	})
+	}
+	if result.solidificationTime, err = marshalUtil.ReadTime(); err != nil {
+		return
+	}
+	if result.finalizationTime, err = marshalUtil.ReadTime(); err != nil {
+		return
+	}
+	if result.solid, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.preferred, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.finalized, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.liked, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.confirmed, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
+	if result.rejected, err = marshalUtil.ReadBool(); err != nil {
+		return
+	}
 
 	return
 }
@@ -364,17 +366,7 @@ func (transactionMetadata *TransactionMetadata) SolidificationTime() time.Time {
 
 // Bytes marshals the TransactionMetadata object into a sequence of bytes.
 func (transactionMetadata *TransactionMetadata) Bytes() []byte {
-	return marshalutil.New(branchmanager.BranchIDLength + 2*marshalutil.TIME_SIZE + 6*marshalutil.BOOL_SIZE).
-		WriteBytes(transactionMetadata.BranchID().Bytes()).
-		WriteTime(transactionMetadata.SolidificationTime()).
-		WriteTime(transactionMetadata.FinalizationTime()).
-		WriteBool(transactionMetadata.Solid()).
-		WriteBool(transactionMetadata.Preferred()).
-		WriteBool(transactionMetadata.Finalized()).
-		WriteBool(transactionMetadata.Liked()).
-		WriteBool(transactionMetadata.Confirmed()).
-		WriteBool(transactionMetadata.Rejected()).
-		Bytes()
+	return byteutils.ConcatBytes(transactionMetadata.ObjectStorageKey(), transactionMetadata.ObjectStorageValue())
 }
 
 // String creates a human readable version of the metadata (for debug purposes).
@@ -400,43 +392,17 @@ func (transactionMetadata *TransactionMetadata) Update(other objectstorage.Stora
 // ObjectStorageValue marshals the TransactionMetadata object into a sequence of bytes and matches the encoding.BinaryMarshaler
 // interface.
 func (transactionMetadata *TransactionMetadata) ObjectStorageValue() []byte {
-	return transactionMetadata.Bytes()
-}
-
-// UnmarshalObjectStorageValue restores the values of a TransactionMetadata object from a sequence of bytes and matches the
-// encoding.BinaryUnmarshaler interface.
-func (transactionMetadata *TransactionMetadata) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	marshalUtil := marshalutil.New(data)
-	if transactionMetadata.branchID, err = branchmanager.ParseBranchID(marshalUtil); err != nil {
-		return
-	}
-	if transactionMetadata.solidificationTime, err = marshalUtil.ReadTime(); err != nil {
-		return
-	}
-	if transactionMetadata.finalizationTime, err = marshalUtil.ReadTime(); err != nil {
-		return
-	}
-	if transactionMetadata.solid, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if transactionMetadata.preferred, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if transactionMetadata.finalized, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if transactionMetadata.liked, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if transactionMetadata.confirmed, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	if transactionMetadata.rejected, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
-
-	return
+	return marshalutil.New(branchmanager.BranchIDLength + 2*marshalutil.TIME_SIZE + 6*marshalutil.BOOL_SIZE).
+		WriteBytes(transactionMetadata.BranchID().Bytes()).
+		WriteTime(transactionMetadata.SolidificationTime()).
+		WriteTime(transactionMetadata.FinalizationTime()).
+		WriteBool(transactionMetadata.Solid()).
+		WriteBool(transactionMetadata.Preferred()).
+		WriteBool(transactionMetadata.Finalized()).
+		WriteBool(transactionMetadata.Liked()).
+		WriteBool(transactionMetadata.Confirmed()).
+		WriteBool(transactionMetadata.Rejected()).
+		Bytes()
 }
 
 // CachedTransactionMetadata is a wrapper for the object storage, that takes care of type casting the TransactionMetadata objects.
diff --git a/dapps/valuetransfers/packages/transaction/transaction.go b/dapps/valuetransfers/packages/transaction/transaction.go
index da41e4a4140bc49d769891ee296f98b86056bfd1..bd552869dd4fee9ec007a1ee1a4cebec9ffe426e 100644
--- a/dapps/valuetransfers/packages/transaction/transaction.go
+++ b/dapps/valuetransfers/packages/transaction/transaction.go
@@ -64,54 +64,96 @@ func New(inputs *Inputs, outputs *Outputs) *Transaction {
 }
 
 // FromBytes unmarshals a Transaction from a sequence of bytes.
-func FromBytes(bytes []byte, optionalTargetObject ...*Transaction) (result *Transaction, consumedBytes int, err error) {
+func FromBytes(bytes []byte) (result *Transaction, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = Parse(marshalUtil, optionalTargetObject...)
+	result, err = Parse(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
-// FromStorageKey is a factory method that creates a new Transaction instance from a storage key of the objectstorage.
+// FromObjectStorage is a factory method that creates a new Transaction instance from a storage key of the objectstorage.
 // It is used by the objectstorage, to create new instances of this entity.
-func FromStorageKey(key []byte, optionalTargetObject ...*Transaction) (result objectstorage.StorableObject, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Transaction{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to FromStorageKey")
+func FromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	// parse the message
+	transaction, err := Parse(marshalutil.New(data))
+	if err != nil {
+		return
 	}
 
-	marshalUtil := marshalutil.New(key)
-	id, err := ParseID(marshalUtil)
+	id, err := ParseID(marshalutil.New(key))
 	if err != nil {
 		return
 	}
-	result.(*Transaction).id = &id
+	transaction.id = &id
+
+	// assign result
+	result = transaction
 
 	return
 }
 
 // Parse unmarshals a Transaction using the given marshalUtil (for easier marshaling/unmarshaling).
-func Parse(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*Transaction) (result *Transaction, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Transaction{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to Parse")
+func Parse(marshalUtil *marshalutil.MarshalUtil) (result *Transaction, err error) {
+	// determine read offset before starting to parse
+	readOffsetStart := marshalUtil.ReadOffset()
+
+	// parse information
+	result = &Transaction{}
+
+	// unmarshal inputs
+	parsedInputs, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return InputsFromBytes(data) })
+	if err != nil {
+		return
 	}
+	result.inputs = parsedInputs.(*Inputs)
 
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
+	// unmarshal outputs
+	parsedOutputs, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return OutputsFromBytes(data) })
+	if err != nil {
+		return
+	}
+	result.outputs = parsedOutputs.(*Outputs)
 
+	// unmarshal data payload size
+	var dataPayloadSize uint32
+	dataPayloadSize, err = marshalUtil.ReadUint32()
+	if err != nil {
 		return
-	})
+	}
+
+	// unmarshal data payload
+	result.dataPayload, err = marshalUtil.ReadBytes(int(dataPayloadSize))
+	if err != nil {
+		return
+	}
+
+	// store essence bytes
+	essenceBytesCount := marshalUtil.ReadOffset() - readOffsetStart
+	result.essenceBytes, err = marshalUtil.ReadBytes(essenceBytesCount, readOffsetStart)
+	if err != nil {
+		return
+	}
+
+	// unmarshal outputs
+	parsedSignatures, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return SignaturesFromBytes(data) })
+	if err != nil {
+		return
+	}
+	result.signatures = parsedSignatures.(*Signatures)
+
+	// store signature bytes
+	signatureBytesCount := marshalUtil.ReadOffset() - readOffsetStart - essenceBytesCount
+	result.signatureBytes, err = marshalUtil.ReadBytes(signatureBytesCount, readOffsetStart+essenceBytesCount)
+	if err != nil {
+		return
+	}
+
+	// store bytes, so we don't have to marshal manually
+	result.bytes, err = marshalUtil.ReadBytes(essenceBytesCount+signatureBytesCount, readOffsetStart)
+	if err != nil {
+		return
+	}
 
 	return
 }
@@ -379,64 +421,6 @@ func (transaction *Transaction) ObjectStorageValue() []byte {
 	return transaction.Bytes()
 }
 
-// UnmarshalObjectStorageValue unmarshals the bytes that are stored in the value of the objectstorage.
-func (transaction *Transaction) UnmarshalObjectStorageValue(bytes []byte) (consumedBytes int, err error) {
-	// initialize helper
-	marshalUtil := marshalutil.New(bytes)
-
-	// unmarshal inputs
-	parsedInputs, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return InputsFromBytes(data) })
-	if err != nil {
-		return
-	}
-	transaction.inputs = parsedInputs.(*Inputs)
-
-	// unmarshal outputs
-	parsedOutputs, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return OutputsFromBytes(data) })
-	if err != nil {
-		return
-	}
-	transaction.outputs = parsedOutputs.(*Outputs)
-
-	// unmarshal data payload size
-	var dataPayloadSize uint32
-	dataPayloadSize, err = marshalUtil.ReadUint32()
-	if err != nil {
-		return
-	}
-
-	// unmarshal data payload
-	transaction.dataPayload, err = marshalUtil.ReadBytes(int(dataPayloadSize))
-	if err != nil {
-		return
-	}
-
-	// store essence bytes
-	essenceBytesCount := marshalUtil.ReadOffset()
-	transaction.essenceBytes = make([]byte, essenceBytesCount)
-	copy(transaction.essenceBytes, bytes[:essenceBytesCount])
-
-	// unmarshal outputs
-	parsedSignatures, err := marshalUtil.Parse(func(data []byte) (interface{}, int, error) { return SignaturesFromBytes(data) })
-	if err != nil {
-		return
-	}
-	transaction.signatures = parsedSignatures.(*Signatures)
-
-	// store signature bytes
-	signatureBytesCount := marshalUtil.ReadOffset() - essenceBytesCount
-	transaction.signatureBytes = make([]byte, signatureBytesCount)
-	copy(transaction.signatureBytes, bytes[essenceBytesCount:essenceBytesCount+signatureBytesCount])
-
-	// return the number of bytes we processed
-	consumedBytes = essenceBytesCount + signatureBytesCount
-
-	// store bytes, so we don't have to marshal manually
-	transaction.bytes = bytes[:consumedBytes]
-
-	return
-}
-
 // endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 // CachedTransaction is a wrapper for the object storage, that takes care of type casting the Transaction objects.
diff --git a/dapps/valuetransfers/packages/transaction/transaction_test.go b/dapps/valuetransfers/packages/transaction/transaction_test.go
index d1bb17271ba803bd0577b2ca40fc635757c5b54d..54e6c698ee1912620d968ad2361cd449703d1745 100644
--- a/dapps/valuetransfers/packages/transaction/transaction_test.go
+++ b/dapps/valuetransfers/packages/transaction/transaction_test.go
@@ -89,8 +89,7 @@ func TestMarshalingEmptyDataPayload(t *testing.T) {
 
 	v := tx.ObjectStorageValue()
 
-	tx1 := Transaction{}
-	_, err := tx1.UnmarshalObjectStorageValue(v)
+	tx1, _, err := FromBytes(v)
 	assert.NoError(t, err)
 
 	assert.Equal(t, true, tx1.SignaturesValid())
@@ -116,8 +115,7 @@ func TestMarshalingDataPayload(t *testing.T) {
 
 	v := tx.ObjectStorageValue()
 
-	tx1 := Transaction{}
-	_, err = tx1.UnmarshalObjectStorageValue(v)
+	tx1, _, err := FromBytes(v)
 
 	assert.NoError(t, err)
 	assert.Equal(t, true, tx1.SignaturesValid())
diff --git a/go.mod b/go.mod
index 8e79858b8638c30738372d7bca97009cff0623a7..638db4d32813fb66e36457ce02f6c694889ed3c7 100644
--- a/go.mod
+++ b/go.mod
@@ -13,7 +13,7 @@ require (
 	github.com/gobuffalo/packr/v2 v2.8.0
 	github.com/golang/protobuf v1.4.2
 	github.com/gorilla/websocket v1.4.2
-	github.com/iotaledger/hive.go v0.0.0-20200909085811-5700df262e21
+	github.com/iotaledger/hive.go v0.0.0-20200910101329-33de3e2e05c6
 	github.com/labstack/echo v3.3.10+incompatible
 	github.com/labstack/gommon v0.3.0
 	github.com/magiconair/properties v1.8.1
diff --git a/go.sum b/go.sum
index efba6b5b5b289306bdfe709d64bf1bcd8c4ce80f..70b3a9f6bf32089d87ff5b448558ab661174ad48 100644
--- a/go.sum
+++ b/go.sum
@@ -350,8 +350,8 @@ github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7
 github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
-github.com/iotaledger/hive.go v0.0.0-20200909085811-5700df262e21 h1:ZbVqGAVePnHgTSF4ZuXXH9G+UBQcp1/KUbqpTBMaapg=
-github.com/iotaledger/hive.go v0.0.0-20200909085811-5700df262e21/go.mod h1:tLI+HS0amqY5YqClfFZDHlFM7eeIZjoU25Oj1u9jCzQ=
+github.com/iotaledger/hive.go v0.0.0-20200910101329-33de3e2e05c6 h1:fYKwzYCzewzTLFb/hCEnJtopHL7Qm+Ztvki+6Z2bVXo=
+github.com/iotaledger/hive.go v0.0.0-20200910101329-33de3e2e05c6/go.mod h1:tLI+HS0amqY5YqClfFZDHlFM7eeIZjoU25Oj1u9jCzQ=
 github.com/iotaledger/iota.go v1.0.0-beta.15 h1:HI8PqerEnO1CCIqmXHJ6zh1IaSFXU+S0qlUAEKshho8=
 github.com/iotaledger/iota.go v1.0.0-beta.15/go.mod h1:Rn6v5hLAn8YBaJlRu1ZQdPAgKlshJR1PTeLQaft2778=
 github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
diff --git a/packages/binary/drng/payload/payload.go b/packages/binary/drng/payload/payload.go
index 8d49709b4789773b376f5544d69b81c9cf7309c0..1849b55b447f11b76641313855cbca19dcb71ff3 100644
--- a/packages/binary/drng/payload/payload.go
+++ b/packages/binary/drng/payload/payload.go
@@ -42,27 +42,18 @@ func Parse(marshalUtil *marshalutil.MarshalUtil) (*Payload, error) {
 
 // FromBytes parses the marshaled version of a Payload into an object.
 // It either returns a new Payload or fills an optionally provided Payload with the parsed information.
-func FromBytes(bytes []byte, optionalTargetObject ...*Payload) (result *Payload, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Payload{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to OutputFromBytes")
-	}
-
+func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) {
 	// initialize helper
 	marshalUtil := marshalutil.New(bytes)
 
 	// read information that are required to identify the payload from the outside
-	if _, err = marshalUtil.ReadUint32(); err != nil {
+	result = &Payload{}
+	len, err := marshalUtil.ReadUint32()
+	if err != nil {
 		return
 	}
 
-	len, err := marshalUtil.ReadUint32()
-	if err != nil {
+	if _, err = marshalUtil.ReadUint32(); err != nil {
 		return
 	}
 
@@ -109,8 +100,8 @@ func (payload *Payload) Bytes() (bytes []byte) {
 	marshalUtil := marshalutil.New()
 
 	// marshal the payload specific information
-	marshalUtil.WriteUint32(Type)
 	marshalUtil.WriteUint32(uint32(len(payload.Data) + header.Length))
+	marshalUtil.WriteUint32(Type)
 	marshalUtil.WriteBytes(payload.Header.Bytes())
 	marshalUtil.WriteBytes(payload.Data[:])
 
@@ -142,17 +133,9 @@ func (payload *Payload) Marshal() (bytes []byte, err error) {
 	return payload.Bytes(), nil
 }
 
-// Unmarshal unmarshals the given bytes into a drng payload.
-func (payload *Payload) Unmarshal(data []byte) (err error) {
-	_, _, err = FromBytes(data, payload)
-
-	return
-}
-
 func init() {
 	payload.RegisterType(Type, ObjectName, func(data []byte) (payload payload.Payload, err error) {
-		payload = &Payload{}
-		err = payload.Unmarshal(data)
+		payload, _, err = FromBytes(data)
 
 		return
 	})
diff --git a/packages/binary/drng/subtypes/collectivebeacon/payload/payload.go b/packages/binary/drng/subtypes/collectivebeacon/payload/payload.go
index 25644f371bd0fa29e01732ff8770ae9a1cb8ff0b..273f419738f49bde12db58b405e84503eb7751e0 100644
--- a/packages/binary/drng/subtypes/collectivebeacon/payload/payload.go
+++ b/packages/binary/drng/subtypes/collectivebeacon/payload/payload.go
@@ -52,17 +52,7 @@ func Parse(marshalUtil *marshalutil.MarshalUtil) (*Payload, error) {
 
 // FromBytes parses the marshaled version of a Payload into an object.
 // It either returns a new Payload or fills an optionally provided Payload with the parsed information.
-func FromBytes(bytes []byte, optionalTargetObject ...*Payload) (result *Payload, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Payload{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to OutputFromBytes")
-	}
-
+func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) {
 	// initialize helper
 	marshalUtil := marshalutil.New(bytes)
 
@@ -75,6 +65,7 @@ func FromBytes(bytes []byte, optionalTargetObject ...*Payload) (result *Payload,
 	}
 
 	// parse header
+	result = &Payload{}
 	if result.Header, err = header.Parse(marshalUtil); err != nil {
 		return
 	}
@@ -132,8 +123,8 @@ func (payload *Payload) Bytes() (bytes []byte) {
 	// marshal fields
 	payloadLength := header.Length + marshalutil.UINT64_SIZE + SignatureSize*2 + PublicKeySize
 	marshalUtil := marshalutil.New(marshalutil.UINT32_SIZE + marshalutil.UINT32_SIZE + payloadLength)
-	marshalUtil.WriteUint32(drngPayload.Type)
 	marshalUtil.WriteUint32(uint32(payloadLength))
+	marshalUtil.WriteUint32(drngPayload.Type)
 	marshalUtil.WriteBytes(payload.Header.Bytes())
 	marshalUtil.WriteUint64(payload.Round)
 	marshalUtil.WriteBytes(payload.PrevSignature)
@@ -171,11 +162,4 @@ func (payload *Payload) Marshal() (bytes []byte, err error) {
 	return payload.Bytes(), nil
 }
 
-// Unmarshal returns a collective beacon payload from the given bytes.
-func (payload *Payload) Unmarshal(data []byte) (err error) {
-	_, _, err = FromBytes(data, payload)
-
-	return
-}
-
 // // endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/packages/binary/messagelayer/message/message.go b/packages/binary/messagelayer/message/message.go
index 95954923f17337327c4e2de5e7b1e17bb3265353..0ea9d7a2f8260fad608c85f596611d46c09385dd 100644
--- a/packages/binary/messagelayer/message/message.go
+++ b/packages/binary/messagelayer/message/message.go
@@ -1,6 +1,7 @@
 package message
 
 import (
+	"fmt"
 	"sync"
 	"time"
 
@@ -52,56 +53,77 @@ func New(parent1ID ID, parent2ID ID, issuingTime time.Time, issuerPublicKey ed25
 }
 
 // FromBytes parses the given bytes into a message.
-func FromBytes(bytes []byte, optionalTargetObject ...*Message) (result *Message, consumedBytes int, err error) {
+func FromBytes(bytes []byte) (result *Message, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = Parse(marshalUtil, optionalTargetObject...)
+	result, err = Parse(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
+
 	return
 }
 
-// Parse parses a message from the given marshal util.
-func Parse(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*Message) (result *Message, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Message{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to Parse")
+// Parse parses a Message using the given marshal util.
+func Parse(marshalUtil *marshalutil.MarshalUtil) (result *Message, err error) {
+	// determine read offset before starting to parse
+	readOffsetStart := marshalUtil.ReadOffset()
+
+	// parse information
+	result = &Message{}
+	if result.parent1ID, err = ParseID(marshalUtil); err != nil {
+		return
 	}
+	if result.parent2ID, err = ParseID(marshalUtil); err != nil {
+		return
+	}
+	if result.issuerPublicKey, err = ed25519.ParsePublicKey(marshalUtil); err != nil {
+		return
+	}
+	if result.issuingTime, err = marshalUtil.ReadTime(); err != nil {
+		return
+	}
+	if result.sequenceNumber, err = marshalUtil.ReadUint64(); err != nil {
+		return
+	}
+	if result.payload, err = payload.Parse(marshalUtil); err != nil {
+		return
+	}
+	if result.nonce, err = marshalUtil.ReadUint64(); err != nil {
+		return
+	}
+	if result.signature, err = ed25519.ParseSignature(marshalUtil); err != nil {
+		return
+	}
+
+	// retrieve the number of bytes we processed
+	readOffsetEnd := marshalUtil.ReadOffset()
 
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
+	// store marshaled version as a copy
+	result.bytes, err = marshalUtil.ReadBytes(readOffsetEnd-readOffsetStart, readOffsetStart)
+	if err != nil {
+		err = fmt.Errorf("error trying to copy raw source bytes: %w", err)
 
 		return
-	})
+	}
 
 	return
 }
 
-// StorableObjectFromKey gets called when we restore a message from storage.
-// The bytes and the content will be unmarshaled by an external caller (the objectStorage factory).
-func StorableObjectFromKey(key []byte, optionalTargetObject ...*Message) (result objectstorage.StorableObject, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Message{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to StorableObjectFromKey")
+// FromObjectStorage gets called when we restore a message from the ObjectStorage.
+func FromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	// parse the message
+	message, err := Parse(marshalutil.New(data))
+	if err != nil {
+		return
 	}
 
-	marshalUtil := marshalutil.New(key)
-	id, idErr := ParseID(marshalUtil)
-	if idErr != nil {
-		err = idErr
-
+	// parse the ID from they key
+	id, err := ParseID(marshalutil.New(key))
+	if err != nil {
 		return
 	}
-	result.(*Message).id = &id
-	consumedBytes = marshalUtil.ReadOffset()
+	message.id = &id
+
+	// assign result
+	result = message
 
 	return
 }
@@ -254,47 +276,6 @@ func (message *Message) Bytes() []byte {
 	return message.bytes
 }
 
-// UnmarshalObjectStorageValue unmarshals the bytes into a message.
-func (message *Message) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	// initialize helper
-	marshalUtil := marshalutil.New(data)
-
-	// parse information
-	if message.parent1ID, err = ParseID(marshalUtil); err != nil {
-		return
-	}
-	if message.parent2ID, err = ParseID(marshalUtil); err != nil {
-		return
-	}
-	if message.issuerPublicKey, err = ed25519.ParsePublicKey(marshalUtil); err != nil {
-		return
-	}
-	if message.issuingTime, err = marshalUtil.ReadTime(); err != nil {
-		return
-	}
-	if message.sequenceNumber, err = marshalUtil.ReadUint64(); err != nil {
-		return
-	}
-	if message.payload, err = payload.Parse(marshalUtil); err != nil {
-		return
-	}
-	if message.nonce, err = marshalUtil.ReadUint64(); err != nil {
-		return
-	}
-	if message.signature, err = ed25519.ParseSignature(marshalUtil); err != nil {
-		return
-	}
-
-	// return the number of bytes we processed
-	consumedBytes = marshalUtil.ReadOffset()
-
-	// store marshaled version
-	message.bytes = make([]byte, consumedBytes)
-	copy(message.bytes, data)
-
-	return
-}
-
 // ObjectStorageKey returns the key of the stored message object.
 // This returns the bytes of the message ID.
 func (message *Message) ObjectStorageKey() []byte {
diff --git a/packages/binary/messagelayer/payload/data.go b/packages/binary/messagelayer/payload/data.go
index 26929cf79531dbadeb6511ccb855ff8dad9d52c5..6623a7f503687410fbd47a077b020481e61bde68 100644
--- a/packages/binary/messagelayer/payload/data.go
+++ b/packages/binary/messagelayer/payload/data.go
@@ -23,32 +23,23 @@ func NewData(data []byte) *Data {
 }
 
 // DataFromBytes creates a new data payload from the given bytes.
-func DataFromBytes(bytes []byte, optionalTargetObject ...*Data) (result *Data, consumedBytes int, err error) {
+func DataFromBytes(bytes []byte) (result *Data, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseData(marshalUtil, optionalTargetObject...)
+	result, err = ParseData(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
 
 // ParseData parses a new data payload out of the given marshal util.
-func ParseData(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*Data) (result *Data, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Data{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to ParseData")
-	}
-
+func ParseData(marshalUtil *marshalutil.MarshalUtil) (result *Data, err error) {
 	// parse information
-	result.payloadType, err = marshalUtil.ReadUint32()
+	result = &Data{}
+	payloadBytes, err := marshalUtil.ReadUint32()
 	if err != nil {
 		return
 	}
-	payloadBytes, err := marshalUtil.ReadUint32()
+	result.payloadType, err = marshalUtil.ReadUint32()
 	if err != nil {
 		return
 	}
@@ -76,21 +67,14 @@ func (dataPayload *Data) Bytes() []byte {
 	marshalUtil := marshalutil.New()
 
 	// marshal the payload specific information
-	marshalUtil.WriteUint32(dataPayload.Type())
 	marshalUtil.WriteUint32(uint32(len(dataPayload.data)))
+	marshalUtil.WriteUint32(dataPayload.Type())
 	marshalUtil.WriteBytes(dataPayload.data[:])
 
 	// return result
 	return marshalUtil.Bytes()
 }
 
-// Unmarshal unmarshalls the byte array to a data payload.
-func (dataPayload *Data) Unmarshal(data []byte) (err error) {
-	_, _, err = DataFromBytes(data, dataPayload)
-
-	return
-}
-
 func (dataPayload *Data) String() string {
 	return stringify.Struct("Data",
 		stringify.StructField("type", int(dataPayload.Type())),
@@ -98,11 +82,9 @@ func (dataPayload *Data) String() string {
 	)
 }
 
-// GenericPayloadUnmarshalerFactory is an unmarshaler for the generic data payload type.
-func GenericPayloadUnmarshalerFactory(payloadType Type) Unmarshaler {
-	return func(data []byte) (payload Payload, err error) {
-		payload = &Data{payloadType: payloadType}
-		err = payload.Unmarshal(data)
-		return
-	}
+// GenericPayloadUnmarshaler is an unmarshaler for the generic data payload type.
+func GenericPayloadUnmarshaler(data []byte) (payload Payload, err error) {
+	payload, _, err = DataFromBytes(data)
+
+	return
 }
diff --git a/packages/binary/messagelayer/payload/payload.go b/packages/binary/messagelayer/payload/payload.go
index fdaab2e5f685820e1686e07739f166e762d44ca9..bdf235ecc7854694caf23982a5d8c384ece2cd79 100644
--- a/packages/binary/messagelayer/payload/payload.go
+++ b/packages/binary/messagelayer/payload/payload.go
@@ -25,9 +25,10 @@ var (
 
 func init() {
 	// register the generic unmarshaler
-	SetGenericUnmarshalerFactory(GenericPayloadUnmarshalerFactory)
+	SetGenericUnmarshaler(GenericPayloadUnmarshaler)
+
 	// register the generic data payload type
-	RegisterType(DataType, ObjectName, GenericPayloadUnmarshalerFactory(DataType))
+	RegisterType(DataType, ObjectName, GenericPayloadUnmarshaler)
 }
 
 // Payload represents some kind of payload of data which only gains meaning by having
@@ -35,10 +36,10 @@ func init() {
 type Payload interface {
 	// Type returns the type of the payload.
 	Type() Type
+
 	// Bytes returns the payload bytes.
 	Bytes() []byte
-	// Unmarshal unmarshals the payload from the given bytes.
-	Unmarshal(bytes []byte) error
+
 	// String returns a human-friendly representation of the payload.
 	String() string
 }
@@ -49,11 +50,6 @@ func FromBytes(bytes []byte) (result Payload, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
 
 	// calculate result
-	payloadType, err := marshalUtil.ReadUint32()
-	if err != nil {
-		return
-	}
-
 	payloadSize, err := marshalUtil.ReadUint32()
 	if err != nil {
 		return
@@ -64,6 +60,11 @@ func FromBytes(bytes []byte) (result Payload, consumedBytes int, err error) {
 		return
 	}
 
+	payloadType, err := marshalUtil.ReadUint32()
+	if err != nil {
+		return
+	}
+
 	marshalUtil.ReadSeek(marshalUtil.ReadOffset() - marshalutil.UINT32_SIZE*2)
 	payloadBytes, err := marshalUtil.ReadBytes(int(payloadSize) + 8)
 	if err != nil {
@@ -75,7 +76,7 @@ func FromBytes(bytes []byte) (result Payload, consumedBytes int, err error) {
 	if err != nil {
 		// fallback to the generic unmarshaler if registered type fails to unmarshal
 		marshalUtil.ReadSeek(readOffset)
-		result, err = GenericPayloadUnmarshalerFactory(payloadType)(payloadBytes)
+		result, err = genericUnmarshaler(payloadBytes)
 		if err != nil {
 			return
 		}
diff --git a/packages/binary/messagelayer/payload/type_register.go b/packages/binary/messagelayer/payload/type_register.go
index eb22e51eca3eeb6d2f5e3342be35de3edb33d9bf..728119f25cb73e2b3efebe78f041915c5d8037c6 100644
--- a/packages/binary/messagelayer/payload/type_register.go
+++ b/packages/binary/messagelayer/payload/type_register.go
@@ -14,9 +14,9 @@ type Definition struct {
 }
 
 var (
-	typeRegister              = make(map[Type]Definition)
-	typeRegisterMutex         sync.RWMutex
-	genericUnmarshalerFactory func(payloadType Type) Unmarshaler
+	typeRegister       = make(map[Type]Definition)
+	typeRegisterMutex  sync.RWMutex
+	genericUnmarshaler Unmarshaler
 )
 
 // RegisterType registers a payload type with the given unmarshaler.
@@ -34,15 +34,17 @@ func RegisterType(payloadType Type, payloadName string, unmarshaler Unmarshaler)
 func GetUnmarshaler(payloadType Type) Unmarshaler {
 	typeRegisterMutex.RLock()
 	defer typeRegisterMutex.RUnlock()
+
 	if definition, exists := typeRegister[payloadType]; exists {
 		return definition.Unmarshaler
 	}
-	return genericUnmarshalerFactory(payloadType)
+
+	return genericUnmarshaler
 }
 
-// SetGenericUnmarshalerFactory sets the generic unmarshaler.
-func SetGenericUnmarshalerFactory(unmarshalerFactory func(payloadType Type) Unmarshaler) {
-	genericUnmarshalerFactory = unmarshalerFactory
+// SetGenericUnmarshaler sets the generic unmarshaler.
+func SetGenericUnmarshaler(unmarshaler Unmarshaler) {
+	genericUnmarshaler = unmarshaler
 }
 
 // Name returns the name of a given payload type.
diff --git a/packages/binary/messagelayer/tangle/approver.go b/packages/binary/messagelayer/tangle/approver.go
index 8dc3a6ff8ef4ff7640f09a31410e4b60ecfd05f2..e5d162de400e4f4abad512533ced10b282924390 100644
--- a/packages/binary/messagelayer/tangle/approver.go
+++ b/packages/binary/messagelayer/tangle/approver.go
@@ -27,54 +27,30 @@ func NewApprover(referencedMessageID message.ID, approverMessageID message.ID) *
 }
 
 // ApproverFromBytes parses the given bytes into an approver.
-func ApproverFromBytes(bytes []byte, optionalTargetObject ...*Approver) (result *Approver, consumedBytes int, err error) {
+func ApproverFromBytes(bytes []byte) (result *Approver, consumedBytes int, err error) {
 	marshalUtil := marshalutil.New(bytes)
-	result, err = ParseApprover(marshalUtil, optionalTargetObject...)
+	result, err = ParseApprover(marshalUtil)
 	consumedBytes = marshalUtil.ReadOffset()
 	return
 }
 
 // ParseApprover parses a new approver from the given marshal util.
-func ParseApprover(marshalUtil *marshalutil.MarshalUtil, optionalTargetObject ...*Approver) (result *Approver, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return ApproverFromStorageKey(data, optionalTargetObject...)
-	})
-	if parseErr != nil {
-		err = parseErr
+func ParseApprover(marshalUtil *marshalutil.MarshalUtil) (result *Approver, err error) {
+	result = &Approver{}
+
+	if result.referencedMessageID, err = message.ParseID(marshalUtil); err != nil {
 		return
 	}
-	result = parsedObject.(*Approver)
-
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.approverMessageID, err = message.ParseID(marshalUtil); err != nil {
 		return
-	})
+	}
 
 	return
 }
 
-// ApproverFromStorageKey returns an approver for the given key.
-func ApproverFromStorageKey(key []byte, optionalTargetObject ...*Approver) (result objectstorage.StorableObject, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Approver{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to ApproverFromStorageKey")
-	}
-
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(key)
-	if result.(*Approver).referencedMessageID, err = message.ParseID(marshalUtil); err != nil {
-		return
-	}
-	if result.(*Approver).approverMessageID, err = message.ParseID(marshalUtil); err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
+// ApproverFromObjectStorage returns an approver for the given key.
+func ApproverFromObjectStorage(key []byte, _ []byte) (result objectstorage.StorableObject, err error) {
+	result, _, err = ApproverFromBytes(key)
 
 	return
 }
@@ -116,11 +92,6 @@ func (approver *Approver) ObjectStorageValue() (result []byte) {
 	return
 }
 
-// UnmarshalObjectStorageValue unmarshals the stored bytes into an approver.
-func (approver *Approver) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	return
-}
-
 // Update updates the approver.
 // This should should never happen and will panic if attempted.
 func (approver *Approver) Update(other objectstorage.StorableObject) {
diff --git a/packages/binary/messagelayer/tangle/messagemetadata.go b/packages/binary/messagelayer/tangle/messagemetadata.go
index cea4d89dde5c406be71249d0fb8ea921c175ef60..840d1837ca4a58292022d6de9496057126f52d9d 100644
--- a/packages/binary/messagelayer/tangle/messagemetadata.go
+++ b/packages/binary/messagelayer/tangle/messagemetadata.go
@@ -4,6 +4,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 
@@ -41,36 +42,32 @@ func MessageMetadataFromBytes(bytes []byte) (result *MessageMetadata, consumedBy
 }
 
 // ParseMessageMetadata parses the marshalUtil into a MessageMetadata.
-// If it successfully parses the marshalUtil, it delegates to MessageMetadataFromStorageKey.
+// If it successfully parses the marshalUtil, it delegates to MessageMetadataFromObjectStorage.
 // Else, delegates to UnmarshalObjectStorageValue.
 func ParseMessageMetadata(marshalUtil *marshalutil.MarshalUtil) (result *MessageMetadata, err error) {
-	parsedObject, parseErr := marshalUtil.Parse(func(data []byte) (interface{}, int, error) {
-		return MessageMetadataFromStorageKey(data, nil)
-	})
-	if parseErr != nil {
-		err = parseErr
+	result = &MessageMetadata{}
+
+	if result.messageID, err = message.ParseID(marshalUtil); err != nil {
 		return
 	}
-	result = parsedObject.(*MessageMetadata)
-	_, err = marshalUtil.Parse(func(data []byte) (parseResult interface{}, parsedBytes int, parseErr error) {
-		parsedBytes, parseErr = result.UnmarshalObjectStorageValue(data)
-
+	if result.receivedTime, err = marshalUtil.ReadTime(); err != nil {
+		return
+	}
+	if result.solidificationTime, err = marshalUtil.ReadTime(); err != nil {
+		return
+	}
+	if result.solid, err = marshalUtil.ReadBool(); err != nil {
 		return
-	})
+	}
 
 	return
 }
 
-// MessageMetadataFromStorageKey unmarshals the stored bytes into a MessageMetadata.
-func MessageMetadataFromStorageKey(key []byte, _ []byte) (result objectstorage.StorableObject, consumedBytes int, err error) {
-	result = &MessageMetadata{}
-
-	marshalUtil := marshalutil.New(key)
-	result.(*MessageMetadata).messageID, err = message.ParseID(marshalUtil)
-	if err != nil {
+// MessageMetadataFromObjectStorage unmarshals the stored bytes into a MessageMetadata.
+func MessageMetadataFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	if result, _, err = MessageMetadataFromBytes(byteutils.ConcatBytes(key, data)); err != nil {
 		return
 	}
-	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
@@ -126,6 +123,11 @@ func (messageMetadata *MessageMetadata) SolidificationTime() time.Time {
 	return messageMetadata.solidificationTime
 }
 
+// Bytes returns a marshaled version of the whole MessageMetadata object.
+func (messageMetadata *MessageMetadata) Bytes() []byte {
+	return byteutils.ConcatBytes(messageMetadata.ObjectStorageKey(), messageMetadata.ObjectStorageValue())
+}
+
 // ObjectStorageKey returns the key of the stored message metadata object.
 // This returns the bytes of the messageID.
 func (messageMetadata *MessageMetadata) ObjectStorageKey() []byte {
@@ -142,25 +144,6 @@ func (messageMetadata *MessageMetadata) ObjectStorageValue() []byte {
 		Bytes()
 }
 
-// UnmarshalObjectStorageValue unmarshals the stored bytes into a messageMetadata.
-func (messageMetadata *MessageMetadata) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	marshalUtil := marshalutil.New(data)
-
-	if messageMetadata.receivedTime, err = marshalUtil.ReadTime(); err != nil {
-		return
-	}
-	if messageMetadata.solidificationTime, err = marshalUtil.ReadTime(); err != nil {
-		return
-	}
-	if messageMetadata.solid, err = marshalUtil.ReadBool(); err != nil {
-		return
-	}
-
-	consumedBytes = marshalUtil.ReadOffset()
-
-	return
-}
-
 // Update updates the message metadata.
 // This should never happen and will panic if attempted.
 func (messageMetadata *MessageMetadata) Update(other objectstorage.StorableObject) {
diff --git a/packages/binary/messagelayer/tangle/missingmessage.go b/packages/binary/messagelayer/tangle/missingmessage.go
index f8ba9f2983b6433c4b3cd3a749bfa8545fe62187..5d691576f7a2073f2778c192aeff23d946e0f7fc 100644
--- a/packages/binary/messagelayer/tangle/missingmessage.go
+++ b/packages/binary/messagelayer/tangle/missingmessage.go
@@ -3,6 +3,7 @@ package tangle
 import (
 	"time"
 
+	"github.com/iotaledger/hive.go/byteutils"
 	"github.com/iotaledger/hive.go/marshalutil"
 	"github.com/iotaledger/hive.go/objectstorage"
 
@@ -25,27 +26,31 @@ func NewMissingMessage(messageID message.ID) *MissingMessage {
 	}
 }
 
-// MissingMessageFromStorageKey unmarshals the stored key into a desirable target specified by 0 or 1 optional argument.
-// The default target is MissingMessage.
-// It unmarshals into the target specified or panics if more than 1 target is specified.
-func MissingMessageFromStorageKey(key []byte, optionalTargetObject ...*MissingMessage) (result objectstorage.StorableObject, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &MissingMessage{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to MissingMessageFromStorageKey")
-	}
+// MissingMessageFromBytes parses the given bytes into a MissingMessage.
+func MissingMessageFromBytes(bytes []byte) (result *MissingMessage, consumedBytes int, err error) {
+	marshalUtil := marshalutil.New(bytes)
+	result, err = ParseMissingMessage(marshalUtil)
+	consumedBytes = marshalUtil.ReadOffset()
+	return
+}
 
-	// parse the properties that are stored in the key
-	marshalUtil := marshalutil.New(key)
-	result.(*MissingMessage).messageID, err = message.ParseID(marshalUtil)
-	if err != nil {
+// MissingMessageFromObjectStorage creates a MissingMessage from the ObjectStorage.
+func MissingMessageFromObjectStorage(key []byte, data []byte) (result objectstorage.StorableObject, err error) {
+	result, _, err = MissingMessageFromBytes(byteutils.ConcatBytes(key, data))
+
+	return
+}
+
+// ParseMissingMessage parses a MissingMessage from the given marshal util.
+func ParseMissingMessage(marshalUtil *marshalutil.MarshalUtil) (result *MissingMessage, err error) {
+	result = &MissingMessage{}
+
+	if result.messageID, err = message.ParseID(marshalUtil); err != nil {
+		return
+	}
+	if result.missingSince, err = marshalUtil.ReadTime(); err != nil {
 		return
 	}
-	consumedBytes = marshalUtil.ReadOffset()
 
 	return
 }
@@ -60,6 +65,11 @@ func (missingMessage *MissingMessage) MissingSince() time.Time {
 	return missingMessage.missingSince
 }
 
+// Bytes returns a marshaled version of this MissingMessage.
+func (missingMessage *MissingMessage) Bytes() []byte {
+	return byteutils.ConcatBytes(missingMessage.ObjectStorageKey(), missingMessage.ObjectStorageValue())
+}
+
 // Update update the missing message.
 // It should never happen and will panic if called.
 func (missingMessage *MissingMessage) Update(other objectstorage.StorableObject) {
@@ -81,15 +91,3 @@ func (missingMessage *MissingMessage) ObjectStorageValue() (result []byte) {
 
 	return
 }
-
-// UnmarshalObjectStorageValue unmarshals the stored bytes into a missing message.
-func (missingMessage *MissingMessage) UnmarshalObjectStorageValue(data []byte) (consumedBytes int, err error) {
-	marshalUtil := marshalutil.New(data)
-	missingMessage.missingSince, err = marshalUtil.ReadTime()
-	if err != nil {
-		return
-	}
-	consumedBytes = marshalUtil.ReadOffset()
-
-	return
-}
diff --git a/packages/binary/messagelayer/tangle/tangle.go b/packages/binary/messagelayer/tangle/tangle.go
index 6c394ef6aade9a663c3f9c9def9b2d1ed4e85c2b..95e21f0870912c56f97e4daee749b527542cda0e 100644
--- a/packages/binary/messagelayer/tangle/tangle.go
+++ b/packages/binary/messagelayer/tangle/tangle.go
@@ -30,28 +30,16 @@ type Tangle struct {
 	shutdown               chan struct{}
 }
 
-func messageFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return message.StorableObjectFromKey(key)
-}
-
-func approverFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return ApproverFromStorageKey(key)
-}
-
-func missingMessageFactory(key []byte, _ []byte) (objectstorage.StorableObject, int, error) {
-	return MissingMessageFromStorageKey(key)
-}
-
 // New creates a new Tangle.
 func New(store kvstore.KVStore) (result *Tangle) {
 	osFactory := objectstorage.NewFactory(store, storageprefix.MessageLayer)
 
 	result = &Tangle{
 		shutdown:               make(chan struct{}),
-		messageStorage:         osFactory.New(PrefixMessage, messageFactory, objectstorage.CacheTime(cacheTime), objectstorage.LeakDetectionEnabled(false)),
-		messageMetadataStorage: osFactory.New(PrefixMessageMetadata, MessageMetadataFromStorageKey, objectstorage.CacheTime(cacheTime), objectstorage.LeakDetectionEnabled(false)),
-		approverStorage:        osFactory.New(PrefixApprovers, approverFactory, objectstorage.CacheTime(cacheTime), objectstorage.PartitionKey(message.IDLength, message.IDLength), objectstorage.LeakDetectionEnabled(false)),
-		missingMessageStorage:  osFactory.New(PrefixMissingMessage, missingMessageFactory, objectstorage.CacheTime(cacheTime), objectstorage.LeakDetectionEnabled(false)),
+		messageStorage:         osFactory.New(PrefixMessage, message.FromObjectStorage, objectstorage.CacheTime(cacheTime), objectstorage.LeakDetectionEnabled(false)),
+		messageMetadataStorage: osFactory.New(PrefixMessageMetadata, MessageMetadataFromObjectStorage, objectstorage.CacheTime(cacheTime), objectstorage.LeakDetectionEnabled(false)),
+		approverStorage:        osFactory.New(PrefixApprovers, ApproverFromObjectStorage, objectstorage.CacheTime(cacheTime), objectstorage.PartitionKey(message.IDLength, message.IDLength), objectstorage.LeakDetectionEnabled(false)),
+		missingMessageStorage:  osFactory.New(PrefixMissingMessage, MissingMessageFromObjectStorage, objectstorage.CacheTime(cacheTime), objectstorage.LeakDetectionEnabled(false)),
 
 		Events: newEvents(),
 	}
diff --git a/packages/binary/messagelayer/tangle/tangle_test.go b/packages/binary/messagelayer/tangle/tangle_test.go
index 5cff80696c84d4cc26f8dd6911ed5db0f5d32ade..1d1ad4caa5d5298ab43dc970df4c67e9deca1dec 100644
--- a/packages/binary/messagelayer/tangle/tangle_test.go
+++ b/packages/binary/messagelayer/tangle/tangle_test.go
@@ -94,7 +94,7 @@ func TestTangle_AttachMessage(t *testing.T) {
 
 func TestTangle_MissingMessages(t *testing.T) {
 	// test parameters
-	messageCount := 200000
+	messageCount := 2000
 	widthOfTheTangle := 2500
 
 	// variables required for the test
diff --git a/packages/binary/messagelayer/test/message_test.go b/packages/binary/messagelayer/test/message_test.go
index 1a59e9b4185a8d54089ff7c3478b7a65b2ae8605..8fd3551f5a853cdfff8e7058703389927621b204 100644
--- a/packages/binary/messagelayer/test/message_test.go
+++ b/packages/binary/messagelayer/test/message_test.go
@@ -17,21 +17,6 @@ import (
 	"github.com/iotaledger/goshimmer/packages/binary/messagelayer/payload"
 )
 
-func TestMessage_StorableObjectFromKey(t *testing.T) {
-	key, err := message.NewID("2DYebCqnZ8PS5PyXBEvAvLB1fCF77Rn9RtofNHjEb2pSTujKi889d31FmguAs5DgL7YURw4GP2Y28JdJ7K4bjudG")
-	if err != nil {
-		panic(err)
-	}
-
-	messageFromKey, consumedBytes, err := message.StorableObjectFromKey(key.Bytes())
-	if err != nil {
-		panic(err)
-	}
-
-	assert.Equal(t, message.IDLength, consumedBytes)
-	assert.Equal(t, key, messageFromKey.(*message.Message).ID())
-}
-
 func TestMessage_VerifySignature(t *testing.T) {
 	keyPair := ed25519.GenerateKeyPair()
 	pl := payload.NewData([]byte("test"))
@@ -57,6 +42,7 @@ func TestMessage_MarshalUnmarshal(t *testing.T) {
 	t.Log(testMessage)
 
 	restoredMessage, _, err := message.FromBytes(testMessage.Bytes())
+
 	if assert.NoError(t, err, err) {
 		assert.Equal(t, testMessage.ID(), restoredMessage.ID())
 		assert.Equal(t, testMessage.Parent1ID(), restoredMessage.Parent1ID())
diff --git a/plugins/syncbeacon/payload/payload.go b/plugins/syncbeacon/payload/payload.go
index 8f4731f3ba7fc206fa2264e72ed04aad1e8f9102..f4319d61456ccfee93326dfc651aff8984357b3e 100644
--- a/plugins/syncbeacon/payload/payload.go
+++ b/plugins/syncbeacon/payload/payload.go
@@ -30,26 +30,17 @@ func NewSyncBeaconPayload(sentTime int64) *Payload {
 
 // FromBytes parses the marshaled version of a Payload into an object.
 // It either returns a new Payload or fills an optionally provided Payload with the parsed information.
-func FromBytes(bytes []byte, optionalTargetObject ...*Payload) (result *Payload, consumedBytes int, err error) {
-	// determine the target object that will hold the unmarshaled information
-	switch len(optionalTargetObject) {
-	case 0:
-		result = &Payload{}
-	case 1:
-		result = optionalTargetObject[0]
-	default:
-		panic("too many arguments in call to FromBytes")
-	}
-
+func FromBytes(bytes []byte) (result *Payload, consumedBytes int, err error) {
 	// initialize helper
 	marshalUtil := marshalutil.New(bytes)
 
 	// read data
-	result.payloadType, err = marshalUtil.ReadUint32()
+	result = &Payload{}
+	_, err = marshalUtil.ReadUint32()
 	if err != nil {
 		return
 	}
-	_, err = marshalUtil.ReadUint32()
+	result.payloadType, err = marshalUtil.ReadUint32()
 	if err != nil {
 		return
 	}
@@ -81,21 +72,14 @@ func (p *Payload) Bytes() []byte {
 	objectLength := marshalutil.INT64_SIZE
 
 	// marshal the p specific information
-	marshalUtil.WriteUint32(Type)
 	marshalUtil.WriteUint32(uint32(objectLength))
+	marshalUtil.WriteUint32(Type)
 	marshalUtil.WriteInt64(p.sentTime)
 
 	// return result
 	return marshalUtil.Bytes()
 }
 
-// Unmarshal unmarshals a given slice of bytes and fills the object.
-func (p *Payload) Unmarshal(data []byte) (err error) {
-	_, _, err = FromBytes(data, p)
-
-	return
-}
-
 // String returns a human readable version of syncbeacon payload (for debug purposes).
 func (p *Payload) String() string {
 	return stringify.Struct("syncBeaconPayload",
@@ -109,8 +93,7 @@ func IsSyncBeaconPayload(p *Payload) bool {
 
 func init() {
 	payload.RegisterType(Type, ObjectName, func(data []byte) (payload payload.Payload, err error) {
-		payload = &Payload{}
-		err = payload.Unmarshal(data)
+		payload, _, err = FromBytes(data)
 
 		return
 	})
diff --git a/tools/integration-tests/runTests.sh b/tools/integration-tests/runTests.sh
index 5783cc458cb9abdda0436ec2138422f78b09e8e9..0c2029fc9ba40e7d0c849b61e8a71097c8ede793 100755
--- a/tools/integration-tests/runTests.sh
+++ b/tools/integration-tests/runTests.sh
@@ -6,7 +6,7 @@ echo "Build GoShimmer image"
 docker build -t iotaledger/goshimmer ../../.
 
 echo "Pull additional Docker images"
-docker pull angelocapossele/drand:1.1.1
+docker pull angelocapossele/drand:1.1.3
 docker pull gaiaadm/pumba:0.7.2
 docker pull gaiadocker/iproute2:latest
 
diff --git a/tools/integration-tests/tester/framework/docker.go b/tools/integration-tests/tester/framework/docker.go
index 1275d21b1cfb99fea821e16f7e57d76fd170c9c9..e7e0ec9405580b108a24cf0d214ae5178dac51e2 100644
--- a/tools/integration-tests/tester/framework/docker.go
+++ b/tools/integration-tests/tester/framework/docker.go
@@ -142,7 +142,7 @@ func (d *DockerContainer) CreateDrandMember(name string, goShimmerAPI string, le
 	}
 	env = append(env, "GOSHIMMER=http://"+goShimmerAPI)
 	containerConfig := &container.Config{
-		Image: "angelocapossele/drand:1.1.1",
+		Image: "angelocapossele/drand:1.1.3",
 		ExposedPorts: nat.PortSet{
 			nat.Port("8000/tcp"): {},
 		},
diff --git a/tools/integration-tests/tester/go.mod b/tools/integration-tests/tester/go.mod
index 59217fa244b040c79587540a371fe717fd723a9d..a6aa9ac729d7484df6f2c6fd8cc1a256d30916f0 100644
--- a/tools/integration-tests/tester/go.mod
+++ b/tools/integration-tests/tester/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/docker/go-units v0.4.0 // indirect
 	github.com/drand/drand v1.1.1
 	github.com/iotaledger/goshimmer v0.1.3
-	github.com/iotaledger/hive.go v0.0.0-20200909085811-5700df262e21
+	github.com/iotaledger/hive.go v0.0.0-20200910101329-33de3e2e05c6
 	github.com/mr-tron/base58 v1.2.0
 	github.com/opencontainers/go-digest v1.0.0 // indirect
 	github.com/stretchr/testify v1.6.1
diff --git a/tools/integration-tests/tester/go.sum b/tools/integration-tests/tester/go.sum
index bcc0347749aacb626c8210ad1e4178b0ad7a7c86..7c9ae207769be3f77520048e1676dc6be108b7e5 100644
--- a/tools/integration-tests/tester/go.sum
+++ b/tools/integration-tests/tester/go.sum
@@ -340,8 +340,10 @@ github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7
 github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
-github.com/iotaledger/hive.go v0.0.0-20200909085811-5700df262e21 h1:ZbVqGAVePnHgTSF4ZuXXH9G+UBQcp1/KUbqpTBMaapg=
-github.com/iotaledger/hive.go v0.0.0-20200909085811-5700df262e21/go.mod h1:tLI+HS0amqY5YqClfFZDHlFM7eeIZjoU25Oj1u9jCzQ=
+github.com/iotaledger/hive.go v0.0.0-20200910095757-d9faf5386bb9 h1:/HxV4+EUwvM0b5rq8UkMSIOvgEpwIfWriexNoZPrYxs=
+github.com/iotaledger/hive.go v0.0.0-20200910095757-d9faf5386bb9/go.mod h1:tLI+HS0amqY5YqClfFZDHlFM7eeIZjoU25Oj1u9jCzQ=
+github.com/iotaledger/hive.go v0.0.0-20200910101329-33de3e2e05c6 h1:fYKwzYCzewzTLFb/hCEnJtopHL7Qm+Ztvki+6Z2bVXo=
+github.com/iotaledger/hive.go v0.0.0-20200910101329-33de3e2e05c6/go.mod h1:tLI+HS0amqY5YqClfFZDHlFM7eeIZjoU25Oj1u9jCzQ=
 github.com/iotaledger/iota.go v1.0.0-beta.15/go.mod h1:Rn6v5hLAn8YBaJlRu1ZQdPAgKlshJR1PTeLQaft2778=
 github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
 github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
diff --git a/tools/integration-tests/tester/tests/drng/drng_test.go b/tools/integration-tests/tester/tests/drng/drng_test.go
index dea82b0676afece108be3d9dd01a8906b15de0cc..f223aaded6df78f3747cf096be90706fa7a62d99 100644
--- a/tools/integration-tests/tester/tests/drng/drng_test.go
+++ b/tools/integration-tests/tester/tests/drng/drng_test.go
@@ -31,7 +31,10 @@ func TestDRNG(t *testing.T) {
 
 	// randomness starts at round = 2
 	firstRound := uint64(2)
-	_, err = waitForRound(t, drng.Peers()[0], firstRound, 200)
+	resp, err := waitForRound(t, drng.Peers()[0], firstRound, 200)
+	if err != nil {
+		t.Log(resp)
+	}
 	require.NoError(t, err)
 
 	log.Printf("Waiting for randomness generation to be started... done\n")