diff --git a/go.mod b/go.mod
index 38e66a20f..d4eb52f4d 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.21
 require (
 	code.gitea.io/sdk/gitea v0.17.1
 	git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3
-	git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45
+	git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e
 	git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
 	git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65
 	git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de
diff --git a/go.sum b/go.sum
index 0849b74a1..84fdbd47a 100644
--- a/go.sum
+++ b/go.sum
@@ -2,8 +2,8 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8=
 code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM=
 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 h1:H5GvrVlowIMWfzqQkhY0p0myooJxQ1sMRVSFfXawwWg=
 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o=
-git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 h1:Tp4I+XOLp3VCJORfxSamQtj3RZNISbaLM4WD5iIzXxg=
-git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc=
+git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4=
+git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc=
 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk=
 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU=
 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI=
diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go
index 169be6bc5..50733d89a 100644
--- a/pkg/morph/client/frostfsid/subject.go
+++ b/pkg/morph/client/frostfsid/subject.go
@@ -1,16 +1,11 @@
 package frostfsid
 
 import (
-	"errors"
 	"fmt"
 
 	frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
 	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
-	"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
-	"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
 	"github.com/nspcc-dev/neo-go/pkg/util"
-	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
-	"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
 )
 
 const (
@@ -28,7 +23,7 @@ func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error)
 		return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err)
 	}
 
-	subj, err := parseSubject(res)
+	subj, err := frostfsidclient.ParseSubject(res)
 	if err != nil {
 		return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err)
 	}
@@ -46,203 +41,10 @@ func (c *Client) GetSubjectExtended(addr util.Uint160) (*frostfsidclient.Subject
 		return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err)
 	}
 
-	subj, err := parseSubjectExtended(res)
+	subj, err := frostfsidclient.ParseSubjectExtended(res)
 	if err != nil {
 		return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err)
 	}
 
 	return subj, nil
 }
-
-func parseSubject(res []stackitem.Item) (*frostfsidclient.Subject, error) {
-	if ln := len(res); ln != 1 {
-		return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln)
-	}
-
-	structArr, err := client.ArrayFromStackItem(res[0])
-	if err != nil {
-		return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err)
-	}
-
-	var subj frostfsidclient.Subject
-
-	subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0]))
-	if err != nil {
-		return nil, err
-	}
-
-	if !structArr[1].Equals(stackitem.Null{}) {
-		subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1]))
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	if !structArr[2].Equals(stackitem.Null{}) {
-		subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2]))
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	if !structArr[3].Equals(stackitem.Null{}) {
-		subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3]))
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	subj.KV, err = parseMap(structArr[4])
-	if err != nil {
-		return nil, err
-	}
-
-	return &subj, nil
-}
-
-func parseSubjectExtended(res []stackitem.Item) (*frostfsidclient.SubjectExtended, error) {
-	if ln := len(res); ln != 1 {
-		return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln)
-	}
-
-	structArr, err := client.ArrayFromStackItem(res[0])
-	if err != nil {
-		return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err)
-	}
-
-	var subj frostfsidclient.SubjectExtended
-
-	subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0]))
-	if err != nil {
-		return nil, err
-	}
-
-	if !structArr[1].Equals(stackitem.Null{}) {
-		subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1]))
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	if !structArr[2].Equals(stackitem.Null{}) {
-		subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2]))
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	if !structArr[3].Equals(stackitem.Null{}) {
-		subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3]))
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	subj.KV, err = parseMap(structArr[4])
-	if err != nil {
-		return nil, err
-	}
-
-	if !structArr[5].Equals(stackitem.Null{}) {
-		groupItems, ok := structArr[5].Value().([]stackitem.Item)
-		if !ok {
-			return nil, errors.New("invalid groups field")
-		}
-
-		subj.Groups, err = parseGroups(groupItems)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	return &subj, nil
-}
-
-func makeValidRes(item stackitem.Item) (*result.Invoke, error) {
-	return &result.Invoke{
-		Stack: []stackitem.Item{item},
-		State: vmstate.Halt.String(),
-	}, nil
-}
-
-func parseMap(item stackitem.Item) (map[string]string, error) {
-	if item.Equals(stackitem.Null{}) {
-		return nil, nil
-	}
-
-	metaMap, err := unwrap.Map(makeValidRes(item))
-	if err != nil {
-		return nil, err
-	}
-
-	meta, ok := metaMap.Value().([]stackitem.MapElement)
-	if !ok {
-		return nil, errors.New("invalid map type")
-	}
-
-	res := make(map[string]string, len(meta))
-	for _, element := range meta {
-		key, err := element.Key.TryBytes()
-		if err != nil {
-			return nil, err
-		}
-		val, err := element.Value.TryBytes()
-		if err != nil {
-			return nil, err
-		}
-		res[string(key)] = string(val)
-	}
-
-	return res, nil
-}
-
-func parseGroups(items []stackitem.Item) ([]*frostfsidclient.Group, error) {
-	var err error
-	res := make([]*frostfsidclient.Group, len(items))
-
-	for i := 0; i < len(items); i++ {
-		arr, ok := items[i].Value().([]stackitem.Item)
-		if !ok {
-			return nil, errors.New("invalid group type")
-		}
-		res[i], err = parseGroup(arr)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	return res, nil
-}
-
-func parseGroup(structArr []stackitem.Item) (*frostfsidclient.Group, error) {
-	if len(structArr) < 4 {
-		return nil, errors.New("invalid response group struct")
-	}
-
-	groupID, err := structArr[0].TryInteger()
-	if err != nil {
-		return nil, err
-	}
-
-	name, err := structArr[1].TryBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	namespace, err := structArr[2].TryBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	kvs, err := parseMap(structArr[3])
-	if err != nil {
-		return nil, err
-	}
-
-	return &frostfsidclient.Group{
-		ID:        groupID.Int64(),
-		Name:      string(name),
-		Namespace: string(namespace),
-		KV:        kvs,
-	}, nil
-}