diff --git a/core/tx_pool.go b/core/tx_pool.go
index 16cd7076b02e778b294a4e435b823f66cc167781..60ae3d72f1d17791976cc9805b9fe01dd635e937 100644
--- a/core/tx_pool.go
+++ b/core/tx_pool.go
@@ -589,6 +589,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
 // whitelisted, preventing any associated transaction from being dropped out of the pool
 // due to pricing constraints.
 func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err error) {
+	tx.SetReceivedTime(time.Now())
 	// If the transaction is already known, discard it
 	hash := tx.Hash()
 	if pool.all.Get(hash) != nil {
diff --git a/core/types/transaction.go b/core/types/transaction.go
index 00fb6feb740d67d0fa0e058f69d7398f72a82b90..f4673b5c3e6c3178b9272a82105afdcdf79312b4 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -22,6 +22,7 @@ import (
 	"io"
 	"math/big"
 	"sync/atomic"
+	"time"
 
 	"github.com/holiman/uint256"
 
@@ -39,6 +40,9 @@ var (
 
 type Transaction struct {
 	data txdata
+
+	// Time when the transaction was added to the txPool
+	receivedTime *time.Time
 	// caches
 	hash atomic.Value
 	size atomic.Value
@@ -181,6 +185,13 @@ func (tx *Transaction) GasPriceIntCmp(other *uint256.Int) int {
 func (tx *Transaction) Value() *uint256.Int { return new(uint256.Int).Set(&tx.data.Amount) }
 func (tx *Transaction) Nonce() uint64       { return tx.data.AccountNonce }
 func (tx *Transaction) CheckNonce() bool    { return true }
+func (tx *Transaction) ReceivedTime() (time.Time, bool) {
+	if tx.receivedTime == nil {
+		return time.Time{}, false
+	}
+
+	return *tx.receivedTime, true
+}
 
 // To returns the recipient address of the transaction.
 // It returns nil if the transaction is a contract creation.
@@ -272,6 +283,11 @@ func (tx *Transaction) RawSignatureValues() (v, r, s *uint256.Int) {
 	return &tx.data.V, &tx.data.R, &tx.data.S
 }
 
+// SetReceivedTime sets the time that this transaction was received at.
+func (tx *Transaction) SetReceivedTime(time time.Time) {
+	tx.receivedTime = &time
+}
+
 // Transactions is a Transaction slice type for basic sorting.
 type Transactions []*Transaction
 
@@ -314,19 +330,35 @@ func (s TxByNonce) Len() int           { return len(s) }
 func (s TxByNonce) Less(i, j int) bool { return s[i].data.AccountNonce < s[j].data.AccountNonce }
 func (s TxByNonce) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
 
-// TxByPrice implements both the sort and the heap interface, making it useful
+// TxByPriceAndReceiveTime implements both the sort and the heap interface, making it useful
 // for all at once sorting as well as individually adding and removing elements.
-type TxByPrice Transactions
+type TxByPriceAndReceiveTime Transactions
+
+func (s TxByPriceAndReceiveTime) Len() int { return len(s) }
+func (s TxByPriceAndReceiveTime) Less(i, j int) bool {
+	// If the price is equal, use the time the tx was received for deterministic sorting
+	if s[i].data.Price.Cmp(s[j].data.Price) == 0 {
+		recvI, ok := s[i].ReceivedTime()
+		if !ok {
+			return true
+		}
 
-func (s TxByPrice) Len() int           { return len(s) }
-func (s TxByPrice) Less(i, j int) bool { return s[i].data.Price.Gt(&s[j].data.Price) }
-func (s TxByPrice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+		recvJ, ok := s[j].ReceivedTime()
+		if !ok {
+			return true
+		}
+		return recvI.UnixNano() < recvJ.UnixNano()
+	}
+
+	return s[i].data.Price.Cmp(s[j].data.Price) > 0
+}
+func (s TxByPriceAndReceiveTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
 
-func (s *TxByPrice) Push(x interface{}) {
+func (s *TxByPriceAndReceiveTime) Push(x interface{}) {
 	*s = append(*s, x.(*Transaction))
 }
 
-func (s *TxByPrice) Pop() interface{} {
+func (s *TxByPriceAndReceiveTime) Pop() interface{} {
 	old := *s
 	n := len(old)
 	x := old[n-1]
@@ -339,7 +371,7 @@ func (s *TxByPrice) Pop() interface{} {
 // entire batches of transactions for non-executable accounts.
 type TransactionsByPriceAndNonce struct {
 	txs    map[common.Address]Transactions // Per account nonce-sorted list of transactions
-	heads  TxByPrice                       // Next transaction for each unique account (price heap)
+	heads  TxByPriceAndReceiveTime         // Next transaction for each unique account (price heap)
 	signer Signer                          // Signer for the set of transactions
 }
 
@@ -349,8 +381,8 @@ type TransactionsByPriceAndNonce struct {
 // Note, the input map is reowned so the caller should not interact any more with
 // if after providing it to the constructor.
 func NewTransactionsByPriceAndNonce(signer Signer, txs map[common.Address]Transactions) *TransactionsByPriceAndNonce {
-	// Initialize a price based heap with the head transactions
-	heads := make(TxByPrice, 0, len(txs))
+	// Initialize a price and received time based heap with the head transactions
+	heads := make(TxByPriceAndReceiveTime, 0, len(txs))
 	for from, accTxs := range txs {
 		heads = append(heads, accTxs[0])
 		// Ensure the sender address is from the signer
diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go
index d608a55765cd94db03e488d4b10d44be88d38414..4b5dd226a228be9ef7cb294a661a802c19d321c7 100644
--- a/core/types/transaction_test.go
+++ b/core/types/transaction_test.go
@@ -21,6 +21,7 @@ import (
 	"crypto/ecdsa"
 	"encoding/json"
 	"testing"
+	"time"
 
 	"github.com/holiman/uint256"
 
@@ -137,6 +138,7 @@ func TestTransactionPriceNonceSort(t *testing.T) {
 		addr := crypto.PubkeyToAddress(key.PublicKey)
 		for i := 0; i < 25; i++ {
 			tx, _ := SignTx(NewTransaction(uint64(start+i), common.Address{}, uint256.NewInt().SetUint64(100), 100, uint256.NewInt().SetUint64(uint64(start+i)), nil), signer, key)
+			tx.SetReceivedTime(time.Unix(0, int64(start)))
 			groups[addr] = append(groups[addr], tx)
 		}
 	}
@@ -170,6 +172,11 @@ func TestTransactionPriceNonceSort(t *testing.T) {
 			if fromi != fromNext && txi.GasPrice().Cmp(next.GasPrice()) < 0 {
 				t.Errorf("invalid gasprice ordering: tx #%d (A=%x P=%v) < tx #%d (A=%x P=%v)", i, fromi[:4], txi.GasPrice(), i+1, fromNext[:4], next.GasPrice())
 			}
+
+			// Make sure receivedTime order is ascending if the txs have the same gas price
+			if txi.GasPrice().Cmp(next.GasPrice()) == 0 && fromi != fromNext && txi.receivedTime.UnixNano() > next.receivedTime.UnixNano() {
+				t.Errorf("invalid received time ordering: tx #%d (A=%x T=%d) > tx #%d (A=%x T=%d)", i, fromi[:4], txi.receivedTime.UnixNano(), i+1, fromNext[:4], next.receivedTime.UnixNano())
+			}
 		}
 	}
 }