diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go
index 81579c7fc..e80dda80e 100644
--- a/cmd/frostfs-node/morph.go
+++ b/cmd/frostfs-node/morph.go
@@ -223,27 +223,21 @@ func registerNotificationHandlers(scHash util.Uint160, lis event.Listener, parse
 	subs map[event.Type][]event.Handler,
 ) {
 	for typ, handlers := range subs {
-		pi := event.NotificationParserInfo{}
-		pi.SetType(typ)
-		pi.SetScriptHash(scHash)
+		hi := event.NotificationHandlerInfo{}
+		hi.SetType(typ)
+		hi.SetScriptHash(scHash)
 
 		p, ok := parsers[typ]
 		if !ok {
 			panic(fmt.Sprintf("missing parser for event %s", typ))
 		}
 
-		pi.SetParser(p)
-
-		lis.SetNotificationParser(pi)
+		hi.SetParser(p)
 
 		for _, h := range handlers {
-			hi := event.NotificationHandlerInfo{}
-			hi.SetType(typ)
-			hi.SetScriptHash(scHash)
-			hi.SetHandler(h)
-
-			lis.RegisterNotificationHandler(hi)
+			hi.AddHandler(h)
 		}
+		lis.RegisterNotificationHandler(hi)
 	}
 }
 
diff --git a/internal/logs/logs.go b/internal/logs/logs.go
index 535802a20..b24f3593d 100644
--- a/internal/logs/logs.go
+++ b/internal/logs/logs.go
@@ -165,7 +165,6 @@ const (
 	EventCouldNotParseNotaryEvent                                        = "could not parse notary event"
 	EventNotaryHandlersForParsedNotificationEventWereNotRegistered       = "notary handlers for parsed notification event were not registered"
 	EventRegisteredNewEventParser                                        = "registered new event parser"
-	EventIgnoreHandlerOfEventWoParser                                    = "ignore handler of event w/o parser"
 	EventRegisteredNewEventHandler                                       = "registered new event handler"
 	EventIgnoreHandlerOfNotaryEventWoParser                              = "ignore handler of notary event w/o parser"
 	StorageOperation                                                     = "local object storage operation"
diff --git a/pkg/innerring/bindings.go b/pkg/innerring/bindings.go
index c4de07a5f..dfada764a 100644
--- a/pkg/innerring/bindings.go
+++ b/pkg/innerring/bindings.go
@@ -8,7 +8,6 @@ type (
 	// ContractProcessor interface defines functions for binding event producers
 	// such as event.Listener and Timers with contract processor.
 	ContractProcessor interface {
-		ListenerNotificationParsers() []event.NotificationParserInfo
 		ListenerNotificationHandlers() []event.NotificationHandlerInfo
 		ListenerNotaryParsers() []event.NotaryParserInfo
 		ListenerNotaryHandlers() []event.NotaryHandlerInfo
@@ -16,11 +15,6 @@ type (
 )
 
 func connectListenerWithProcessor(l event.Listener, p ContractProcessor) {
-	// register notification parsers
-	for _, parser := range p.ListenerNotificationParsers() {
-		l.SetNotificationParser(parser)
-	}
-
 	// register notification handlers
 	for _, handler := range p.ListenerNotificationHandlers() {
 		l.RegisterNotificationHandler(handler)
diff --git a/pkg/innerring/processors/alphabet/processor.go b/pkg/innerring/processors/alphabet/processor.go
index 3992e00f3..2c4654e7c 100644
--- a/pkg/innerring/processors/alphabet/processor.go
+++ b/pkg/innerring/processors/alphabet/processor.go
@@ -114,11 +114,6 @@ func (ap *Processor) SetParsedWallets(parsedWallets []util.Uint160) {
 	ap.pwLock.Unlock()
 }
 
-// ListenerNotificationParsers for the 'event.Listener' event producer.
-func (ap *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
-	return nil
-}
-
 // ListenerNotificationHandlers for the 'event.Listener' event producer.
 func (ap *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
 	return nil
diff --git a/pkg/innerring/processors/balance/processor.go b/pkg/innerring/processors/balance/processor.go
index e2f649600..d323238c7 100644
--- a/pkg/innerring/processors/balance/processor.go
+++ b/pkg/innerring/processors/balance/processor.go
@@ -88,20 +88,6 @@ func New(p *Params) (*Processor, error) {
 	}, nil
 }
 
-// ListenerNotificationParsers for the 'event.Listener' event producer.
-func (bp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
-	var parsers []event.NotificationParserInfo
-
-	// new lock event
-	lock := event.NotificationParserInfo{}
-	lock.SetType(lockNotification)
-	lock.SetScriptHash(bp.balanceSC)
-	lock.SetParser(balanceEvent.ParseLock)
-	parsers = append(parsers, lock)
-
-	return parsers
-}
-
 // ListenerNotificationHandlers for the 'event.Listener' event producer.
 func (bp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
 	var handlers []event.NotificationHandlerInfo
@@ -110,7 +96,8 @@ func (bp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI
 	lock := event.NotificationHandlerInfo{}
 	lock.SetType(lockNotification)
 	lock.SetScriptHash(bp.balanceSC)
-	lock.SetHandler(bp.handleLock)
+	lock.SetParser(balanceEvent.ParseLock)
+	lock.AddHandler(bp.handleLock)
 	handlers = append(handlers, lock)
 
 	return handlers
diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go
index 58b90457c..a0b7491e1 100644
--- a/pkg/innerring/processors/container/processor.go
+++ b/pkg/innerring/processors/container/processor.go
@@ -118,11 +118,6 @@ func New(p *Params) (*Processor, error) {
 	}, nil
 }
 
-// ListenerNotificationParsers for the 'event.Listener' event producer.
-func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
-	return nil
-}
-
 // ListenerNotificationHandlers for the 'event.Listener' event producer.
 func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
 	return nil
diff --git a/pkg/innerring/processors/frostfs/processor.go b/pkg/innerring/processors/frostfs/processor.go
index 6c29d330d..64b171f7f 100644
--- a/pkg/innerring/processors/frostfs/processor.go
+++ b/pkg/innerring/processors/frostfs/processor.go
@@ -142,39 +142,6 @@ func New(p *Params) (*Processor, error) {
 	}, nil
 }
 
-// ListenerNotificationParsers for the 'event.Listener' event producer.
-func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
-	var (
-		parsers = make([]event.NotificationParserInfo, 0, 6)
-
-		p event.NotificationParserInfo
-	)
-
-	p.SetScriptHash(np.frostfsContract)
-
-	// deposit event
-	p.SetType(event.TypeFromString(depositNotification))
-	p.SetParser(frostfsEvent.ParseDeposit)
-	parsers = append(parsers, p)
-
-	// withdraw event
-	p.SetType(event.TypeFromString(withdrawNotification))
-	p.SetParser(frostfsEvent.ParseWithdraw)
-	parsers = append(parsers, p)
-
-	// cheque event
-	p.SetType(event.TypeFromString(chequeNotification))
-	p.SetParser(frostfsEvent.ParseCheque)
-	parsers = append(parsers, p)
-
-	// config event
-	p.SetType(event.TypeFromString(configNotification))
-	p.SetParser(frostfsEvent.ParseConfig)
-	parsers = append(parsers, p)
-
-	return parsers
-}
-
 // ListenerNotificationHandlers for the 'event.Listener' event producer.
 func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
 	var (
@@ -187,22 +154,26 @@ func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI
 
 	// deposit handler
 	h.SetType(event.TypeFromString(depositNotification))
-	h.SetHandler(np.handleDeposit)
+	h.SetParser(frostfsEvent.ParseDeposit)
+	h.AddHandler(np.handleDeposit)
 	handlers = append(handlers, h)
 
 	// withdraw handler
 	h.SetType(event.TypeFromString(withdrawNotification))
-	h.SetHandler(np.handleWithdraw)
+	h.SetParser(frostfsEvent.ParseWithdraw)
+	h.AddHandler(np.handleWithdraw)
 	handlers = append(handlers, h)
 
 	// cheque handler
 	h.SetType(event.TypeFromString(chequeNotification))
-	h.SetHandler(np.handleCheque)
+	h.SetParser(frostfsEvent.ParseCheque)
+	h.AddHandler(np.handleCheque)
 	handlers = append(handlers, h)
 
 	// config handler
 	h.SetType(event.TypeFromString(configNotification))
-	h.SetHandler(np.handleConfig)
+	h.SetParser(frostfsEvent.ParseConfig)
+	h.AddHandler(np.handleConfig)
 	handlers = append(handlers, h)
 
 	return handlers
diff --git a/pkg/innerring/processors/governance/processor.go b/pkg/innerring/processors/governance/processor.go
index 565f4c27d..313a0baea 100644
--- a/pkg/innerring/processors/governance/processor.go
+++ b/pkg/innerring/processors/governance/processor.go
@@ -155,21 +155,13 @@ func New(p *Params) (*Processor, error) {
 	}, nil
 }
 
-// ListenerNotificationParsers for the 'event.Listener' event producer.
-func (gp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
-	var pi event.NotificationParserInfo
-	pi.SetScriptHash(gp.designate)
-	pi.SetType(event.TypeFromString(native.DesignationEventName))
-	pi.SetParser(rolemanagement.ParseDesignate)
-	return []event.NotificationParserInfo{pi}
-}
-
 // ListenerNotificationHandlers for the 'event.Listener' event producer.
 func (gp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
 	var hi event.NotificationHandlerInfo
 	hi.SetScriptHash(gp.designate)
 	hi.SetType(event.TypeFromString(native.DesignationEventName))
-	hi.SetHandler(gp.HandleAlphabetSync)
+	hi.SetParser(rolemanagement.ParseDesignate)
+	hi.AddHandler(gp.HandleAlphabetSync)
 	return []event.NotificationHandlerInfo{hi}
 }
 
diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go
index b3d57e85b..c726df955 100644
--- a/pkg/innerring/processors/netmap/processor.go
+++ b/pkg/innerring/processors/netmap/processor.go
@@ -161,22 +161,6 @@ func New(p *Params) (*Processor, error) {
 	}, nil
 }
 
-// ListenerNotificationParsers for the 'event.Listener' event producer.
-func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
-	parsers := make([]event.NotificationParserInfo, 0, 3)
-
-	var p event.NotificationParserInfo
-
-	p.SetScriptHash(np.netmapClient.ContractAddress())
-
-	// new epoch event
-	p.SetType(newEpochNotification)
-	p.SetParser(netmapEvent.ParseNewEpoch)
-	parsers = append(parsers, p)
-
-	return parsers
-}
-
 // ListenerNotificationHandlers for the 'event.Listener' event producer.
 func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
 	handlers := make([]event.NotificationHandlerInfo, 0, 3)
@@ -187,7 +171,8 @@ func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI
 
 	// new epoch handler
 	i.SetType(newEpochNotification)
-	i.SetHandler(np.handleNewEpoch)
+	i.SetParser(netmapEvent.ParseNewEpoch)
+	i.AddHandler(np.handleNewEpoch)
 	handlers = append(handlers, i)
 
 	return handlers
diff --git a/pkg/morph/event/handlers.go b/pkg/morph/event/handlers.go
index 822335329..e96abb846 100644
--- a/pkg/morph/event/handlers.go
+++ b/pkg/morph/event/handlers.go
@@ -18,17 +18,23 @@ type BlockHandler func(context.Context, *block.Block)
 type NotificationHandlerInfo struct {
 	scriptHashWithType
 
-	h Handler
+	parser   NotificationParser
+	handlers []Handler
 }
 
-// SetHandler is an event handler setter.
-func (s *NotificationHandlerInfo) SetHandler(v Handler) {
-	s.h = v
+// SetParser is an event handler setter.
+func (s *NotificationHandlerInfo) SetParser(p NotificationParser) {
+	s.parser = p
+}
+
+// AddHandler adds an event handler.
+func (s *NotificationHandlerInfo) AddHandler(v Handler) {
+	s.handlers = append(s.handlers, v)
 }
 
 // Handler returns an event handler.
-func (s NotificationHandlerInfo) Handler() Handler {
-	return s.h
+func (s NotificationHandlerInfo) Handlers() []Handler {
+	return s.handlers
 }
 
 // NotaryHandlerInfo is a structure that groups
diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go
index 64ff205be..8fe95cf49 100644
--- a/pkg/morph/event/listener.go
+++ b/pkg/morph/event/listener.go
@@ -33,13 +33,6 @@ type Listener interface {
 	// it could not be started.
 	ListenWithError(context.Context, chan<- error)
 
-	// SetNotificationParser must set the parser of particular contract event.
-	//
-	// Parser of each event must be set once. All parsers must be set before Listen call.
-	//
-	// Must ignore nil parsers and all calls after listener has been started.
-	SetNotificationParser(NotificationParserInfo)
-
 	// RegisterNotificationHandler must register the event handler for particular notification event of contract.
 	//
 	// The specified handler must be called after each capture and parsing of the event.
@@ -444,27 +437,6 @@ func (l *listener) parseAndHandleNotary(ctx context.Context, nr *result.NotaryRe
 	handler(ctx, event)
 }
 
-// SetNotificationParser sets the parser of particular contract event.
-//
-// Ignores nil and already set parsers.
-// Ignores the parser if listener is started.
-func (l *listener) SetNotificationParser(pi NotificationParserInfo) {
-	log := l.log.With(
-		zap.String("contract", pi.ScriptHash().StringLE()),
-		zap.Stringer("event_type", pi.getType()),
-	)
-
-	l.mtx.Lock()
-	defer l.mtx.Unlock()
-
-	// add event parser
-	if _, ok := l.notificationParsers[pi.scriptHashWithType]; !ok {
-		l.notificationParsers[pi.scriptHashWithType] = pi.parser()
-	}
-
-	log.Debug(context.Background(), logs.EventRegisteredNewEventParser)
-}
-
 // RegisterNotificationHandler registers the handler for particular notification event of contract.
 //
 // Ignores nil handlers.
@@ -476,22 +448,14 @@ func (l *listener) RegisterNotificationHandler(hi NotificationHandlerInfo) {
 	)
 
 	// check if parser was set
-	l.mtx.RLock()
-	_, ok := l.notificationParsers[hi.scriptHashWithType]
-	l.mtx.RUnlock()
-
-	if !ok {
-		log.Warn(context.Background(), logs.EventIgnoreHandlerOfEventWoParser)
-		return
-	}
-
-	// add event handler
 	l.mtx.Lock()
+	defer l.mtx.Unlock()
+
+	l.notificationParsers[hi.scriptHashWithType] = hi.parser
 	l.notificationHandlers[hi.scriptHashWithType] = append(
 		l.notificationHandlers[hi.scriptHashWithType],
-		hi.Handler(),
+		hi.handlers...,
 	)
-	l.mtx.Unlock()
 
 	log.Debug(context.Background(), logs.EventRegisteredNewEventHandler)
 }
diff --git a/pkg/morph/event/listener_test.go b/pkg/morph/event/listener_test.go
index c0f9722d7..02dad2fd3 100644
--- a/pkg/morph/event/listener_test.go
+++ b/pkg/morph/event/listener_test.go
@@ -48,20 +48,18 @@ func TestEventHandling(t *testing.T) {
 		},
 	}
 
-	l.SetNotificationParser(NotificationParserInfo{
-		scriptHashWithType: key,
-		p: func(cne *state.ContainedNotificationEvent) (Event, error) {
-			return testNotificationEvent{source: cne}, nil
-		},
-	})
-
 	notificationHandled := make(chan bool)
 	handledNotifications := make([]Event, 0)
 	l.RegisterNotificationHandler(NotificationHandlerInfo{
 		scriptHashWithType: key,
-		h: func(_ context.Context, e Event) {
-			handledNotifications = append(handledNotifications, e)
-			notificationHandled <- true
+		parser: func(cne *state.ContainedNotificationEvent) (Event, error) {
+			return testNotificationEvent{source: cne}, nil
+		},
+		handlers: []Handler{
+			func(_ context.Context, e Event) {
+				handledNotifications = append(handledNotifications, e)
+				notificationHandled <- true
+			},
 		},
 	})
 
diff --git a/pkg/morph/event/parsers.go b/pkg/morph/event/parsers.go
index 90eff0bd2..5adeb4b30 100644
--- a/pkg/morph/event/parsers.go
+++ b/pkg/morph/event/parsers.go
@@ -11,15 +11,6 @@ import (
 // from the StackItem list.
 type NotificationParser func(*state.ContainedNotificationEvent) (Event, error)
 
-// NotificationParserInfo is a structure that groups
-// the parameters of particular contract
-// notification event parser.
-type NotificationParserInfo struct {
-	scriptHashWithType
-
-	p NotificationParser
-}
-
 // NotaryPreparator constructs NotaryEvent
 // from the NotaryRequest event.
 type NotaryPreparator interface {
@@ -47,24 +38,6 @@ func (n *NotaryParserInfo) SetParser(p NotaryParser) {
 	n.p = p
 }
 
-// SetParser is an event parser setter.
-func (s *NotificationParserInfo) SetParser(v NotificationParser) {
-	s.p = v
-}
-
-func (s NotificationParserInfo) parser() NotificationParser {
-	return s.p
-}
-
-// SetType is an event type setter.
-func (s *NotificationParserInfo) SetType(v Type) {
-	s.typ = v
-}
-
-func (s NotificationParserInfo) getType() Type {
-	return s.typ
-}
-
 type wrongPrmNumber struct {
 	exp, act int
 }