diff --git a/dapps/valuetransfers/packages/branchmanager/branchmanager.go b/dapps/valuetransfers/packages/branchmanager/branchmanager.go
index 3b8232c117d7a11282885c72717c269f0841b38b..07bc1bef733d39d63e3decf7612a9df150f8f9a9 100644
--- a/dapps/valuetransfers/packages/branchmanager/branchmanager.go
+++ b/dapps/valuetransfers/packages/branchmanager/branchmanager.go
@@ -481,9 +481,9 @@ func (branchManager *BranchManager) propagateConfirmedToChildBranches(cachedBran
 			branchManager.Events.BranchConfirmed.Trigger(cachedBranch)
 
 			// schedule confirmed checks of children
-			for _, cachedChildBranch := range branchManager.ChildBranches(branch.ID()) {
-				propagationStack.PushBack(cachedChildBranch)
-			}
+			branchManager.ChildBranches(branch.ID()).Consume(func(childBranch *ChildBranch) {
+				propagationStack.PushBack(branchManager.Branch(childBranch.childID))
+			})
 		})
 		propagationStack.Remove(stackElement)
 	}
diff --git a/dapps/valuetransfers/packages/tangle/tangle.go b/dapps/valuetransfers/packages/tangle/tangle.go
index 9390b4b960a508e5e074a2b293cd52d19ffc6be7..70bdf8dc52777dfc150aca26846778707432b479 100644
--- a/dapps/valuetransfers/packages/tangle/tangle.go
+++ b/dapps/valuetransfers/packages/tangle/tangle.go
@@ -452,12 +452,12 @@ func (tangle *Tangle) onBranchFinalized(cachedBranch *branchmanager.CachedBranch
 
 // onBranchConfirmed gets triggered when a branch in the branch DAG is marked as confirmed.
 func (tangle *Tangle) onBranchConfirmed(cachedBranch *branchmanager.CachedBranch) {
-	tangle.propagateBranchConfirmedRejectedChangesToTangle(cachedBranch)
+	tangle.propagateBranchConfirmedRejectedChangesToTangle(cachedBranch, true)
 }
 
 // onBranchRejected gets triggered when a branch in the branch DAG is marked as rejected.
 func (tangle *Tangle) onBranchRejected(cachedBranch *branchmanager.CachedBranch) {
-	tangle.propagateBranchConfirmedRejectedChangesToTangle(cachedBranch)
+	tangle.propagateBranchConfirmedRejectedChangesToTangle(cachedBranch, false)
 }
 
 // propagateBranchPreferredChangesToTangle triggers the propagation of preferred status changes of a branch to the value
@@ -518,7 +518,7 @@ func (tangle *Tangle) propagateBranchedLikedChangesToTangle(cachedBranch *branch
 
 // propagateBranchConfirmedRejectedChangesToTangle triggers the propagation of confirmed and rejected status changes of
 // a branch to the value tangle and its UTXO DAG.
-func (tangle *Tangle) propagateBranchConfirmedRejectedChangesToTangle(cachedBranch *branchmanager.CachedBranch) {
+func (tangle *Tangle) propagateBranchConfirmedRejectedChangesToTangle(cachedBranch *branchmanager.CachedBranch, confirmed bool) {
 	cachedBranch.Consume(func(branch *branchmanager.Branch) {
 		if !branch.IsAggregated() {
 			transactionID, _, err := transaction.IDFromBytes(branch.ID().Bytes())
@@ -527,7 +527,7 @@ func (tangle *Tangle) propagateBranchConfirmedRejectedChangesToTangle(cachedBran
 			}
 
 			// propagate changes to future cone of transaction (value tangle)
-			tangle.propagateValuePayloadConfirmedRejectedUpdates(transactionID)
+			tangle.propagateValuePayloadConfirmedRejectedUpdates(transactionID, confirmed)
 		}
 	})
 }
@@ -576,7 +576,7 @@ func (tangle *Tangle) setTransactionFinalized(transactionID transaction.ID, even
 				}
 
 				// propagate changes to future cone of transaction (value tangle)
-				tangle.propagateValuePayloadConfirmedRejectedUpdates(transactionID)
+				tangle.propagateValuePayloadConfirmedRejectedUpdates(transactionID, metadata.Preferred())
 			}
 		}
 	})
@@ -605,6 +605,12 @@ func (tangle *Tangle) propagateRejectedToTransactions(transactionID transaction.
 			if !metadata.setRejected(true) {
 				return
 			}
+			metadata.setPreferred(false)
+
+			if _, err := tangle.setTransactionFinalized(metadata.ID(), EventSourceTangle); err != nil {
+				tangle.Events.Error.Trigger(err)
+				return
+			}
 
 			cachedTransaction := tangle.Transaction(currentTransactionID)
 			cachedTransaction.Consume(func(tx *transaction.Transaction) {
@@ -638,7 +644,7 @@ func (tangle *Tangle) propagateRejectedToTransactions(transactionID transaction.
 }
 
 // TODO: WRITE COMMENT
-func (tangle *Tangle) propagateValuePayloadConfirmedRejectedUpdates(transactionID transaction.ID) {
+func (tangle *Tangle) propagateValuePayloadConfirmedRejectedUpdates(transactionID transaction.ID, confirmed bool) {
 	// initiate stack with the attachments of the passed in transaction
 	propagationStack := list.New()
 	tangle.Attachments(transactionID).Consume(func(attachment *Attachment) {
@@ -656,12 +662,12 @@ func (tangle *Tangle) propagateValuePayloadConfirmedRejectedUpdates(transactionI
 	// iterate through stack (future cone of transactions)
 	for propagationStack.Len() >= 1 {
 		currentAttachmentEntry := propagationStack.Front()
-		tangle.propagateValuePayloadConfirmedRejectedUpdateStackEntry(propagationStack, seenPayloads, currentAttachmentEntry.Value.(*valuePayloadPropagationStackEntry))
+		tangle.propagateValuePayloadConfirmedRejectedUpdateStackEntry(propagationStack, seenPayloads, currentAttachmentEntry.Value.(*valuePayloadPropagationStackEntry), confirmed)
 		propagationStack.Remove(currentAttachmentEntry)
 	}
 }
 
-func (tangle *Tangle) propagateValuePayloadConfirmedRejectedUpdateStackEntry(propagationStack *list.List, processedPayloads map[payload.ID]types.Empty, propagationStackEntry *valuePayloadPropagationStackEntry) {
+func (tangle *Tangle) propagateValuePayloadConfirmedRejectedUpdateStackEntry(propagationStack *list.List, processedPayloads map[payload.ID]types.Empty, propagationStackEntry *valuePayloadPropagationStackEntry, confirmed bool) {
 	// release the entry when we are done
 	defer propagationStackEntry.Release()
 
@@ -672,10 +678,10 @@ func (tangle *Tangle) propagateValuePayloadConfirmedRejectedUpdateStackEntry(pro
 	}
 
 	// perform different logic depending on the type of the change (liked vs dislike)
-	switch currentTransactionMetadata.Preferred() {
+	switch confirmed {
 	case true:
 		// abort if the transaction is not preferred, the branch of the payload is not liked, the referenced value payloads are not liked or the payload was marked as liked before
-		if !currentTransactionMetadata.Finalized() || !tangle.BranchManager().IsBranchConfirmed(currentPayloadMetadata.BranchID()) || !tangle.ValuePayloadsConfirmed(currentPayload.TrunkID(), currentPayload.BranchID()) || !currentPayloadMetadata.setConfirmed(true) {
+		if !currentTransactionMetadata.Preferred() || !currentTransactionMetadata.Finalized() || !tangle.BranchManager().IsBranchConfirmed(currentPayloadMetadata.BranchID()) || !tangle.ValuePayloadsConfirmed(currentPayload.TrunkID(), currentPayload.BranchID()) || !currentPayloadMetadata.setConfirmed(true) {
 			return
 		}
 
@@ -695,6 +701,11 @@ func (tangle *Tangle) propagateValuePayloadConfirmedRejectedUpdateStackEntry(pro
 			tangle.Events.TransactionConfirmed.Trigger(propagationStackEntry.CachedTransaction, propagationStackEntry.CachedTransactionMetadata)
 		}
 	case false:
+		// abort if transaction is not finalized and neither of parents is rejected
+		if !currentTransactionMetadata.Finalized() && !(tangle.payloadRejected(currentPayload.BranchID()) || tangle.payloadRejected(currentPayload.TrunkID())) {
+			return
+		}
+
 		// abort if the payload has been marked as disliked before
 		if !currentPayloadMetadata.setRejected(true) {
 			return
@@ -891,6 +902,13 @@ func (tangle *Tangle) createValuePayloadFutureConeIterator(propagationStack *lis
 	}
 }
 
+func (tangle *Tangle) payloadRejected(payloadID payload.ID) (rejected bool) {
+	tangle.PayloadMetadata(payloadID).Consume(func(payloadMetadata *PayloadMetadata) {
+		rejected = payloadMetadata.Rejected()
+	})
+	return
+}
+
 func (tangle *Tangle) storePayload(payloadToStore *payload.Payload) (cachedPayload *payload.CachedPayload, cachedMetadata *CachedPayloadMetadata, payloadStored bool) {
 	storedPayload, newPayload := tangle.payloadStorage.StoreIfAbsent(payloadToStore)
 	if !newPayload {
diff --git a/dapps/valuetransfers/packages/tangle/tangle_test.go b/dapps/valuetransfers/packages/tangle/tangle_test.go
index 6d3718b1ad644a792d11bd43eb25138051f92bf9..ea2a2a34a112ca2922444d1b336d95a73726a7d8 100644
--- a/dapps/valuetransfers/packages/tangle/tangle_test.go
+++ b/dapps/valuetransfers/packages/tangle/tangle_test.go
@@ -1865,7 +1865,7 @@ const (
 	Y
 )
 
-func preparePropagationScenario() (*Tangle, map[string]*transaction.Transaction, map[string]*payload.Payload) {
+func preparePropagationScenario1() (*Tangle, map[string]*transaction.Transaction, map[string]*payload.Payload, *wallet.Seed) {
 	// create tangle
 	tangle := New(mapdb.NewMapDB())
 
@@ -1991,189 +1991,356 @@ func preparePropagationScenario() (*Tangle, map[string]*transaction.Transaction,
 		tangle.AttachPayloadSync(valueObjects["[-E, -F, G+]"])
 	}
 
-	return tangle, transactions, valueObjects
+	return tangle, transactions, valueObjects, seed
 }
 
-func TestPropagation(t *testing.T) {
+func preparePropagationScenario2() (*Tangle, map[string]*transaction.Transaction, map[string]*payload.Payload, *wallet.Seed) {
+	tangle, transactions, valueObjects, seed := preparePropagationScenario1()
 
-	transactionsSlice := []string{
-		"[-GENESIS, A+, B+, C+]",
-		"[-A, D+]",
-		"[-B, -C, E+]",
-		"[-B, -C, E+] (Reattachment)",
-		"[-A, F+]",
-		"[-E, -F, G+]",
+	// [-C, H+]
+	{
+		// create transaction + payload
+		transactions["[-C, H+]"] = transaction.New(
+			transaction.NewInputs(
+				transaction.NewOutputID(seed.Address(C), transactions["[-GENESIS, A+, B+, C+]"].ID()),
+			),
+
+			transaction.NewOutputs(map[address.Address][]*balance.Balance{
+				seed.Address(H): {
+					balance.New(balance.ColorIOTA, 1111),
+				},
+			}),
+		)
+		valueObjects["[-C, H+]"] = payload.New(valueObjects["[-GENESIS, A+, B+, C+]"].ID(), valueObjects["[-A, D+]"].ID(), transactions["[-C, H+]"])
+
+		// attach payload
+		tangle.AttachPayloadSync(valueObjects["[-C, H+]"])
 	}
 
-	//{
-	//	tangle, transactions, valueObjects := preparePropagationScenario()
-	//	//tangle.TransactionMetadata(transactions["[-E, -F, G+]"].ID()).Consume(func(metadata *TransactionMetadata) {
-	//	//	fmt.Println(metadata.Conflicting())
-	//	//})
-	//	setTransactionPreferredWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"], true)
-	//	//setTransactionFinalizedWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"])
-	//
-	//	setTransactionPreferredWithCheck(t, tangle, transactions["[-B, -C, E+]"], true)
-	//	setTransactionFinalizedWithCheck(t, tangle, transactions["[-B, -C, E+]"])
-	//
-	//	assert.True(t, tangle.TransactionMetadata(transactions["[-B, -C, E+]"].ID()).Consume(func(metadata *TransactionMetadata) {
-	//		assert.True(t, metadata.Preferred())
-	//		assert.True(t, metadata.Finalized())
-	//	}))
-	//	assert.True(t, tangle.PayloadMetadata(valueObjects["[-B, -C, E+]"].ID()).Consume(func(payloadMetadata *PayloadMetadata) {
-	//		assert.True(t, payloadMetadata.Liked())
-	//		assert.False(t, payloadMetadata.Confirmed())
-	//		assert.False(t, payloadMetadata.Rejected())
-	//	}))
-	//
-	//	for _, name := range transactionsSlice {
-	//		valueObject := valueObjects[name]
-	//		cachedTxMetadata := tangle.TransactionMetadata(valueObject.Transaction().ID())
-	//		cachedValueObjectMetadata := tangle.PayloadMetadata(valueObject.ID())
-	//		fmt.Println("----", name, "----")
-	//
-	//		assert.True(t, cachedTxMetadata.Consume(func(metadata *TransactionMetadata) {
-	//			log.Println("Preferred:", metadata.Preferred())
-	//			log.Println("Finalized:", metadata.Finalized())
-	//		}))
-	//
-	//		assert.True(t, cachedValueObjectMetadata.Consume(func(payloadMetadata *PayloadMetadata) {
-	//			log.Println("Payload Liked:", payloadMetadata.Liked())
-	//			log.Println("Payload Confirmed:", payloadMetadata.Confirmed())
-	//			log.Println("Payload Rejected:", payloadMetadata.Rejected())
-	//		}))
-	//
-	//		fmt.Println()
-	//	}
-	//}
-
-	//{
-	//	tangle, transactions, valueObjects := preparePropagationScenario()
-	//	//tangle.TransactionMetadata(transactions["[-E, -F, G+]"].ID()).Consume(func(metadata *TransactionMetadata) {
-	//	//	fmt.Println(metadata.Conflicting())
-	//	//})
-	//	setTransactionPreferredWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"], true)
-	//	//setTransactionFinalizedWithCheck(t, tangle, transactions["[-GENESIS, A+, B+, C+]"])
-	//	setTransactionPreferredWithCheck(t, tangle, transactions["[-B, -C, E+]"], true)
-	//	setTransactionFinalizedWithCheck(t, tangle, transactions["[-B, -C, E+]"])
-	//
-	//	setTransactionPreferredWithCheck(t, tangle, transactions["[-A, D+]"], true)
-	//	// TODO: should become rejected
-	//
-	//	assert.True(t, tangle.branchManager.Branch(branchmanager.NewBranchID(transactions["[-A, D+]"].ID())).Consume(func(branch *branchmanager.Branch) {
-	//		assert.True(t, branch.Liked())
-	//		assert.False(t, branch.Finalized())
-	//
-	//		assert.False(t, branch.Confirmed())
-	//		assert.False(t, branch.Rejected())
-	//	}))
-	//
-	//	// vote result
-	//	setTransactionPreferredWithCheck(t, tangle, transactions["[-A, F+]"], true)
-	//	setTransactionFinalizedWithCheck(t, tangle, transactions["[-A, F+]"])
-	//	// TODO: should become confirmed
-	//
-	//	assert.True(t, tangle.branchManager.Branch(branchmanager.NewBranchID(transactions["[-A, D+]"].ID())).Consume(func(branch *branchmanager.Branch) {
-	//		assert.False(t, branch.Liked())
-	//		assert.True(t, branch.Finalized())
-	//
-	//		assert.False(t, branch.Confirmed())
-	//		assert.True(t, branch.Rejected())
-	//	}))
-	//
-	//	setTransactionPreferredWithCheck(t, tangle, transactions["[-E, -F, G+]"], true)
-	//
-	//	for _, name := range transactionsSlice {
-	//		valueObject := valueObjects[name]
-	//		cachedTxMetadata := tangle.TransactionMetadata(valueObject.Transaction().ID())
-	//		cachedValueObjectMetadata := tangle.PayloadMetadata(valueObject.ID())
-	//		fmt.Println("----", name, "----")
-	//
-	//		assert.True(t, cachedTxMetadata.Consume(func(metadata *TransactionMetadata) {
-	//			log.Println("Preferred:", metadata.Preferred())
-	//			log.Println("Finalized:", metadata.Finalized())
-	//		}))
-	//
-	//		assert.True(t, cachedValueObjectMetadata.Consume(func(payloadMetadata *PayloadMetadata) {
-	//			log.Println("Payload Liked:", payloadMetadata.Liked())
-	//			log.Println("Payload Confirmed:", payloadMetadata.Confirmed())
-	//			log.Println("Payload Rejected:", payloadMetadata.Rejected())
-	//		}))
-	//
-	//		fmt.Println()
-	//	}
-	//}
+	// [-H, -D, I+]
+	{
+		// create transaction + payload
+		transactions["[-H, -D, I+]"] = transaction.New(
+			transaction.NewInputs(
+				transaction.NewOutputID(seed.Address(H), transactions["[-C, H+]"].ID()),
+				transaction.NewOutputID(seed.Address(D), transactions["[-A, D+]"].ID()),
+			),
+
+			transaction.NewOutputs(map[address.Address][]*balance.Balance{
+				seed.Address(I): {
+					balance.New(balance.ColorIOTA, 2222),
+				},
+			}),
+		)
+		valueObjects["[-H, -D, I+]"] = payload.New(valueObjects["[-C, H+]"].ID(), valueObjects["[-A, D+]"].ID(), transactions["[-H, -D, I+]"])
+
+		// attach payload
+		tangle.AttachPayloadSync(valueObjects["[-H, -D, I+]"])
+	}
+
+	// [-B, J+]
+	{
+		// create transaction + payload
+		transactions["[-B, J+]"] = transaction.New(
+			transaction.NewInputs(
+				transaction.NewOutputID(seed.Address(B), transactions["[-GENESIS, A+, B+, C+]"].ID()),
+			),
+
+			transaction.NewOutputs(map[address.Address][]*balance.Balance{
+				seed.Address(J): {
+					balance.New(balance.ColorIOTA, 1111),
+				},
+			}),
+		)
+		valueObjects["[-B, J+]"] = payload.New(valueObjects["[-C, H+]"].ID(), valueObjects["[-A, D+]"].ID(), transactions["[-B, J+]"])
+		// attach payload
+		tangle.AttachPayloadSync(valueObjects["[-B, J+]"])
+	}
+
+	return tangle, transactions, valueObjects, seed
+}
+
+func TestPropagationScenario1(t *testing.T) {
+	// test past cone monotonicity - all value objects MUST be confirmed
+	{
+		tangle, transactions, valueObjects, _ := preparePropagationScenario1()
+
+		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
+		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+]
+		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)
+	}
+
+	// test future cone monotonicity simple - everything MUST be rejected and finalized if spending funds from rejected tx
+	{
+		tangle, transactions, valueObjects, _ := preparePropagationScenario1()
+
+		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)
+	}
+
+	// test future cone monotonicity more complex - everything MUST be rejected and finalized if spending funds from rejected tx
+	{
+		transactionsSlice := []string{
+			"[-GENESIS, A+, B+, C+]",
+			"[-A, D+]",
+			"[-B, -C, E+]",
+			"[-B, -C, E+] (Reattachment)",
+			"[-A, F+]",
+			"[-E, -F, G+]",
+		}
+		tangle, transactions, valueObjects, _ := preparePropagationScenario1()
+
+		for _, name := range transactionsSlice {
+			fmt.Println(name, valueObjects[name].Transaction().ID())
+		}
+
+		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)
+
+		// finalize & reject
+		setTransactionFinalizedWithCheck(t, tangle, transactions["[-B, -C, E+]"])
+		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+]"], false, true, false, false, true)
+
+		// check future cone to be rejected
+		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+] (Reattachment)"], false, true, false, false, true)
+
+		// [-A, F+] should be rejected but the tx not finalized since it spends funds from [-GENESIS, A+, B+, C+] which is confirmed
+		verifyInclusionState(t, tangle, valueObjects["[-A, F+]"], false, false, false, false, true)
+		verifyBranchState(t, tangle, valueObjects["[-A, F+]"], false, false, false, true)
+		//TODO:
+
+		// [-E, -F, G+] should be finalized and rejected since it spends funds from [-B, -C, E+]
+		verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], false, true, false, false, true)
+
+		// [-A, D+] should be unchanged
+		verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], false, false, false, false, false)
+		verifyBranchState(t, tangle, valueObjects["[-A, D+]"], false, false, false, false)
+	}
+
+	// simulate vote on [-A, F+] -> Branch A becomes rejected, Branch B confirmed
+	{
+		tangle, transactions, valueObjects, _ := preparePropagationScenario1()
+
+		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)
+
+		// check future cone
+		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+]"], false, false, false, false, false)
+		verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+] (Reattachment)"], false, false, false, false, false)
+		verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], false, false, false, false, false)
+		verifyInclusionState(t, tangle, valueObjects["[-A, F+]"], false, false, false, false, false)
+		verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], false, false, false, false, false)
+
+		// 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)
+
+		// prefer [-A, D+]
+		setTransactionPreferredWithCheck(t, tangle, transactions["[-A, D+]"], true)
+		verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], true, false, true, false, false)
+		verifyBranchState(t, tangle, valueObjects["[-A, D+]"], false, true, false, false)
+
+		// 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, valueObjects["[-A, F+]"], true, true, true, false)
+
+		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, valueObjects["[-A, D+]"], true, false, false, true)
+	}
 
+	// simulate vote on [-A, D+] -> Branch B becomes rejected, Branch A confirmed
 	{
-		tangle, transactions, valueObjects := preparePropagationScenario()
+		tangle, transactions, valueObjects, _ := preparePropagationScenario1()
 
+		// 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)
+
+		// 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)
 
+		// 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, valueObjects["[-A, F+]"], false, true, false, false)
+		// prefer [-E, -F, G+]
 		setTransactionPreferredWithCheck(t, tangle, transactions["[-E, -F, G+]"], true)
-		// TODO: check tstat
+		verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], true, false, true, false, false)
 
-		// vote result
+		// 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+]"])
-		assert.True(t, tangle.branchManager.Branch(branchmanager.NewBranchID(transactions["[-A, D+]"].ID())).Consume(func(branch *branchmanager.Branch) {
-			assert.True(t, branch.Liked())
-			assert.True(t, branch.Finalized())
+		verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], true, true, true, true, false)
+		verifyBranchState(t, tangle, valueObjects["[-A, D+]"], true, true, true, false)
 
-			assert.True(t, branch.Confirmed())
-			assert.False(t, branch.Rejected())
-		}))
+		// [-A, F+], [-E, -F, G+] should be finalized and rejected
+		verifyInclusionState(t, tangle, valueObjects["[-A, F+]"], false, true, false, false, true)
+		verifyBranchState(t, tangle, valueObjects["[-A, F+]"], true, false, false, true)
+		verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], false, true, false, false, true)
+	}
+}
 
-		// check [-A, F+] and to be rejected [-E, -F, G+]
-		assert.True(t, tangle.branchManager.Branch(branchmanager.NewBranchID(transactions["[-A, F+]"].ID())).Consume(func(branch *branchmanager.Branch) {
-			assert.False(t, branch.Liked())
-			assert.True(t, branch.Finalized())
+func TestPropagationScenario2(t *testing.T) {
+	tangle, transactions, valueObjects, _ := preparePropagationScenario2()
 
-			assert.False(t, branch.Confirmed())
-			assert.True(t, branch.Rejected())
-		}))
-		assert.True(t, tangle.TransactionMetadata(transactions["[-A, F+]"].ID()).Consume(func(metadata *TransactionMetadata) {
-			assert.False(t, metadata.Preferred())
-			assert.True(t, metadata.Finalized())
-		}))
-		assert.True(t, tangle.PayloadMetadata(valueObjects["[-A, F+]"].ID()).Consume(func(payloadMetadata *PayloadMetadata) {
-			assert.False(t, payloadMetadata.Liked())
-			assert.False(t, payloadMetadata.Confirmed())
-			assert.True(t, payloadMetadata.Rejected())
-		}))
-		assert.True(t, tangle.TransactionMetadata(transactions["[-E, -F, G+]"].ID()).Consume(func(metadata *TransactionMetadata) {
-			assert.True(t, metadata.Preferred())
-			assert.False(t, metadata.Finalized())
-		}))
-		assert.True(t, tangle.PayloadMetadata(valueObjects["[-E, -F, G+]"].ID()).Consume(func(payloadMetadata *PayloadMetadata) {
-			assert.False(t, payloadMetadata.Liked())
-			assert.False(t, payloadMetadata.Confirmed())
-			assert.True(t, payloadMetadata.Rejected())
-		}))
+	// 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)
 
-		for _, name := range transactionsSlice {
-			valueObject := valueObjects[name]
-			cachedTxMetadata := tangle.TransactionMetadata(valueObject.Transaction().ID())
-			cachedValueObjectMetadata := tangle.PayloadMetadata(valueObject.ID())
-			fmt.Println("----", name, "----")
-
-			assert.True(t, cachedTxMetadata.Consume(func(metadata *TransactionMetadata) {
-				log.Println("Preferred:", metadata.Preferred())
-				log.Println("Finalized:", metadata.Finalized())
-			}))
+	// 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, valueObjects["[-B, -C, E+]"], false, true, false, false)
+	verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+] (Reattachment)"], true, false, true, false, false)
 
-			assert.True(t, cachedValueObjectMetadata.Consume(func(payloadMetadata *PayloadMetadata) {
-				log.Println("Payload Liked:", payloadMetadata.Liked())
-				log.Println("Payload Confirmed:", payloadMetadata.Confirmed())
-				log.Println("Payload Rejected:", payloadMetadata.Rejected())
-			}))
+	// 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, valueObjects["[-A, F+]"], false, true, false, false)
 
-			fmt.Println()
-		}
-	}
+	// prefer [-E, -F, G+]
+	setTransactionPreferredWithCheck(t, tangle, transactions["[-E, -F, G+]"], true)
+	verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], true, false, true, false, false)
+
+	// verify states of other transactions, value objects and branches
+	verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], false, false, false, false, false)
+	verifyBranchState(t, tangle, valueObjects["[-A, D+]"], false, false, false, false)
+
+	verifyInclusionState(t, tangle, valueObjects["[-C, H+]"], false, false, false, false, false)
+	verifyBranchState(t, tangle, valueObjects["[-C, H+]"], false, false, false, false)
+
+	verifyInclusionState(t, tangle, valueObjects["[-H, -D, I+]"], false, false, false, false, false)
+
+	verifyInclusionState(t, tangle, valueObjects["[-B, J+]"], false, false, false, false, false)
+	verifyBranchState(t, tangle, valueObjects["[-B, J+]"], false, false, false, false)
+
+	// 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)
+
+	// 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+]"])
+	verifyInclusionState(t, tangle, valueObjects["[-A, D+]"], true, true, true, true, false)
+	verifyBranchState(t, tangle, valueObjects["[-A, D+]"], true, true, true, false)
+
+	verifyInclusionState(t, tangle, valueObjects["[-A, F+]"], false, true, false, false, true)
+	verifyBranchState(t, tangle, valueObjects["[-A, F+]"], true, false, false, true)
+	verifyInclusionState(t, tangle, valueObjects["[-E, -F, G+]"], false, true, false, false, true)
+
+	// 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+]"])
+	verifyInclusionState(t, tangle, valueObjects["[-C, H+]"], true, true, true, true, false)
+	verifyBranchState(t, tangle, valueObjects["[-C, H+]"], true, true, true, false)
+
+	branches := make(map[string]branchmanager.BranchID)
+	branches["A"] = branchmanager.NewBranchID(transactions["[-A, D+]"].ID())
+	branches["C"] = branchmanager.NewBranchID(transactions["[-C, H+]"].ID())
+	branches["AC"] = tangle.BranchManager().GenerateAggregatedBranchID(branches["A"], branches["C"])
+	verifyBranchState2(t, tangle, branches["AC"], true, true, true, false)
+
+	//verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+]"], false, true, false, false, true)
+	//verifyBranchState(t, tangle, valueObjects["[-B, -C, E+]"], true, false, false, true)
+	//verifyInclusionState(t, tangle, valueObjects["[-B, -C, E+] (Reattachment)"], false, true, false, false, true)
+	//
+	//// [-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)
+	//// [-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)
+}
+
+func verifyBranchState(t *testing.T, tangle *Tangle, valueObject *payload.Payload, finalized, liked, confirmed, rejected bool) {
+	assert.True(t, tangle.branchManager.Branch(branchmanager.NewBranchID(valueObject.Transaction().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")
+
+		assert.Equalf(t, confirmed, branch.Confirmed(), "branch confirmed state does not match")
+		assert.Equalf(t, rejected, branch.Rejected(), "branch rejected state does not match")
+	}))
+}
+
+func verifyBranchState2(t *testing.T, tangle *Tangle, 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")
+
+		assert.Equalf(t, confirmed, branch.Confirmed(), "branch confirmed state does not match")
+		assert.Equalf(t, rejected, branch.Rejected(), "branch rejected state does not match")
+	}))
+}
+
+func verifyInclusionState(t *testing.T, tangle *Tangle, valueObject *payload.Payload, preferred, finalized, liked, confirmed, rejected bool) {
+	tx := valueObject.Transaction()
+
+	// check outputs
+	tx.Outputs().ForEach(func(address address.Address, balances []*balance.Balance) bool {
+		assert.True(t, tangle.TransactionOutput(transaction.NewOutputID(address, tx.ID())).Consume(func(output *Output) {
+			assert.Equalf(t, liked, output.Liked(), "output liked state does not match")
+			assert.Equalf(t, confirmed, output.Confirmed(), "output confirmed state does not match")
+			assert.Equalf(t, rejected, output.Rejected(), "output rejected state does not match")
+		}))
+		return true
+	})
+
+	// check transaction
+	assert.True(t, tangle.TransactionMetadata(tx.ID()).Consume(func(metadata *TransactionMetadata) {
+		assert.Equalf(t, preferred, metadata.Preferred(), "tx preferred state does not match")
+		assert.Equalf(t, finalized, metadata.Finalized(), "tx finalized state does not match")
+
+		assert.Equalf(t, liked, metadata.Liked(), "tx liked state does not match")
+		assert.Equalf(t, confirmed, metadata.Confirmed(), "tx confirmed state does not match")
+		assert.Equalf(t, rejected, metadata.Rejected(), "tx rejected state does not match")
+	}))
+
+	// check value object
+	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")
+		assert.Equalf(t, rejected, payloadMetadata.Rejected(), "value object rejected state does not match")
+	}))
 }
 
 func setTransactionPreferredWithCheck(t *testing.T, tangle *Tangle, tx *transaction.Transaction, preferred bool) {