Repository: skalenetwork/IMA (language: python)

Issue:
S2S stability fixes, survive on bad SGX call
- S2S stability fixes
- survive on bad SGX call
- fixed S2S ERC20 transfers
- fixed S2S ERC721 transfers
- fixed S2S ERC1155 transfers
- fixed S2S ERC1155 Batch transfers


Discussion / hints:

Fix patch:
diff --git a/agent/bls.js b/agent/bls.js
index 3494f22bb..87418aa4c 100644
--- a/agent/bls.js
+++ b/agent/bls.js
@@ -224,7 +224,7 @@ function perform_bls_glue( details, strDirection, jarrMessages, arrSignResults )
         for( i = 0; i < cnt; ++i ) {
             const jo = arrSignResults[i];
             const strPath = strActionDir + "/sign-result" + jo.index + ".json";
-            details.write( strLogPrefix + cc.normal( "Saving " ) + cc.notice( strPath ) + cc.debug( " file..." ) + "\n" );
+            details.write( strLogPrefix + cc.normal( "Saving " ) + cc.notice( strPath ) + cc.debug( " file containing " ) + cc.j( jo ) + "\n" );
             imaUtils.jsonFileSave( strPath, jo );
             strInput += " --input " + strPath;
         }
@@ -234,11 +234,11 @@ function perform_bls_glue( details, strDirection, jarrMessages, arrSignResults )
             " --n " + nParticipants +
             strInput +
             " --output " + strActionDir + "/glue-result.json";
-        details.write( strLogPrefix + cc.normal( "Will execute BLS glue command:\n" ) + cc.notice( strGlueCommand ) + "\n" );
+        details.write( strLogPrefix + cc.debug( "Will execute BLS glue command:\n" ) + cc.notice( strGlueCommand ) + "\n" );
         strOutput = child_process.execSync( strGlueCommand );
-        details.write( strLogPrefix + cc.normal( "BLS glue output is:\n" ) + cc.notice( strOutput ) + "\n" );
+        details.write( strLogPrefix + cc.debug( "BLS glue output is:\n" ) + cc.notice( strOutput ) + "\n" );
         joGlueResult = imaUtils.jsonFileLoad( strActionDir + "/glue-result.json" );
-        details.write( strLogPrefix + cc.normal( "BLS glue result is: " ) + cc.j( joGlueResult ) + "\n" );
+        details.write( strLogPrefix + cc.debug( "BLS glue result is: " ) + cc.j( joGlueResult ) + "\n" );
         if( "X" in joGlueResult.signature && "Y" in joGlueResult.signature ) {
             details.write( strLogPrefix + cc.success( "BLS glue success" ) + "\n" );
             joGlueResult.hashSrc = strSummaryMessage;
@@ -703,6 +703,7 @@ async function check_correctness_of_messages_to_sign( details, strLogPrefix, str
 }
 
 async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsgBlockStart, details, joExtraSignOpts, fn ) {
+    let bHaveResultReportCalled = false;
     const strLogPrefix = cc.bright( strDirection ) + " " + cc.info( "Sign msgs:" ) + " ";
     log.write( strLogPrefix + cc.debug( " Invoking " ) + cc.bright( strDirection ) + cc.debug( " signing messages procedure " ) + "\n" );
     details.write( strLogPrefix + cc.debug( " Invoking " ) + cc.bright( strDirection ) + cc.debug( " signing messages procedure " ) + "\n" );
@@ -715,6 +716,8 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
             "\n" );
         await check_correctness_of_messages_to_sign( details, strLogPrefix, strDirection, jarrMessages, nIdxCurrentMsgBlockStart, joExtraSignOpts );
         await fn( null, jarrMessages, null );
+        bHaveResultReportCalled = true;
+        return;
     }
     await check_correctness_of_messages_to_sign( details, strLogPrefix, strDirection, jarrMessages, nIdxCurrentMsgBlockStart, joExtraSignOpts );
     //
@@ -739,7 +742,7 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
     // }
     //
     details.write( strLogPrefix + cc.debug( "Will sign " ) + cc.info( jarrMessages.length ) + cc.debug( " message(s)..." ) + "\n" );
-    log.write( strLogPrefix + cc.debug( "Will sign " ) + cc.info( jarrMessages ) + cc.debug( " message(s)..." ) + "\n" );
+    log.write( strLogPrefix + cc.debug( "Will sign " ) + cc.j( jarrMessages ) + cc.debug( " message(s)..." ) + "\n" );
     const joGatheringTracker = {
         nCountReceived: 0, // including errors
         nCountErrors: 0,
@@ -757,6 +760,7 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
     details.write( strLogPrefix + cc.debug( "Discovered number of BLS participants is " ) + cc.info( nParticipants ) + cc.debug( "." ) + "\n" );
     if( nThreshold <= 0 ) {
         await fn( "signature error, S-Chain information was not discovered properly and BLS threshold is unknown", jarrMessages, null );
+        bHaveResultReportCalled = true;
         return;
     }
     const nCountOfBlsPartsToCollect = 0 + nThreshold;
@@ -764,7 +768,7 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
     //     details.write( strLogPrefix + cc.warning( "Minimal BLS parts number for dicovery was increased." ) + "\n" );
     //     nCountOfBlsPartsToCollect = 2;
     // }
-    log.write( strLogPrefix + cc.debug( "Will collect " ) + cc.info( nCountOfBlsPartsToCollect ) + "\n" );
+    log.write( strLogPrefix + cc.debug( "Will collect " ) + cc.info( nCountOfBlsPartsToCollect ) + cc.debug( " signature(s)" ) + "\n" );
     details.write( strLogPrefix + cc.debug( "Will collect " ) + cc.info( nCountOfBlsPartsToCollect ) + cc.debug( " from " ) + cc.info( jarrNodes.length ) + cc.debug( " nodes" ) + "\n" );
     for( let i = 0; i < jarrNodes.length; ++i ) {
         const joNode = jarrNodes[i];
@@ -973,8 +977,11 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
                     details.write( strErrorMessage );
                     reject( new Error( strErrorMessage ) );
                 } );
+                bHaveResultReportCalled = true;
                 if( ! strError )
                     resolve( strSuccessfulResultDescription );
+                else
+                    reject( new Error( strError ) );
                 return;
             }
             if( joGatheringTracker.nCountReceived >= jarrNodes.length ) {
@@ -988,6 +995,7 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
                     details.write( strErrorMessage );
                     reject( new Error( strErrorMessage ) );
                 } );
+                bHaveResultReportCalled = true;
                 return;
             }
             if( joGatheringTracker.nWaitIntervalStepsDone >= joGatheringTracker.nWaitIntervalMaxSteps ) {
@@ -1001,6 +1009,7 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
                     details.write( strErrorMessage );
                     reject( new Error( strErrorMessage ) );
                 } );
+                bHaveResultReportCalled = true;
                 return;
             }
         }, joGatheringTracker.nWaitIntervalStepMilliseconds );
@@ -1011,11 +1020,36 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
         const strLogMessage = cc.success( "BLS sign result await finished with: " ) + cc.info( strSuccessfulResultDescription ) + "\n";
         details.write( strLogMessage );
         log.write( strLogMessage );
-    } ).catch( err => {
-        const strErrorMessage = cc.error( "Failed BLS sign result awaiting: " ) + cc.warning( err.toString() ) + "\n";
+    } ).catch( async err => {
+        const strErrorMessage = cc.error( "Failed BLS sign result awaiting(1): " ) + cc.warning( err.toString() ) + "\n";
         log.write( strErrorMessage );
         details.write( strErrorMessage );
+        if( ! bHaveResultReportCalled ) {
+            bHaveResultReportCalled = true;
+            await fn( "Failed to gather BLS signatures in " + jarrNodes.length + " node(s), trakcer data is: " + JSON.stringify( joGatheringTracker ), jarrMessages, null ).catch( ( err ) => {
+                const strErrorMessage =
+                    cc.error( "Problem(5) in BLS sign result handler, not enough successful BLS signature parts(" ) +
+                    cc.info( cntSuccess ) + cc.error( ") and timeout reached, error details: " ) +
+                    cc.warning( err ) + "\n";
+                log.write( strErrorMessage );
+                details.write( strErrorMessage );
+            } );
+        }
     } );
+    if( ! bHaveResultReportCalled ) {
+        const strErrorMessage = cc.error( "Failed BLS sign result awaiting(2): " ) + cc.warning( err.toString() ) + "\n";
+        log.write( strErrorMessage );
+        details.write( strErrorMessage );
+        bHaveResultReportCalled = true;
+        await fn( "Failed to gather BLS signatures in " + jarrNodes.length + " node(s), trakcer data is: " + JSON.stringify( joGatheringTracker ), jarrMessages, null ).catch( ( err ) => {
+            const strErrorMessage =
+                cc.error( "Problem(6) in BLS sign result handler, not enough successful BLS signature parts(" ) +
+                cc.info( cntSuccess ) + cc.error( ") and timeout reached, error details: " ) +
+                cc.warning( err ) + "\n";
+            log.write( strErrorMessage );
+            details.write( strErrorMessage );
+        } );
+    }
 }
 
 async function do_sign_messages_m2s( jarrMessages, nIdxCurrentMsgBlockStart, details, joExtraSignOpts, fn ) {
diff --git a/npms/skale-ima/index.js b/npms/skale-ima/index.js
index e96bfb886..d1eefae15 100644
--- a/npms/skale-ima/index.js
+++ b/npms/skale-ima/index.js
@@ -263,7 +263,7 @@ async function get_web3_pastEvents( details, w3, attempts, joContract, strEventN
     let idxAttempt = 2;
     while( joAllEventsInBlock === "" && idxAttempt <= cntAttempts ) {
         details.write(
-            cc.warning( "Repeat " ) + cc.info( "getPastEvents" ) + cc.warning( "/" ) + cc.error( attention ) +
+            cc.warning( "Repeat " ) + cc.info( "getPastEvents" ) + cc.warning( "/" ) + cc.error( attempts ) +
             cc.warning( ", attempt " ) + cc.error( idxAttempt ) +
             cc.warning( ", from block " ) + cc.info( nBlockFrom ) +
             cc.warning( ", to block " ) + cc.info( nBlockTo ) +
@@ -373,7 +373,14 @@ async function get_web3_pastEventsIterative( details, w3, attempts, joContract,
                     cc.success( " block range is " ) + cc.j( joAllEventsInBlock ) + "\n" );
                 return joAllEventsInBlock;
             }
-        } catch ( err ) {}
+        } catch ( err ) {
+            details.write(
+                cc.error( "Got scan error during interative scan of " ) +
+                cc.info( idxBlockSubRangeFrom ) + cc.error( "/" ) + cc.info( idxBlockSubRangeTo ) +
+                cc.error( " block sub-range in " ) + cc.info( nBlockFrom ) + cc.error( "/" ) + cc.info( nBlockTo ) +
+                cc.error( " block range, error is: " ) + cc.warning( err.toString() ) + "\n"
+            );
+        }
         idxBlockSubRangeFrom = idxBlockSubRangeTo;
         if( idxBlockSubRangeFrom == nBlockTo )
             break;
diff --git a/npms/skale-observer/observer.js b/npms/skale-observer/observer.js
index cb47f31c9..88258ddf9 100644
--- a/npms/skale-observer/observer.js
+++ b/npms/skale-observer/observer.js
@@ -319,7 +319,7 @@ async function cache_schains( strChainNameConnectedTo, w3, addressFrom, opts ) {
             g_arr_schains_cached = arr_schains;
         if( opts && opts.details ) {
             opts.details.write(
-                cc.debug( "Connected" ) + cc.attention( "S-Chains" ) + cc.debug( " cache was updated: " ) +
+                cc.debug( "Connected " ) + cc.attention( "S-Chains" ) + cc.debug( " cache was updated: " ) +
                 cc.j( g_arr_schains_cached ) + "\n" );
         }
         if( opts.fn_chache_changed )
diff --git a/proxy/.solcover.js b/proxy/.solcover.js
index edb2862d0..7dca39eef 100644
--- a/proxy/.solcover.js
+++ b/proxy/.solcover.js
@@ -1,3 +1,3 @@
 module.exports = {
-    skipFiles: ['Migrations.sol', 'test/', 'extensions/', 'schain/bls/']
+    skipFiles: ['Migrations.sol', 'test/', 'extensions/', 'schain/bls/', 'thirdparty/', 'schain/KeyStorage.sol']
 };
diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol
index 5024e4fc5..7c21f9c1a 100644
--- a/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol
+++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol
@@ -28,6 +28,7 @@ import "@skalenetwork/ima-interfaces/schain/TokenManagers/ITokenManagerERC1155.s
 import "../../Messages.sol";
 import "../tokens/ERC1155OnChain.sol";
 import "../TokenManager.sol";
+import "../../thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol";
 
 
 /**
@@ -37,7 +38,7 @@ import "../TokenManager.sol";
  * and creates ERC1155 clones.
  * TokenManagerERC1155 mints tokens. When a user exits a SKALE chain, it burns them.
  */
-contract TokenManagerERC1155 is TokenManager, ITokenManagerERC1155 {
+contract TokenManagerERC1155 is TokenManager, ERC1155ReceiverUpgradeableWithoutGap, ITokenManagerERC1155 {
     using AddressUpgradeable for address;
     using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
 
@@ -250,6 +251,53 @@ contract TokenManagerERC1155 is TokenManager, ITokenManagerERC1155 {
         );
     }
 
+    function onERC1155Received(
+        address operator,
+        address,
+        uint256,
+        uint256,
+        bytes calldata
+    )
+        external
+        view
+        override
+        returns(bytes4)
+    {
+        require(operator == address(this), "Revert ERC1155 transfer");
+        return bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"));
+    }
+
+    function onERC1155BatchReceived(
+        address operator,
+        address,
+        uint256[] calldata,
+        uint256[] calldata,
+        bytes calldata
+    )
+        external
+        view
+        override
+        returns(bytes4)
+    {
+        require(operator == address(this), "Revert ERC1155 batch transfer");
+        return bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"));
+    }
+
+    /**
+     * @dev Checks whether contract supports such interface (first 4 bytes of method name and its params).
+     */
+    function supportsInterface(
+        bytes4 interfaceId
+    )
+        public
+        view
+        override(AccessControlEnumerableUpgradeable, ERC1155ReceiverUpgradeableWithoutGap)
+        returns (bool)
+    {
+        return interfaceId == type(TokenManager).interfaceId
+            || super.supportsInterface(interfaceId);
+    }
+
 
     /**
      * @dev Allows TokenManager to send ERC1155 tokens.
@@ -287,7 +335,11 @@ contract TokenManagerERC1155 is TokenManager, ITokenManagerERC1155 {
                 emit ERC1155TokenCreated(fromChainHash, token, address(contractOnSchain));
             }
         }
-        if (messageType == Messages.MessageType.TRANSFER_ERC721 && fromChainHash != MAINNET_HASH) {
+        if (
+            messageType == Messages.MessageType.TRANSFER_ERC1155 &&
+            fromChainHash != MAINNET_HASH &&
+            _schainToERC1155[fromChainHash].contains(token)
+        ) {
             require(token.isContract(), "Incorrect main chain token");
             _removeTransferredAmount(fromChainHash, token, _asSingletonArray(id), _asSingletonArray(amount));
             IERC1155Upgradeable(token).safeTransferFrom(address(this), receiver, id, amount, "");
@@ -339,7 +391,11 @@ contract TokenManagerERC1155 is TokenManager, ITokenManagerERC1155 {
                 emit ERC1155TokenCreated(fromChainHash, token, address(contractOnSchain));
             }
         }
-        if (messageType == Messages.MessageType.TRANSFER_ERC721 && fromChainHash != MAINNET_HASH) {
+        if (
+            messageType == Messages.MessageType.TRANSFER_ERC1155_BATCH &&
+            fromChainHash != MAINNET_HASH &&
+            _schainToERC1155[fromChainHash].contains(token)
+        ) {
             require(token.isContract(), "Incorrect main chain token");
             _removeTransferredAmount(fromChainHash, token, ids, amounts);
             IERC1155Upgradeable(token).safeBatchTransferFrom(address(this), receiver, ids, amounts, "");
diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol
index 874c44818..247b69d32 100644
--- a/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol
+++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol
@@ -213,15 +213,7 @@ contract TokenManagerERC20 is TokenManager, ITokenManagerERC20 {
         Messages.MessageType messageType = Messages.getMessageType(data);
         (address receiver, address token, uint256 amount) = _decodeErc20Message(data);
         ERC20OnChain contractOnSchain;
-        if (messageType == Messages.MessageType.TRANSFER_ERC20) {
-            require(token.isContract() && _schainToERC20[fromChainHash].contains(token), "Incorrect main chain token");
-            require(ERC20Upgradeable(token).balanceOf(address(this)) >= amount, "Not enough money");
-            _removeTransferredAmount(fromChainHash, token, amount);
-            require(
-                ERC20Upgradeable(token).transferFrom(address(this), receiver, amount),
-                "Transfer was failed"
-            );
-        } else {
+        if (messageType != Messages.MessageType.TRANSFER_ERC20) {
             uint256 totalSupply;
             if (messageType == Messages.MessageType.TRANSFER_ERC20_AND_TOTAL_SUPPLY) {
                 Messages.TransferErc20AndTotalSupplyMessage memory message =
@@ -253,6 +245,14 @@ contract TokenManagerERC20 is TokenManager, ITokenManagerERC20 {
                 "Total supply exceeded"
             );
             contractOnSchain.mint(receiver, amount);
+        } else {
+            require(token.isContract() && _schainToERC20[fromChainHash].contains(token), "Incorrect main chain token");
+            require(ERC20Upgradeable(token).balanceOf(address(this)) >= amount, "Not enough money");
+            _removeTransferredAmount(fromChainHash, token, amount);
+            require(
+                ERC20Upgradeable(token).transfer(receiver, amount),
+                "Transfer was failed"
+            );
         }
         emit ERC20TokenReceived(fromChainHash, token, address(contractOnSchain), amount);
         return receiver;
diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol
index 9f8fd667c..de3b00151 100644
--- a/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol
+++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol
@@ -233,7 +233,11 @@ contract TokenManagerERC721 is TokenManager, ITokenManagerERC721 {
                 emit ERC721TokenCreated(fromChainHash, token, address(contractOnSchain));
             }
         }
-        if (messageType == Messages.MessageType.TRANSFER_ERC721 && fromChainHash != MAINNET_HASH) {
+        if (
+            messageType == Messages.MessageType.TRANSFER_ERC721 &&
+            fromChainHash != MAINNET_HASH &&
+            _schainToERC721[fromChainHash].contains(token)
+        ) {
             require(token.isContract(), "Incorrect main chain token");
             require(IERC721Upgradeable(token).ownerOf(tokenId) == address(this), "Incorrect tokenId");
             _removeTransferredAmount(fromChainHash, token, tokenId);
diff --git a/proxy/contracts/thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol b/proxy/contracts/thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol
new file mode 100644
index 000000000..abe928e89
--- /dev/null
+++ b/proxy/contracts/thirdparty/ERC1155ReceiverUpgradeableWithoutGap.sol
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: AGPL-3.0-only
+
+pragma solidity 0.8.6;
+
+import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
+import "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";
+import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155ReceiverUpgradeable.sol";
+
+abstract contract ERC1155ReceiverUpgradeableWithoutGap is
+    Initializable,
+    ERC165Upgradeable,
+    IERC1155ReceiverUpgradeable
+{
+    /**
+     * @dev See {IERC165-supportsInterface}.
+     */
+    function supportsInterface(bytes4 interfaceId)
+        public
+        view
+        virtual
+        override(ERC165Upgradeable, IERC165Upgradeable)
+        returns (bool)
+    {
+        return interfaceId == type(IERC1155ReceiverUpgradeable).interfaceId || super.supportsInterface(interfaceId);
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __ERC1155Receiver_init() internal initializer {
+        __ERC165_init_unchained();
+        __ERC1155Receiver_init_unchained();
+    }
+
+    // solhint-disable-next-line func-name-mixedcase, no-empty-blocks
+    function __ERC1155Receiver_init_unchained() internal initializer {
+    }
+}
\ No newline at end of file
diff --git a/proxy/slither.config.json b/proxy/slither.config.json
index fbe6896bc..000b22c31 100644
--- a/proxy/slither.config.json
+++ b/proxy/slither.config.json
@@ -1,4 +1,4 @@
 {
     "detectors_to_exclude": "uninitialized-local,calls-loop,reentrancy-events,assembly,solc-version,timestamp,unused-return,variable-scope,dead-code",
-    "filter_paths": "test|@openzeppelin/contracts"
+    "filter_paths": "test|@openzeppelin/contracts|thirdparty"
 }
\ No newline at end of file
diff --git a/proxy/yarn.lock b/proxy/yarn.lock
index 18bf6ab6b..d5c99a897 100644
--- a/proxy/yarn.lock
+++ b/proxy/yarn.lock
@@ -757,10 +757,10 @@
   resolved "https://registry.yarnpkg.com/@skalenetwork/etherbase-interfaces/-/etherbase-interfaces-0.0.1-develop.20.tgz#33f61e18d695fd47063aa39dce4df335d26b9528"
   integrity sha512-j3xnuQtOtjvjAoUMJgSUFxRa9/Egkg1RyA8r6PjcEb33VksE4LWLBy0PNFUFehLZv48595JROTcViGeXXwg5HQ==
 
-"@skalenetwork/ima-interfaces@1.0.0-skale-4866-token-mananger-interchain-interfaces.1":
-  version "1.0.0-skale-4866-token-mananger-interchain-interfaces.1"
-  resolved "https://registry.yarnpkg.com/@skalenetwork/ima-interfaces/-/ima-interfaces-1.0.0-skale-4866-token-mananger-interchain-interfaces.1.tgz#774a0dfd4bd8bbd280743ab004b383806220f14b"
-  integrity sha512-7SH69r3mnRs/Ff2wqWqP+sL+DbnH+fj7Q2KHcj2rs9H2IPrUQ4WGg/m+d7MR0o63GfHojxt5Tjp8XGQIMBe8tg==
+"@skalenetwork/ima-interfaces@1.0.0-develop.14":
+  version "1.0.0-develop.14"
+  resolved "https://registry.yarnpkg.com/@skalenetwork/ima-interfaces/-/ima-interfaces-1.0.0-develop.14.tgz#51efd2fa0ed3bc12c2a9a0e3a97dfff8dd98a9c8"
+  integrity sha512-R3rJl1u5c9miAFbE07YjII9uRZNZAVT7BaeKgMer69plVRnIf3Sd9NLth8K/e9ATLIjb7V0tk7mz32E3ptF+Ow==
   dependencies:
     "@skalenetwork/skale-manager-interfaces" "^0.1.2"
 


Test patch:
diff --git a/proxy/test/TokenManagerERC1155.ts b/proxy/test/TokenManagerERC1155.ts
index 1ae88feff..d09ec6667 100644
--- a/proxy/test/TokenManagerERC1155.ts
+++ b/proxy/test/TokenManagerERC1155.ts
@@ -59,16 +59,17 @@ describe("TokenManagerERC1155", () => {
     let schainOwner: SignerWithAddress;
 
     const schainName = "V-chain";
+    const schainId = stringValue(web3.utils.soliditySha3(schainName));
     const id = 1;
     const amount = 4;
     const ids = [1, 2, 3, 4];
     const amounts = [4, 3, 2, 1];
-    const schainId = web3.utils.soliditySha3(schainName);
     const mainnetName = "Mainnet";
     const mainnetId = stringValue(web3.utils.soliditySha3("Mainnet"));
     let to: string;
     let token: ERC1155OnChain;
     let fakeDepositBox: string;
+    let fakeCommunityPool: string;
     let tokenClone: ERC1155OnChain;
     let tokenManagerERC1155: TokenManagerERC1155;
     let tokenManagerLinker: TokenManagerLinker;
@@ -90,7 +91,7 @@ describe("TokenManagerERC1155", () => {
         tokenManagerLinker = await deployTokenManagerLinker(messageProxyForSchain, deployer.address);
         messages = await deployMessages();
         fakeDepositBox = messages.address;
-        const fakeCommunityPool = messages.address;
+        fakeCommunityPool = messages.address;
 
         communityLocker = await deployCommunityLocker(schainName, messageProxyForSchain.address, tokenManagerLinker, fakeCommunityPool);
 
@@ -192,71 +193,1680 @@ describe("TokenManagerERC1155", () => {
             .should.be.eventually.rejectedWith("Could not relink clone");
     });
 
-    it("should successfully call transferToSchainERC1155", async () => {
-        const newSchainName = randomString(10);
-        const chainConnectorRole = await messageProxyForSchain.CHAIN_CONNECTOR_ROLE();
-        await messageProxyForSchain.grantRole(chainConnectorRole, deployer.address);
-        await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+    describe("tests for transferToSchainERC1155", async () => {
+
+        let erc1155OnOriginChain: ERC1155OnChain;
+        let erc1155OnTargetChain: ERC1155OnChain;
+        let messageProxyForSchain2: MessageProxyForSchainTester;
+        let tokenManagerLinker2: TokenManagerLinker;
+        let tokenManagerERC11552: TokenManagerERC1155;
+        let communityLocker2: CommunityLocker;
+        const newSchainName = "NewChain";
+        const newSchainId = stringValue(web3.utils.soliditySha3(newSchainName));
+
+        beforeEach(async () => {
+            erc1155OnOriginChain = await deployERC1155OnChain("NewToken");
+            erc1155OnTargetChain = await deployERC1155OnChain("NewToke1n");
+
+            const keyStorage2 = await deployKeyStorageMock();
+            messageProxyForSchain2 = await deployMessageProxyForSchainTester(keyStorage2.address, newSchainName);
+            tokenManagerLinker2 = await deployTokenManagerLinker(messageProxyForSchain2, deployer.address);
+            communityLocker2 = await deployCommunityLocker(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, fakeCommunityPool);
+            tokenManagerERC11552 = await deployTokenManagerERC1155(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, communityLocker2, fakeDepositBox);
+            await erc1155OnTargetChain.connect(deployer).grantRole(await erc1155OnTargetChain.MINTER_ROLE(), tokenManagerERC11552.address);
+            await tokenManagerLinker2.registerTokenManager(tokenManagerERC11552.address);
+        });
+
+        it("should invoke `transferToSchainERC1155` without mistakes", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount);
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+        });
+
+        it("should invoke `transferToSchainERC1155` and receive tokens without mistakes", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount);
+
+            const data = await messages.encodeTransferErc1155AndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC11552.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const addressERC1155OnSchain = await tokenManagerERC11552.clonesErc1155(schainId, erc1155OnOriginChain.address);
+            const targetErc1155OnChain = await (await ethers.getContractFactory("ERC1155OnChain")).attach(addressERC1155OnSchain) as ERC1155OnChain;
+            expect((await targetErc1155OnChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+        });
+
+        it("should invoke `transferToSchainERC1155` and receive tokens without mistakes double", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount);
+
+            let data = await messages.encodeTransferErc1155AndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC11552.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const addressERC1155OnSchain = await tokenManagerERC11552.clonesErc1155(schainId, erc1155OnOriginChain.address);
+            const targetErc1155OnChain = await (await ethers.getContractFactory("ERC1155OnChain")).attach(addressERC1155OnSchain) as ERC1155OnChain;
+            expect((await targetErc1155OnChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+            const amount2 = 77;
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount2, "0x");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount2);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const amountSum = 81;
+
+            expect((await targetErc1155OnChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amountSum.toString());
+
+        });
+
+        it("should invoke `transferToSchainERC1155` and receive tokens without mistakes double with attached token", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount);
+
+            let data = await messages.encodeTransferErc1155AndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+
+            await tokenManagerERC11552.connect(schainOwner).addERC1155TokenByOwner(schainName,  erc1155OnOriginChain.address, erc1155OnTargetChain.address).should.be.eventually.rejectedWith("TOKEN_REGISTRAR_ROLE is required");
+            await tokenManagerERC11552.connect(deployer).grantRole(await tokenManagerERC11552.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerERC11552.connect(schainOwner).addERC1155TokenByOwner(schainName,  erc1155OnOriginChain.address, erc1155OnTargetChain.address).should.be.eventually.rejectedWith("Chain is not connected");
+
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.connect(schainOwner).addERC1155TokenByOwner(schainName,  erc1155OnOriginChain.address, erc1155OnTargetChain.address);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            expect((await erc1155OnTargetChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+            const amount2 = 77;
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount2, "0x");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount2);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const amountSum = 81;
+
+            expect((await erc1155OnTargetChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amountSum.toString());
+
+        });
+
+        it("should invoke `transferToSchainERC1155` and transfer back without mistakes", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount);
+
+            let data = await messages.encodeTransferErc1155AndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC11552.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const addressERC1155OnSchain = await tokenManagerERC11552.clonesErc1155(schainId, erc1155OnOriginChain.address);
+            const targetErc1155OnChain = await (await ethers.getContractFactory("ERC1155OnChain")).attach(addressERC1155OnSchain) as ERC1155OnChain;
+            expect((await targetErc1155OnChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
+
+            await targetErc1155OnChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            expect((await erc1155OnOriginChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+        });
+
+        it("should invoke `transferToSchainERC1155` and transfer back without mistakes with attached tokens", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount);
+
+            let data = await messages.encodeTransferErc1155AndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+            await tokenManagerERC11552.connect(deployer).grantRole(await tokenManagerERC11552.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerERC11552.connect(schainOwner).addERC1155TokenByOwner(schainName,  erc1155OnOriginChain.address, erc1155OnTargetChain.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
+
+            await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+            expect((await erc1155OnOriginChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+        });
+
+
+        it("should invoke `transferToSchainERC1155` and transfer back without mistakes double", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount);
+
+            let data = await messages.encodeTransferErc1155AndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC11552.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const addressERC1155OnSchain = await tokenManagerERC11552.clonesErc1155(schainId, erc1155OnOriginChain.address);
+            const targetErc1155OnChain = await (await ethers.getContractFactory("ERC1155OnChain")).attach(addressERC1155OnSchain) as ERC1155OnChain;
+            expect((await targetErc1155OnChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
+
+            await targetErc1155OnChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+            expect((await erc1155OnOriginChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            expect((await targetErc1155OnChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+            const amount2 = 77;
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount2, "0x");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount2);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const amountSum = 81;
+
+            expect((await targetErc1155OnChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amountSum.toString());
+
+            await targetErc1155OnChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+            expect((await erc1155OnOriginChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount2);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount2
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            expect((await erc1155OnOriginChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amountSum.toString());
+
+        });
+
+        it("should invoke `transferToSchainERC1155` and transfer back without mistakes double with attached tokens", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount);
+
+            let data = await messages.encodeTransferErc1155AndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+            await tokenManagerERC11552.connect(deployer).grantRole(await tokenManagerERC11552.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerERC11552.connect(schainOwner).addERC1155TokenByOwner(schainName,  erc1155OnOriginChain.address, erc1155OnTargetChain.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
+
+            await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+            expect((await erc1155OnOriginChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            expect((await erc1155OnTargetChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+            const amount2 = 77;
+
+            await erc1155OnOriginChain.connect(deployer).mint(user.address, id, amount2, "0x");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, amount2);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const amountSum = 81;
+
+            expect((await erc1155OnTargetChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amountSum.toString());
+
+            await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+            expect((await erc1155OnOriginChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amount.toString());
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount2);
+
+            data = await messages.encodeTransferErc1155Message(
+                erc1155OnOriginChain.address,
+                user.address,
+                id,
+                amount2
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            expect((await erc1155OnOriginChain.functions.balanceOf(user.address, id)).toString()).to.be.equal(amountSum.toString());
+
+        });
+
+    });
+
+    describe("tests for transferToSchainERC1155Batch", async () => {
+
+        let erc1155OnOriginChain: ERC1155OnChain;
+        let erc1155OnTargetChain: ERC1155OnChain;
+        let messageProxyForSchain2: MessageProxyForSchainTester;
+        let tokenManagerLinker2: TokenManagerLinker;
+        let tokenManagerERC11552: TokenManagerERC1155;
+        let communityLocker2: CommunityLocker;
+        const newSchainName = "NewChain";
+        const newSchainId = stringValue(web3.utils.soliditySha3(newSchainName));
+
+        beforeEach(async () => {
+            erc1155OnOriginChain = await deployERC1155OnChain("NewToken");
+            erc1155OnTargetChain = await deployERC1155OnChain("NewToke1n");
+
+            const keyStorage2 = await deployKeyStorageMock();
+            messageProxyForSchain2 = await deployMessageProxyForSchainTester(keyStorage2.address, newSchainName);
+            tokenManagerLinker2 = await deployTokenManagerLinker(messageProxyForSchain2, deployer.address);
+            communityLocker2 = await deployCommunityLocker(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, fakeCommunityPool);
+            tokenManagerERC11552 = await deployTokenManagerERC1155(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, communityLocker2, fakeDepositBox);
+            await erc1155OnTargetChain.connect(deployer).grantRole(await erc1155OnTargetChain.MINTER_ROLE(), tokenManagerERC11552.address);
+            await tokenManagerLinker2.registerTokenManager(tokenManagerERC11552.address);
+        });
+
+        it("should invoke `transferToSchainERC1155` without mistakes", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts);
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+        });
+
+        it("should invoke `transferToSchainERC1155` and receive tokens without mistakes", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts);
+
+            const data = await messages.encodeTransferErc1155BatchAndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC11552.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const addressERC1155OnSchain = await tokenManagerERC11552.clonesErc1155(schainId, erc1155OnOriginChain.address);
+            const targetErc1155OnChain = await (await ethers.getContractFactory("ERC1155OnChain")).attach(addressERC1155OnSchain) as ERC1155OnChain;
+
+            const balanceIds = await targetErc1155OnChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            const balanceIdsNumber: number[] = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+        });
+
+        it("should invoke `transferToSchainERC1155` and receive tokens without mistakes double", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts);
+
+            let data = await messages.encodeTransferErc1155BatchAndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC11552.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const addressERC1155OnSchain = await tokenManagerERC11552.clonesErc1155(schainId, erc1155OnOriginChain.address);
+            const targetErc1155OnChain = await (await ethers.getContractFactory("ERC1155OnChain")).attach(addressERC1155OnSchain) as ERC1155OnChain;
+
+            let balanceIds = await targetErc1155OnChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            let balanceIdsNumber: number[] = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+            const amounts2 = [77, 78, 79, 80];
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts2, "0x");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts2);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const amountsSum = [81, 81, 81, 81];
+
+            balanceIds = await targetErc1155OnChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amountsSum);
+
+        });
+
+        it("should invoke `transferToSchainERC1155` and receive tokens without mistakes double with attached token", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts);
+
+            let data = await messages.encodeTransferErc1155BatchAndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+
+            await tokenManagerERC11552.connect(schainOwner).addERC1155TokenByOwner(schainName,  erc1155OnOriginChain.address, erc1155OnTargetChain.address).should.be.eventually.rejectedWith("TOKEN_REGISTRAR_ROLE is required");
+            await tokenManagerERC11552.connect(deployer).grantRole(await tokenManagerERC11552.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerERC11552.connect(schainOwner).addERC1155TokenByOwner(schainName,  erc1155OnOriginChain.address, erc1155OnTargetChain.address).should.be.eventually.rejectedWith("Chain is not connected");
+
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.connect(schainOwner).addERC1155TokenByOwner(schainName,  erc1155OnOriginChain.address, erc1155OnTargetChain.address);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            let balanceIds = await erc1155OnTargetChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            let balanceIdsNumber: number[] = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+            const amounts2 = [77, 78, 79, 80];
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts2, "0x");
 
-        await tokenManagerERC1155
-            .connect(deployer)
-            .transferToSchainERC1155(newSchainName, token.address, id, amount)
-            .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts2);
 
-        await tokenManagerERC1155.addTokenManager(newSchainName, deployer.address);
-        await tokenManagerERC1155.connect(schainOwner).addERC1155TokenByOwner(newSchainName,  token.address, tokenClone.address);
-        await tokenClone.connect(deployer).mint(deployer.address, id, amount, "0x");
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts2
+            );
 
-        await tokenManagerERC1155
-            .connect(deployer)
-            .transferToSchainERC1155(newSchainName, token.address, id, amount)
-            .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
 
-        await tokenClone.connect(deployer).setApprovalForAll(tokenManagerERC1155.address, true);
+            const amountsSum = [81, 81, 81, 81];
 
-        // execution:
-        await tokenManagerERC1155
-            .connect(deployer)
-            .transferToSchainERC1155(newSchainName, token.address, id, amount);
-        // expectation:
-        const outgoingMessagesCounter = BigNumber.from(
-            await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)
-        );
-        outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
-    });
+            balanceIds = await erc1155OnTargetChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amountsSum);
 
-    it("should successfully call transferToSchainERC1155Batch", async () => {
-        const newSchainName = randomString(10);
+        });
 
-        const chainConnectorRole = await messageProxyForSchain.CHAIN_CONNECTOR_ROLE();
-        await messageProxyForSchain.grantRole(chainConnectorRole, deployer.address);
-        await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+        it("should invoke `transferToSchainERC1155` and transfer back without mistakes", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
 
-        await tokenManagerERC1155
-            .connect(deployer)
-            .transferToSchainERC1155Batch(newSchainName, token.address, ids, amounts)
-            .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
 
-        await tokenManagerERC1155.addTokenManager(newSchainName, deployer.address);
-        await tokenManagerERC1155.connect(schainOwner).addERC1155TokenByOwner(newSchainName,  token.address, tokenClone.address);
-        await tokenClone.connect(deployer).mintBatch(deployer.address, ids, amounts, "0x");
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
 
-        await tokenManagerERC1155
-            .connect(deployer)
-            .transferToSchainERC1155Batch(newSchainName, token.address, ids, amounts)
-            .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
 
-        await tokenClone.connect(deployer).setApprovalForAll(tokenManagerERC1155.address, true);
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts);
+
+            let data = await messages.encodeTransferErc1155BatchAndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC11552.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const addressERC1155OnSchain = await tokenManagerERC11552.clonesErc1155(schainId, erc1155OnOriginChain.address);
+            const targetErc1155OnChain = await (await ethers.getContractFactory("ERC1155OnChain")).attach(addressERC1155OnSchain) as ERC1155OnChain;
+
+            let balanceIds = await targetErc1155OnChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            let balanceIdsNumber: number[] = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
+
+            await targetErc1155OnChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            balanceIds = await erc1155OnOriginChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+        });
+
+        it("should invoke `transferToSchainERC1155` and transfer back without mistakes with attached tokens", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts);
+
+            let data = await messages.encodeTransferErc1155BatchAndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+            await tokenManagerERC11552.connect(deployer).grantRole(await tokenManagerERC11552.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerERC11552.connect(schainOwner).addERC1155TokenByOwner(schainName,  erc1155OnOriginChain.address, erc1155OnTargetChain.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
+
+            await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            const balanceIds = await erc1155OnOriginChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            const balanceIdsNumber: number[] = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+        });
+
+
+        it("should invoke `transferToSchainERC1155` and transfer back without mistakes double", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts);
+
+            let data = await messages.encodeTransferErc1155BatchAndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC11552.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const addressERC1155OnSchain = await tokenManagerERC11552.clonesErc1155(schainId, erc1155OnOriginChain.address);
+            const targetErc1155OnChain = await (await ethers.getContractFactory("ERC1155OnChain")).attach(addressERC1155OnSchain) as ERC1155OnChain;
+
+            let balanceIds = await targetErc1155OnChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            let balanceIdsNumber: number[] = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
+
+            await targetErc1155OnChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            balanceIds = await erc1155OnOriginChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            balanceIds = await targetErc1155OnChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+            const amounts2 = [77, 78, 79, 80];
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts2, "0x");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts2);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const amountsSum = [81, 81, 81, 81];
+
+            balanceIds = await targetErc1155OnChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amountsSum);
+
+            await targetErc1155OnChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            balanceIds = await erc1155OnOriginChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts2);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts2
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            balanceIds = await erc1155OnOriginChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amountsSum);
+
+        });
+
+        it("should invoke `transferToSchainERC1155` and transfer back without mistakes double with attached tokens", async () => {
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts, "0x");
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address);
+
+            // execution:
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts);
+
+            let data = await messages.encodeTransferErc1155BatchAndTokenInfoMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts,
+                {
+                    uri: await erc1155OnOriginChain.uri(0)
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC11552.addTokenManager(schainName, tokenManagerERC1155.address);
+
+            await tokenManagerERC11552.connect(deployer).grantRole(await tokenManagerERC11552.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerERC11552.connect(schainOwner).addERC1155TokenByOwner(schainName,  erc1155OnOriginChain.address, erc1155OnTargetChain.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
+
+            await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            let balanceIds = await erc1155OnOriginChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            let balanceIdsNumber: number[] = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+            await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            balanceIds = await erc1155OnTargetChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+            const amounts2 = [77, 78, 79, 80];
+
+            await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, amounts2, "0x");
+
+            await tokenManagerERC1155
+                .connect(user)
+                .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, amounts2);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC11552.address, schainId, tokenManagerERC1155.address, data);
+
+            const amountsSum = [81, 81, 81, 81];
+
+            balanceIds = await erc1155OnTargetChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amountsSum);
+
+            await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            balanceIds = await erc1155OnOriginChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amounts);
+
+            await tokenManagerERC11552
+                .connect(user)
+                .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts2);
+
+            data = await messages.encodeTransferErc1155BatchMessage(
+                erc1155OnOriginChain.address,
+                user.address,
+                ids,
+                amounts2
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC1155.address, newSchainId, tokenManagerERC11552.address, data);
+
+            balanceIds = await erc1155OnOriginChain.balanceOfBatch([user.address, user.address, user.address, user.address], ids);
+            balanceIdsNumber = [];
+            balanceIds.forEach((element: any) => {
+                balanceIdsNumber.push(BigNumber.from(element).toNumber())
+            });
+            expect(balanceIdsNumber).to.deep.equal(amountsSum);
+
+        });
 
-        // execution:
-        await tokenManagerERC1155
-            .connect(deployer)
-            .transferToSchainERC1155Batch(newSchainName, token.address, ids, amounts);
-        // expectation:
-        const outgoingMessagesCounter = BigNumber.from(
-            await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)
-        );
-        outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
     });
 
     describe("tests for `postMessage` function", async () => {
diff --git a/proxy/test/TokenManagerERC20.ts b/proxy/test/TokenManagerERC20.ts
index 4690b7fb8..3b6239b3b 100644
--- a/proxy/test/TokenManagerERC20.ts
+++ b/proxy/test/TokenManagerERC20.ts
@@ -60,7 +60,7 @@ describe("TokenManagerERC20", () => {
 
     const mainnetName = "Mainnet";
     const schainName = "D2-chain";
-    const schainId = web3.utils.soliditySha3(schainName);
+    const schainId = stringValue(web3.utils.soliditySha3(schainName));
     const mainnetId = stringValue(web3.utils.soliditySha3("Mainnet"));
     let fakeDepositBox: string;
     let fakeCommunityPool: any;
@@ -246,41 +246,827 @@ describe("TokenManagerERC20", () => {
         outgoingMessagesCounterMainnet.should.be.deep.equal(BigNumber.from(1));
     });
 
-    it("should invoke `transferToSchainERC20` without mistakes", async () => {
-        const amount = "20000000000000000";
-        const amountReduceCost = "8000000000000000";
-        const newSchainName = randomString(10);
-        await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address);
+    describe("tests for transferToSchainERC20", async () => {
+
+        let erc20OnOriginChain: ERC20OnChain;
+        let erc20OnTargetChain: ERC20OnChain;
+        let messageProxyForSchain2: MessageProxyForSchainTester;
+        let tokenManagerLinker2: TokenManagerLinker;
+        let tokenManagerErc202: TokenManagerERC20;
+        let communityLocker2: CommunityLocker;
+        const newSchainName = "NewChain";
+        const newSchainId = stringValue(web3.utils.soliditySha3(newSchainName));
+
+        beforeEach(async () => {
+            erc20OnOriginChain = await deployERC20OnChain("NewToken", "NTN");
+            erc20OnTargetChain = await deployERC20OnChain("NewToke1n", "NTN1");
+
+            const keyStorage2 = await deployKeyStorageMock();
+            messageProxyForSchain2 = await deployMessageProxyForSchainTester(keyStorage2.address, newSchainName);
+            tokenManagerLinker2 = await deployTokenManagerLinker(messageProxyForSchain2, deployer.address);
+            communityLocker2 = await deployCommunityLocker(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, fakeCommunityPool);
+            tokenManagerErc202 = await deployTokenManagerERC20(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, communityLocker2, fakeDepositBox);
+            await erc20OnTargetChain.connect(deployer).grantRole(await erc20OnTargetChain.MINTER_ROLE(), tokenManagerErc202.address);
+            await tokenManagerLinker2.registerTokenManager(tokenManagerErc202.address);
+        });
 
-        // add connected chain:
-        await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
-        await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+        it("should invoke `transferToSchainERC20` without mistakes", async () => {
+            const amount = "20000000000000000";
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address);
 
-        await tokenManagerErc20.connect(schainOwner).addERC20TokenByOwner(newSchainName,  erc20OnMainnet.address, erc20OnChain.address);
-        await erc20OnChain.connect(deployer).mint(user.address, amount);
-        await erc20OnChain.connect(user).approve(tokenManagerErc20.address, amount);
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
 
-        await tokenManagerErc20
-            .connect(user)
-            .transferToSchainERC20(newSchainName, erc20OnMainnet.address, amountReduceCost)
-            .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount);
 
-        await tokenManagerErc20
-            .connect(user)
-            .transferToSchainERC20("Mainnet", erc20OnMainnet.address, amountReduceCost)
-            .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
 
-        await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc20.address);
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
 
-        // execution:
-        await tokenManagerErc20
-            .connect(user)
-            .transferToSchainERC20(newSchainName, erc20OnMainnet.address, amountReduceCost);
+            await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc202.address);
+
+            // execution:
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount);
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+        });
+
+        it("should invoke `transferToSchainERC20` and receive tokens without mistakes", async () => {
+            const amount = "20000000000000000";
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc202.address);
+
+            // execution:
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount);
+
+            const data = await messages.encodeTransferErc20AndTokenInfoMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount,
+                (await erc20OnOriginChain.totalSupply()).toString(),
+                {
+                    name: await erc20OnOriginChain.name(),
+                    symbol: await erc20OnOriginChain.symbol(),
+                    decimals: BigNumber.from(await erc20OnOriginChain.decimals()).toString()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerErc202.addTokenManager(schainName, tokenManagerErc20.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerErc202.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            const addressERC20OnSchain = await tokenManagerErc202.clonesErc20(schainId, erc20OnOriginChain.address);
+            const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain;
+            expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+        });
+
+        it("should invoke `transferToSchainERC20` and receive tokens without mistakes double", async () => {
+            const amount = "20000000000000000";
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc202.address);
+
+            // execution:
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount);
+
+            let data = await messages.encodeTransferErc20AndTokenInfoMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount,
+                (await erc20OnOriginChain.totalSupply()).toString(),
+                {
+                    name: await erc20OnOriginChain.name(),
+                    symbol: await erc20OnOriginChain.symbol(),
+                    decimals: BigNumber.from(await erc20OnOriginChain.decimals()).toString()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerErc202.addTokenManager(schainName, tokenManagerErc20.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerErc202.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            const addressERC20OnSchain = await tokenManagerErc202.clonesErc20(schainId, erc20OnOriginChain.address);
+            const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain;
+            expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+            const amount2 = "50000000000000000";
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount2);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount2);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount2);
+
+            data = await messages.encodeTransferErc20AndTotalSupplyMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount2,
+                (await erc20OnOriginChain.totalSupply()).toString()
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            const amountSum = "70000000000000000";
+
+            expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amountSum);
+
+        });
+
+        it("should invoke `transferToSchainERC20` and receive tokens without mistakes double with attached token", async () => {
+            const amount = "20000000000000000";
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc202.address);
+
+            // execution:
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount);
+
+            let data = await messages.encodeTransferErc20AndTokenInfoMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount,
+                (await erc20OnOriginChain.totalSupply()).toString(),
+                {
+                    name: await erc20OnOriginChain.name(),
+                    symbol: await erc20OnOriginChain.symbol(),
+                    decimals: BigNumber.from(await erc20OnOriginChain.decimals()).toString()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+
+            await tokenManagerErc202.connect(schainOwner).addERC20TokenByOwner(schainName,  erc20OnOriginChain.address, erc20OnTargetChain.address).should.be.eventually.rejectedWith("TOKEN_REGISTRAR_ROLE is required");
+            await tokenManagerErc202.connect(deployer).grantRole(await tokenManagerErc202.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerErc202.connect(schainOwner).addERC20TokenByOwner(schainName,  erc20OnOriginChain.address, erc20OnTargetChain.address).should.be.eventually.rejectedWith("Chain is not connected");
+
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerErc202.connect(schainOwner).addERC20TokenByOwner(schainName,  erc20OnOriginChain.address, erc20OnTargetChain.address);
+            await tokenManagerErc202.addTokenManager(schainName, tokenManagerErc20.address);
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            expect((await erc20OnTargetChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+            const amount2 = "50000000000000000";
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount2);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount2);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount2);
+
+            data = await messages.encodeTransferErc20AndTotalSupplyMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount2,
+                (await erc20OnOriginChain.totalSupply()).toString()
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            const amountSum = "70000000000000000";
+
+            expect((await erc20OnTargetChain.functions.balanceOf(user.address)).toString()).to.be.equal(amountSum);
+
+        });
+
+        it("should invoke `transferToSchainERC20` and transfer back without mistakes", async () => {
+            const amount = "20000000000000000";
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc202.address);
+
+            // execution:
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount);
+
+            let data = await messages.encodeTransferErc20AndTokenInfoMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount,
+                (await erc20OnOriginChain.totalSupply()).toString(),
+                {
+                    name: await erc20OnOriginChain.name(),
+                    symbol: await erc20OnOriginChain.symbol(),
+                    decimals: BigNumber.from(await erc20OnOriginChain.decimals()).toString()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerErc202.addTokenManager(schainName, tokenManagerErc20.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerErc202.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            const addressERC20OnSchain = await tokenManagerErc202.clonesErc20(schainId, erc20OnOriginChain.address);
+            const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain;
+            expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Transfer is not approved by token holder");
+
+            await targetErc20OnChain.connect(user).approve(tokenManagerErc202.address, amount);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerErc202.address);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount);
+
+            data = await messages.encodeTransferErc20Message(
+                erc20OnOriginChain.address,
+                user.address,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerErc20.address, newSchainId, tokenManagerErc202.address, data);
+            expect((await erc20OnOriginChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+        });
+
+        it("should invoke `transferToSchainERC20` and transfer back without mistakes with attached tokens", async () => {
+            const amount = "20000000000000000";
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc202.address);
+
+            // execution:
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount);
+
+            let data = await messages.encodeTransferErc20AndTokenInfoMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount,
+                (await erc20OnOriginChain.totalSupply()).toString(),
+                {
+                    name: await erc20OnOriginChain.name(),
+                    symbol: await erc20OnOriginChain.symbol(),
+                    decimals: BigNumber.from(await erc20OnOriginChain.decimals()).toString()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerErc202.addTokenManager(schainName, tokenManagerErc20.address);
+
+            await tokenManagerErc202.connect(deployer).grantRole(await tokenManagerErc202.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerErc202.connect(schainOwner).addERC20TokenByOwner(schainName,  erc20OnOriginChain.address, erc20OnTargetChain.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Transfer is not approved by token holder");
+
+            await erc20OnTargetChain.connect(user).approve(tokenManagerErc202.address, amount);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerErc202.address);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount);
+
+            data = await messages.encodeTransferErc20Message(
+                erc20OnOriginChain.address,
+                user.address,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerErc20.address, newSchainId, tokenManagerErc202.address, data);
+            expect((await erc20OnOriginChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+        });
+
+
+        it("should invoke `transferToSchainERC20` and transfer back without mistakes double", async () => {
+            const amount = "20000000000000000";
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc202.address);
+
+            // execution:
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount);
+
+            let data = await messages.encodeTransferErc20AndTokenInfoMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount,
+                (await erc20OnOriginChain.totalSupply()).toString(),
+                {
+                    name: await erc20OnOriginChain.name(),
+                    symbol: await erc20OnOriginChain.symbol(),
+                    decimals: BigNumber.from(await erc20OnOriginChain.decimals()).toString()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerErc202.addTokenManager(schainName, tokenManagerErc20.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerErc202.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            const addressERC20OnSchain = await tokenManagerErc202.clonesErc20(schainId, erc20OnOriginChain.address);
+            const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain;
+            expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Transfer is not approved by token holder");
+
+            await targetErc20OnChain.connect(user).approve(tokenManagerErc202.address, amount);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerErc202.address);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount);
+
+            data = await messages.encodeTransferErc20Message(
+                erc20OnOriginChain.address,
+                user.address,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerErc20.address, newSchainId, tokenManagerErc202.address, data);
+            expect((await erc20OnOriginChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount);
+
+            data = await messages.encodeTransferErc20AndTotalSupplyMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount,
+                (await erc20OnOriginChain.totalSupply()).toString()
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+            const amount2 = "50000000000000000";
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount2);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount2);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount2);
+
+            data = await messages.encodeTransferErc20AndTotalSupplyMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount2,
+                (await erc20OnOriginChain.totalSupply()).toString()
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            const amountSum = "70000000000000000";
+
+            expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amountSum);
+
+            await targetErc20OnChain.connect(user).approve(tokenManagerErc202.address, amount);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount);
+
+            data = await messages.encodeTransferErc20Message(
+                erc20OnOriginChain.address,
+                user.address,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerErc20.address, newSchainId, tokenManagerErc202.address, data);
+            expect((await erc20OnOriginChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+            await targetErc20OnChain.connect(user).approve(tokenManagerErc202.address, amount2);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount2);
+
+            data = await messages.encodeTransferErc20Message(
+                erc20OnOriginChain.address,
+                user.address,
+                amount2
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerErc20.address, newSchainId, tokenManagerErc202.address, data);
+
+            expect((await erc20OnOriginChain.functions.balanceOf(user.address)).toString()).to.be.equal(amountSum);
+
+        });
+
+        it("should invoke `transferToSchainERC20` and transfer back without mistakes double with attached tokens", async () => {
+            const amount = "20000000000000000";
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc202.address);
+
+            // execution:
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount);
+
+            let data = await messages.encodeTransferErc20AndTokenInfoMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount,
+                (await erc20OnOriginChain.totalSupply()).toString(),
+                {
+                    name: await erc20OnOriginChain.name(),
+                    symbol: await erc20OnOriginChain.symbol(),
+                    decimals: BigNumber.from(await erc20OnOriginChain.decimals()).toString()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerErc202.addTokenManager(schainName, tokenManagerErc20.address);
+
+            await tokenManagerErc202.connect(deployer).grantRole(await tokenManagerErc202.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerErc202.connect(schainOwner).addERC20TokenByOwner(schainName,  erc20OnOriginChain.address, erc20OnTargetChain.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Transfer is not approved by token holder");
+
+            await erc20OnTargetChain.connect(user).approve(tokenManagerErc202.address, amount);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerErc202.address);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount);
+
+            data = await messages.encodeTransferErc20Message(
+                erc20OnOriginChain.address,
+                user.address,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerErc20.address, newSchainId, tokenManagerErc202.address, data);
+            expect((await erc20OnOriginChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount);
+
+            data = await messages.encodeTransferErc20AndTotalSupplyMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount,
+                (await erc20OnOriginChain.totalSupply()).toString()
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            expect((await erc20OnTargetChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+            const amount2 = "50000000000000000";
+
+            await erc20OnOriginChain.connect(deployer).mint(user.address, amount2);
+            await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount2);
+
+            await tokenManagerErc20
+                .connect(user)
+                .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount2);
+
+            data = await messages.encodeTransferErc20AndTotalSupplyMessage(
+                erc20OnOriginChain.address,
+                user.address,
+                amount2,
+                (await erc20OnOriginChain.totalSupply()).toString()
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data);
+
+            const amountSum = "70000000000000000";
+
+            expect((await erc20OnTargetChain.functions.balanceOf(user.address)).toString()).to.be.equal(amountSum);
+
+            await erc20OnTargetChain.connect(user).approve(tokenManagerErc202.address, amount);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount);
+
+            data = await messages.encodeTransferErc20Message(
+                erc20OnOriginChain.address,
+                user.address,
+                amount
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerErc20.address, newSchainId, tokenManagerErc202.address, data);
+            expect((await erc20OnOriginChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount);
+
+            await erc20OnTargetChain.connect(user).approve(tokenManagerErc202.address, amount2);
+
+            await tokenManagerErc202
+                .connect(user)
+                .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount2);
+
+            data = await messages.encodeTransferErc20Message(
+                erc20OnOriginChain.address,
+                user.address,
+                amount2
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerErc20.address, newSchainId, tokenManagerErc202.address, data);
+
+            expect((await erc20OnOriginChain.functions.balanceOf(user.address)).toString()).to.be.equal(amountSum);
+
+        });
 
-        // expectation:
-        const outgoingMessagesCounter = BigNumber.from(
-            await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
-        outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
     });
 
     describe("tests for `postMessage` function", async () => {
diff --git a/proxy/test/TokenManagerERC721.ts b/proxy/test/TokenManagerERC721.ts
index c7225a947..433f8d88c 100644
--- a/proxy/test/TokenManagerERC721.ts
+++ b/proxy/test/TokenManagerERC721.ts
@@ -59,6 +59,7 @@ describe("TokenManagerERC721", () => {
     let schainOwner: SignerWithAddress;
 
     const schainName = "V-chain";
+    const schainId = stringValue(web3.utils.soliditySha3(schainName));
     const tokenId = 1;
     const mainnetName = "Mainnet";
     const mainnetId = stringValue(web3.utils.soliditySha3("Mainnet"));
@@ -66,6 +67,7 @@ describe("TokenManagerERC721", () => {
     let token: ERC721OnChain;
     let tokenClone: ERC721OnChain;
     let fakeDepositBox: string;
+    let fakeCommunityPool: string;
     let tokenManagerERC721: TokenManagerERC721;
     let tokenManagerLinker: TokenManagerLinker;
     let messages: MessagesTester;
@@ -86,7 +88,7 @@ describe("TokenManagerERC721", () => {
         tokenManagerLinker = await deployTokenManagerLinker(messageProxyForSchain, deployer.address);
         messages = await deployMessages();
         fakeDepositBox = messages.address;
-        const fakeCommunityPool = messages.address;
+        fakeCommunityPool = messages.address;
 
         communityLocker = await deployCommunityLocker(schainName, messageProxyForSchain.address, tokenManagerLinker, fakeCommunityPool);
 
@@ -200,45 +202,796 @@ describe("TokenManagerERC721", () => {
             .should.be.eventually.rejectedWith("Could not relink clone");
     });
 
-    it("should successfully call transferToSchainERC721", async () => {
-        const newSchainName = randomString(10);
+    describe("tests for transferToSchainERC721", async () => {
 
-        await messageProxyForSchain.grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
-        await messageProxyForSchain.addConnectedChain(newSchainName);
+        let erc721OnOriginChain: ERC721OnChain;
+        let erc721OnTargetChain: ERC721OnChain;
+        let messageProxyForSchain2: MessageProxyForSchainTester;
+        let tokenManagerLinker2: TokenManagerLinker;
+        let tokenManagerERC7212: TokenManagerERC721;
+        let communityLocker2: CommunityLocker;
+        const newSchainName = "NewChain";
+        const newSchainId = stringValue(web3.utils.soliditySha3(newSchainName));
 
-        await tokenManagerERC721
-            .connect(deployer)
-            .transferToSchainERC721(newSchainName, token.address, tokenId)
-            .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+        beforeEach(async () => {
+            erc721OnOriginChain = await deployERC721OnChain("NewToken", "NTN");
+            erc721OnTargetChain = await deployERC721OnChain("NewToke1n", "NTN1");
 
-        await tokenManagerERC721.addTokenManager(newSchainName, deployer.address);
-        await tokenManagerERC721.connect(schainOwner).addERC721TokenByOwner(newSchainName,  token.address, tokenClone.address);
-        await tokenClone.connect(deployer).mint(deployer.address, tokenId);
+            const keyStorage2 = await deployKeyStorageMock();
+            messageProxyForSchain2 = await deployMessageProxyForSchainTester(keyStorage2.address, newSchainName);
+            tokenManagerLinker2 = await deployTokenManagerLinker(messageProxyForSchain2, deployer.address);
+            communityLocker2 = await deployCommunityLocker(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, fakeCommunityPool);
+            tokenManagerERC7212 = await deployTokenManagerERC721(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, communityLocker2, fakeDepositBox);
+            await erc721OnTargetChain.connect(deployer).grantRole(await erc721OnTargetChain.MINTER_ROLE(), tokenManagerERC7212.address);
+            await tokenManagerLinker2.registerTokenManager(tokenManagerERC7212.address);
+        });
 
-        await tokenManagerERC721
-            .connect(deployer)
-            .transferToSchainERC721(newSchainName, token.address, tokenId)
-            .should.be.eventually.rejectedWith("Not allowed ERC721 Token");
+        it("should invoke `transferToSchainERC721` without mistakes", async () => {
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address);
 
-        await tokenClone.connect(deployer).approve(tokenManagerERC721.address, tokenId);
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
 
-        await tokenManagerERC721
-            .connect(deployer)
-            .transferToSchainERC721(newSchainName, token.address, tokenId)
-            .should.be.eventually.rejectedWith("Sender contract is not registered");
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId);
 
-        await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address);
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
 
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC721.addTokenManager(newSchainName, tokenManagerERC7212.address);
+
+            // execution:
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId);
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+        });
+
+        it("should invoke `transferToSchainERC721` and receive tokens without mistakes", async () => {
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC721.addTokenManager(newSchainName, tokenManagerERC7212.address);
+
+            // execution:
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId);
+
+            const data = await messages.encodeTransferErc721AndTokenInfoMessage(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId,
+                {
+                    name: await erc721OnOriginChain.name(),
+                    symbol: await erc721OnOriginChain.symbol()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC7212.addTokenManager(schainName, tokenManagerERC721.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC7212.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            const addressERC721OnSchain = await tokenManagerERC7212.clonesErc721(schainId, erc721OnOriginChain.address);
+            const targetErc721OnChain = await (await ethers.getContractFactory("ERC721OnChain")).attach(addressERC721OnSchain) as ERC721OnChain;
+            expect((await targetErc721OnChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+        });
+
+        it("should invoke `transferToSchainERC721` and receive tokens without mistakes double", async () => {
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC721.addTokenManager(newSchainName, tokenManagerERC7212.address);
+
+            // execution:
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId);
+
+            let data = await messages.encodeTransferErc721AndTokenInfoMessage(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId,
+                {
+                    name: await erc721OnOriginChain.name(),
+                    symbol: await erc721OnOriginChain.symbol()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC7212.addTokenManager(schainName, tokenManagerERC721.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC7212.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            const addressERC721OnSchain = await tokenManagerERC7212.clonesErc721(schainId, erc721OnOriginChain.address);
+            const targetErc721OnChain = await (await ethers.getContractFactory("ERC721OnChain")).attach(addressERC721OnSchain) as ERC721OnChain;
+            expect((await targetErc721OnChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+            const tokenId2 = 2;
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId2);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId2);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId2);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            expect((await targetErc721OnChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+            expect((await targetErc721OnChain.functions.ownerOf(tokenId2)).toString()).to.be.equal(user.address);
+
+        });
+
+        it("should invoke `transferToSchainERC721` and receive tokens without mistakes double with attached token", async () => {
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC721.addTokenManager(newSchainName, tokenManagerERC7212.address);
+
+            // execution:
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId);
+
+            let data = await messages.encodeTransferErc721AndTokenInfoMessage(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId,
+                {
+                    name: await erc721OnOriginChain.name(),
+                    symbol: await erc721OnOriginChain.symbol()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+
+            await tokenManagerERC7212.connect(schainOwner).addERC721TokenByOwner(schainName,  erc721OnOriginChain.address, erc721OnTargetChain.address).should.be.eventually.rejectedWith("TOKEN_REGISTRAR_ROLE is required");
+            await tokenManagerERC7212.connect(deployer).grantRole(await tokenManagerERC7212.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerERC7212.connect(schainOwner).addERC721TokenByOwner(schainName,  erc721OnOriginChain.address, erc721OnTargetChain.address).should.be.eventually.rejectedWith("Chain is not connected");
+
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC7212.connect(schainOwner).addERC721TokenByOwner(schainName,  erc721OnOriginChain.address, erc721OnTargetChain.address);
+            await tokenManagerERC7212.addTokenManager(schainName, tokenManagerERC721.address);
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            expect((await erc721OnTargetChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+            const tokenId2 = 2;
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId2);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId2);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId2);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            expect((await erc721OnTargetChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+            expect((await erc721OnTargetChain.functions.ownerOf(tokenId2)).toString()).to.be.equal(user.address);
+
+        });
+
+        it("should invoke `transferToSchainERC721` and transfer back without mistakes", async () => {
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC721.addTokenManager(newSchainName, tokenManagerERC7212.address);
+
+            // execution:
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId);
+
+            let data = await messages.encodeTransferErc721AndTokenInfoMessage(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId,
+                {
+                    name: await erc721OnOriginChain.name(),
+                    symbol: await erc721OnOriginChain.symbol()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC7212.addTokenManager(schainName, tokenManagerERC721.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC7212.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            const addressERC721OnSchain = await tokenManagerERC7212.clonesErc721(schainId, erc721OnOriginChain.address);
+            const targetErc721OnChain = await (await ethers.getContractFactory("ERC721OnChain")).attach(addressERC721OnSchain) as ERC721OnChain;
+            expect((await targetErc721OnChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Not allowed ERC721 Token");
+
+            await targetErc721OnChain.connect(user).approve(tokenManagerERC7212.address, tokenId);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC7212.address);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC721.address, newSchainId, tokenManagerERC7212.address, data);
+            expect((await erc721OnOriginChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+        });
+
+        it("should invoke `transferToSchainERC721` and transfer back without mistakes with attached tokens", async () => {
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC721.addTokenManager(newSchainName, tokenManagerERC7212.address);
+
+            // execution:
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId);
+
+            let data = await messages.encodeTransferErc721AndTokenInfoMessage(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId,
+                {
+                    name: await erc721OnOriginChain.name(),
+                    symbol: await erc721OnOriginChain.symbol()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC7212.addTokenManager(schainName, tokenManagerERC721.address);
+
+            await tokenManagerERC7212.connect(deployer).grantRole(await tokenManagerERC7212.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerERC7212.connect(schainOwner).addERC721TokenByOwner(schainName,  erc721OnOriginChain.address, erc721OnTargetChain.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Not allowed ERC721 Token");
+
+            await erc721OnTargetChain.connect(user).approve(tokenManagerERC7212.address, tokenId);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC7212.address);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC721.address, newSchainId, tokenManagerERC7212.address, data);
+            expect((await erc721OnOriginChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+        });
+
+
+        it("should invoke `transferToSchainERC721` and transfer back without mistakes double", async () => {
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC721.addTokenManager(newSchainName, tokenManagerERC7212.address);
+
+            // execution:
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId);
+
+            let data = await messages.encodeTransferErc721AndTokenInfoMessage(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId,
+                {
+                    name: await erc721OnOriginChain.name(),
+                    symbol: await erc721OnOriginChain.symbol()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC7212.addTokenManager(schainName, tokenManagerERC721.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled");
+
+            await tokenManagerERC7212.enableAutomaticDeploy();
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            const addressERC721OnSchain = await tokenManagerERC7212.clonesErc721(schainId, erc721OnOriginChain.address);
+            const targetErc721OnChain = await (await ethers.getContractFactory("ERC721OnChain")).attach(addressERC721OnSchain) as ERC721OnChain;
+            expect((await targetErc721OnChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Not allowed ERC721 Token");
+
+            await targetErc721OnChain.connect(user).approve(tokenManagerERC7212.address, tokenId);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC7212.address);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC721.address, newSchainId, tokenManagerERC7212.address, data);
+            expect((await erc721OnOriginChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            expect((await targetErc721OnChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+            const tokenId2 = 2;
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId2);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId2);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId2);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            expect((await targetErc721OnChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+            expect((await targetErc721OnChain.functions.ownerOf(tokenId2)).toString()).to.be.equal(user.address);
+
+            await targetErc721OnChain.connect(user).approve(tokenManagerERC7212.address, tokenId);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC721.address, newSchainId, tokenManagerERC7212.address, data);
+            expect((await erc721OnOriginChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+            await targetErc721OnChain.connect(user).approve(tokenManagerERC7212.address, tokenId2);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId2);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId2
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC721.address, newSchainId, tokenManagerERC7212.address, data);
+
+            expect((await erc721OnOriginChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+            expect((await erc721OnOriginChain.functions.ownerOf(tokenId2)).toString()).to.be.equal(user.address);
+
+        });
+
+        it("should invoke `transferToSchainERC721` and transfer back without mistakes double with attached tokens", async () => {
+            await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address);
+
+            // add connected chain:
+            await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
+            await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName);
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC721.addTokenManager(newSchainName, tokenManagerERC7212.address);
+
+            // execution:
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId);
+
+            let data = await messages.encodeTransferErc721AndTokenInfoMessage(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId,
+                {
+                    name: await erc721OnOriginChain.name(),
+                    symbol: await erc721OnOriginChain.symbol()
+                }
+            );
+
+            // expectation:
+            const outgoingMessagesCounter = BigNumber.from(
+                await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName));
+            outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
+
+            // receive:
+            //  registration:
+            await messageProxyForSchain2.connect(deployer).addConnectedChain(schainName);
+            await tokenManagerERC7212.addTokenManager(schainName, tokenManagerERC721.address);
+
+            await tokenManagerERC7212.connect(deployer).grantRole(await tokenManagerERC7212.TOKEN_REGISTRAR_ROLE(), schainOwner.address);
+            await tokenManagerERC7212.connect(schainOwner).addERC721TokenByOwner(schainName,  erc721OnOriginChain.address, erc721OnTargetChain.address);
+
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Incorrect Token Manager address");
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Not allowed ERC721 Token");
+
+            await erc721OnTargetChain.connect(user).approve(tokenManagerERC7212.address, tokenId);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId)
+                .should.be.eventually.rejectedWith("Sender contract is not registered");
+
+            await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC7212.address);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC721.address, newSchainId, tokenManagerERC7212.address, data);
+            expect((await erc721OnOriginChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            expect((await erc721OnTargetChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+            const tokenId2 = 2;
+
+            await erc721OnOriginChain.connect(deployer).mint(user.address, tokenId2);
+            await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId2);
+
+            await tokenManagerERC721
+                .connect(user)
+                .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, tokenId2);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId2
+            );
+
+            await messageProxyForSchain2.postMessage(tokenManagerERC7212.address, schainId, tokenManagerERC721.address, data);
+
+            expect((await erc721OnTargetChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+            expect((await erc721OnTargetChain.functions.ownerOf(tokenId2)).toString()).to.be.equal(user.address);
+
+            await erc721OnTargetChain.connect(user).approve(tokenManagerERC7212.address, tokenId);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC721.address, newSchainId, tokenManagerERC7212.address, data);
+            expect((await erc721OnOriginChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+
+            await erc721OnTargetChain.connect(user).approve(tokenManagerERC7212.address, tokenId2);
+
+            await tokenManagerERC7212
+                .connect(user)
+                .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId2);
+
+            data = await messages.encodeTransferErc721Message(
+                erc721OnOriginChain.address,
+                user.address,
+                tokenId2
+            );
+
+            await messageProxyForSchain.postMessage(tokenManagerERC721.address, newSchainId, tokenManagerERC7212.address, data);
+
+            expect((await erc721OnOriginChain.functions.ownerOf(tokenId)).toString()).to.be.equal(user.address);
+            expect((await erc721OnOriginChain.functions.ownerOf(tokenId2)).toString()).to.be.equal(user.address);
+        });
 
-        // execution:
-        await tokenManagerERC721
-            .connect(deployer)
-            .transferToSchainERC721(newSchainName, token.address, tokenId);
-        // expectation:
-        const outgoingMessagesCounter = BigNumber.from(
-            await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)
-        );
-        outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1));
     });
 
     describe("tests for `postMessage` function", async () => {