diff --git a/dapps/valuetransfers/packages/consensus/fcob.go b/dapps/valuetransfers/packages/consensus/fcob.go
index d5b86548b57dc8c2eeb850a6ab5d7aa6cd564e44..1d2a98aa55f4a4299b015386b24a7bdf1f33e7fb 100644
--- a/dapps/valuetransfers/packages/consensus/fcob.go
+++ b/dapps/valuetransfers/packages/consensus/fcob.go
@@ -3,6 +3,7 @@ package consensus
 import (
 	"time"
 
+	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/branchmanager"
 	"github.com/iotaledger/hive.go/events"
 
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/tangle"
@@ -138,9 +139,10 @@ func (fcob *FCOB) setFinalized(cachedTransactionMetadata *tangle.CachedTransacti
 
 // onFork triggers a voting process whenever a Transaction gets forked into a new Branch. The initial opinion is derived
 // from the preferred flag that was set using the FCOB rule.
-func (fcob *FCOB) onFork(cachedTransaction *transaction.CachedTransaction, cachedTransactionMetadata *tangle.CachedTransactionMetadata) {
+func (fcob *FCOB) onFork(cachedTransaction *transaction.CachedTransaction, cachedTransactionMetadata *tangle.CachedTransactionMetadata, cachedTargetBranch *branchmanager.CachedBranch, conflictingInputs []transaction.OutputID) {
 	defer cachedTransaction.Release()
 	defer cachedTransactionMetadata.Release()
+	defer cachedTargetBranch.Release()
 
 	transactionMetadata := cachedTransactionMetadata.Unwrap()
 	if transactionMetadata == nil {
diff --git a/dapps/valuetransfers/packages/tangle/tangle.go b/dapps/valuetransfers/packages/tangle/tangle.go
index 104194ff524c394dfd7bf17933fb5b06414d2eba..9a52491bd76f88d858c4f4729109efaa1c96b3f3 100644
--- a/dapps/valuetransfers/packages/tangle/tangle.go
+++ b/dapps/valuetransfers/packages/tangle/tangle.go
@@ -4,6 +4,7 @@ import (
 	"container/list"
 	"errors"
 	"fmt"
+	"log"
 	"math"
 	"time"
 
@@ -77,8 +78,10 @@ func (tangle *Tangle) AttachPayload(payload *payload.Payload) {
 // AttachPayloadSync is the worker function that stores the payload and calls the corresponding storage events.
 func (tangle *Tangle) AttachPayloadSync(payloadToStore *payload.Payload) {
 	// store the payload models or abort if we have seen the payload already
+	log.Println("storing payload", payloadToStore.ID())
 	cachedPayload, cachedPayloadMetadata, payloadStored := tangle.storePayload(payloadToStore)
 	if !payloadStored {
+		log.Println("could not store payload", payloadToStore.ID())
 		return
 	}
 	defer cachedPayload.Release()
@@ -235,7 +238,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
@@ -944,6 +947,7 @@ func (tangle *Tangle) storeTransactionModels(solidPayload *payload.Payload) (cac
 	})}
 
 	if transactionIsNew {
+		log.Println("stored transaction", cachedTransaction.Unwrap().ID())
 		cachedTransactionMetadata = &CachedTransactionMetadata{CachedObject: tangle.transactionMetadataStorage.Store(NewTransactionMetadata(solidPayload.Transaction().ID()))}
 
 		// store references to the consumed outputs
@@ -953,6 +957,7 @@ func (tangle *Tangle) storeTransactionModels(solidPayload *payload.Payload) (cac
 			return true
 		})
 	} else {
+		log.Println("transaction was already stored", cachedTransaction.Unwrap().ID())
 		cachedTransactionMetadata = &CachedTransactionMetadata{CachedObject: tangle.transactionMetadataStorage.Load(solidPayload.Transaction().ID().Bytes())}
 	}
 
diff --git a/plugins/webapi/value/gettransactionbyid/handler.go b/plugins/webapi/value/gettransactionbyid/handler.go
index 3bd214df64635497b423d0ee0319f303e5987ef3..8e68d9ef71c06550995bee9f09d104b88568f0f7 100644
--- a/plugins/webapi/value/gettransactionbyid/handler.go
+++ b/plugins/webapi/value/gettransactionbyid/handler.go
@@ -1,20 +1,20 @@
 package gettransactionbyid
 
 import (
+	"log"
 	"net/http"
 
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
 	"github.com/iotaledger/goshimmer/plugins/webapi/value/utils"
 	"github.com/labstack/echo"
-	"github.com/labstack/gommon/log"
 )
 
 // Handler gets the transaction by id.
 func Handler(c echo.Context) error {
 	txnID, err := transaction.IDFromBase58(c.QueryParam("txnID"))
 	if err != nil {
-		log.Info(err)
+		log.Println(err)
 		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
 	}
 
@@ -22,16 +22,19 @@ func Handler(c echo.Context) error {
 	cachedTxnMetaObj := valuetransfers.Tangle.TransactionMetadata(txnID)
 	defer cachedTxnMetaObj.Release()
 	if !cachedTxnMetaObj.Exists() {
+		log.Println("transaction meta doesn't exist for", txnID)
 		return c.JSON(http.StatusNotFound, Response{Error: "Transaction not found"})
 	}
 	cachedTxnObj := valuetransfers.Tangle.Transaction(txnID)
 	defer cachedTxnObj.Release()
 	if !cachedTxnObj.Exists() {
+		log.Println("transaction doesn't exist for", txnID)
 		return c.JSON(http.StatusNotFound, Response{Error: "Transaction not found"})
 	}
 	txn := utils.ParseTransaction(cachedTxnObj.Unwrap())
 
 	txnMeta := cachedTxnMetaObj.Unwrap()
+	txnMeta.Preferred()
 	return c.JSON(http.StatusOK, Response{
 		Transaction: txn,
 		InclusionState: utils.InclusionState{
@@ -41,6 +44,7 @@ func Handler(c echo.Context) error {
 			Solid:     txnMeta.Solid(),
 			Rejected:  txnMeta.Rejected(),
 			Finalized: txnMeta.Finalized(),
+			Preferred: txnMeta.Preferred(),
 		},
 	})
 }
diff --git a/plugins/webapi/value/sendtransaction/handler.go b/plugins/webapi/value/sendtransaction/handler.go
index b1dfa63d99ed7f3b85b4ac1432f4e9e4ab1ecc61..bbf8bd6782964c0b8d6af3e55a94c7106c954b12 100644
--- a/plugins/webapi/value/sendtransaction/handler.go
+++ b/plugins/webapi/value/sendtransaction/handler.go
@@ -1,37 +1,39 @@
 package sendtransaction
 
 import (
+	"log"
 	"net/http"
 
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers"
 	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
 	"github.com/iotaledger/goshimmer/plugins/issuer"
 	"github.com/labstack/echo"
-	"github.com/labstack/gommon/log"
 )
 
 // Handler sends a transaction.
 func Handler(c echo.Context) error {
 	var request Request
 	if err := c.Bind(&request); err != nil {
-		log.Info(err.Error())
+		log.Println(err.Error())
 		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
 	}
 
 	// prepare transaction
 	tx, _, err := transaction.FromBytes(request.TransactionBytes)
 	if err != nil {
-		log.Info(err.Error())
+		log.Println(err.Error())
 		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
 	}
 
 	// Prepare value payload and send the message to tangle
 	payload := valuetransfers.ValueObjectFactory().IssueTransaction(tx)
+	log.Println("issued transaction")
 	_, err = issuer.IssuePayload(payload)
 	if err != nil {
-		log.Info(err.Error())
+		log.Println(err.Error())
 		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
 	}
+	log.Println("issued payload")
 
 	return c.JSON(http.StatusOK, Response{TransactionID: tx.ID().String()})
 }
diff --git a/plugins/webapi/value/utils/transaction_handler.go b/plugins/webapi/value/utils/transaction_handler.go
index 26acd8d9e25001a6428128348d3ae4cd84ec3b12..3c50c38d3d5ffbd0ccb7dcb9647697c10959401d 100644
--- a/plugins/webapi/value/utils/transaction_handler.go
+++ b/plugins/webapi/value/utils/transaction_handler.go
@@ -70,4 +70,5 @@ type InclusionState struct {
 	Solid     bool `json:"solid,omitempty"`
 	Rejected  bool `json:"rejected,omitempty"`
 	Finalized bool `json:"finalized,omitempty"`
+	Preferred bool `json:"preferred,omitempty"`
 }
diff --git a/tools/integration-tests/assets/entrypoint.sh b/tools/integration-tests/assets/entrypoint.sh
index 7e5f060f00c41ae1b7f58e452fddc87a7909221d..9d690630ac57a3be7f712d57beeca177d7fc6f5b 100644
--- a/tools/integration-tests/assets/entrypoint.sh
+++ b/tools/integration-tests/assets/entrypoint.sh
@@ -6,4 +6,4 @@ chmod 777 /assets/*
 echo "assets:"
 ls /assets
 echo "running tests..."
-go test ./tests/"${TEST_NAME}" -run TestConsensusConflicts -v -timeout 30m
+go test ./tests/"${TEST_NAME}" -run TestConsensusFiftyFiftyOpinionSplit -v -timeout 30m
diff --git a/tools/integration-tests/tester/framework/framework.go b/tools/integration-tests/tester/framework/framework.go
index f246f21f916d7129195b1013975f6ab5cdc40812..4c19cc4ac861bf931af96574c19e1b94b2ee70dc 100644
--- a/tools/integration-tests/tester/framework/framework.go
+++ b/tools/integration-tests/tester/framework/framework.go
@@ -80,7 +80,7 @@ func (f *Framework) CreateNetwork(name string, peers int, minimumNeighbors int,
 	// create peers/GoShimmer nodes
 	for i := 0; i < peers; i++ {
 		config := GoShimmerConfig{
-			Bootstrap:                             i == 0,
+			Bootstrap:                             true,
 			BootstrapInitialIssuanceTimePeriodSec: bootstrapInitialIssuanceTimePeriodSec,
 			Faucet:                                i == 0,
 		}
@@ -128,7 +128,7 @@ func (f *Framework) CreateNetworkWithPartitions(name string, peers, partitions,
 
 	// create peers/GoShimmer nodes
 	for i := 0; i < peers; i++ {
-		config := GoShimmerConfig{Bootstrap: i == 0}
+		config := GoShimmerConfig{Bootstrap: true}
 		if _, err = network.CreatePeer(config); err != nil {
 			return nil, err
 		}
diff --git a/tools/integration-tests/tester/tests/consensus/consensus_conflicts_test.go b/tools/integration-tests/tester/tests/consensus/consensus_conflicts_test.go
index 842e4780dec2cbb242828166b9e3edf29159560d..ceecb87bb82980a67b32125fb3e45dc053be19d6 100644
--- a/tools/integration-tests/tester/tests/consensus/consensus_conflicts_test.go
+++ b/tools/integration-tests/tester/tests/consensus/consensus_conflicts_test.go
@@ -18,14 +18,15 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-// TestConsensusConflicts issues valid conflicting value objects and makes sure that
-// the conflicts are resolved via FPC.
-func TestConsensusConflicts(t *testing.T) {
+// TestConsensusFiftyFiftyOpinionSplit spawns two network partitions with their own peers,
+// then issues valid value objects spending the genesis in both, deletes the partitions (and lets them merge)
+// and then checks that the conflicts are resolved via FPC.
+func TestConsensusFiftyFiftyOpinionSplit(t *testing.T) {
 	n, err := f.CreateNetworkWithPartitions("consensus_TestConsensusConflicts", 8, 2, 4)
 	require.NoError(t, err)
 	defer tests.ShutdownNetwork(t, n)
 
-	time.Sleep(10 * time.Second)
+	time.Sleep(5 * time.Second)
 
 	// split the network
 	for i, partition := range n.Partitions() {
@@ -58,7 +59,7 @@ func TestConsensusConflicts(t *testing.T) {
 			transaction.NewInputs(genesisOutputID),
 			transaction.NewOutputs(map[address.Address][]*balance.Balance{
 				destAddr: {
-					{Value: genesisBalance / 2, Color: balance.ColorIOTA},
+					{Value: genesisBalance, Color: balance.ColorIOTA},
 				},
 			}))
 		tx = tx.Sign(signaturescheme.ED25519(*genesisWallet.Seed().KeyPair(0)))
@@ -72,7 +73,7 @@ func TestConsensusConflicts(t *testing.T) {
 		assert.NoError(t, err)
 
 		// check that the transaction is actually available on all the peers of the partition
-		missing, err := tests.AwaitTransactionAvailability(partition.Peers(), []string{txID}, 4*time.Second)
+		missing, err := tests.AwaitTransactionAvailability(partition.Peers(), []string{txID}, 15*time.Second)
 		if err != nil {
 			assert.NoError(t, err, "transactions should have been available in partition")
 			for p, missingOnPeer := range missing {
@@ -90,6 +91,22 @@ func TestConsensusConflicts(t *testing.T) {
 	// sleep the avg. network delay so both partitions prefer their own first seen transaction
 	time.Sleep(valuetransfers.AverageNetworkDelay)
 
+	// check that each partition is preferring its corresponding transaction
+	log.Println("checking that each partition likes its corresponding transaction before the conflict:")
+	for i, partition := range n.Partitions() {
+		tests.CheckTransactions(t, partition.Peers(), map[string]*tests.ExpectedTransaction{
+			conflictingTxIDs[i]: nil,
+		}, true, tests.ExpectedInclusionState{
+			Confirmed: tests.False(),
+			Finalized: tests.False(),
+			Conflict:  tests.False(),
+			Solid:     tests.True(),
+			Rejected:  tests.False(),
+			Liked:     tests.True(),
+			Preferred: tests.True(),
+		})
+	}
+
 	// merge back the partitions
 	log.Println("merging partitions...")
 	assert.NoError(t, n.DeletePartitions(), "merging the network partitions should work")
@@ -125,13 +142,42 @@ func TestConsensusConflicts(t *testing.T) {
 		}
 	}
 
+	// check that the transactions are marked as conflicting
 	tests.CheckTransactions(t, n.Peers(), expectations, true, tests.ExpectedInclusionState{
-		Confirmed: tests.False(),
-		Finalized: tests.False(),
-		// should be part of a conflict set
-		Conflict: tests.True(),
-		Solid:    tests.True(),
-		Rejected: tests.False(),
-		Liked:    tests.False(),
+		Finalized: tests.True(),
+		Conflict:  tests.True(),
+		Solid:     tests.True(),
 	})
+
+	// now all transactions must be finalized and at most one must be confirmed
+	var confirmedOverConflictSet int
+	for _, conflictingTx := range conflictingTxIDs {
+		var rejected, confirmed int
+		for _, p := range n.Peers() {
+			tx, err := p.GetTransactionByID(conflictingTx)
+			assert.NoError(t, err)
+			if tx.InclusionState.Confirmed {
+				confirmed++
+				continue
+			}
+			if tx.InclusionState.Rejected {
+				rejected++
+			}
+		}
+
+		if rejected != 0 {
+			assert.Len(t, n.Peers(), rejected, "the rejected count for %s should be equal to the amount of peers", conflictingTx)
+		}
+		if confirmed != 0 {
+			assert.Len(t, n.Peers(), confirmed, "the confirmed count for %s should be equal to the amount of peers", conflictingTx)
+			confirmedOverConflictSet++
+		}
+
+		assert.False(t, rejected == 0 && confirmed == 0, "a transaction must either be rejected or confirmed")
+	}
+
+	// there must only be one confirmed transaction out of the conflict set
+	if confirmedOverConflictSet != 0 {
+		assert.Equal(t, 1, confirmedOverConflictSet, "only one transaction can be confirmed out of the conflict set. %d of %d are confirmed", confirmedOverConflictSet, len(conflictingTxIDs))
+	}
 }
diff --git a/tools/integration-tests/tester/tests/testutil.go b/tools/integration-tests/tester/tests/testutil.go
index 65ff862860e9d0421e9d2a8b8f18ed5c7eca32c8..d0b6e75f4270b3bcc15ed012bd6130a78047bcbf 100644
--- a/tools/integration-tests/tester/tests/testutil.go
+++ b/tools/integration-tests/tester/tests/testutil.go
@@ -383,6 +383,8 @@ type ExpectedInclusionState struct {
 	Rejected *bool
 	// The optional liked state to check against.
 	Liked *bool
+	// The optional preferred state to check against.
+	Preferred *bool
 }
 
 // True returns a pointer to a true bool.
@@ -426,30 +428,33 @@ func CheckTransactions(t *testing.T, peers []*framework.Peer, transactionIDs map
 
 			// check inclusion state
 			if expectedInclusionState.Confirmed != nil {
-				assert.Equal(t, *expectedInclusionState.Confirmed, resp.InclusionState.Confirmed, "confirmed state doesn't match")
+				assert.Equal(t, *expectedInclusionState.Confirmed, resp.InclusionState.Confirmed, "confirmed state doesn't match - %s", txId)
 			}
 			if expectedInclusionState.Conflict != nil {
-				assert.Equal(t, *expectedInclusionState.Conflict, resp.InclusionState.Conflict, "conflict state doesn't match")
+				assert.Equal(t, *expectedInclusionState.Conflict, resp.InclusionState.Conflict, "conflict state doesn't match - %s", txId)
 			}
 			if expectedInclusionState.Solid != nil {
-				assert.Equal(t, *expectedInclusionState.Solid, resp.InclusionState.Solid, "solid state doesn't match")
+				assert.Equal(t, *expectedInclusionState.Solid, resp.InclusionState.Solid, "solid state doesn't match - %s", txId)
 			}
 			if expectedInclusionState.Rejected != nil {
-				assert.Equal(t, *expectedInclusionState.Rejected, resp.InclusionState.Rejected, "rejected state doesn't match")
+				assert.Equal(t, *expectedInclusionState.Rejected, resp.InclusionState.Rejected, "rejected state doesn't match - %s", txId)
 			}
 			if expectedInclusionState.Liked != nil {
-				assert.Equal(t, *expectedInclusionState.Liked, resp.InclusionState.Liked, "liked state doesn't match")
+				assert.Equal(t, *expectedInclusionState.Liked, resp.InclusionState.Liked, "liked state doesn't match - %s", txId)
+			}
+			if expectedInclusionState.Preferred != nil {
+				assert.Equal(t, *expectedInclusionState.Preferred, resp.InclusionState.Preferred, "preferred state doesn't match - %s", txId)
 			}
 
 			if expectedTransaction != nil {
 				if expectedTransaction.Inputs != nil {
-					assert.Equal(t, *expectedTransaction.Inputs, resp.Transaction.Inputs, "inputs do not match")
+					assert.Equal(t, *expectedTransaction.Inputs, resp.Transaction.Inputs, "inputs do not match - %s", txId)
 				}
 				if expectedTransaction.Outputs != nil {
-					assert.Equal(t, *expectedTransaction.Outputs, resp.Transaction.Outputs, "outputs do not match")
+					assert.Equal(t, *expectedTransaction.Outputs, resp.Transaction.Outputs, "outputs do not match - %s", txId)
 				}
 				if expectedTransaction.Signature != nil {
-					assert.Equal(t, *expectedTransaction.Signature, resp.Transaction.Signature, "signatures do not match")
+					assert.Equal(t, *expectedTransaction.Signature, resp.Transaction.Signature, "signatures do not match - %s", txId)
 				}
 			}
 		}