diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go
index a59fecd2e8f3750ad9fe7fbbb21d808dacf7fc6d..a33681c1d827e07649646c737f4c9566289f78a8 100644
--- a/consensus/bor/bor.go
+++ b/consensus/bor/bor.go
@@ -205,13 +205,13 @@ func CalcDifficulty(snap *Snapshot, signer common.Address, epoch uint64) *big.In
 	return big.NewInt(0).SetUint64(snap.inturn(snap.Number+1, signer, epoch))
 }
 
-// CalcProducerDelay is the producer delay algorithm based on block time.
-func CalcProducerDelay(snap *Snapshot, signer common.Address, period uint64, epoch uint64, producerDelay uint64) uint64 {
-	// if block is epoch start block, proposer will be inturn signer
-	if (snap.Number+1)%epoch == 0 {
+// CalcProducerDelay is the block delay algorithm based on block time and period / producerDelay values in genesis
+func CalcProducerDelay(number uint64, period uint64, sprint uint64, producerDelay uint64) uint64 {
+	// When the block is the first block of the sprint, it is expected to be delayed by `producerDelay`.
+	// That is to allow time for block propagation in the last sprint
+	if number%sprint == 0 {
 		return producerDelay
 	}
-
 	return period
 }
 
@@ -331,6 +331,17 @@ func (c *Bor) verifyHeader(chain consensus.ChainReader, header *types.Header, pa
 	}
 	number := header.Number.Uint64()
 
+	var parent *types.Header
+	if len(parents) > 0 { // if parents is nil, len(parents) is zero
+		parent = parents[len(parents)-1]
+	} else if number > 0 {
+		parent = chain.GetHeader(header.ParentHash, number-1)
+	}
+
+	if parent != nil && header.Time < parent.Time+CalcProducerDelay(number, c.config.Period, c.config.Sprint, c.config.ProducerDelay) {
+		return consensus.ErrBlockTooSoon
+	}
+
 	// Don't waste time checking blocks from the future
 	if header.Time > uint64(time.Now().Unix()) {
 		return consensus.ErrFutureBlock
@@ -654,7 +665,7 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error {
 		return consensus.ErrUnknownAncestor
 	}
 
-	header.Time = parent.Time + CalcProducerDelay(snap, c.signer, c.config.Period, c.config.Sprint, c.config.ProducerDelay)
+	header.Time = parent.Time + CalcProducerDelay(number, c.config.Period, c.config.Sprint, c.config.ProducerDelay)
 	if header.Time < uint64(time.Now().Unix()) {
 		header.Time = uint64(time.Now().Unix())
 	}
@@ -1190,7 +1201,7 @@ func (c *Bor) CommitStates(
 		}
 
 		// check if chain id matches with event record
-		if eventRecord.ChainID != "" && eventRecord.ChainID != c.chainConfig.ChainID.String() {
+		if eventRecord.ChainID != c.chainConfig.ChainID.String() {
 			return fmt.Errorf(
 				"Chain id proposed state in span, %s, and bor chain id, %s, doesn't match",
 				eventRecord.ChainID,
diff --git a/consensus/bor/bor_test/bor_test.go b/consensus/bor/bor_test/bor_test.go
index ce1585f6f2f8788c8b2c1d709b00a706685ee6fd..13fb4f2e6bed889a9580412953c6c38bba19f07a 100644
--- a/consensus/bor/bor_test/bor_test.go
+++ b/consensus/bor/bor_test/bor_test.go
@@ -32,7 +32,7 @@ func TestCommitSpan(t *testing.T) {
 	db := init.ethereum.ChainDb()
 	block := init.genesis.ToBlock(db)
 	// Build 1st block's header
-	header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor.Period)
+	header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor)
 
 	statedb, err := chain.State()
 	if err != nil {
@@ -89,7 +89,7 @@ func TestIsValidatorAction(t *testing.T) {
 	db := init.ethereum.ChainDb()
 	block := init.genesis.ToBlock(db)
 
-	header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor.Period)
+	header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor)
 	statedb, err := chain.State()
 	if err != nil {
 		t.Fatalf("%s", err)
@@ -101,7 +101,7 @@ func TestIsValidatorAction(t *testing.T) {
 
 	var headers []*types.Header
 	for i := int64(2); i <= 255; i++ {
-		header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor.Period)
+		header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor)
 		headers = append(headers, header)
 		block = types.NewBlockWithHeader(header)
 	}
diff --git a/consensus/bor/bor_test/helper.go b/consensus/bor/bor_test/helper.go
index 54ab949983a9861a096f4182bca649563ac1790a..9a5c0facc561a073075ff4150a590103ce8f3908 100644
--- a/consensus/bor/bor_test/helper.go
+++ b/consensus/bor/bor_test/helper.go
@@ -16,6 +16,7 @@ import (
 	"github.com/maticnetwork/bor/eth"
 	"github.com/maticnetwork/bor/ethdb"
 	"github.com/maticnetwork/bor/node"
+	"github.com/maticnetwork/bor/params"
 )
 
 var (
@@ -99,11 +100,11 @@ func insertNewBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, header
 	}
 }
 
-func buildMinimalNextHeader(t *testing.T, block *types.Block, period uint64) *types.Header {
+func buildMinimalNextHeader(t *testing.T, block *types.Block, borConfig *params.BorConfig) *types.Header {
 	header := block.Header()
 	header.Number.Add(header.Number, big.NewInt(1))
 	header.ParentHash = block.Hash()
-	header.Time += (period + 1)
+	header.Time += bor.CalcProducerDelay(header.Number.Uint64(), borConfig.Period, borConfig.Sprint, borConfig.ProducerDelay)
 	header.Extra = make([]byte, 97) // vanity (32) + extraSeal (65)
 	_key, _ := hex.DecodeString(privKey)
 	sig, err := secp256k1.Sign(crypto.Keccak256(bor.BorRLP(header)), _key)
diff --git a/consensus/errors.go b/consensus/errors.go
index a005c5f63de802cbb2bf54203257d23fe16a3109..04342bea8a7c8a6e9ef9959b4d215fa7a04955ad 100644
--- a/consensus/errors.go
+++ b/consensus/errors.go
@@ -31,6 +31,9 @@ var (
 	// to the current node.
 	ErrFutureBlock = errors.New("block in the future")
 
+	// ErrBlockTooSoon is returned when the period / producerDelay values in the genesis were not respected
+	ErrBlockTooSoon = errors.New("block was produced sooner than expected")
+
 	// ErrInvalidNumber is returned if a block's number doesn't equal it's parent's
 	// plus one.
 	ErrInvalidNumber = errors.New("invalid block number")