diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go
index f2521bd083..f5a03fa298 100644
--- a/pkg/innerring/state.go
+++ b/pkg/innerring/state.go
@@ -117,7 +117,7 @@ func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) erro
 	)
 
 	if prm.Hash != nil {
-		nonce, vub, err = s.morphClient.CalculateNonceAndVUB(*prm.Hash)
+		nonce, vub, err = s.morphClient.CalculateNonceAndVUB(prm.Hash)
 		if err != nil {
 			return fmt.Errorf("could not calculate nonce and `validUntilBlock` values: %w", err)
 		}
diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go
index dfdd7c03b1..5b817a8056 100644
--- a/pkg/morph/client/notary.go
+++ b/pkg/morph/client/notary.go
@@ -289,7 +289,7 @@ func (c *Client) UpdateNotaryList(prm UpdateNotaryListPrm) error {
 		panic(notaryNotEnabledPanicMsg)
 	}
 
-	nonce, vub, err := c.CalculateNonceAndVUB(prm.hash)
+	nonce, vub, err := c.CalculateNonceAndVUB(&prm.hash)
 	if err != nil {
 		return fmt.Errorf("could not calculate nonce and `valicUntilBlock` values: %w", err)
 	}
@@ -337,7 +337,7 @@ func (c *Client) UpdateNeoFSAlphabetList(prm UpdateAlphabetListPrm) error {
 		panic(notaryNotEnabledPanicMsg)
 	}
 
-	nonce, vub, err := c.CalculateNonceAndVUB(prm.hash)
+	nonce, vub, err := c.CalculateNonceAndVUB(&prm.hash)
 	if err != nil {
 		return fmt.Errorf("could not calculate nonce and `valicUntilBlock` values: %w", err)
 	}
@@ -763,17 +763,19 @@ func CalculateNotaryDepositAmount(c *Client, gasMul, gasDiv int64) (fixedn.Fixed
 
 // CalculateNonceAndVUB calculates nonce and ValidUntilBlock values
 // based on transaction hash.
-func (c *Client) CalculateNonceAndVUB(hash util.Uint256) (nonce uint32, vub uint32, err error) {
+func (c *Client) CalculateNonceAndVUB(hash *util.Uint256) (nonce uint32, vub uint32, err error) {
 	return c.calculateNonceAndVUB(hash, false)
 }
 
 // CalculateNonceAndVUBControl calculates nonce and rounded ValidUntilBlock values
 // based on transaction hash for use in control transactions.
-func (c *Client) CalculateNonceAndVUBControl(hash util.Uint256) (nonce uint32, vub uint32, err error) {
+func (c *Client) CalculateNonceAndVUBControl(hash *util.Uint256) (nonce uint32, vub uint32, err error) {
 	return c.calculateNonceAndVUB(hash, true)
 }
 
-func (c *Client) calculateNonceAndVUB(hash util.Uint256, roundBlockHeight bool) (nonce uint32, vub uint32, err error) {
+// If hash specified, transaction's height and hash are used to compute VUB and nonce.
+// If not, then current block height used to compute VUB and nonce.
+func (c *Client) calculateNonceAndVUB(hash *util.Uint256, roundBlockHeight bool) (nonce uint32, vub uint32, err error) {
 	c.switchLock.RLock()
 	defer c.switchLock.RUnlock()
 
@@ -785,11 +787,18 @@ func (c *Client) calculateNonceAndVUB(hash util.Uint256, roundBlockHeight bool)
 		return 0, 0, nil
 	}
 
-	nonce = binary.LittleEndian.Uint32(hash.BytesLE())
+	var height uint32
 
-	height, err := c.getTransactionHeight(hash)
-	if err != nil {
-		return 0, 0, fmt.Errorf("could not get transaction height: %w", err)
+	if hash != nil {
+		height, err = c.getTransactionHeight(*hash)
+		if err != nil {
+			return 0, 0, fmt.Errorf("could not get transaction height: %w", err)
+		}
+	} else {
+		height, err = c.rpcActor.GetBlockCount()
+		if err != nil {
+			return 0, 0, fmt.Errorf("could not get chain height: %w", err)
+		}
 	}
 
 	// For control transactions, we round down the block height to control the
@@ -800,7 +809,10 @@ func (c *Client) calculateNonceAndVUB(hash util.Uint256, roundBlockHeight bool)
 		height = height / inc * inc
 	}
 
-	return nonce, height + c.notary.txValidTime, nil
+	if hash != nil {
+		return binary.LittleEndian.Uint32(hash.BytesLE()), height + c.notary.txValidTime, nil
+	}
+	return height + c.notary.txValidTime, height + c.notary.txValidTime, nil
 }
 
 func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) {
diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go
index 595e114213..dfcf62b834 100644
--- a/pkg/morph/client/static.go
+++ b/pkg/morph/client/static.go
@@ -154,9 +154,9 @@ func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) {
 
 			if prm.hash != nil {
 				if prm.controlTX {
-					nonce, vub, err = s.client.CalculateNonceAndVUBControl(*prm.hash)
+					nonce, vub, err = s.client.CalculateNonceAndVUBControl(prm.hash)
 				} else {
-					nonce, vub, err = s.client.CalculateNonceAndVUB(*prm.hash)
+					nonce, vub, err = s.client.CalculateNonceAndVUB(prm.hash)
 				}
 				if err != nil {
 					return InvokeRes{}, fmt.Errorf("could not calculate nonce and VUB for notary alphabet invoke: %w", err)