diff --git a/dapps/valuetransfers/packages/tangle/errors.go b/dapps/valuetransfers/packages/tangle/errors.go
new file mode 100644
index 0000000000000000000000000000000000000000..3ada3b8ae0f57de974ed9bcc4a11012a6db3b5c4
--- /dev/null
+++ b/dapps/valuetransfers/packages/tangle/errors.go
@@ -0,0 +1,14 @@
+package tangle
+
+import "errors"
+
+var (
+	// ErrFatal represents an error that is not "expected".
+	ErrFatal = errors.New("fatal error")
+
+	// ErrTransactionInvalid represents an error type that is triggered when an invalid transaction is detected.
+	ErrTransactionInvalid = errors.New("transaction invalid")
+
+	// ErrPayloadInvalid represents an error type that is triggered when an invalid payload is detected.
+	ErrPayloadInvalid = errors.New("payload invalid")
+)
diff --git a/dapps/valuetransfers/packages/tangle/events.go b/dapps/valuetransfers/packages/tangle/events.go
index 8194f08f1e9d8e2fe71bc17b0627e41cd276cf84..17207555c01f1fd714c7fdef352e46fbab7cd994 100644
--- a/dapps/valuetransfers/packages/tangle/events.go
+++ b/dapps/valuetransfers/packages/tangle/events.go
@@ -19,7 +19,6 @@ type Events struct {
 	MissingPayloadReceived *events.Event
 	PayloadMissing         *events.Event
 	PayloadInvalid         *events.Event
-	PayloadUnsolidifiable  *events.Event
 
 	// TransactionReceived gets triggered whenever a transaction was received for the first time (not solid yet).
 	TransactionReceived *events.Event
@@ -81,7 +80,6 @@ func newEvents() *Events {
 		MissingPayloadReceived: events.NewEvent(cachedPayloadEvent),
 		PayloadMissing:         events.NewEvent(payloadIDEvent),
 		PayloadInvalid:         events.NewEvent(cachedPayloadErrorEvent),
-		PayloadUnsolidifiable:  events.NewEvent(payloadIDEvent),
 		TransactionReceived:    events.NewEvent(cachedTransactionAttachmentEvent),
 		TransactionInvalid:     events.NewEvent(cachedTransactionErrorEvent),
 		TransactionSolid:       events.NewEvent(cachedTransactionEvent),
diff --git a/dapps/valuetransfers/packages/tangle/tangle.go b/dapps/valuetransfers/packages/tangle/tangle.go
index 6b0fa17d077f11125bf4e75a429178b1c3b1d0fa..e87870868934de9320f5e05aba1884585b10b24d 100644
--- a/dapps/valuetransfers/packages/tangle/tangle.go
+++ b/dapps/valuetransfers/packages/tangle/tangle.go
@@ -36,7 +36,7 @@ type Tangle struct {
 	outputStorage              *objectstorage.ObjectStorage
 	consumerStorage            *objectstorage.ObjectStorage
 
-	Events Events
+	Events *Events
 
 	workerPool async.WorkerPool
 }
@@ -58,7 +58,7 @@ func New(store kvstore.KVStore) (tangle *Tangle) {
 		outputStorage:              osFactory.New(osOutput, osOutputFactory, OutputKeyPartitions, objectstorage.CacheTime(cacheTime), osLeakDetectionOption),
 		consumerStorage:            osFactory.New(osConsumer, osConsumerFactory, ConsumerPartitionKeys, objectstorage.CacheTime(cacheTime), osLeakDetectionOption),
 
-		Events: *newEvents(),
+		Events: newEvents(),
 	}
 	tangle.setupDAGSynchronization()
 
@@ -194,13 +194,13 @@ func (tangle *Tangle) Fork(transactionID transaction.ID, conflictingInputs []tra
 
 	tx := cachedTransaction.Unwrap()
 	if tx == nil {
-		err = fmt.Errorf("failed to load transaction '%s'", transactionID)
+		err = fmt.Errorf("failed to load transaction '%s': %w", transactionID, ErrFatal)
 
 		return
 	}
 	txMetadata := cachedTransactionMetadata.Unwrap()
 	if txMetadata == nil {
-		err = fmt.Errorf("failed to load metadata of transaction '%s'", transactionID)
+		err = fmt.Errorf("failed to load metadata of transaction '%s': %w", transactionID, ErrFatal)
 
 		return
 	}
@@ -235,7 +235,7 @@ func (tangle *Tangle) Fork(transactionID transaction.ID, conflictingInputs []tra
 	}
 
 	// trigger events + set result
-	tangle.Events.Fork.Trigger(cachedTransaction, cachedTransactionMetadata)
+	tangle.Events.Fork.Trigger(cachedTransaction, cachedTransactionMetadata, cachedTargetBranch, conflictingInputs)
 	forked = true
 
 	return
@@ -1033,7 +1033,7 @@ func (tangle *Tangle) solidifyPayload(cachedPayload *payload.CachedPayload, cach
 
 // deleteTransactionFutureCone removes a transaction and its whole future cone from the database (including all of the
 // reference models).
-func (tangle *Tangle) deleteTransactionFutureCone(transactionID transaction.ID) {
+func (tangle *Tangle) deleteTransactionFutureCone(transactionID transaction.ID, cause error) {
 	// initialize stack with current transaction
 	deleteStack := list.New()
 	deleteStack.PushBack(transactionID)
@@ -1046,7 +1046,7 @@ func (tangle *Tangle) deleteTransactionFutureCone(transactionID transaction.ID)
 		currentTransactionID := currentTransactionIDEntry.Value.(transaction.ID)
 
 		// delete the transaction
-		consumers, attachments := tangle.deleteTransaction(currentTransactionID)
+		consumers, attachments := tangle.deleteTransaction(currentTransactionID, cause)
 
 		// queue consumers to also be deleted
 		for _, consumer := range consumers {
@@ -1055,7 +1055,7 @@ func (tangle *Tangle) deleteTransactionFutureCone(transactionID transaction.ID)
 
 		// remove payload future cone
 		for _, attachingPayloadID := range attachments {
-			tangle.deletePayloadFutureCone(attachingPayloadID)
+			tangle.deletePayloadFutureCone(attachingPayloadID, cause)
 		}
 	}
 }
@@ -1063,13 +1063,21 @@ func (tangle *Tangle) deleteTransactionFutureCone(transactionID transaction.ID)
 // deleteTransaction deletes a single transaction and all of its related models from the database.
 // Note: We do not immediately remove the attachments as this is related to the Payloads and is therefore left to the
 //       caller to clean this up.
-func (tangle *Tangle) deleteTransaction(transactionID transaction.ID) (consumers []transaction.ID, attachments []payload.ID) {
+func (tangle *Tangle) deleteTransaction(transactionID transaction.ID, cause error) (consumers []transaction.ID, attachments []payload.ID) {
 	// create result
 	consumers = make([]transaction.ID, 0)
 	attachments = make([]payload.ID, 0)
 
+	cachedTransaction := tangle.Transaction(transactionID)
+	cachedTransactionMetadata := tangle.TransactionMetadata(transactionID)
+
 	// process transaction and its models
-	tangle.Transaction(transactionID).Consume(func(tx *transaction.Transaction) {
+	cachedTransaction.Consume(func(tx *transaction.Transaction) {
+		// if the removal was triggered by an invalid Transaction
+		if errors.Is(cause, ErrTransactionInvalid) {
+			tangle.Events.TransactionInvalid.Trigger(cachedTransaction, cachedTransactionMetadata, cause)
+		}
+
 		// mark transaction as deleted
 		tx.Delete()
 
@@ -1107,7 +1115,9 @@ func (tangle *Tangle) deleteTransaction(transactionID transaction.ID) (consumers
 	})
 
 	// delete transaction metadata
-	tangle.transactionMetadataStorage.Delete(transactionID.Bytes())
+	cachedTransactionMetadata.Consume(func(metadata *TransactionMetadata) {
+		metadata.Delete()
+	})
 
 	// process attachments
 	tangle.Attachments(transactionID).Consume(func(attachment *Attachment) {
@@ -1119,7 +1129,7 @@ func (tangle *Tangle) deleteTransaction(transactionID transaction.ID) (consumers
 
 // deletePayloadFutureCone removes a payload and its whole future cone from the database (including all of the reference
 // models).
-func (tangle *Tangle) deletePayloadFutureCone(payloadID payload.ID) {
+func (tangle *Tangle) deletePayloadFutureCone(payloadID payload.ID, cause error) {
 	// initialize stack with current transaction
 	deleteStack := list.New()
 	deleteStack.PushBack(payloadID)
@@ -1131,8 +1141,16 @@ func (tangle *Tangle) deletePayloadFutureCone(payloadID payload.ID) {
 		deleteStack.Remove(currentTransactionIDEntry)
 		currentPayloadID := currentTransactionIDEntry.Value.(payload.ID)
 
+		cachedPayload := tangle.Payload(currentPayloadID)
+		cachedPayloadMetadata := tangle.PayloadMetadata(currentPayloadID)
+
 		// process payload
-		tangle.Payload(currentPayloadID).Consume(func(currentPayload *payload.Payload) {
+		cachedPayload.Consume(func(currentPayload *payload.Payload) {
+			// trigger payload invalid if it was called with an "invalid cause"
+			if errors.Is(cause, ErrPayloadInvalid) || errors.Is(cause, ErrTransactionInvalid) {
+				tangle.Events.PayloadInvalid.Trigger(cachedPayload, cachedPayloadMetadata, cause)
+			}
+
 			// delete payload
 			currentPayload.Delete()
 
@@ -1147,12 +1165,14 @@ func (tangle *Tangle) deletePayloadFutureCone(payloadID payload.ID) {
 
 			// if this was the last attachment of the transaction then we also delete the transaction
 			if !tangle.Attachments(currentPayload.Transaction().ID()).Consume(func(attachment *Attachment) {}) {
-				tangle.deleteTransaction(currentPayload.Transaction().ID())
+				tangle.deleteTransaction(currentPayload.Transaction().ID(), nil)
 			}
 		})
 
 		// delete payload metadata
-		tangle.payloadMetadataStorage.Delete(currentPayloadID.Bytes())
+		cachedPayloadMetadata.Consume(func(payloadMetadata *PayloadMetadata) {
+			payloadMetadata.Delete()
+		})
 
 		// queue approvers
 		tangle.Approvers(currentPayloadID).Consume(func(approver *PayloadApprover) {
@@ -1176,9 +1196,7 @@ func (tangle *Tangle) processSolidificationStackEntry(solidificationStack *list.
 	// abort if the transaction is not solid or invalid
 	transactionSolid, consumedBranches, transactionSolidityErr := tangle.checkTransactionSolidity(currentTransaction, currentTransactionMetadata)
 	if transactionSolidityErr != nil {
-		tangle.Events.TransactionInvalid.Trigger(solidificationStackEntry.CachedTransaction, solidificationStackEntry.CachedTransactionMetadata, transactionSolidityErr)
-
-		tangle.deleteTransactionFutureCone(currentTransaction.ID())
+		tangle.deleteTransactionFutureCone(currentTransaction.ID(), transactionSolidityErr)
 
 		return
 	}
@@ -1189,9 +1207,7 @@ func (tangle *Tangle) processSolidificationStackEntry(solidificationStack *list.
 	// abort if the payload is not solid or invalid
 	payloadSolid, payloadSolidityErr := tangle.payloadBecameNewlySolid(currentPayload, currentPayloadMetadata, consumedBranches)
 	if payloadSolidityErr != nil {
-		tangle.Events.PayloadInvalid.Trigger(solidificationStackEntry.CachedPayload, solidificationStackEntry.CachedPayloadMetadata, payloadSolidityErr)
-
-		tangle.deletePayloadFutureCone(currentPayload.ID())
+		tangle.deletePayloadFutureCone(currentPayload.ID(), payloadSolidityErr)
 
 		return
 	}
@@ -1275,7 +1291,7 @@ func (tangle *Tangle) bookTransaction(cachedTransaction *transaction.CachedTrans
 		// abort if the output could not be found
 		output := cachedOutput.Unwrap()
 		if output == nil {
-			err = fmt.Errorf("could not load output '%s'", outputID)
+			err = fmt.Errorf("could not load output '%s': %w", outputID, ErrFatal)
 
 			return false
 		}
@@ -1493,7 +1509,7 @@ func (tangle *Tangle) payloadBecameNewlySolid(p *payload.Payload, payloadMetadat
 		return
 	}
 	if branchesConflicting {
-		err = fmt.Errorf("the payload '%s' combines conflicting versions of the ledger state", p.ID())
+		err = fmt.Errorf("the payload '%s' combines conflicting versions of the ledger state: %w", p.ID(), ErrPayloadInvalid)
 
 		return false, err
 	}
@@ -1527,7 +1543,7 @@ func (tangle *Tangle) checkTransactionSolidity(tx *transaction.Transaction, meta
 
 	// abort if the outputs are not matching the inputs
 	if !tangle.checkTransactionOutputs(consumedBalances, tx.Outputs()) {
-		err = fmt.Errorf("the outputs do not match the inputs in transaction with id '%s'", tx.ID())
+		err = fmt.Errorf("the outputs do not match the inputs in transaction with id '%s': %w", tx.ID(), ErrTransactionInvalid)
 
 		return
 	}
@@ -1539,7 +1555,7 @@ func (tangle *Tangle) checkTransactionSolidity(tx *transaction.Transaction, meta
 		return
 	}
 	if branchesConflicting {
-		err = fmt.Errorf("the transaction '%s' spends conflicting inputs", tx.ID())
+		err = fmt.Errorf("the transaction '%s' spends conflicting inputs: %w", tx.ID(), ErrTransactionInvalid)
 
 		return
 	}
@@ -1582,7 +1598,7 @@ func (tangle *Tangle) retrieveConsumedInputDetails(tx *transaction.Transaction)
 				// check overflows in the numbers
 				if inputBalance.Value() > math.MaxInt64-currentBalance {
 					// TODO: make it an explicit error var
-					err = fmt.Errorf("buffer overflow in balances of inputs")
+					err = fmt.Errorf("buffer overflow in balances of inputs: %w", ErrTransactionInvalid)
 
 					cachedInputs.Release()
 
@@ -1783,7 +1799,7 @@ func (tangle *Tangle) moveTransactionToBranch(cachedTransaction *transaction.Cac
 						// unwrap output
 						output := cachedOutput.Unwrap()
 						if output == nil {
-							err = fmt.Errorf("failed to load output '%s'", outputID)
+							err = fmt.Errorf("failed to load output '%s': %w", outputID, ErrFatal)
 
 							return false
 						}
@@ -1905,7 +1921,7 @@ func (tangle *Tangle) calculateBranchOfTransaction(currentTransaction *transacti
 
 		transactionOutput := cachedTransactionOutput.Unwrap()
 		if transactionOutput == nil {
-			err = fmt.Errorf("failed to load output '%s'", outputId)
+			err = fmt.Errorf("failed to load output '%s': %w", outputId, ErrFatal)
 
 			return false
 		}
diff --git a/dapps/valuetransfers/packages/tangle/tangle_event_test.go b/dapps/valuetransfers/packages/tangle/tangle_event_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..bdd3f1dfc42386262c342e644c8d298852563958
--- /dev/null
+++ b/dapps/valuetransfers/packages/tangle/tangle_event_test.go
@@ -0,0 +1,211 @@
+package tangle
+
+import (
+	"reflect"
+	"testing"
+
+	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/branchmanager"
+	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload"
+	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
+	"github.com/iotaledger/hive.go/events"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
+)
+
+// eventTangle is a wrapper around Tangle used to test the triggered events.
+type eventTangle struct {
+	mock.Mock
+	*Tangle
+
+	attached []struct {
+		*events.Event
+		*events.Closure
+	}
+}
+
+func newEventTangle(t *testing.T, tangle *Tangle) *eventTangle {
+	e := &eventTangle{Tangle: tangle}
+	e.Test(t)
+
+	// attach all events
+	e.attach(tangle.Events.PayloadAttached, e.PayloadAttached)
+	e.attach(tangle.Events.PayloadSolid, e.PayloadSolid)
+	e.attach(tangle.Events.PayloadLiked, e.PayloadLiked)
+	e.attach(tangle.Events.PayloadConfirmed, e.PayloadConfirmed)
+	e.attach(tangle.Events.PayloadRejected, e.PayloadRejected)
+	e.attach(tangle.Events.PayloadDisliked, e.PayloadDisliked)
+	e.attach(tangle.Events.MissingPayloadReceived, e.MissingPayloadReceived)
+	e.attach(tangle.Events.PayloadMissing, e.PayloadMissing)
+	e.attach(tangle.Events.PayloadInvalid, e.PayloadInvalid)
+	e.attach(tangle.Events.TransactionReceived, e.TransactionReceived)
+	e.attach(tangle.Events.TransactionInvalid, e.TransactionInvalid)
+	e.attach(tangle.Events.TransactionSolid, e.TransactionSolid)
+	e.attach(tangle.Events.TransactionBooked, e.TransactionBooked)
+	e.attach(tangle.Events.TransactionPreferred, e.TransactionPreferred)
+	e.attach(tangle.Events.TransactionUnpreferred, e.TransactionUnpreferred)
+	e.attach(tangle.Events.TransactionLiked, e.TransactionLiked)
+	e.attach(tangle.Events.TransactionDisliked, e.TransactionDisliked)
+	e.attach(tangle.Events.TransactionFinalized, e.TransactionFinalized)
+	e.attach(tangle.Events.TransactionConfirmed, e.TransactionConfirmed)
+	e.attach(tangle.Events.TransactionRejected, e.TransactionRejected)
+	e.attach(tangle.Events.Fork, e.Fork)
+	e.attach(tangle.Events.Error, e.Error)
+
+	// assure that all available events are mocked
+	numEvents := reflect.ValueOf(tangle.Events).Elem().NumField()
+	assert.Equalf(t, len(e.attached), numEvents, "not all events in Tangle.Events have been attached")
+
+	return e
+}
+
+// DetachAll detaches all attached event mocks.
+func (e *eventTangle) DetachAll() {
+	for _, a := range e.attached {
+		a.Event.Detach(a.Closure)
+	}
+}
+
+func (e *eventTangle) attach(event *events.Event, f interface{}) {
+	closure := events.NewClosure(f)
+	event.Attach(closure)
+	e.attached = append(e.attached, struct {
+		*events.Event
+		*events.Closure
+	}{event, closure})
+}
+
+// Expect starts a description of an expectation of the specified event being triggered.
+func (e *eventTangle) Expect(eventName string, arguments ...interface{}) {
+	e.On(eventName, arguments...).Once()
+}
+
+func (e *eventTangle) PayloadAttached(payload *payload.CachedPayload, payloadMetadata *CachedPayloadMetadata) {
+	defer payload.Release()
+	defer payloadMetadata.Release()
+	e.Called(payload.Unwrap(), payloadMetadata.Unwrap())
+}
+
+func (e *eventTangle) PayloadSolid(payload *payload.CachedPayload, payloadMetadata *CachedPayloadMetadata) {
+	defer payload.Release()
+	defer payloadMetadata.Release()
+	e.Called(payload.Unwrap(), payloadMetadata.Unwrap())
+}
+
+func (e *eventTangle) PayloadLiked(payload *payload.CachedPayload, payloadMetadata *CachedPayloadMetadata) {
+	defer payload.Release()
+	defer payloadMetadata.Release()
+	e.Called(payload.Unwrap(), payloadMetadata.Unwrap())
+}
+
+func (e *eventTangle) PayloadConfirmed(payload *payload.CachedPayload, payloadMetadata *CachedPayloadMetadata) {
+	defer payload.Release()
+	defer payloadMetadata.Release()
+	e.Called(payload.Unwrap(), payloadMetadata.Unwrap())
+}
+
+func (e *eventTangle) PayloadRejected(payload *payload.CachedPayload, payloadMetadata *CachedPayloadMetadata) {
+	defer payload.Release()
+	defer payloadMetadata.Release()
+	e.Called(payload.Unwrap(), payloadMetadata.Unwrap())
+}
+
+func (e *eventTangle) PayloadDisliked(payload *payload.CachedPayload, payloadMetadata *CachedPayloadMetadata) {
+	defer payload.Release()
+	defer payloadMetadata.Release()
+	e.Called(payload.Unwrap(), payloadMetadata.Unwrap())
+}
+
+func (e *eventTangle) MissingPayloadReceived(payload *payload.CachedPayload, payloadMetadata *CachedPayloadMetadata) {
+	defer payload.Release()
+	defer payloadMetadata.Release()
+	e.Called(payload.Unwrap(), payloadMetadata.Unwrap())
+}
+
+func (e *eventTangle) PayloadMissing(id payload.ID) {
+	e.Called(id)
+}
+
+func (e *eventTangle) PayloadInvalid(payload *payload.CachedPayload, payloadMetadata *CachedPayloadMetadata, err error) {
+	defer payload.Release()
+	defer payloadMetadata.Release()
+	e.Called(payload.Unwrap(), payloadMetadata.Unwrap(), err)
+}
+
+func (e *eventTangle) TransactionReceived(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata, attachment *CachedAttachment) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	defer attachment.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap(), attachment.Unwrap())
+}
+
+func (e *eventTangle) TransactionInvalid(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata, err error) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap(), err)
+}
+
+func (e *eventTangle) TransactionSolid(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap())
+}
+
+func (e *eventTangle) TransactionBooked(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata, decisionPending bool) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap(), decisionPending)
+}
+
+func (e *eventTangle) TransactionPreferred(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap())
+}
+
+func (e *eventTangle) TransactionUnpreferred(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap())
+}
+
+func (e *eventTangle) TransactionLiked(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap())
+}
+
+func (e *eventTangle) TransactionDisliked(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap())
+}
+
+func (e *eventTangle) TransactionFinalized(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap())
+}
+
+func (e *eventTangle) TransactionConfirmed(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap())
+}
+
+func (e *eventTangle) TransactionRejected(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap())
+}
+
+func (e *eventTangle) Fork(transaction *transaction.CachedTransaction, transactionMetadata *CachedTransactionMetadata, branch *branchmanager.CachedBranch, outputIDs []transaction.OutputID) {
+	defer transaction.Release()
+	defer transactionMetadata.Release()
+	defer branch.Release()
+	e.Called(transaction.Unwrap(), transactionMetadata.Unwrap(), branch.Unwrap(), outputIDs)
+}
+
+// TODO: Error is never tested
+func (e *eventTangle) Error(err error) {
+	e.Called(err)
+}
diff --git a/dapps/valuetransfers/packages/tangle/tangle_scenario_test.go b/dapps/valuetransfers/packages/tangle/tangle_scenario_test.go
index 63a8889e3eb4bd02e0a2a7de51cf75599643f3a3..5d185f9637fef1a7bef59f8e8b69138936f2ac37 100644
--- a/dapps/valuetransfers/packages/tangle/tangle_scenario_test.go
+++ b/dapps/valuetransfers/packages/tangle/tangle_scenario_test.go
@@ -12,6 +12,7 @@ import (
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/wallet"
 	"github.com/iotaledger/hive.go/kvstore/mapdb"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
 	"github.com/stretchr/testify/require"
 )
 
@@ -33,9 +34,9 @@ const (
 // TODO: clean up create scenario with some helper functions: DRY!
 
 // preparePropagationScenario1 creates a tangle according to `img/scenario1.png`.
-func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction.Transaction, map[string]*payload.Payload, map[string]branchmanager.BranchID, *wallet.Seed) {
+func preparePropagationScenario1(t *testing.T) (*eventTangle, map[string]*transaction.Transaction, map[string]*payload.Payload, map[string]branchmanager.BranchID, *wallet.Seed) {
 	// create tangle
-	tangle := New(mapdb.NewMapDB())
+	tangle := newEventTangle(t, New(mapdb.NewMapDB()))
 
 	// create seed for testing
 	seed := wallet.NewSeed()
@@ -80,6 +81,12 @@ func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction
 		// check if signatures are valid
 		assert.True(t, transactions["[-GENESIS, A+, B+, C+]"].SignaturesValid())
 
+		tangle.Expect("PayloadAttached", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("PayloadSolid", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionReceived", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything, mock.Anything)
+		tangle.Expect("TransactionSolid", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionBooked", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything, true)
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-GENESIS, A+, B+, C+]"])
 
@@ -148,6 +155,12 @@ func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction
 		// check if signatures are valid
 		assert.True(t, transactions["[-A, D+]"].SignaturesValid())
 
+		tangle.Expect("PayloadAttached", valueObjects["[-A, D+]"], mock.Anything)
+		tangle.Expect("PayloadSolid", valueObjects["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionReceived", transactions["[-A, D+]"], mock.Anything, mock.Anything)
+		tangle.Expect("TransactionSolid", transactions["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionBooked", transactions["[-A, D+]"], mock.Anything, true)
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-A, D+]"])
 
@@ -202,6 +215,12 @@ func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction
 		// check if signatures are valid
 		assert.True(t, transactions["[-B, -C, E+]"].SignaturesValid())
 
+		tangle.Expect("PayloadAttached", valueObjects["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadSolid", valueObjects["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionReceived", transactions["[-B, -C, E+]"], mock.Anything, mock.Anything)
+		tangle.Expect("TransactionSolid", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionBooked", transactions["[-B, -C, E+]"], mock.Anything, true)
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-B, -C, E+]"])
 
@@ -247,6 +266,9 @@ func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction
 		// create payload
 		valueObjects["[-B, -C, E+] (Reattachment)"] = payload.New(valueObjects["[-B, -C, E+]"].ID(), valueObjects["[-GENESIS, A+, B+, C+]"].ID(), transactions["[-B, -C, E+]"])
 
+		tangle.Expect("PayloadAttached", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+		tangle.Expect("PayloadSolid", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-B, -C, E+] (Reattachment)"])
 
@@ -290,9 +312,10 @@ func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction
 	// [-A, F+]
 	{
 		// create transaction + payload
+		outputA := transaction.NewOutputID(seed.Address(A), transactions["[-GENESIS, A+, B+, C+]"].ID())
 		transactions["[-A, F+]"] = transaction.New(
 			transaction.NewInputs(
-				transaction.NewOutputID(seed.Address(A), transactions["[-GENESIS, A+, B+, C+]"].ID()),
+				outputA,
 			),
 
 			transaction.NewOutputs(map[address.Address][]*balance.Balance{
@@ -307,6 +330,13 @@ func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction
 		// check if signatures are valid
 		assert.True(t, transactions["[-A, F+]"].SignaturesValid())
 
+		tangle.Expect("PayloadAttached", valueObjects["[-A, F+]"], mock.Anything)
+		tangle.Expect("PayloadSolid", valueObjects["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionReceived", transactions["[-A, F+]"], mock.Anything, mock.Anything)
+		tangle.Expect("TransactionSolid", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionBooked", transactions["[-A, F+]"], mock.Anything, true)
+		tangle.Expect("Fork", transactions["[-A, D+]"], mock.Anything, mock.Anything, []transaction.OutputID{outputA})
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-A, F+]"])
 
@@ -384,6 +414,12 @@ func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction
 		// check if signatures are valid
 		assert.True(t, transactions["[-E, -F, G+]"].SignaturesValid())
 
+		tangle.Expect("PayloadAttached", valueObjects["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("PayloadSolid", valueObjects["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionReceived", transactions["[-E, -F, G+]"], mock.Anything, mock.Anything)
+		tangle.Expect("TransactionSolid", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionBooked", transactions["[-E, -F, G+]"], mock.Anything, true)
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-E, -F, G+]"])
 
@@ -446,6 +482,11 @@ func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction
 		// check if signatures are valid
 		assert.True(t, transactions["[-F, -D, Y+]"].SignaturesValid())
 
+		tangle.Expect("PayloadAttached", valueObjects["[-F, -D, Y+]"], mock.Anything)
+		tangle.Expect("PayloadInvalid", valueObjects["[-F, -D, Y+]"], mock.Anything, mock.MatchedBy(func(err error) bool { return assert.Error(t, err) }))
+		tangle.Expect("TransactionReceived", transactions["[-F, -D, Y+]"], mock.Anything, mock.Anything)
+		tangle.Expect("TransactionInvalid", transactions["[-F, -D, Y+]"], mock.Anything, mock.MatchedBy(func(err error) bool { return assert.Error(t, err) }))
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-F, -D, Y+]"])
 
@@ -469,6 +510,9 @@ func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction
 	{
 		valueObjects["[-B, -C, E+] (2nd Reattachment)"] = payload.New(valueObjects["[-A, F+]"].ID(), valueObjects["[-A, D+]"].ID(), transactions["[-B, -C, E+]"])
 
+		tangle.Expect("PayloadAttached", valueObjects["[-B, -C, E+] (2nd Reattachment)"], mock.Anything)
+		tangle.Expect("PayloadInvalid", valueObjects["[-B, -C, E+] (2nd Reattachment)"], mock.Anything, mock.MatchedBy(func(err error) bool { return assert.Error(t, err) }))
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-B, -C, E+] (2nd Reattachment)"])
 
@@ -498,15 +542,16 @@ func preparePropagationScenario1(t *testing.T) (*Tangle, map[string]*transaction
 }
 
 // preparePropagationScenario1 creates a tangle according to `img/scenario2.png`.
-func preparePropagationScenario2(t *testing.T) (*Tangle, map[string]*transaction.Transaction, map[string]*payload.Payload, map[string]branchmanager.BranchID, *wallet.Seed) {
+func preparePropagationScenario2(t *testing.T) (*eventTangle, map[string]*transaction.Transaction, map[string]*payload.Payload, map[string]branchmanager.BranchID, *wallet.Seed) {
 	tangle, transactions, valueObjects, branches, seed := preparePropagationScenario1(t)
 
 	// [-C, H+]
 	{
 		// create transaction + payload
+		outputC := transaction.NewOutputID(seed.Address(C), transactions["[-GENESIS, A+, B+, C+]"].ID())
 		transactions["[-C, H+]"] = transaction.New(
 			transaction.NewInputs(
-				transaction.NewOutputID(seed.Address(C), transactions["[-GENESIS, A+, B+, C+]"].ID()),
+				outputC,
 			),
 
 			transaction.NewOutputs(map[address.Address][]*balance.Balance{
@@ -521,6 +566,13 @@ func preparePropagationScenario2(t *testing.T) (*Tangle, map[string]*transaction
 		// check if signatures are valid
 		assert.True(t, transactions["[-C, H+]"].SignaturesValid())
 
+		tangle.Expect("PayloadAttached", valueObjects["[-C, H+]"], mock.Anything)
+		tangle.Expect("PayloadSolid", valueObjects["[-C, H+]"], mock.Anything)
+		tangle.Expect("TransactionReceived", transactions["[-C, H+]"], mock.Anything, mock.Anything)
+		tangle.Expect("TransactionSolid", transactions["[-C, H+]"], mock.Anything)
+		tangle.Expect("TransactionBooked", transactions["[-C, H+]"], mock.Anything, true)
+		tangle.Expect("Fork", transactions["[-B, -C, E+]"], mock.Anything, mock.Anything, []transaction.OutputID{outputC})
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-C, H+]"])
 
@@ -620,6 +672,12 @@ func preparePropagationScenario2(t *testing.T) (*Tangle, map[string]*transaction
 		// check if signatures are valid
 		assert.True(t, transactions["[-H, -D, I+]"].SignaturesValid())
 
+		tangle.Expect("PayloadAttached", valueObjects["[-H, -D, I+]"], mock.Anything)
+		tangle.Expect("PayloadSolid", valueObjects["[-H, -D, I+]"], mock.Anything)
+		tangle.Expect("TransactionReceived", transactions["[-H, -D, I+]"], mock.Anything, mock.Anything)
+		tangle.Expect("TransactionSolid", transactions["[-H, -D, I+]"], mock.Anything)
+		tangle.Expect("TransactionBooked", transactions["[-H, -D, I+]"], mock.Anything, true)
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-H, -D, I+]"])
 
@@ -683,6 +741,12 @@ func preparePropagationScenario2(t *testing.T) (*Tangle, map[string]*transaction
 		// check if signatures are valid
 		assert.True(t, transactions["[-B, J+]"].SignaturesValid())
 
+		tangle.Expect("PayloadAttached", valueObjects["[-B, J+]"], mock.Anything)
+		tangle.Expect("PayloadSolid", valueObjects["[-B, J+]"], mock.Anything)
+		tangle.Expect("TransactionReceived", transactions["[-B, J+]"], mock.Anything, mock.Anything)
+		tangle.Expect("TransactionSolid", transactions["[-B, J+]"], mock.Anything)
+		tangle.Expect("TransactionBooked", transactions["[-B, J+]"], mock.Anything, true)
+
 		// attach payload
 		tangle.AttachPayloadSync(valueObjects["[-B, J+]"])
 
@@ -736,6 +800,7 @@ func TestPropagationScenario1(t *testing.T) {
 	// test past cone monotonicity - all value objects MUST be confirmed
 	{
 		tangle, transactions, valueObjects, _, _ := preparePropagationScenario1(t)
+		defer tangle.DetachAll()
 
 		// initialize debugger for this test
 		debugger.ResetAliases()
@@ -746,42 +811,79 @@ func TestPropagationScenario1(t *testing.T) {
 			debugger.RegisterAlias(tx.ID(), "TransactionID"+name)
 		}
 
+		// preferring [-GENESIS, A+, B+, C+] will get it liked
+		tangle.Expect("TransactionPreferred", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("PayloadLiked", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"], true)
 		verifyInclusionState(t, tangle, valueObjects["[-GENESIS, A+, B+, C+]"], true, false, true, false, false)
 
-		// should not be confirmed because [-GENESIS, A+, B+, C+] is not confirmed
+		// finalizing [-B, -C, E+] will not get it confirmed, as [-GENESIS, A+, B+, C+] is not yet confirmed
+		tangle.Expect("TransactionPreferred", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadLiked", valueObjects["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadLiked", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-B, -C, E+]"], true)
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-B, -C, E+]"])
 		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+]"], true, true, true, false, false)
 
-		// now finalize [-GENESIS, A+, B+, C+]
+		// finalize [-GENESIS, A+, B+, C+] to also get [-B, -C, E+] as well as [-B, -C, E+] (Reattachment) confirmed
+		tangle.Expect("TransactionFinalized", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionConfirmed", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionConfirmed", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"])
 		verifyInclusionState(t, tangle, valueObjects["[-GENESIS, A+, B+, C+]"], true, true, true, true, false)
-
-		// and [-B, -C, E+] should be confirmed now too
 		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+]"], true, true, true, true, false)
-		// as well as the reattachment
 		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+] (Reattachment)"], true, true, true, true, false)
+
+		tangle.AssertExpectations(t)
 	}
 
 	// test future cone monotonicity simple - everything MUST be rejected and finalized if spending funds from rejected tx
 	{
 		tangle, transactions, valueObjects, _, _ := preparePropagationScenario1(t)
+		defer tangle.DetachAll()
+
+		// finalizing [-GENESIS, A+, B+, C+] will get the entire future cone finalized and rejected
+		tangle.Expect("TransactionFinalized", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionRejected", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionRejected", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionRejected", transactions["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionRejected", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionRejected", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-A, D+]"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-A, F+]"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-E, -F, G+]"], mock.Anything)
 
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"])
 		verifyInclusionState(t, tangle, valueObjects["[-GENESIS, A+, B+, C+]"], false, true, false, false, true)
-
-		// check future cone to be rejected
 		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+]"], false, true, false, false, true)
 		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+] (Reattachment)"], false, true, false, false, true)
 		verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], false, true, false, false, true)
 		verifyInclusionState(t, tangle, valueObjects["[-A, F+]"], false, true, false, false, true)
 		verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], false, true, false, false, true)
+
+		tangle.AssertExpectations(t)
 	}
 
 	// test future cone monotonicity more complex - everything MUST be rejected and finalized if spending funds from rejected tx
 	{
 		tangle, transactions, valueObjects, branches, _ := preparePropagationScenario1(t)
+		defer tangle.DetachAll()
 
 		// initialize debugger for this test
 		debugger.ResetAliases()
@@ -792,10 +894,26 @@ func TestPropagationScenario1(t *testing.T) {
 			debugger.RegisterAlias(tx.ID(), "TransactionID"+name)
 		}
 
+		tangle.Expect("TransactionPreferred", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionConfirmed", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("PayloadLiked", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"], true)
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"])
 		verifyInclusionState(t, tangle, valueObjects["[-GENESIS, A+, B+, C+]"], true, true, true, true, false)
 
+		tangle.Expect("PayloadRejected", valueObjects["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionRejected", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-A, F+]"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionRejected", transactions["[-E, -F, G+]"], mock.Anything)
+
 		// finalize & reject
 		//debugger.Enable()
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-B, -C, E+]"])
@@ -816,11 +934,21 @@ func TestPropagationScenario1(t *testing.T) {
 		// [-A, D+] should be unchanged
 		verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], false, false, false, false, false)
 		verifyBranchState(t, tangle, branches["A"], false, false, false, false)
+
+		tangle.AssertExpectations(t)
 	}
 
 	// simulate vote on [-A, F+] -> Branch A becomes rejected, Branch B confirmed
 	{
 		tangle, transactions, valueObjects, branches, _ := preparePropagationScenario1(t)
+		defer tangle.DetachAll()
+
+		tangle.Expect("PayloadLiked", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionPreferred", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionConfirmed", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
 
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"], true)
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"])
@@ -833,55 +961,135 @@ func TestPropagationScenario1(t *testing.T) {
 		verifyInclusionState(t, tangle, valueObjects["[-A, F+]"], false, false, false, false, false)
 		verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], false, false, false, false, false)
 
+		tangle.Expect("PayloadLiked", valueObjects["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadLiked", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+		tangle.Expect("TransactionPreferred", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionConfirmed", transactions["[-B, -C, E+]"], mock.Anything)
+
 		// confirm [-B, -C, E+]
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-B, -C, E+]"], true)
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-B, -C, E+]"])
 		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+]"], true, true, true, true, false)
 		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+] (Reattachment)"], true, true, true, true, false)
 
+		tangle.Expect("PayloadLiked", valueObjects["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionPreferred", transactions["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-A, D+]"], mock.Anything)
+
 		// prefer [-A, D+]
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-A, D+]"], true)
 		verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], true, false, true, false, false)
 		verifyBranchState(t, tangle, branches["A"], false, true, false, false)
 
+		tangle.Expect("PayloadLiked", valueObjects["[-A, F+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionPreferred", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionConfirmed", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-A, D+]"], mock.Anything)
+		tangle.Expect("PayloadDisliked", valueObjects["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionUnpreferred", transactions["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionDisliked", transactions["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionRejected", transactions["[-A, D+]"], mock.Anything)
+
 		// simulate vote result to like [-A, F+] -> [-A, F+] becomes confirmed and [-A, D+] rejected
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-A, F+]"], true)
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-A, F+]"])
 		verifyInclusionState(t, tangle, valueObjects["[-A, F+]"], true, true, true, true, false)
 		verifyBranchState(t, tangle, branches["B"], true, true, true, false)
+		// [-A, D+] should be rejected
+		verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], false, true, false, false, true)
+		verifyBranchState(t, tangle, branches["A"], true, false, false, true)
+
+		tangle.Expect("PayloadLiked", valueObjects["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionPreferred", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionConfirmed", transactions["[-E, -F, G+]"], mock.Anything)
 
 		verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], false, false, false, false, false)
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-E, -F, G+]"], true)
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-E, -F, G+]"])
 		verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], true, true, true, true, false)
 
-		// [-A, D+] should be rejected
-		verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], false, true, false, false, true)
-		verifyBranchState(t, tangle, branches["A"], true, false, false, true)
+		tangle.AssertExpectations(t)
 	}
 
 	// simulate vote on [-A, D+] -> Branch B becomes rejected, Branch A confirmed
 	{
 		tangle, transactions, valueObjects, branches, _ := preparePropagationScenario1(t)
+		defer tangle.DetachAll()
+
+		tangle.Expect("PayloadLiked", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionPreferred", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+		tangle.Expect("TransactionConfirmed", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
 
 		// confirm [-GENESIS, A+, B+, C+]
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"], true)
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"])
 		verifyInclusionState(t, tangle, valueObjects["[-GENESIS, A+, B+, C+]"], true, true, true, true, false)
 
+		tangle.Expect("PayloadLiked", valueObjects["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("PayloadLiked", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+		tangle.Expect("TransactionPreferred", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-B, -C, E+]"], mock.Anything)
+		tangle.Expect("TransactionConfirmed", transactions["[-B, -C, E+]"], mock.Anything)
+
 		// confirm [-B, -C, E+]
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-B, -C, E+]"], true)
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-B, -C, E+]"])
 		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+]"], true, true, true, true, false)
 
+		tangle.Expect("PayloadLiked", valueObjects["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionPreferred", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-A, F+]"], mock.Anything)
+
 		// prefer [-A, F+] and thus Branch B
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-A, F+]"], true)
 		verifyInclusionState(t, tangle, valueObjects["[-A, F+]"], true, false, true, false, false)
 		verifyBranchState(t, tangle, branches["B"], false, true, false, false)
+
+		tangle.Expect("PayloadLiked", valueObjects["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionPreferred", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-E, -F, G+]"], mock.Anything)
+
 		// prefer [-E, -F, G+]
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-E, -F, G+]"], true)
 		verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], true, false, true, false, false)
 
+		tangle.Expect("PayloadLiked", valueObjects["[-A, D+]"], mock.Anything)
+		tangle.Expect("PayloadConfirmed", valueObjects["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionPreferred", transactions["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionLiked", transactions["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-A, D+]"], mock.Anything)
+		tangle.Expect("TransactionConfirmed", transactions["[-A, D+]"], mock.Anything)
+
+		tangle.Expect("PayloadRejected", valueObjects["[-A, F+]"], mock.Anything)
+		tangle.Expect("PayloadDisliked", valueObjects["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionUnpreferred", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionDisliked", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("TransactionRejected", transactions["[-A, F+]"], mock.Anything)
+		tangle.Expect("PayloadRejected", valueObjects["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("PayloadDisliked", valueObjects["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionUnpreferred", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionDisliked", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionFinalized", transactions["[-E, -F, G+]"], mock.Anything)
+		tangle.Expect("TransactionRejected", transactions["[-E, -F, G+]"], mock.Anything)
+
 		// simulate vote result to like [-A, D+] -> [-A, D+] becomes confirmed and [-A, F+], [-E, -F, G+] rejected
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-A, D+]"], true)
 		setTransactionFinalizedWithCheck(t, tangle, transactions["[-A, D+]"])
@@ -892,12 +1100,15 @@ func TestPropagationScenario1(t *testing.T) {
 		verifyInclusionState(t, tangle, valueObjects["[-A, F+]"], false, true, false, false, true)
 		verifyBranchState(t, tangle, branches["B"], true, false, false, true)
 		verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], false, true, false, false, true)
+
+		tangle.AssertExpectations(t)
 	}
 }
 
 func TestPropagationScenario2(t *testing.T) {
 	// img/scenario2.png
 	tangle, transactions, valueObjects, branches, _ := preparePropagationScenario2(t)
+	defer tangle.DetachAll()
 
 	// initialize debugger for this test
 	debugger.ResetAliases()
@@ -908,22 +1119,42 @@ func TestPropagationScenario2(t *testing.T) {
 		debugger.RegisterAlias(tx.ID(), "TransactionID"+name)
 	}
 
+	tangle.Expect("PayloadLiked", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+	tangle.Expect("PayloadConfirmed", valueObjects["[-GENESIS, A+, B+, C+]"], mock.Anything)
+	tangle.Expect("TransactionPreferred", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+	tangle.Expect("TransactionLiked", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+	tangle.Expect("TransactionFinalized", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+	tangle.Expect("TransactionConfirmed", transactions["[-GENESIS, A+, B+, C+]"], mock.Anything)
+
 	// confirm [-GENESIS, A+, B+, C+]
 	setTransactionPreferredWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"], true)
 	setTransactionFinalizedWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"])
 	verifyInclusionState(t, tangle, valueObjects["[-GENESIS, A+, B+, C+]"], true, true, true, true, false)
 
+	tangle.Expect("PayloadLiked", valueObjects["[-B, -C, E+]"], mock.Anything)
+	tangle.Expect("PayloadLiked", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+	tangle.Expect("TransactionPreferred", transactions["[-B, -C, E+]"], mock.Anything)
+	tangle.Expect("TransactionLiked", transactions["[-B, -C, E+]"], mock.Anything)
+
 	// prefer [-B, -C, E+] and thus Branch D
 	setTransactionPreferredWithCheck(t, tangle, transactions["[-B, -C, E+]"], true)
 	verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+]"], true, false, true, false, false)
 	verifyBranchState(t, tangle, branches["D"], false, true, false, false)
 	verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+] (Reattachment)"], true, false, true, false, false)
 
+	tangle.Expect("PayloadLiked", valueObjects["[-A, F+]"], mock.Anything)
+	tangle.Expect("TransactionPreferred", transactions["[-A, F+]"], mock.Anything)
+	tangle.Expect("TransactionLiked", transactions["[-A, F+]"], mock.Anything)
+
 	// prefer [-A, F+] and thus Branch B
 	setTransactionPreferredWithCheck(t, tangle, transactions["[-A, F+]"], true)
 	verifyInclusionState(t, tangle, valueObjects["[-A, F+]"], true, false, true, false, false)
 	verifyBranchState(t, tangle, branches["B"], false, true, false, false)
 
+	tangle.Expect("PayloadLiked", valueObjects["[-E, -F, G+]"], mock.Anything)
+	tangle.Expect("TransactionPreferred", transactions["[-E, -F, G+]"], mock.Anything)
+	tangle.Expect("TransactionLiked", transactions["[-E, -F, G+]"], mock.Anything)
+
 	// prefer [-E, -F, G+]
 	setTransactionPreferredWithCheck(t, tangle, transactions["[-E, -F, G+]"], true)
 	verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], true, false, true, false, false)
@@ -945,10 +1176,34 @@ func TestPropagationScenario2(t *testing.T) {
 	verifyBranchState(t, tangle, branches["E"], false, false, false, false)
 	verifyBranchState(t, tangle, branches["ACE"], false, false, false, false)
 
+	tangle.Expect("PayloadLiked", valueObjects["[-H, -D, I+]"], mock.Anything)
+	tangle.Expect("TransactionPreferred", transactions["[-H, -D, I+]"], mock.Anything)
+	tangle.Expect("TransactionLiked", transactions["[-H, -D, I+]"], mock.Anything)
+
 	// prefer [-H, -D, I+] - should be liked after votes on [-A, D+] and [-C, H+]
 	setTransactionPreferredWithCheck(t, tangle, transactions["[-H, -D, I+]"], true)
 	verifyInclusionState(t, tangle, valueObjects["[-H, -D, I+]"], true, false, false, false, false)
 
+	tangle.Expect("PayloadLiked", valueObjects["[-A, D+]"], mock.Anything)
+	tangle.Expect("PayloadConfirmed", valueObjects["[-A, D+]"], mock.Anything)
+	tangle.Expect("TransactionPreferred", transactions["[-A, D+]"], mock.Anything)
+	tangle.Expect("TransactionLiked", transactions["[-A, D+]"], mock.Anything)
+	tangle.Expect("TransactionFinalized", transactions["[-A, D+]"], mock.Anything)
+	tangle.Expect("TransactionConfirmed", transactions["[-A, D+]"], mock.Anything)
+
+	tangle.Expect("PayloadRejected", valueObjects["[-A, F+]"], mock.Anything)
+	tangle.Expect("PayloadDisliked", valueObjects["[-A, F+]"], mock.Anything)
+	tangle.Expect("TransactionUnpreferred", transactions["[-A, F+]"], mock.Anything)
+	tangle.Expect("TransactionDisliked", transactions["[-A, F+]"], mock.Anything)
+	tangle.Expect("TransactionFinalized", transactions["[-A, F+]"], mock.Anything)
+	tangle.Expect("TransactionRejected", transactions["[-A, F+]"], mock.Anything)
+	tangle.Expect("PayloadRejected", valueObjects["[-E, -F, G+]"], mock.Anything)
+	tangle.Expect("PayloadDisliked", valueObjects["[-E, -F, G+]"], mock.Anything)
+	tangle.Expect("TransactionUnpreferred", transactions["[-E, -F, G+]"], mock.Anything)
+	tangle.Expect("TransactionDisliked", transactions["[-E, -F, G+]"], mock.Anything)
+	tangle.Expect("TransactionFinalized", transactions["[-E, -F, G+]"], mock.Anything)
+	tangle.Expect("TransactionRejected", transactions["[-E, -F, G+]"], mock.Anything)
+
 	// simulate vote result to like [-A, D+] -> [-A, D+] becomes confirmed and [-A, F+], [-E, -F, G+] rejected
 	setTransactionPreferredWithCheck(t, tangle, transactions["[-A, D+]"], true)
 	setTransactionFinalizedWithCheck(t, tangle, transactions["[-A, D+]"])
@@ -959,6 +1214,22 @@ func TestPropagationScenario2(t *testing.T) {
 	verifyBranchState(t, tangle, branches["B"], true, false, false, true)
 	verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], false, true, false, false, true)
 
+	tangle.Expect("PayloadLiked", valueObjects["[-C, H+]"], mock.Anything)
+	tangle.Expect("PayloadConfirmed", valueObjects["[-C, H+]"], mock.Anything)
+	tangle.Expect("TransactionPreferred", transactions["[-C, H+]"], mock.Anything)
+	tangle.Expect("TransactionLiked", transactions["[-C, H+]"], mock.Anything)
+	tangle.Expect("TransactionFinalized", transactions["[-C, H+]"], mock.Anything)
+	tangle.Expect("TransactionConfirmed", transactions["[-C, H+]"], mock.Anything)
+
+	tangle.Expect("PayloadRejected", valueObjects["[-B, -C, E+]"], mock.Anything)
+	tangle.Expect("PayloadDisliked", valueObjects["[-B, -C, E+]"], mock.Anything)
+	tangle.Expect("TransactionUnpreferred", transactions["[-B, -C, E+]"], mock.Anything)
+	tangle.Expect("TransactionDisliked", transactions["[-B, -C, E+]"], mock.Anything)
+	tangle.Expect("TransactionFinalized", transactions["[-B, -C, E+]"], mock.Anything)
+	tangle.Expect("TransactionRejected", transactions["[-B, -C, E+]"], mock.Anything)
+	tangle.Expect("PayloadRejected", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+	tangle.Expect("PayloadDisliked", valueObjects["[-B, -C, E+] (Reattachment)"], mock.Anything)
+
 	// simulate vote result to like [-C, H+] -> [-C, H+] becomes confirmed and [-B, -C, E+], [-B, -C, E+] (Reattachment) rejected
 	setTransactionPreferredWithCheck(t, tangle, transactions["[-C, H+]"], true)
 	setTransactionFinalizedWithCheck(t, tangle, transactions["[-C, H+]"])
@@ -973,23 +1244,37 @@ func TestPropagationScenario2(t *testing.T) {
 	verifyBranchState(t, tangle, branches["BD"], true, false, false, true)
 	// TODO: BD is not finalized
 
+	// [-H, -D, I+] is already preferred
+	tangle.Expect("PayloadConfirmed", valueObjects["[-H, -D, I+]"], mock.Anything)
+	tangle.Expect("TransactionFinalized", transactions["[-H, -D, I+]"], mock.Anything)
+	tangle.Expect("TransactionConfirmed", transactions["[-H, -D, I+]"], mock.Anything)
+
 	// [-H, -D, I+] should now be liked
 	verifyInclusionState(t, tangle, valueObjects["[-H, -D, I+]"], true, false, true, false, false)
 	setTransactionFinalizedWithCheck(t, tangle, transactions["[-H, -D, I+]"])
 	verifyInclusionState(t, tangle, valueObjects["[-H, -D, I+]"], true, true, true, true, false)
-
 	// [-B, J+] should be unchanged
 	verifyInclusionState(t, tangle, valueObjects["[-B, J+]"], false, false, false, false, false)
+
+	tangle.Expect("PayloadLiked", valueObjects["[-B, J+]"], mock.Anything)
+	tangle.Expect("PayloadConfirmed", valueObjects["[-B, J+]"], mock.Anything)
+	tangle.Expect("TransactionPreferred", transactions["[-B, J+]"], mock.Anything)
+	tangle.Expect("TransactionLiked", transactions["[-B, J+]"], mock.Anything)
+	tangle.Expect("TransactionFinalized", transactions["[-B, J+]"], mock.Anything)
+	tangle.Expect("TransactionConfirmed", transactions["[-B, J+]"], mock.Anything)
+
 	// [-B, J+] should become confirmed after preferring and finalizing
 	setTransactionPreferredWithCheck(t, tangle, transactions["[-B, J+]"], true)
 	setTransactionFinalizedWithCheck(t, tangle, transactions["[-B, J+]"])
 	verifyInclusionState(t, tangle, valueObjects["[-B, J+]"], true, true, true, true, false)
 	verifyBranchState(t, tangle, branches["E"], true, true, true, false)
 	verifyBranchState(t, tangle, branches["ACE"], true, true, true, false)
+
+	tangle.AssertExpectations(t)
 }
 
 // verifyBranchState verifies the the branch state according to the given parameters.
-func verifyBranchState(t *testing.T, tangle *Tangle, id branchmanager.BranchID, finalized, liked, confirmed, rejected bool) {
+func verifyBranchState(t *testing.T, tangle *eventTangle, id branchmanager.BranchID, finalized, liked, confirmed, rejected bool) {
 	assert.True(t, tangle.branchManager.Branch(id).Consume(func(branch *branchmanager.Branch) {
 		assert.Equalf(t, finalized, branch.Finalized(), "branch finalized state does not match")
 		assert.Equalf(t, liked, branch.Liked(), "branch liked state does not match")
@@ -1000,7 +1285,7 @@ func verifyBranchState(t *testing.T, tangle *Tangle, id branchmanager.BranchID,
 }
 
 // verifyInclusionState verifies the inclusion state of outputs and transaction according to the given parameters.
-func verifyTransactionInclusionState(t *testing.T, tangle *Tangle, valueObject *payload.Payload, preferred, finalized, liked, confirmed, rejected bool) {
+func verifyTransactionInclusionState(t *testing.T, tangle *eventTangle, valueObject *payload.Payload, preferred, finalized, liked, confirmed, rejected bool) {
 	tx := valueObject.Transaction()
 
 	// check outputs
@@ -1025,7 +1310,7 @@ func verifyTransactionInclusionState(t *testing.T, tangle *Tangle, valueObject *
 }
 
 // verifyValueObjectInclusionState verifies the inclusion state of a value object according to the given parameters.
-func verifyValueObjectInclusionState(t *testing.T, tangle *Tangle, valueObject *payload.Payload, liked, confirmed, rejected bool) {
+func verifyValueObjectInclusionState(t *testing.T, tangle *eventTangle, valueObject *payload.Payload, liked, confirmed, rejected bool) {
 	assert.True(t, tangle.PayloadMetadata(valueObject.ID()).Consume(func(payloadMetadata *PayloadMetadata) {
 		assert.Equalf(t, liked, payloadMetadata.Liked(), "value object liked state does not match")
 		assert.Equalf(t, confirmed, payloadMetadata.Confirmed(), "value object confirmed state does not match")
@@ -1034,20 +1319,20 @@ func verifyValueObjectInclusionState(t *testing.T, tangle *Tangle, valueObject *
 }
 
 // verifyInclusionState verifies the inclusion state of outputs, transaction and value object according to the given parameters.
-func verifyInclusionState(t *testing.T, tangle *Tangle, valueObject *payload.Payload, preferred, finalized, liked, confirmed, rejected bool) {
+func verifyInclusionState(t *testing.T, tangle *eventTangle, valueObject *payload.Payload, preferred, finalized, liked, confirmed, rejected bool) {
 	verifyTransactionInclusionState(t, tangle, valueObject, preferred, finalized, liked, confirmed, rejected)
 	verifyValueObjectInclusionState(t, tangle, valueObject, liked, confirmed, rejected)
 }
 
 // setTransactionPreferredWithCheck sets the transaction to preferred and makes sure that no error occurred and it's modified.
-func setTransactionPreferredWithCheck(t *testing.T, tangle *Tangle, tx *transaction.Transaction, preferred bool) {
+func setTransactionPreferredWithCheck(t *testing.T, tangle *eventTangle, tx *transaction.Transaction, preferred bool) {
 	modified, err := tangle.SetTransactionPreferred(tx.ID(), preferred)
 	require.NoError(t, err)
 	assert.True(t, modified)
 }
 
 // setTransactionFinalizedWithCheck sets the transaction to finalized and makes sure that no error occurred and it's modified.
-func setTransactionFinalizedWithCheck(t *testing.T, tangle *Tangle, tx *transaction.Transaction) {
+func setTransactionFinalizedWithCheck(t *testing.T, tangle *eventTangle, tx *transaction.Transaction) {
 	modified, err := tangle.SetTransactionFinalized(tx.ID())
 	require.NoError(t, err)
 	assert.True(t, modified)
diff --git a/dapps/valuetransfers/packages/tangle/tangle_test.go b/dapps/valuetransfers/packages/tangle/tangle_test.go
index 0849dc3ff9a58ea3f837bb8b455b941a5878b99b..b00f07ee80c5240ef88c693706faad102c72d32c 100644
--- a/dapps/valuetransfers/packages/tangle/tangle_test.go
+++ b/dapps/valuetransfers/packages/tangle/tangle_test.go
@@ -5,30 +5,34 @@ import (
 	"math"
 	"testing"
 
-	"github.com/google/go-cmp/cmp"
-
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/branchmanager"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
-
-	"github.com/iotaledger/hive.go/events"
 	"github.com/iotaledger/hive.go/kvstore/mapdb"
 	"github.com/iotaledger/hive.go/types"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
 	"github.com/stretchr/testify/require"
 )
 
 func TestSetTransactionPreferred(t *testing.T) {
 	tangle := New(mapdb.NewMapDB())
+	event := newEventTangle(t, tangle)
+	defer event.DetachAll()
+
 	tx := createDummyTransaction()
 	valueObject := payload.New(payload.GenesisID, payload.GenesisID, tx)
 	tangle.storeTransactionModels(valueObject)
 
+	event.Expect("TransactionPreferred", tx, mock.Anything)
+
 	modified, err := tangle.SetTransactionPreferred(tx.ID(), true)
 	require.NoError(t, err)
 	assert.True(t, modified)
+
+	event.AssertExpectations(t)
 }
 
 // TestBookTransaction tests the following cases:
@@ -41,19 +45,32 @@ func TestBookTransaction(t *testing.T) {
 	// CASE: missing output
 	t.Run("CASE: missing output", func(t *testing.T) {
 		tangle := New(mapdb.NewMapDB())
+		event := newEventTangle(t, tangle)
+		defer event.DetachAll()
+
 		tx := createDummyTransaction()
 		valueObject := payload.New(payload.GenesisID, payload.GenesisID, tx)
-		cachedTransaction, cachedTransactionMetadata, _, _ := tangle.storeTransactionModels(valueObject)
 
+		cachedTransaction, cachedTransactionMetadata, _, transactionIsNew := tangle.storeTransactionModels(valueObject)
+		assert.True(t, transactionIsNew)
+
+		event.Expect("TransactionSolid", tx, mock.Anything)
+
+		// manually trigger a booking: tx will be marked solid, but it cannot be book as its inputs are unavailable
 		transactionBooked, decisionPending, err := tangle.bookTransaction(cachedTransaction, cachedTransactionMetadata)
 		assert.False(t, transactionBooked)
 		assert.False(t, decisionPending)
 		assert.Error(t, err)
+
+		event.AssertExpectations(t)
 	})
 
 	// CASE: transaction already booked by another process
 	t.Run("CASE: transaction already booked by another process", func(t *testing.T) {
 		tangle := New(mapdb.NewMapDB())
+		event := newEventTangle(t, tangle)
+		defer event.DetachAll()
+
 		tx := createDummyTransaction()
 		valueObject := payload.New(payload.GenesisID, payload.GenesisID, tx)
 		cachedTransaction, cachedTransactionMetadata, _, _ := tangle.storeTransactionModels(valueObject)
@@ -65,11 +82,15 @@ func TestBookTransaction(t *testing.T) {
 		require.NoError(t, err)
 		assert.False(t, transactionBooked)
 		assert.False(t, decisionPending)
+
+		event.AssertExpectations(t)
 	})
 
 	// CASE: booking first spend
 	t.Run("CASE: booking first spend", func(t *testing.T) {
 		tangle := New(mapdb.NewMapDB())
+		event := newEventTangle(t, tangle)
+		defer event.DetachAll()
 
 		// prepare snapshot
 		color1 := [32]byte{1}
@@ -85,7 +106,7 @@ func TestBookTransaction(t *testing.T) {
 		inputIDs := loadSnapshotFromOutputs(tangle, outputs)
 
 		// build first spending
-		tx := transaction.New(
+		tx1 := transaction.New(
 			transaction.NewInputs(inputIDs...),
 			// outputs
 			transaction.NewOutputs(map[address.Address][]*balance.Balance{
@@ -96,13 +117,16 @@ func TestBookTransaction(t *testing.T) {
 			}),
 		)
 
-		valueObject := payload.New(payload.GenesisID, payload.GenesisID, tx)
+		valueObject := payload.New(payload.GenesisID, payload.GenesisID, tx1)
 		cachedTransaction, cachedTransactionMetadata, _, _ := tangle.storeTransactionModels(valueObject)
 		txMetadata := cachedTransactionMetadata.Unwrap()
 
 		// assert that branchID is undefined before being booked
 		assert.Equal(t, branchmanager.UndefinedBranchID, txMetadata.BranchID())
 
+		event.Expect("TransactionSolid", tx1, mock.Anything)
+		// TransactionBooked is triggered outside of bookTransaction
+
 		transactionBooked, decisionPending, err := tangle.bookTransaction(cachedTransaction, cachedTransactionMetadata)
 		require.NoError(t, err)
 		assert.True(t, transactionBooked, "transactionBooked")
@@ -114,7 +138,7 @@ func TestBookTransaction(t *testing.T) {
 		// CASE: booking double spend
 		t.Run("CASE: booking double spend", func(t *testing.T) {
 			// build second spending
-			tx := transaction.New(
+			tx2 := transaction.New(
 				transaction.NewInputs(inputIDs...),
 				// outputs
 				transaction.NewOutputs(map[address.Address][]*balance.Balance{
@@ -125,13 +149,17 @@ func TestBookTransaction(t *testing.T) {
 				}),
 			)
 
-			valueObject := payload.New(payload.GenesisID, payload.GenesisID, tx)
+			valueObject := payload.New(payload.GenesisID, payload.GenesisID, tx2)
 			cachedTransaction, cachedTransactionMetadata, _, _ = tangle.storeTransactionModels(valueObject)
 			txMetadata := cachedTransactionMetadata.Unwrap()
 
 			// assert that branchID is undefined before being booked
 			assert.Equal(t, branchmanager.UndefinedBranchID, txMetadata.BranchID())
 
+			// manually book the double spending tx2, this will mark it as solid and trigger a fork
+			event.Expect("TransactionSolid", tx2, mock.Anything)
+			event.Expect("Fork", tx1, mock.Anything, mock.Anything, inputIDs)
+
 			transactionBooked, decisionPending, err := tangle.bookTransaction(cachedTransaction, cachedTransactionMetadata)
 			require.NoError(t, err)
 			assert.True(t, transactionBooked, "transactionBooked")
@@ -140,6 +168,8 @@ func TestBookTransaction(t *testing.T) {
 			// assert that first spend and double spend have different BranchIDs
 			assert.NotEqual(t, branchmanager.MasterBranchID, txMetadata.BranchID(), "BranchID")
 		})
+
+		event.AssertExpectations(t)
 	})
 }
 
@@ -230,6 +260,9 @@ func TestFork(t *testing.T) {
 	// CASE: already finalized
 	t.Run("CASE: already finalized", func(t *testing.T) {
 		tangle := New(mapdb.NewMapDB())
+		event := newEventTangle(t, tangle)
+		defer event.DetachAll()
+
 		// prepare snapshot
 		color1 := [32]byte{1}
 		outputs := map[address.Address][]*balance.Balance{
@@ -259,14 +292,20 @@ func TestFork(t *testing.T) {
 
 		txMetadata.setFinalized(true)
 
+		// no fork created so no event should be triggered
 		forked, finalized, err := tangle.Fork(tx.ID(), []transaction.OutputID{})
 		require.NoError(t, err)
 		assert.False(t, forked)
 		assert.True(t, finalized)
+
+		event.AssertExpectations(t)
 	})
 
 	t.Run("CASE: normal fork", func(t *testing.T) {
 		tangle := New(mapdb.NewMapDB())
+		event := newEventTangle(t, tangle)
+		defer event.DetachAll()
+
 		// prepare snapshot
 		color1 := [32]byte{1}
 		outputs := map[address.Address][]*balance.Balance{
@@ -293,24 +332,30 @@ func TestFork(t *testing.T) {
 		valueObject := payload.New(payload.GenesisID, payload.GenesisID, tx)
 		tangle.storeTransactionModels(valueObject)
 
+		event.Expect("Fork", tx, mock.Anything, mock.Anything, []transaction.OutputID{})
+
 		forked, finalized, err := tangle.Fork(tx.ID(), []transaction.OutputID{})
 		require.NoError(t, err)
 		assert.True(t, forked, "forked")
 		assert.False(t, finalized, "finalized")
 
 		t.Run("CASE: branch existed already", func(t *testing.T) {
+			// no fork created so no event should be triggered
 			forked, finalized, err = tangle.Fork(tx.ID(), []transaction.OutputID{})
 			require.NoError(t, err)
 			assert.False(t, forked, "forked")
 			assert.False(t, finalized, "finalized")
 		})
-	})
 
+		event.AssertExpectations(t)
+	})
 }
 
 func TestBookPayload(t *testing.T) {
 	t.Run("CASE: undefined branchID", func(t *testing.T) {
 		tangle := New(mapdb.NewMapDB())
+		event := newEventTangle(t, tangle)
+		defer event.DetachAll()
 
 		valueObject := payload.New(payload.GenesisID, payload.GenesisID, createDummyTransaction())
 		cachedPayload, cachedMetadata, _ := tangle.storePayload(valueObject)
@@ -325,10 +370,14 @@ func TestBookPayload(t *testing.T) {
 
 		require.NoError(t, err)
 		assert.False(t, payloadBooked, "payloadBooked")
+
+		event.AssertExpectations(t)
 	})
 
 	t.Run("CASE: successfully book", func(t *testing.T) {
 		tangle := New(mapdb.NewMapDB())
+		event := newEventTangle(t, tangle)
+		defer event.DetachAll()
 
 		valueObject := payload.New(payload.GenesisID, payload.GenesisID, createDummyTransaction())
 		cachedPayload, cachedMetadata, _ := tangle.storePayload(valueObject)
@@ -341,6 +390,7 @@ func TestBookPayload(t *testing.T) {
 		txMetadata := cachedTransactionMetadata.Unwrap()
 		txMetadata.setBranchID(branchmanager.BranchID{1})
 
+		event.Expect("PayloadSolid", valueObject, mock.Anything)
 		payloadBooked, err := tangle.bookPayload(cachedPayload.Retain(), cachedMetadata.Retain(), cachedTransactionMetadata.Retain())
 		defer func() {
 			cachedPayload.Release()
@@ -350,10 +400,14 @@ func TestBookPayload(t *testing.T) {
 
 		require.NoError(t, err)
 		assert.True(t, payloadBooked, "payloadBooked")
+
+		event.AssertExpectations(t)
 	})
 
 	t.Run("CASE: not booked", func(t *testing.T) {
 		tangle := New(mapdb.NewMapDB())
+		event := newEventTangle(t, tangle)
+		defer event.DetachAll()
 
 		valueObject := payload.New(payload.GenesisID, payload.GenesisID, createDummyTransaction())
 		cachedPayload, cachedMetadata, _ := tangle.storePayload(valueObject)
@@ -366,6 +420,7 @@ func TestBookPayload(t *testing.T) {
 		txMetadata := cachedTransactionMetadata.Unwrap()
 		txMetadata.setBranchID(branchmanager.BranchID{1})
 
+		event.Expect("PayloadSolid", valueObject, mock.Anything)
 		payloadBooked, err := tangle.bookPayload(cachedPayload.Retain(), cachedMetadata.Retain(), cachedTransactionMetadata.Retain())
 		defer func() {
 			cachedPayload.Release()
@@ -375,6 +430,8 @@ func TestBookPayload(t *testing.T) {
 
 		require.NoError(t, err)
 		assert.False(t, payloadBooked, "payloadBooked")
+
+		event.AssertExpectations(t)
 	})
 
 }
@@ -382,6 +439,8 @@ func TestBookPayload(t *testing.T) {
 // TestStorePayload checks whether a value object is correctly stored.
 func TestStorePayload(t *testing.T) {
 	tangle := New(mapdb.NewMapDB())
+	event := newEventTangle(t, tangle)
+	defer event.DetachAll()
 
 	tx := createDummyTransaction()
 	valueObject := payload.New(payload.GenesisID, payload.GenesisID, tx)
@@ -415,6 +474,8 @@ func TestStorePayload(t *testing.T) {
 			assert.Equal(t, valueObject.ID(), payloadMetadata.PayloadID())
 		})
 	}
+
+	event.AssertExpectations(t)
 }
 
 // TestStoreTransactionModels checks whether all models corresponding to a transaction are correctly created.
@@ -925,7 +986,7 @@ func TestRetrieveConsumedInputDetails(t *testing.T) {
 		cachedInputs.Consume(func(input *Output) {
 			assert.ElementsMatch(t, outputs[input.Address()], input.Balances())
 		})
-		assert.True(t, cmp.Equal(sumOutputsByColor(outputs), consumedBalances))
+		assert.Equal(t, sumOutputsByColor(outputs), consumedBalances)
 		assert.Len(t, consumedBranches, 1)
 		assert.Contains(t, consumedBranches, branchmanager.MasterBranchID)
 	}
@@ -967,7 +1028,7 @@ func TestRetrieveConsumedInputDetails(t *testing.T) {
 		cachedInputs.Consume(func(input *Output) {
 			assert.ElementsMatch(t, outputs[input.Address()], input.Balances())
 		})
-		assert.True(t, cmp.Equal(sumOutputsByColor(outputs), consumedBalances))
+		assert.Equal(t, sumOutputsByColor(outputs), consumedBalances)
 		assert.Len(t, consumedBranches, 1)
 		assert.Contains(t, consumedBranches, branchmanager.MasterBranchID)
 	}
@@ -1032,7 +1093,7 @@ func TestRetrieveConsumedInputDetails(t *testing.T) {
 		cachedInputs.Consume(func(input *Output) {
 			assert.ElementsMatch(t, outputs[input.Address()], input.Balances())
 		})
-		assert.True(t, cmp.Equal(sumOutputsByColor(outputs), consumedBalances))
+		assert.Equal(t, sumOutputsByColor(outputs), consumedBalances)
 		assert.Len(t, consumedBranches, 2)
 		assert.Contains(t, consumedBranches, branchmanager.MasterBranchID)
 		assert.Contains(t, consumedBranches, newBranch)
@@ -1201,6 +1262,8 @@ func TestCheckTransactionSolidity(t *testing.T) {
 
 func TestPayloadBranchID(t *testing.T) {
 	tangle := New(mapdb.NewMapDB())
+	event := newEventTangle(t, tangle)
+	defer event.DetachAll()
 
 	{
 		branchID := tangle.payloadBranchID(payload.GenesisID)
@@ -1226,19 +1289,19 @@ func TestPayloadBranchID(t *testing.T) {
 	// test missing value object
 	{
 		valueObject := payload.New(payload.GenesisID, payload.GenesisID, createDummyTransaction())
-		missing := 0
-		tangle.Events.PayloadMissing.Attach(events.NewClosure(func(payloadID payload.ID) {
-			missing++
-		}))
 
+		event.Expect("PayloadMissing", valueObject.ID())
 		branchID := tangle.payloadBranchID(valueObject.ID())
 		assert.Equal(t, branchmanager.UndefinedBranchID, branchID)
-		assert.Equal(t, 1, missing)
 	}
+
+	event.AssertExpectations(t)
 }
 
 func TestCheckPayloadSolidity(t *testing.T) {
 	tangle := New(mapdb.NewMapDB())
+	event := newEventTangle(t, tangle)
+	defer event.DetachAll()
 
 	// check with already solid payload
 	{
@@ -1344,12 +1407,17 @@ func TestCheckPayloadSolidity(t *testing.T) {
 		assert.False(t, solid)
 		assert.Error(t, err)
 	}
+
+	event.AssertExpectations(t)
 }
 
 func TestCreateValuePayloadFutureConeIterator(t *testing.T) {
 	// check with new payload -> should be added to stack
 	{
 		tangle := New(mapdb.NewMapDB())
+		event := newEventTangle(t, tangle)
+		defer event.DetachAll()
+
 		solidificationStack := list.New()
 		processedPayloads := make(map[payload.ID]types.Empty)
 		iterator := tangle.createValuePayloadFutureConeIterator(solidificationStack, processedPayloads)
@@ -1378,11 +1446,16 @@ func TestCreateValuePayloadFutureConeIterator(t *testing.T) {
 		currentSolidificationEntry.CachedTransactionMetadata.Consume(func(metadata *TransactionMetadata) {
 			assert.Equal(t, tx.ID(), metadata.ID())
 		})
+
+		event.AssertExpectations(t)
 	}
 
 	// check with already processed payload -> should not be added to stack
 	{
 		tangle := New(mapdb.NewMapDB())
+		event := newEventTangle(t, tangle)
+		defer event.DetachAll()
+
 		solidificationStack := list.New()
 		processedPayloads := make(map[payload.ID]types.Empty)
 		iterator := tangle.createValuePayloadFutureConeIterator(solidificationStack, processedPayloads)
@@ -1400,6 +1473,8 @@ func TestCreateValuePayloadFutureConeIterator(t *testing.T) {
 
 		iterator(cachedPayload, cachedMetadata, cachedTransaction, cachedTransactionMetadata)
 		assert.Equal(t, 0, solidificationStack.Len())
+
+		event.AssertExpectations(t)
 	}
 }
 
@@ -1498,6 +1573,55 @@ func TestForeachApprovers(t *testing.T) {
 	assert.Equal(t, 2, counter)
 }
 
+func TestMissingPayloadReceived(t *testing.T) {
+	tangle := New(mapdb.NewMapDB())
+	event := newEventTangle(t, tangle)
+	defer event.DetachAll()
+
+	// prepare snapshot
+	unspentOutputs := loadSnapshotFromOutputs(
+		tangle,
+		map[address.Address][]*balance.Balance{
+			address.Random(): {
+				balance.New(balance.ColorIOTA, 3),
+			},
+		},
+	)
+
+	// create transaction spending those snapshot outputs
+	tx := transaction.New(
+		transaction.NewInputs(unspentOutputs...),
+		transaction.NewOutputs(map[address.Address][]*balance.Balance{
+			address.Random(): {
+				balance.New(balance.ColorIOTA, 3),
+			},
+		}),
+	)
+
+	// create two value objects for this transaction referencing each other
+	parent := payload.New(payload.GenesisID, payload.GenesisID, tx)
+	child := payload.New(parent.ID(), parent.ID(), tx)
+
+	event.Expect("PayloadAttached", child, mock.Anything)
+	event.Expect("PayloadMissing", parent.ID(), mock.Anything)
+	event.Expect("TransactionReceived", tx, mock.Anything, mock.Anything)
+
+	// submit the child first; it cannot be solidified
+	tangle.AttachPayloadSync(child)
+
+	event.Expect("PayloadAttached", parent, mock.Anything)
+	event.Expect("PayloadSolid", parent, mock.Anything)
+	event.Expect("MissingPayloadReceived", parent, mock.Anything)
+	event.Expect("PayloadSolid", child, mock.Anything)
+	event.Expect("TransactionSolid", tx, mock.Anything, mock.Anything)
+	event.Expect("TransactionBooked", tx, mock.Anything, true)
+
+	// submitting the parent makes everything solid
+	tangle.AttachPayloadSync(parent)
+
+	event.AssertExpectations(t)
+}
+
 func storeParentPayloadWithMetadataFunc(t *testing.T, tangle *Tangle, consume func(*PayloadMetadata)) payload.ID {
 	parent1 := payload.New(payload.GenesisID, payload.GenesisID, createDummyTransaction())
 	cachedPayload, cachedMetadata, stored := tangle.storePayload(parent1)
diff --git a/go.mod b/go.mod
index c2392c60fefc4b66be7d848ed2769ce2101bc68a..7d5fd68a00f5d8f3fc24eb3808b65dec480f82f5 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,6 @@ require (
 	github.com/drand/kyber v1.0.1-0.20200331114745-30e90cc60f99
 	github.com/gobuffalo/packr/v2 v2.7.1
 	github.com/golang/protobuf v1.3.5
-	github.com/google/go-cmp v0.4.0
 	github.com/gorilla/websocket v1.4.1
 	github.com/iotaledger/hive.go v0.0.0-20200617164933-c48b4401b814
 	github.com/iotaledger/iota.go v1.0.0-beta.14
@@ -22,7 +21,7 @@ require (
 	github.com/pkg/errors v0.9.1
 	github.com/spf13/pflag v1.0.5
 	github.com/spf13/viper v1.6.2
-	github.com/stretchr/testify v1.5.1
+	github.com/stretchr/testify v1.6.1
 	github.com/valyala/fasttemplate v1.1.0 // indirect
 	go.dedis.ch/kyber/v3 v3.0.12
 	go.uber.org/atomic v1.6.0
diff --git a/go.sum b/go.sum
index 575831135fb95140a69b8b1210e0f51e7f29808a..4586afd00fcc72e9328807b0277c02e60df952f5 100644
--- a/go.sum
+++ b/go.sum
@@ -297,6 +297,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
@@ -491,6 +493,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
diff --git a/tools/integration-tests/tester/go.mod b/tools/integration-tests/tester/go.mod
index 3d3c66376488f6ea025677cc2be9824f3f3bc784..6fa168b7f05b59cb11712ac49db923f5cc286f70 100644
--- a/tools/integration-tests/tester/go.mod
+++ b/tools/integration-tests/tester/go.mod
@@ -12,7 +12,7 @@ require (
 	github.com/iotaledger/goshimmer v0.1.3
 	github.com/iotaledger/hive.go v0.0.0-20200617164933-c48b4401b814
 	github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
-	github.com/stretchr/testify v1.5.1
+	github.com/stretchr/testify v1.6.1
 )
 
 replace github.com/iotaledger/goshimmer => ../../..
diff --git a/tools/integration-tests/tester/go.sum b/tools/integration-tests/tester/go.sum
index 949a92ace7064e1be5d5990ed3b925e708dcd0f2..701c02c13d3ff0bcfe99eb6d4f922e8297be14c5 100644
--- a/tools/integration-tests/tester/go.sum
+++ b/tools/integration-tests/tester/go.sum
@@ -287,6 +287,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
@@ -478,6 +480,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=