diff --git a/alphabet/alphabet_contract.go b/alphabet/alphabet_contract.go
index 15b7e7c..28f8817 100644
--- a/alphabet/alphabet_contract.go
+++ b/alphabet/alphabet_contract.go
@@ -79,8 +79,7 @@ func balance(hash string, addr []byte) int {
 }
 
 func irList() []common.IRNode {
-	netmapContractAddr := storage.Get(ctx, netmapKey).([]byte)
-	return contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	return common.InnerRingListViaStorage(ctx, netmapKey)
 }
 
 func currentEpoch() int {
diff --git a/audit/audit_contract.go b/audit/audit_contract.go
index eed9c88..66f2064 100644
--- a/audit/audit_contract.go
+++ b/audit/audit_contract.go
@@ -2,7 +2,6 @@ package auditcontract
 
 import (
 	"github.com/nspcc-dev/neo-go/pkg/interop"
-	"github.com/nspcc-dev/neo-go/pkg/interop/contract"
 	"github.com/nspcc-dev/neo-go/pkg/interop/crypto"
 	"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
 	"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
@@ -11,10 +10,6 @@ import (
 )
 
 type (
-	irNode struct {
-		key interop.PublicKey
-	}
-
 	auditHeader struct {
 		epoch int
 		cid   []byte
@@ -70,15 +65,14 @@ func Init(addrNetmap interop.Hash160) {
 }
 
 func Put(rawAuditResult []byte) bool {
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode)
+	innerRing := common.InnerRingListViaStorage(ctx, netmapContractKey)
 
 	hdr := newAuditHeader(rawAuditResult)
 	presented := false
 
 	for i := range innerRing {
 		ir := innerRing[i]
-		if common.BytesEqual(ir.key, hdr.from) {
+		if common.BytesEqual(ir.PublicKey, hdr.from) {
 			presented = true
 
 			break
diff --git a/balance/balance_contract.go b/balance/balance_contract.go
index c4c515f..15f3053 100644
--- a/balance/balance_contract.go
+++ b/balance/balance_contract.go
@@ -3,7 +3,6 @@ package balancecontract
 import (
 	"github.com/nspcc-dev/neo-go/pkg/interop"
 	"github.com/nspcc-dev/neo-go/pkg/interop/binary"
-	"github.com/nspcc-dev/neo-go/pkg/interop/contract"
 	"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
 	"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
 	"github.com/nspcc-dev/neo-go/pkg/interop/storage"
@@ -109,8 +108,7 @@ func TransferX(from, to interop.Hash160, amount int, details []byte) bool {
 		hashTxID []byte // ballot key of the inner ring invocation
 	)
 
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	irKey := common.InnerRingInvoker(innerRing)
@@ -145,8 +143,7 @@ func TransferX(from, to interop.Hash160, amount int, details []byte) bool {
 }
 
 func Lock(txID []byte, from, to interop.Hash160, amount, until int) bool {
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	irKey := common.InnerRingInvoker(innerRing)
@@ -183,8 +180,7 @@ func Lock(txID []byte, from, to interop.Hash160, amount, until int) bool {
 }
 
 func NewEpoch(epochNum int) bool {
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	irKey := common.InnerRingInvoker(innerRing)
@@ -222,8 +218,7 @@ func NewEpoch(epochNum int) bool {
 }
 
 func Mint(to interop.Hash160, amount int, details []byte) bool {
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	irKey := common.InnerRingInvoker(innerRing)
@@ -253,8 +248,7 @@ func Mint(to interop.Hash160, amount int, details []byte) bool {
 }
 
 func Burn(from interop.Hash160, amount int, details []byte) bool {
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	irKey := common.InnerRingInvoker(innerRing)
@@ -411,3 +405,7 @@ func fromKnownContract(caller interop.Hash160) bool {
 
 	return common.BytesEqual(caller, containerContractAddr)
 }
+
+func irList() []common.IRNode {
+	return common.InnerRingListViaStorage(ctx, netmapContractKey)
+}
diff --git a/common/ir.go b/common/ir.go
new file mode 100644
index 0000000..41e7689
--- /dev/null
+++ b/common/ir.go
@@ -0,0 +1,24 @@
+package common
+
+import (
+	"github.com/nspcc-dev/neo-go/pkg/interop"
+	"github.com/nspcc-dev/neo-go/pkg/interop/contract"
+	"github.com/nspcc-dev/neo-go/pkg/interop/storage"
+)
+
+const irListMethod = "innerRingList"
+
+// InnerRingList returns list of inner ring nodes through calling
+// "innerRingList" method of smart contract.
+//
+// Address of smart contract is received from storage by key.
+func InnerRingListViaStorage(ctx storage.Context, key interface{}) []IRNode {
+	sc := storage.Get(ctx, key).([]byte)
+	return InnerRingList(sc)
+}
+
+// InnerRingList gets list of inner ring through
+// calling "innerRingList" method of smart contract.
+func InnerRingList(sc interop.Hash160) []IRNode {
+	return contract.Call(sc, irListMethod).([]IRNode)
+}
diff --git a/container/container_contract.go b/container/container_contract.go
index f2b9f87..07e2669 100644
--- a/container/container_contract.go
+++ b/container/container_contract.go
@@ -83,7 +83,7 @@ func Init(addrNetmap, addrBalance, addrID []byte) {
 
 func Put(container, signature, publicKey []byte) bool {
 	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := common.InnerRingList(netmapContractAddr)
 	threshold := len(innerRing)/3*2 + 1
 
 	offset := int(container[1])
@@ -149,8 +149,7 @@ func Put(container, signature, publicKey []byte) bool {
 }
 
 func Delete(containerID, signature []byte) bool {
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	ownerID := getOwnerByID(ctx, containerID)
@@ -336,8 +335,7 @@ func ListContainerSizes(epoch int) [][]byte {
 }
 
 func ProcessEpoch(epochNum int) {
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	irKey := common.InnerRingInvoker(innerRing)
@@ -360,8 +358,7 @@ func ProcessEpoch(epochNum int) {
 }
 
 func StartContainerEstimation(epoch int) bool {
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	irKey := common.InnerRingInvoker(innerRing)
@@ -384,8 +381,7 @@ func StartContainerEstimation(epoch int) bool {
 }
 
 func StopContainerEstimation(epoch int) bool {
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	irKey := common.InnerRingInvoker(innerRing)
@@ -595,3 +591,7 @@ func keysToDelete(epoch int) [][]byte {
 
 	return results
 }
+
+func irList() []common.IRNode {
+	return common.InnerRingListViaStorage(ctx, netmapContractKey)
+}
diff --git a/neofsid/neofsid_contract.go b/neofsid/neofsid_contract.go
index 6088c85..95cae24 100644
--- a/neofsid/neofsid_contract.go
+++ b/neofsid/neofsid_contract.go
@@ -2,7 +2,6 @@ package neofsidcontract
 
 import (
 	"github.com/nspcc-dev/neo-go/pkg/interop/binary"
-	"github.com/nspcc-dev/neo-go/pkg/interop/contract"
 	"github.com/nspcc-dev/neo-go/pkg/interop/crypto"
 	"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
 	"github.com/nspcc-dev/neo-go/pkg/interop/storage"
@@ -59,8 +58,7 @@ func AddKey(owner []byte, keys [][]byte) bool {
 		panic("addKey: incorrect owner")
 	}
 
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	irKey := common.InnerRingInvoker(innerRing)
@@ -113,8 +111,7 @@ func RemoveKey(owner []byte, keys [][]byte) bool {
 		panic("removeKey: incorrect owner")
 	}
 
-	netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
-	innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode)
+	innerRing := irList()
 	threshold := len(innerRing)/3*2 + 1
 
 	irKey := common.InnerRingInvoker(innerRing)
@@ -199,3 +196,7 @@ func fromKnownContract(caller []byte) bool {
 
 	return false
 }
+
+func irList() []common.IRNode {
+	return common.InnerRingListViaStorage(ctx, netmapContractKey)
+}