diff --git a/dapps/valuetransfers/packages/address/sort.go b/dapps/valuetransfers/packages/address/sort.go
new file mode 100644
index 0000000000000000000000000000000000000000..933d74dd6df828c66c53b9cce05bcdf5044455cd
--- /dev/null
+++ b/dapps/valuetransfers/packages/address/sort.go
@@ -0,0 +1,25 @@
+package address
+
+import (
+	"bytes"
+	"sort"
+)
+
+type sortedAddresses []Address
+
+func (s sortedAddresses) Len() int {
+	return len(s)
+}
+
+func (s sortedAddresses) Less(i, j int) bool {
+	return bytes.Compare(s[i][:], s[j][:]) < 0
+}
+
+func (s sortedAddresses) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+
+// Sort function sorts the slice of addresses
+func Sort(addresses []Address) {
+	sort.Sort(sortedAddresses(addresses))
+}
diff --git a/dapps/valuetransfers/packages/transaction/outputs.go b/dapps/valuetransfers/packages/transaction/outputs.go
index fd825d65e73b57855c813e5926ccea32b507e1af..25511b27d5d6888e4ac64258d62c7ef94e4bae89 100644
--- a/dapps/valuetransfers/packages/transaction/outputs.go
+++ b/dapps/valuetransfers/packages/transaction/outputs.go
@@ -16,11 +16,17 @@ type Outputs struct {
 
 // NewOutputs is the constructor of the Outputs struct and creates the list of Outputs from the given details.
 func NewOutputs(outputs map[address.Address][]*balance.Balance) (result *Outputs) {
-	result = &Outputs{orderedmap.New()}
-	for address, balances := range outputs {
-		result.Add(address, balances)
+	// sorting outputs first before adding to the ordered map to have a deterministic order
+	toSort := make([]address.Address, 0, len(outputs))
+	for a := range outputs {
+		toSort = append(toSort, a)
 	}
+	address.Sort(toSort)
 
+	result = &Outputs{orderedmap.New()}
+	for _, addr := range toSort {
+		result.Add(addr, outputs[addr])
+	}
 	return
 }
 
@@ -49,7 +55,7 @@ func OutputsFromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *O
 	// iterate the corresponding times and collect addresses + their details
 	for i := uint32(0); i < addressCount; i++ {
 		// read address
-		address, addressErr := address.Parse(marshalUtil)
+		addr, addressErr := address.Parse(marshalUtil)
 		if addressErr != nil {
 			err = addressErr
 
@@ -78,7 +84,7 @@ func OutputsFromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *O
 		}
 
 		// add the gathered information as an output
-		result.Add(address, coloredBalances)
+		result.Add(addr, coloredBalances)
 	}
 
 	// return the number of bytes we processed
@@ -117,8 +123,8 @@ func (outputs *Outputs) Bytes() []byte {
 		marshalUtil.WriteBytes(address.Bytes())
 		marshalUtil.WriteUint32(uint32(len(balances)))
 
-		for _, balance := range balances {
-			marshalUtil.WriteBytes(balance.Bytes())
+		for _, bal := range balances {
+			marshalUtil.WriteBytes(bal.Bytes())
 		}
 
 		return true
@@ -141,10 +147,10 @@ func (outputs *Outputs) String() string {
 		result += "    " + address.String() + ": [\n"
 
 		balancesEmpty := true
-		for _, balance := range balances {
+		for _, bal := range balances {
 			balancesEmpty = false
 
-			result += "        " + balance.String() + ",\n"
+			result += "        " + bal.String() + ",\n"
 		}
 
 		if balancesEmpty {
diff --git a/dapps/valuetransfers/packages/transaction/outputs_test.go b/dapps/valuetransfers/packages/transaction/outputs_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..65c05160bbd45ff5ac55abdd1204107b9a0c0244
--- /dev/null
+++ b/dapps/valuetransfers/packages/transaction/outputs_test.go
@@ -0,0 +1,45 @@
+package transaction
+
+import (
+	"bytes"
+	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
+	"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance"
+	"github.com/magiconair/properties/assert"
+	"golang.org/x/crypto/blake2b"
+	"testing"
+)
+
+func TestOutputs(t *testing.T) {
+	rndAddrs := make([]address.Address, 15)
+	for i := range rndAddrs {
+		rndAddrs[i] = address.RandomOfType(address.VersionED25519)
+	}
+
+	theMap1 := make(map[address.Address][]*balance.Balance)
+	for i := 0; i < len(rndAddrs); i++ {
+		theMap1[rndAddrs[i]] = []*balance.Balance{balance.New(balance.ColorIOTA, int64(i))}
+	}
+	out1 := NewOutputs(theMap1)
+
+	theMap2 := make(map[address.Address][]*balance.Balance)
+	for i := len(rndAddrs) - 1; i >= 0; i-- {
+		theMap2[rndAddrs[i]] = []*balance.Balance{balance.New(balance.ColorIOTA, int64(i))}
+	}
+	out2 := NewOutputs(theMap2)
+
+	//t.Logf("%s", out1.String())
+	//t.Logf("%s", out2.String())
+
+	h1 := hashOutputs(t, out1)
+	h2 := hashOutputs(t, out2)
+
+	assert.Equal(t, bytes.Equal(h1, h2), true)
+}
+
+func hashOutputs(t *testing.T, out *Outputs) []byte {
+	h, err := blake2b.New256(nil)
+	assert.Equal(t, err, nil)
+
+	h.Write(out.Bytes())
+	return h.Sum(nil)
+}