Repository: skalenetwork/IMA (language: python)

Issue:
Enhancement/skale 4572 refactor srw beta



Discussion / hints:

Fix patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index d2cbc44a8..7c9ecc24e 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -37,7 +37,7 @@ jobs:
     - name: Set up Node
       uses: actions/setup-node@v2
       with:
-        node-version: '10'
+        node-version: '12'
 
     - name: Set up Python
       uses: actions/setup-python@v2
@@ -177,7 +177,7 @@ jobs:
         echo ------------ check lcov
         lcov --version || true
 
-    - name: NODE 10.x
+    - name: NODE 12.x
       run: |
         echo ------------ uninstall
         sudo apt-get remove nodejs || true
@@ -187,7 +187,7 @@ jobs:
         sudo rm -f /usr/bin/node || true
         sudo rm -f /usr/bin/npm || true
         echo ------------ download
-        curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
+        curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
         echo ------------ install
         sudo apt-get install nodejs
         echo ------------ node version check
@@ -294,7 +294,7 @@ jobs:
     - name: Set up Node
       uses: actions/setup-node@v2
       with:
-        node-version: '10'
+        node-version: '12'
 
     - name: Set up Python
       uses: actions/setup-python@v2
diff --git a/Dockerfile b/Dockerfile
index 3153f1153..92c01c459 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:10.18.0
+FROM node:12
 
 RUN mkdir /ima
 WORKDIR /ima
@@ -19,5 +19,4 @@ RUN cd npms/skale-owasp && yarn install && cd ../..
 RUN cd npms/skale-ima && yarn install && cd ../..
 RUN cd agent && yarn install && cd ..
 
-
 CMD ["bash", "/ima/agent/run.sh"]
diff --git a/README.md b/README.md
index fbf4ee6d6..def732ee6 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
 
 The IMA is still in active development and therefore should be regarded as _alpha software_. The development is still subject to further security hardening, testing, and breaking changes.
 
-**The proxy contracts have been reviewed and audited by a third-party for security.**
+**The proxy contracts have been reviewed and audited by a third-parties for security.**
 Please see [SECURITY.md](.github/SECURITY.md) for audit reports and reporting policies.
 
 ## Software Architecture
diff --git a/agent/bls.js b/agent/bls.js
index 548cf0814..27fb2687a 100644
--- a/agent/bls.js
+++ b/agent/bls.js
@@ -39,7 +39,7 @@ function discover_bls_threshold( joSChainNetworkInfo ) {
     const jarrNodes = imaState.joSChainNetworkInfo.network;
     for( let i = 0; i < jarrNodes.length; ++i ) {
         const joNode = jarrNodes[i];
-        if( "imaInfo" in joNode && typeof joNode.imaInfo === "object" &&
+        if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" &&
             "t" in joNode.imaInfo && typeof joNode.imaInfo.t === "number" &&
             joNode.imaInfo.t > 0
         )
@@ -52,7 +52,7 @@ function discover_bls_participants( joSChainNetworkInfo ) {
     const jarrNodes = imaState.joSChainNetworkInfo.network;
     for( let i = 0; i < jarrNodes.length; ++i ) {
         const joNode = jarrNodes[i];
-        if( "imaInfo" in joNode && typeof joNode.imaInfo === "object" &&
+        if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" &&
             "n" in joNode.imaInfo && typeof joNode.imaInfo.n === "number" &&
             joNode.imaInfo.n > 0
         )
@@ -64,7 +64,7 @@ function discover_bls_participants( joSChainNetworkInfo ) {
 function discover_public_key_by_index( nNodeIndex, joSChainNetworkInfo ) {
     const jarrNodes = imaState.joSChainNetworkInfo.network;
     const joNode = jarrNodes[nNodeIndex];
-    if( "imaInfo" in joNode && typeof joNode.imaInfo === "object" &&
+    if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" &&
         "BLSPublicKey0" in joNode.imaInfo && typeof joNode.imaInfo.BLSPublicKey0 === "string" && joNode.imaInfo.BLSPublicKey0.length > 0 &&
         "BLSPublicKey1" in joNode.imaInfo && typeof joNode.imaInfo.BLSPublicKey1 === "string" && joNode.imaInfo.BLSPublicKey1.length > 0 &&
         "BLSPublicKey2" in joNode.imaInfo && typeof joNode.imaInfo.BLSPublicKey2 === "string" && joNode.imaInfo.BLSPublicKey2.length > 0 &&
@@ -84,7 +84,7 @@ function discover_common_public_key( joSChainNetworkInfo ) {
     const jarrNodes = imaState.joSChainNetworkInfo.network;
     for( let i = 0; i < jarrNodes.length; ++i ) {
         const joNode = jarrNodes[i];
-        if( "imaInfo" in joNode && typeof joNode.imaInfo === "object" &&
+        if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" &&
             "commonBLSPublicKey0" in joNode.imaInfo && typeof joNode.imaInfo.commonBLSPublicKey0 === "string" && joNode.imaInfo.commonBLSPublicKey0.length > 0 &&
             "commonBLSPublicKey1" in joNode.imaInfo && typeof joNode.imaInfo.commonBLSPublicKey1 === "string" && joNode.imaInfo.commonBLSPublicKey1.length > 0 &&
             "commonBLSPublicKey2" in joNode.imaInfo && typeof joNode.imaInfo.commonBLSPublicKey2 === "string" && joNode.imaInfo.commonBLSPublicKey2.length > 0 &&
@@ -503,13 +503,19 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
     for( let i = 0; i < jarrNodes.length; ++i ) {
         const joNode = jarrNodes[i];
         const strNodeURL = imaUtils.compose_schain_node_url( joNode );
+        const strNodeDescColorized = cc.u( strNodeURL ) + " " +
+            cc.normal( "(" ) + cc.bright( i ) + cc.normal( "/" ) + cc.bright( jarrNodes.length ) + cc.normal( ", ID " ) + cc.info( joNode.nodeID ) + cc.normal( ")" );
         const rpcCallOpts = null;
         await rpcCall.create( strNodeURL, rpcCallOpts, async function( joCall, err ) {
             if( err ) {
                 ++nCountReceived; // including errors
                 ++nCountErrors;
-                log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to S-Chain failed" ) + "\n" );
-                details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to S-Chain failed" ) + "\n" );
+                const strErrorMessage =
+                    strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) +
+                    cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized +
+                    cc.error( " failed, RPC call was not created, error: " ) + cc.warning( err ) + "\n";
+                log.write( strErrorMessage );
+                details.write( strErrorMessage );
                 return;
             }
             let targetChainName = ""; let fromChainName = "";
@@ -534,18 +540,30 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
                 ++nCountReceived; // including errors
                 if( err ) {
                     ++nCountErrors;
-                    log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to S-Chain failed, error: " ) + cc.warning( err ) + "\n" );
-                    details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to S-Chain failed, error: " ) + cc.warning( err ) + "\n" );
+                    const strErrorMessage =
+                        strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) +
+                        cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized +
+                        cc.error( " failed, RPC call reported error: " ) + cc.warning( err ) + "\n";
+                    log.write( strErrorMessage );
+                    details.write( strErrorMessage );
                     return;
                 }
                 if( joOut.result == null || joOut.result == undefined || ( !typeof joOut.result == "object" ) ) {
                     ++nCountErrors;
                     if( "error" in joOut && "message" in joOut.error ) {
-                        log.write( strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " + cc.error( "S-Chain reported wallet error: " ) + cc.warning( joOut.error.message ) + "\n" );
-                        details.write( strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " + cc.error( "S-Chain reported wallet error: " ) + cc.warning( joOut.error.message ) + "\n" );
+                        const strErrorMessage =
+                            strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " +
+                            cc.error( "S-Chain node " ) + strNodeDescColorized +
+                            cc.error( " reported wallet error: " ) + cc.warning( joOut.error.message ) + "\n";
+                        log.write( strErrorMessage );
+                        details.write( strErrorMessage );
                     } else {
-                        log.write( strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " + cc.error( "JSON RPC call to S-Chain failed with " ) + cc.warning( "unknown wallet error" ) + "\n" );
-                        details.write( strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " + cc.error( "JSON RPC call to S-Chain failed with " ) + cc.warning( "unknown wallet error" ) + "\n" );
+                        const strErrorMessage =
+                            strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " +
+                            cc.error( "JSON RPC call to S-Chain node " ) + strNodeDescColorized +
+                            cc.error( " failed with " ) + cc.warning( "unknown wallet error" ) + "\n";
+                        log.write( strErrorMessage );
+                        details.write( strErrorMessage );
                     }
                     return;
                 }
@@ -577,8 +595,12 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
                                 details.write( strLogPrefixA + cc.fatal( "CRITICAL ERROR:" ) + " " + cc.error( strError ) + "\n" );
                             }
                         } catch ( err ) {
-                            log.write( strLogPrefixA + cc.fatal( "Node sign CRITICAL ERROR:" ) + cc.error( " partial signature fail from node " ) + cc.info( joNode.nodeID ) + cc.error( " with index " ) + cc.info( nZeroBasedNodeIndex ) + cc.error( ", error is " ) + cc.warning( err.toString() ) + "\n" );
-                            details.write( strLogPrefixA + cc.fatal( "Node sign CRITICAL ERROR:" ) + cc.error( " partial signature fail from node " ) + cc.info( joNode.nodeID ) + cc.error( " with index " ) + cc.info( nZeroBasedNodeIndex ) + cc.error( ", error is " ) + cc.warning( err.toString() ) + "\n" );
+                            const strErrorMessage =
+                                strLogPrefixA + cc.error( "S-Chain node " ) + strNodeDescColorized + cc.error( " sign " ) +
+                                cc.error( " CRITICAL ERROR:" ) + cc.error( " partial signature fail from with index " ) + cc.info( nZeroBasedNodeIndex ) +
+                                cc.error( ", error is " ) + cc.warning( err.toString() ) + "\n";
+                            log.write( strErrorMessage );
+                            details.write( strErrorMessage );
                         }
                         //
                         // sign result for bls_glue should look like:
@@ -602,8 +624,12 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
                     }
                 } catch ( err ) {
                     ++nCountErrors;
-                    log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " signature fail from node " ) + cc.info( joNode.nodeID ) + cc.error( ", error is " ) + cc.warning( err.toString() ) + "\n" );
-                    details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " signature fail from node " ) + cc.info( joNode.nodeID ) + cc.error( ", error is " ) + cc.warning( err.toString() ) + "\n" );
+                    const strErrorMessage =
+                        strLogPrefix + cc.error( "S-Chain node " ) + strNodeDescColorized + " " + cc.fatal( "CRITICAL ERROR:" ) +
+                        cc.error( " signature fail from node " ) + cc.info( joNode.nodeID ) +
+                        cc.error( ", error is " ) + cc.warning( err.toString() ) + "\n";
+                    log.write( strErrorMessage );
+                    details.write( strErrorMessage );
                 }
             } );
         } );
@@ -630,15 +656,26 @@ async function do_sign_messages_impl( strDirection, jarrMessages, nIdxCurrentMsg
                 }
             } else {
                 strError = "BLS glue failed";
-                log.write( strLogPrefixB + cc.fatal( "CRITICAL ERROR:" ) + " " + cc.error( strError ) + "\n" );
-                details.write( strLogPrefixB + cc.fatal( "CRITICAL ERROR:" ) + " " + cc.error( strError ) + "\n" );
+                const strErrorMessage =
+                    strLogPrefixB + cc.error( "S-Chain node " ) + strNodeDescColorized + " " +
+                    cc.fatal( "CRITICAL ERROR:" ) + " " + cc.error( strError ) + "\n";
+                log.write( strErrorMessage );
+                details.write( strErrorMessage );
             }
-            await fn( strError, jarrMessages, joGlueResult );
+            await fn( strError, jarrMessages, joGlueResult ).catch( ( err ) => {
+                const strErrorMessage = cc.error( "Problem(1) in BLS sign result handler: " ) + cc.warning( err ) + "\n";
+                log.write( strErrorMessage );
+                details.write( strErrorMessage );
+            } );
             return;
         }
         if( nCountReceived >= jarrNodes.length ) {
             clearInterval( iv );
-            await fn( "signature error in " + nCountErrors + " node(s) of " + jarrNodes.length + " node(s)", jarrMessages, null );
+            await fn( "signature error in " + nCountErrors + " node(s) of " + jarrNodes.length + " node(s)", jarrMessages, null ).catch( ( err ) => {
+                const strErrorMessage = cc.error( "Problem(2) in BLS sign result handler: " ) + cc.warning( err ) + "\n";
+                log.write( strErrorMessage );
+                details.write( strErrorMessage );
+            } );
         }
     }, 100 );
 }
diff --git a/agent/cli.js b/agent/cli.js
index 5cca330c5..2095dcb03 100644
--- a/agent/cli.js
+++ b/agent/cli.js
@@ -346,7 +346,12 @@ function parse( joExternalHandlers, argv ) {
             console.log( soi + cc.debug( "--" ) + cc.bright( "reimbursement-withdraw" ) + cc.sunny( "=" ) + cc.note( "v" ) + cc.warning( "u" ) + cc.debug( "....." ) + cc.notice( "Withdraw user wallet with specified value " ) + cc.attention( "v" ) + cc.notice( ", unit name " ) + cc.attention( "u" ) + cc.notice( " is well known Ethereum unit name like " ) + cc.attention( "ether" ) + cc.notice( " or " ) + cc.attention( "wei" ) + cc.notice( "." ) );
             console.log( soi + cc.debug( "--" ) + cc.bright( "reimbursement-balance" ) + cc.debug( "........." ) + cc.notice( "Show wallet balance." ) );
             console.log( soi + cc.debug( "--" ) + cc.bright( "reimbursement-range" ) + cc.sunny( "=" ) + cc.note( "number" ) + cc.debug( "...." ) + cc.notice( "Sets minimal time interval between transfers from S-Chain to Main Net." ) );
-
+            //
+            console.log( cc.sunny( "PAST EVENTS SCAN" ) + cc.info( " options:" ) );
+            console.log( soi + cc.debug( "--" ) + cc.bright( "bs-step-size" ) + cc.sunny( "=" ) + cc.note( "number" ) + cc.debug( "..........." ) + cc.notice( "Specifies step block range size to search iterative past events step by step. Zero to disable iterative search." ) );
+            console.log( soi + cc.debug( "--" ) + cc.bright( "bs-max-all-range" ) + cc.sunny( "=" ) + cc.note( "number" ) + cc.debug( "......." ) + cc.notice( "Specifies max number of steps to allow to search as [0...latest] range. Zero to disable iterative search." ) );
+            console.log( soi + cc.debug( "--" ) + cc.bright( "bs-progressive-enable" ) + cc.debug( "........." ) + cc.notice( "Enables progressive block scan to search past events." ) );
+            console.log( soi + cc.debug( "--" ) + cc.bright( "bs-progressive-disable" ) + cc.debug( "........" ) + cc.notice( "Disables progressive block scan to search past events." ) );
             //
             console.log( cc.sunny( "TEST" ) + cc.info( " options:" ) );
             console.log( soi + cc.debug( "--" ) + cc.bright( "browse-s-chain" ) + cc.debug( "................" ) + cc.notice( "Download S-Chain network information." ) );
@@ -908,6 +913,24 @@ function parse( joExternalHandlers, argv ) {
             imaState.nReimbursementRange = owaspUtils.toInteger( joArg.value );
             continue;
         }
+        if( joArg.name == "bs-step-size" ) {
+            owaspUtils.verifyArgumentIsInteger( joArg );
+            IMA.setBlocksCountInInIterativeStepOfEventsScan( owaspUtils.toInteger( joArg.value ) );
+            continue;
+        }
+        if( joArg.name == "bs-max-all-range" ) {
+            owaspUtils.verifyArgumentIsInteger( joArg );
+            IMA.setMaxIterationsInAllRangeEventsScan( owaspUtils.toInteger( joArg.value ) );
+            continue;
+        }
+        if( joArg.name == "bs-progressive-enable" ) {
+            IMA.setEnabledProgressiveEventsScan( true );
+            continue;
+        }
+        if( joArg.name == "bs-progressive-disable" ) {
+            IMA.setEnabledProgressiveEventsScan( false );
+            continue;
+        }
         if( joArg.name == "register" ||
             joArg.name == "register1" ||
             joArg.name == "check-registration" ||
@@ -940,7 +963,23 @@ function getWeb3FromURL( strURL ) {
         const u = cc.safeURL( strURL );
         const strProtocol = u.protocol.trim().toLowerCase().replace( ":", "" ).replace( "/", "" );
         if( strProtocol == "ws" || strProtocol == "wss" ) {
-            const w3ws = new w3mod.providers.WebsocketProvider( strURL );
+            const w3ws = new w3mod.providers.WebsocketProvider( strURL, {
+                // see: https://github.com/ChainSafe/web3.js/tree/1.x/packages/web3-providers-ws#usage
+                clientConfig: {
+                    // // if requests are large:
+                    // maxReceivedFrameSize: 100000000,   // bytes - default: 1MiB
+                    // maxReceivedMessageSize: 100000000, // bytes - default: 8MiB
+                    // keep a connection alive
+                    keepalive: true,
+                    keepaliveInterval: 200000 // ms
+                },
+                reconnect: { // enable auto reconnection
+                    auto: true,
+                    delay: 5000, // ms
+                    maxAttempts: 10000000, // 10 million times
+                    onTimeout: false
+                }
+            } );
             w3 = new w3mod( w3ws );
         } else {
             const w3http = new w3mod.providers.HttpProvider( strURL );
@@ -956,6 +995,8 @@ function getWeb3FromURL( strURL ) {
 }
 
 function ima_common_init() {
+    log.write( cc.info( "This process " ) + cc.sunny( "PID" ) + cc.info( " is " ) + cc.bright( process.pid ) + "\n" );
+
     let n1 = 0;
     let n2 = 0;
     imaState.joTrufflePublishResult_main_net = imaUtils.jsonFileLoad( imaState.strPathAbiJson_main_net, null );
diff --git a/agent/main.js b/agent/main.js
index 8391629be..0b367933a 100644
--- a/agent/main.js
+++ b/agent/main.js
@@ -202,7 +202,7 @@ global.imaState = {
     },
 
     "optsStateFile": {
-        "isEnabled": true,
+        "isEnabled": false, // true
         "path": "./ima.state.json"
     },
 
@@ -214,6 +214,11 @@ global.imaState = {
     "nReimbursementWithdraw": 0,
     "nReimbursementRange": -1, // < 0 - do not change anything
 
+    "joSChainDiscovery": {
+        "isSilentReDiscovery": true,
+        "repeatIntervalMilliseconds": 10 * 1000 // zero to disable (for debugging only)
+    },
+
     "arrActions": [] // array of actions to run
 };
 
@@ -874,7 +879,9 @@ imaCLI.parse( {
                     }
                     await joCall.call( {
                         "method": "skale_nodesRpcInfo",
-                        "params": { }
+                        "params": {
+                            "fromImaAgentIndex": imaState.nNodeNumber
+                        }
                     }, async function( joIn, joOut, err ) {
                         if( err ) {
                             console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to S-Chain failed, error: " ) + cc.warning( err ) );
@@ -885,6 +892,12 @@ imaCLI.parse( {
                         const jarrNodes = joOut.result.network;
                         for( let i = 0; i < jarrNodes.length; ++ i ) {
                             const joNode = jarrNodes[i];
+                            if( ! joNode ) {
+                                log.write(
+                                    strLogPrefix + cc.error( "Discovery node " ) + cc.info( i ) +
+                                    cc.error( " is completely unknown and will be skipped" ) + "\n" );
+                                continue;
+                            }
                             const strNodeURL = imaUtils.compose_schain_node_url( joNode );
                             const rpcCallOpts = null;
                             await rpcCall.create( strNodeURL, rpcCallOpts, async function( joCall, err ) {
@@ -894,7 +907,9 @@ imaCLI.parse( {
                                 }
                                 await joCall.call( {
                                     "method": "skale_imaInfo",
-                                    "params": { }
+                                    "params": {
+                                        "fromImaAgentIndex": imaState.nNodeNumber
+                                    }
                                 }, function( joIn, joOut, err ) {
                                     ++ nCountReceivedImaDescriptions;
                                     if( err ) {
@@ -1066,7 +1081,7 @@ function get_s_chain_discovered_nodes_count( joSChainNetworkInfo ) {
 let g_timer_s_chain_discovery = null;
 let g_b_in_s_chain_discovery = false;
 
-async function continue_schain_discovery_in_background_if_needed() {
+async function continue_schain_discovery_in_background_if_needed( isSilent ) {
     const cntNodes = get_s_chain_nodes_count( imaState.joSChainNetworkInfo );
     const cntDiscovered = get_s_chain_discovered_nodes_count( imaState.joSChainNetworkInfo );
     if( cntDiscovered >= cntNodes ) {
@@ -1078,25 +1093,77 @@ async function continue_schain_discovery_in_background_if_needed() {
     }
     if( g_timer_s_chain_discovery != null )
         return;
+    if( imaState.joSChainDiscovery.repeatIntervalMilliseconds <= 0 )
+        return; // no S-Chain re-discovery (for debugging only)
     g_timer_s_chain_discovery = setInterval( async function() {
-        if( g_b_in_s_chain_discovery )
+        if( g_b_in_s_chain_discovery ) {
+            if( IMA.verbose_get() >= IMA.RV_VERBOSE.information )
+                log.write( cc.warning( "Notice: long S-Chain discovery is in progress" ) + "\n" );
             return;
+        }
         g_b_in_s_chain_discovery = true;
         try {
-            if( IMA.verbose_get() >= IMA.RV_VERBOSE.information )
-                log.write( cc.info( "Will re-discover S-Chain network..." ) + "\n" );
+            if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) {
+                log.write(
+                    cc.info( "Will re-discover " ) + cc.notice( cntNodes ) + cc.info( "-node S-Chain network, " ) +
+                    cc.notice( cntDiscovered ) + cc.info( " node(s) already discovered..." ) + "\n" );
+            }
             await discover_s_chain_network( function( err, joSChainNetworkInfo ) {
                 if( ! err ) {
-                    if( IMA.verbose_get() >= IMA.RV_VERBOSE.information )
-                        log.write( cc.success( "S-Chain network was re-discovered: " ) + cc.j( joSChainNetworkInfo ) + "\n" );
+                    const cntDiscoveredNew = get_s_chain_discovered_nodes_count( joSChainNetworkInfo );
+                    if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) {
+                        const strDiscoveryStatus = cc.info( cntDiscoveredNew ) + cc.success( " nodes known" );
+                        let strMessage =
+                            cc.success( "S-Chain network was re-discovered, " ) + cc.info( cntDiscoveredNew ) +
+                            cc.success( " of " ) + cc.info( cntNodes ) +
+                            cc.success( " node(s) (" ) + strDiscoveryStatus + cc.success( ")" );
+                        const cntStillUnknown = cntNodes - cntDiscoveredNew;
+                        if( cntStillUnknown > 0 ) {
+                            strMessage += cc.success( ", " ) +
+                                cc.info( cntStillUnknown ) + cc.success( " of " ) + cc.info( cntNodes ) +
+                                cc.success( " still unknown (" );
+                            try {
+                                const jarrNodes = joSChainNetworkInfo.network;
+                                let cntBad = 0;
+                                for( let i = 0; i < jarrNodes.length; ++i ) {
+                                    const joNode = jarrNodes[i];
+                                    try {
+                                        if( ! ( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" &&
+                                            "t" in joNode.imaInfo && typeof joNode.imaInfo.t === "number" ) ) {
+                                            if( cntBad > 0 )
+                                                strMessage += cc.success( ", " );
+                                            const strNodeURL = imaUtils.compose_schain_node_url( joNode );
+                                            const strNodeDescColorized =
+                                                cc.notice( "#" ) + cc.info( i ) +
+                                                cc.attention( "(" ) + cc.u( strNodeURL ) + cc.attention( ")" );
+                                            strMessage += strNodeDescColorized;
+                                            ++ cntBad;
+                                        }
+                                    } catch ( err ) { }
+                                }
+                            } catch ( err ) { }
+                            strMessage += cc.success( ")" );
+                        }
+                        if( ! isSilent ) {
+                            strMessage +=
+                                cc.success( ", complete re-discovered S-Chain network info: " ) +
+                                cc.j( joSChainNetworkInfo );
+                        }
+                        log.write( strMessage + "\n" );
+                    }
                     imaState.joSChainNetworkInfo = joSChainNetworkInfo;
                 }
-                continue_schain_discovery_in_background_if_needed();
-            }, false, imaState.joSChainNetworkInfo, cntNodes );
-        } catch ( err ) {
-        }
+                continue_schain_discovery_in_background_if_needed( isSilent );
+            }, isSilent, imaState.joSChainNetworkInfo, cntNodes ).catch( ( err ) => {
+                log.write(
+                    cc.fatal( "CRITICAL ERROR:" ) +
+                    cc.error( " S-Chain network re-discovery failed: " ) +
+                    cc.warning( err ) + "\n"
+                );
+            } );
+        } catch ( err ) { }
         g_b_in_s_chain_discovery = false;
-    }, 1 * 1000 );
+    }, imaState.joSChainDiscovery.repeatIntervalMilliseconds );
 }
 
 async function discover_s_chain_network( fnAfter, isSilent, joPrevSChainNetworkInfo, nCountToWait ) {
@@ -1104,7 +1171,7 @@ async function discover_s_chain_network( fnAfter, isSilent, joPrevSChainNetworkI
     joPrevSChainNetworkInfo = joPrevSChainNetworkInfo || null;
     if( nCountToWait == null || nCountToWait == undefined || nCountToWait < 0 )
         nCountToWait = 0;
-    const strLogPrefix = cc.info( "S net discover:" ) + " ";
+    const strLogPrefix = cc.info( "S-Chain network discovery:" ) + " ";
     fnAfter = fnAfter || function() {};
     let joSChainNetworkInfo = null;
     const rpcCallOpts = null;
@@ -1123,7 +1190,9 @@ async function discover_s_chain_network( fnAfter, isSilent, joPrevSChainNetworkI
             }
             await joCall.call( {
                 "method": "skale_nodesRpcInfo",
-                "params": { }
+                "params": {
+                    "fromImaAgentIndex": imaState.nNodeNumber
+                }
             }, async function( joIn, joOut, err ) {
                 if( err ) {
                     if( ! isSilent ) {
@@ -1137,7 +1206,7 @@ async function discover_s_chain_network( fnAfter, isSilent, joPrevSChainNetworkI
                     return;
                 }
                 if( ( !isSilent ) && IMA.verbose_get() >= IMA.RV_VERBOSE.trace )
-                    log.write( strLogPrefix + cc.normal( "OK, got (own) S-Chain network information: " ) + cc.j( joOut.result ) + "\n" );
+                    log.write( strLogPrefix + cc.debug( "OK, got (own) S-Chain network information: " ) + cc.j( joOut.result ) + "\n" );
                 else if( ( !isSilent ) && IMA.verbose_get() >= IMA.RV_VERBOSE.information )
                     log.write( strLogPrefix + cc.success( "OK, got S-Chain " ) + cc.u( imaState.strURL_s_chain ) + cc.success( " network information." ) + "\n" );
                 //
@@ -1170,12 +1239,18 @@ async function discover_s_chain_network( fnAfter, isSilent, joPrevSChainNetworkI
                 let cntFailed = 0;
                 for( let i = 0; i < cntNodes; ++ i ) {
                     const nCurrentNodeIdx = 0 + i;
+                    const joNode = jarrNodes[nCurrentNodeIdx];
+                    const strNodeURL = imaUtils.compose_schain_node_url( joNode );
+                    const strNodeDescColorized =
+                        cc.notice( "#" ) + cc.info( nCurrentNodeIdx ) +
+                        cc.attention( "(" ) + cc.u( strNodeURL ) + cc.attention( ")" );
                     try {
                         if( joPrevSChainNetworkInfo && "network" in joPrevSChainNetworkInfo && joPrevSChainNetworkInfo.network ) {
                             const joPrevNode = joPrevSChainNetworkInfo.network[nCurrentNodeIdx];
                             if( joPrevNode && "imaInfo" in joPrevNode && typeof joPrevNode.imaInfo === "object" &&
                                 "t" in joPrevNode.imaInfo && typeof joPrevNode.imaInfo.t === "number"
                             ) {
+                                joNode.imaInfo = JSON.parse( JSON.stringify( joPrevNode.imaInfo ) );
                                 if( ( !isSilent ) && IMA.verbose_get() >= IMA.RV_VERBOSE.information ) {
                                     log.write(
                                         strLogPrefix + cc.info( "OK, in case of " ) + strNodeDescColorized +
@@ -1188,11 +1263,6 @@ async function discover_s_chain_network( fnAfter, isSilent, joPrevSChainNetworkI
                         }
                     } catch ( err ) {
                     }
-                    const joNode = jarrNodes[nCurrentNodeIdx];
-                    const strNodeURL = imaUtils.compose_schain_node_url( joNode );
-                    const strNodeDescColorized =
-                        cc.notice( "#" ) + cc.info( nCurrentNodeIdx ) +
-                        cc.attention( "(" ) + cc.u( strNodeURL ) + + cc.attention( ")" );
                     const rpcCallOpts = null;
                     try {
                         await rpcCall.create( strNodeURL, rpcCallOpts, function( joCall, err ) {
@@ -1210,7 +1280,9 @@ async function discover_s_chain_network( fnAfter, isSilent, joPrevSChainNetworkI
                             }
                             joCall.call( {
                                 "method": "skale_imaInfo",
-                                "params": { }
+                                "params": {
+                                    "fromImaAgentIndex": imaState.nNodeNumber
+                                }
                             }, function( joIn, joOut, err ) {
                                 ++ nCountReceivedImaDescriptions;
                                 if( err ) {
@@ -1285,14 +1357,19 @@ async function discover_s_chain_network( fnAfter, isSilent, joPrevSChainNetworkI
                     );
                 }
                 let nWaitAttempt = 0;
-                const cntWaitAttempts = 300;
+                const nWaitStepMilliseconds = 1000;
+                let cntWaitAttempts = Math.floor( imaState.joSChainDiscovery.repeatIntervalMilliseconds / nWaitStepMilliseconds ) - 3;
+                if( cntWaitAttempts < 1 )
+                    cntWaitAttempts = 1;
                 const iv = setInterval( function() {
                     nCountAvailable = cntNodes - cntFailed;
                     if( ! isSilent ) {
                         log.write(
-                            cc.debug( "Waiting for S-Chain nodes, total " ) + cc.warning( cntNodes ) +
-                            cc.debug( ", available " ) + cc.warning( nCountAvailable ) +
-                            cc.debug( ", expected at least " ) + cc.warning( nCountToWait ) +
+                            cc.debug( "Waiting attempt " ) +
+                            cc.info( nWaitAttempt ) + cc.debug( " of " ) + cc.info( cntWaitAttempts ) +
+                            cc.debug( " for S-Chain nodes, total " ) + cc.info( cntNodes ) +
+                            cc.debug( ", available " ) + cc.info( nCountAvailable ) +
+                            cc.debug( ", expected at least " ) + cc.info( nCountToWait ) +
                             "\n"
                         );
                     }
@@ -1302,35 +1379,33 @@ async function discover_s_chain_network( fnAfter, isSilent, joPrevSChainNetworkI
                             cc.info( nCountReceivedImaDescriptions ) + cc.debug( " node(s)." ) + "\n"
                         );
                     }
-                    if( nCountReceivedImaDescriptions >= nCountToWait ) {
-                        clearInterval( iv );
-                        fnAfter( null, joSChainNetworkInfo );
-                        return;
-                    }
+                    // if( nCountReceivedImaDescriptions >= nCountToWait ) {
+                    //     clearInterval( iv );
+                    //     fnAfter( null, joSChainNetworkInfo );
+                    //     return;
+                    // }
                     ++ nWaitAttempt;
-                    if( nWaitAttempt > cntWaitAttempts ) {
-                        if( ! isSilent ) {
-                            log.write(
-                                strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) +
-                                cc.error( " S-Chain network discovery wait timeout" ) +
-                                "\n"
-                            );
-                        }
-                        const err = new Error(
-                            "S-Chain network discovery wait timeout"
-                        );
-                        fnAfter( err, null );
+                    if( nWaitAttempt >= cntWaitAttempts ) {
+                        clearInterval( iv );
+                        const strErrorDescription = "S-Chain network discovery wait timeout, network will be re-discovered";
+                        if( ! isSilent )
+                            log.write( strLogPrefix + cc.error( "WARNING:" ) + " " + cc.warning( strErrorDescription ) + "\n" );
+                        if( get_s_chain_discovered_nodes_count( joSChainNetworkInfo ) > 0 )
+                            fnAfter( null, joSChainNetworkInfo );
+                        else
+                            fnAfter( new Error( strErrorDescription ), null );
                         return;
                     }
                     if( ! isSilent ) {
                         log.write(
-                            strLogPrefix + cc.debug( " Waiting for " ) +
-                            cc.notice( nCountToWait - nCountReceivedImaDescriptions ) +
+                            strLogPrefix + cc.debug( " Waiting attempt " ) +
+                            cc.info( nWaitAttempt ) + cc.debug( " of " ) + cc.info( cntWaitAttempts ) +
+                            cc.debug( " for " ) + cc.notice( nCountToWait - nCountReceivedImaDescriptions ) +
                             cc.debug( " node answer(s)" ) +
                             "\n"
                         );
                     }
-                }, 1000 );
+                }, nWaitStepMilliseconds );
             } );
         } );
     } catch ( err ) {
@@ -1524,6 +1599,7 @@ if( imaState.bSignMessages ) {
         process.exit( 160 );
     }
     if( ! imaState.bNoWaitSChainStarted ) {
+        const isSilent = imaState.joSChainDiscovery.isSilentReDiscovery;
         wait_until_s_chain_started().then( function() { // uses call to discover_s_chain_network()
             discover_s_chain_network( function( err, joSChainNetworkInfo ) {
                 if( err )
@@ -1531,10 +1607,16 @@ if( imaState.bSignMessages ) {
                 if( IMA.verbose_get() >= IMA.RV_VERBOSE.information )
                     log.write( cc.success( "S-Chain network was discovered: " ) + cc.j( joSChainNetworkInfo ) + "\n" );
                 imaState.joSChainNetworkInfo = joSChainNetworkInfo;
-                continue_schain_discovery_in_background_if_needed();
+                continue_schain_discovery_in_background_if_needed( isSilent );
                 do_the_job();
                 return 0; // FINISH
-            }, false, imaState.joSChainNetworkInfo, -1 );
+            }, isSilent, imaState.joSChainNetworkInfo, -1 ).catch( ( err ) => {
+                log.write(
+                    cc.fatal( "CRITICAL ERROR:" ) +
+                    cc.error( " S-Chain network discovery failed: " ) +
+                    cc.warning( err ) + "\n"
+                );
+            } );
         } );
     }
 } else
@@ -1783,7 +1865,13 @@ async function wait_until_s_chain_started() {
             const joSChainNetworkInfo = await discover_s_chain_network( function( err, joSChainNetworkInfo ) {
                 if( ! err )
                     bSuccess = true;
-            }, true, null, -1 );
+            }, true, null, -1 ).catch( ( err ) => {
+                log.write(
+                    cc.fatal( "CRITICAL ERROR:" ) +
+                    cc.error( " S-Chain network discovery failed: " ) +
+                    cc.warning( err ) + "\n"
+                );
+            } );
             if( ! joSChainNetworkInfo )
                 bSuccess = false;
         } catch ( err ) {
diff --git a/agent/package.json b/agent/package.json
index 422a23411..0d640d202 100644
--- a/agent/package.json
+++ b/agent/package.json
@@ -10,10 +10,10 @@
         "colors": "^1.4.0",
         "ethereumjs-tx": "2.1.2",
         "ethereumjs-wallet": "1.0.1",
-        "ethereumjs-util": "7.0.10",
+        "ethereumjs-util": "7.1.0",
         "web3": "^1.4.0",
         "uuid": "8.3.2",
-        "ws": "^7.5.2",
+        "ws": "^7.5.3",
         "request": "^2.88.2",
         "sha3": "2.1.4",
         "shelljs": "0.8.4"
diff --git a/agent/yarn.lock b/agent/yarn.lock
index 490fd24f0..641803706 100644
--- a/agent/yarn.lock
+++ b/agent/yarn.lock
@@ -957,10 +957,10 @@ ethereumjs-tx@2.1.2:
     ethereumjs-common "^1.5.0"
     ethereumjs-util "^6.0.0"
 
-ethereumjs-util@7.0.10, ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2:
-  version "7.0.10"
-  resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz#5fb7b69fa1fda0acc59634cf39d6b0291180fc1f"
-  integrity sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==
+ethereumjs-util@7.1.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz#e2b43a30bfcdbcb432a4eb42bd5f2393209b3fd5"
+  integrity sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw==
   dependencies:
     "@types/bn.js" "^5.1.0"
     bn.js "^5.1.2"
@@ -982,6 +982,18 @@ ethereumjs-util@^6.0.0:
     ethjs-util "0.1.6"
     rlp "^2.2.3"
 
+ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2:
+  version "7.0.10"
+  resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz#5fb7b69fa1fda0acc59634cf39d6b0291180fc1f"
+  integrity sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==
+  dependencies:
+    "@types/bn.js" "^5.1.0"
+    bn.js "^5.1.2"
+    create-hash "^1.1.2"
+    ethereum-cryptography "^0.1.3"
+    ethjs-util "0.1.6"
+    rlp "^2.2.4"
+
 ethereumjs-wallet@1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-1.0.1.tgz#664a4bcacfc1291ca2703de066df1178938dba1c"
@@ -2771,10 +2783,10 @@ ws@^3.0.0:
     safe-buffer "~5.1.0"
     ultron "~1.1.0"
 
-ws@^7.5.2:
-  version "7.5.2"
-  resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.2.tgz#09cc8fea3bec1bc5ed44ef51b42f945be36900f6"
-  integrity sha512-lkF7AWRicoB9mAgjeKbGqVUekLnSNO4VjKVnuPHpQeOxZOErX6BPXwJk70nFslRCEEA8EVW7ZjKwXaP9N+1sKQ==
+ws@^7.5.3:
+  version "7.5.3"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74"
+  integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==
 
 xhr-request-promise@^0.1.2:
   version "0.1.3"
diff --git a/npms/skale-cc/cc.js b/npms/skale-cc/cc.js
index d462807e5..98779a5ca 100644
--- a/npms/skale-cc/cc.js
+++ b/npms/skale-cc/cc.js
@@ -87,31 +87,24 @@ function url_obj_colorized( objURL ) {
     let strURL = "";
     if( !objURL )
         return strURL;
-
     // if( objURL.strStrippedStringComma )
     //     strURL += module.exports.normal(objURL.strStrippedStringComma);
-    if( objURL.protocol )
+    if( objURL.protocol && objURL.protocol !== null && objURL.protocol !== undefined )
         strURL += "" + module.exports.yellow( objURL.protocol ) + module.exports.normal( "//" );
-
-    if( objURL.username ) {
+    if( objURL.username && objURL.username !== null && objURL.username !== undefined ) {
         strURL += "" + module.exports.magenta( objURL.username );
-        if( objURL.password )
+        if( objURL.password && objURL.password !== null && objURL.password !== undefined )
             strURL += module.exports.normal( ":" ) + module.exports.yellow( objURL.password );
-
         strURL += module.exports.normal( "@" );
     }
     if( objURL.hostname )
         strURL += "" + module.exports.magenta( log_arg_to_str_as_ipv4( objURL.hostname ) );
-
-    if( objURL.port )
+    if( objURL.port && objURL.port !== null && objURL.port !== undefined )
         strURL += module.exports.normal( ":" ) + log_arg_to_str( objURL.port );
-
-    if( objURL.pathname )
+    if( objURL.pathname && objURL.pathname !== null && objURL.pathname !== undefined && objURL.pathname !== "/" )
         strURL += "" + module.exports.yellow( replaceAll( objURL.pathname, "/", module.exports.normal( "/" ) ) );
-
-    if( objURL.search )
+    if( objURL.search && objURL.search !== null && objURL.search !== undefined )
         strURL += "" + module.exports.magenta( objURL.search );
-
     // if( objURL.strStrippedStringComma )
     //     strURL += module.exports.normal(objURL.strStrippedStringComma);
     return strURL;
@@ -121,14 +114,12 @@ function url_str_colorized( s ) {
     const objURL = safeURL( s );
     if( !objURL )
         return "";
-
     return url_obj_colorized( objURL );
 }
 
 function url_colorized( x ) {
     if( typeof x === "string" || x instanceof String )
         return url_str_colorized( x );
-
     return url_obj_colorized( x );
 }
 
@@ -212,6 +203,10 @@ function log_arg_to_str() {
             s += "" + module.exports.nullval( arg );
             continue;
         }
+        if( isNaN( arg ) ) {
+            s += "" + module.exports.nanval( arg );
+            continue;
+        }
         if( typeof arg === "boolean" ) {
             s += "" + _tf_( arg );
             continue;
@@ -624,6 +619,11 @@ module.exports = {
             return s;
         return "" + this.fgGreen + this.enlight + s + this.reset;
     },
+    nanval: function( s ) {
+        if( !g_bEnabled )
+            return s;
+        return "" + this.fgGreen + this.enlight + s + this.reset;
+    },
     yellow: function( s ) {
         if( !g_bEnabled )
             return s;
diff --git a/npms/skale-ima/index.js b/npms/skale-ima/index.js
index f0552d3df..1c7da9f89 100644
--- a/npms/skale-ima/index.js
+++ b/npms/skale-ima/index.js
@@ -153,96 +153,89 @@ const sleep = ( milliseconds ) => { return new Promise( resolve => setTimeout( r
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-function parseIntSafer( s ) {
-    s = s.trim();
-    if( s.length > 2 && s[0] == "0" && ( s[1] == "x" || s[1] == "X" ) )
-        return parseInt( s, 10 );
-    return parseInt( s, 16 );
-}
-
 async function wait_for_next_block_to_appear( details, w3 ) {
     const nBlockNumber = await get_web3_blockNumber( details, 10, w3 );
     details.write( cc.debug( "Waiting for next block to appear..." ) + "\n" );
-    details.write( cc.debug( "    ...have block " ) + cc.info( parseIntSafer( nBlockNumber ) ) + "\n" );
+    details.write( cc.debug( "    ...have block " ) + cc.info( parseIntOrHex( nBlockNumber ) ) + "\n" );
     for( ; true; ) {
         await sleep( 1000 );
         const nBlockNumber2 = await get_web3_blockNumber( details, 10, w3 );
-        details.write( cc.debug( "    ...have block " ) + cc.info( parseIntSafer( nBlockNumber2 ) ) + "\n" );
+        details.write( cc.debug( "    ...have block " ) + cc.info( parseIntOrHex( nBlockNumber2 ) ) + "\n" );
         if( nBlockNumber2 > nBlockNumber )
             break;
     }
 }
 
 async function get_web3_blockNumber( details, attempts, w3 ) {
-    const allAttempts = parseInt( attempts ) < 1 ? 1 : parseInt( attempts );
+    const cntAttempts = parseIntOrHex( attempts ) < 1 ? 1 : parseIntOrHex( attempts );
     let nLatestBlockNumber = "";
     try {
         nLatestBlockNumber = await w3.eth.getBlockNumber();
     } catch ( e ) {}
-    let attemptIndex = 2;
-    while( nLatestBlockNumber === "" && attemptIndex <= allAttempts ) {
+    let idxAttempt = 2;
+    while( nLatestBlockNumber === "" && idxAttempt <= cntAttempts ) {
         details.write(
-            cc.warning( "Repeat " ) + cc.error( "getBlockNumber" ) + cc.warning( ", attempt " ) + cc.info( attemptIndex ) +
+            cc.warning( "Repeat " ) + cc.error( "getBlockNumber" ) + cc.warning( ", attempt " ) + cc.info( idxAttempt ) +
             cc.info( ", previous result is: " ) + cc.info( nLatestBlockNumber ) + "\n" );
         await sleep( 10000 );
         try {
             nLatestBlockNumber = await w3.eth.getBlockNumber();
         } catch ( e ) {}
-        attemptIndex++;
+        idxAttempt++;
     }
-    if( attemptIndex + 1 > allAttempts && nLatestBlockNumber === "" )
+    if( idxAttempt + 1 > cntAttempts && nLatestBlockNumber === "" )
         throw new Error( "Could not not get blockNumber" );
     return nLatestBlockNumber;
 }
 
 async function get_web3_transactionCount( details, attempts, w3, address, param ) {
-    const allAttempts = parseInt( attempts ) < 1 ? 1 : parseInt( attempts );
+    const cntAttempts = parseIntOrHex( attempts ) < 1 ? 1 : parseIntOrHex( attempts );
     let txc = "";
     try {
         txc = await w3.eth.getTransactionCount( address, param );
     } catch ( e ) {}
-    let attemptIndex = 2;
-    while( txc === "" && attemptIndex <= allAttempts ) {
+    let idxAttempt = 2;
+    while( txc === "" && idxAttempt <= cntAttempts ) {
         details.write(
             cc.warning( "Repeat " ) + cc.error( "getTransactionCount" ) +
-            cc.warning( " attempt " ) + cc.error( attemptIndex ) +
+            cc.warning( " attempt " ) + cc.error( idxAttempt ) +
             cc.warning( ", previous result is: " ) + cc.info( txc ) + "\n"
         );
         await sleep( 10000 );
         try {
             txc = await w3.eth.getBlockNumber();
         } catch ( e ) {}
-        attemptIndex++;
+        idxAttempt++;
     }
-    if( attemptIndex + 1 > allAttempts && txc === "" )
+    if( idxAttempt + 1 > cntAttempts && txc === "" )
         throw new Error( "Could not not get Transaction Count" );
     return txc;
 }
 
 async function get_web3_transactionReceipt( details, attempts, w3, txHash ) {
-    const allAttempts = parseInt( attempts ) < 1 ? 1 : parseInt( attempts );
+    const cntAttempts = parseIntOrHex( attempts ) < 1 ? 1 : parseIntOrHex( attempts );
     let txReceipt = "";
     try {
         txReceipt = await w3.eth.getTransactionReceipt( txHash );
     } catch ( e ) {}
-    let attemptIndex = 2;
-    while( txReceipt === "" && attemptIndex <= allAttempts ) {
+    let idxAttempt = 2;
+    while( txReceipt === "" && idxAttempt <= cntAttempts ) {
         details.write(
-            cc.warning( "Repeat " ) + cc.error( "getTransactionReceipt" ) + cc.warning( ", attempt " ) + cc.error( attemptIndex ) +
+            cc.warning( "Repeat " ) + cc.error( "getTransactionReceipt" ) + cc.warning( ", attempt " ) + cc.error( idxAttempt ) +
             cc.warning( ", previous result is: " ) + cc.j( txReceipt ) + "\n" );
         await sleep( 10000 );
         try {
             txReceipt = await w3.eth.getTransactionReceipt( txHash );
         } catch ( e ) {}
-        attemptIndex++;
+        idxAttempt++;
     }
-    if( attemptIndex + 1 > allAttempts && txReceipt === "" )
-        throw new Error( "Could not not get Transaction Count" );
+    if( idxAttempt + 1 > cntAttempts && ( txReceipt === "" || txReceipt === undefined ) )
+        throw new Error( "Could not not get Transaction Receipt" );
     return txReceipt;
 }
 
-async function get_web3_pastEvents( details, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ) {
-    const allAttempts = parseInt( attempts ) < 1 ? 1 : parseInt( attempts );
+async function get_web3_pastEvents( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ) {
+    const cntAttempts = parseIntOrHex( attempts ) < 1 ? 1 : parseIntOrHex( attempts );
     let joAllEventsInBlock = "";
     try {
         joAllEventsInBlock = await joContract.getPastEvents( "" + strEventName, {
@@ -250,12 +243,14 @@ async function get_web3_pastEvents( details, attempts, joContract, strEventName,
             fromBlock: nBlockFrom,
             toBlock: nBlockTo
         } );
-    } catch ( e ) {}
-    let attemptIndex = 2;
-    while( joAllEventsInBlock === "" && attemptIndex <= allAttempts ) {
+    } catch ( err ) {}
+    let idxAttempt = 2;
+    while( joAllEventsInBlock === "" && idxAttempt <= cntAttempts ) {
         details.write(
             cc.warning( "Repeat " ) + cc.error( "getPastEvents" ) + cc.warning( "/" ) + cc.error( strEventName ) +
-            cc.warning( ", attempt " ) + cc.error( attemptIndex ) +
+            cc.warning( ", attempt " ) + cc.error( idxAttempt ) +
+            cc.warning( ", from block " ) + cc.info( nBlockFrom ) +
+            cc.warning( ", to block " ) + cc.info( nBlockTo ) +
             cc.warning( ", previous result is: " ) + cc.j( joAllEventsInBlock ) + "\n" );
         await sleep( 1000 );
         try {
@@ -264,26 +259,222 @@ async function get_web3_pastEvents( details, attempts, joContract, strEventName,
                 fromBlock: nBlockFrom,
                 toBlock: nBlockTo
             } );
-        } catch ( e ) {}
-        attemptIndex++;
+        } catch ( err ) {}
+        idxAttempt++;
+    }
+    if( idxAttempt + 1 === cntAttempts && joAllEventsInBlock === "" ) {
+        throw new Error(
+            "Could not not get Event \"" + strEventName +
+            "\", from block " + nBlockFrom + ", to block " + nBlockTo
+        );
     }
-    if( attemptIndex + 1 === allAttempts && joAllEventsInBlock === "" )
-        throw new Error( "Could not not get Event" + strEventName );
     return joAllEventsInBlock;
 }
 
+let g_nCountOfBlocksInIterativeStep = 1000;
+let g_nMaxBlockScanIterationsInAllRange = 5000;
+
+function getBlocksCountInInIterativeStepOfEventsScan() {
+    return g_nCountOfBlocksInIterativeStep;
+}
+function setBlocksCountInInIterativeStepOfEventsScan( n ) {
+    if( ! n )
+        g_nCountOfBlocksInIterativeStep = 0;
+    else {
+        g_nCountOfBlocksInIterativeStep = parseIntOrHex( n );
+        if( g_nCountOfBlocksInIterativeStep < 0 )
+            g_nCountOfBlocksInIterativeStep = 0;
+    }
+}
+
+function getMaxIterationsInAllRangeEventsScan() {
+    return g_nCountOfBlocksInIterativeStep;
+}
+function setMaxIterationsInAllRangeEventsScan( n ) {
+    if( ! n )
+        g_nMaxBlockScanIterationsInAllRange = 0;
+    else {
+        g_nMaxBlockScanIterationsInAllRange = parseIntOrHex( n );
+        if( g_nMaxBlockScanIterationsInAllRange < 0 )
+            g_nMaxBlockScanIterationsInAllRange = 0;
+    }
+}
+
+async function get_web3_pastEventsIterative( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ) {
+    if( g_nCountOfBlocksInIterativeStep <= 0 || g_nMaxBlockScanIterationsInAllRange <= 0 ) {
+        details.write(
+            cc.fatal( "IMPORTANT NOTICE:" ) + " " +
+            cc.warning( "Will skip " ) + cc.attention( "iterative" ) + cc.warning( " events scan in block range from " ) +
+            cc.info( nBlockFrom ) + cc.warning( " to " ) + cc.info( nBlockTo ) +
+            cc.warning( " because it's " ) + cc.error( "DISABLED" ) + "\n" );
+        return await get_web3_pastEvents( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter );
+    }
+    if( nBlockFrom == 0 && nBlockTo == "latest" ) {
+        const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3 );
+        if( ( nLatestBlockNumber / g_nCountOfBlocksInIterativeStep ) > g_nMaxBlockScanIterationsInAllRange ) {
+            details.write(
+                cc.fatal( "IMPORTANT NOTICE:" ) + " " +
+                cc.warning( "Will skip " ) + cc.attention( "iterative" ) + cc.warning( " scan and use scan in block range from " ) +
+                cc.info( nBlockFrom ) + cc.warning( " to " ) + cc.info( nBlockTo ) + "\n" );
+            return await get_web3_pastEvents( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter );
+        }
+    }
+    details.write(
+        cc.debug( "Iterative scan in " ) +
+        cc.info( nBlockFrom ) + cc.debug( "/" ) + cc.info( nBlockTo ) +
+        cc.debug( " block range..." ) + "\n" );
+    if( nBlockTo == "latest" ) {
+        const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3 );
+        nBlockTo = nLatestBlockNumber;
+        details.write(
+            cc.debug( "Iterative scan up to latest block " ) +
+            cc.attention( "#" ) + cc.info( nBlockTo ) +
+            cc.debug( " assumed instead of " ) + cc.attention( "latest" ) + "\n" );
+    }
+    let idxBlockSubRangeFrom = parseIntOrHex( nBlockFrom );
+    for( ; true; ) {
+        let idxBlockSubRangeTo = idxBlockSubRangeFrom + g_nCountOfBlocksInIterativeStep;
+        if( idxBlockSubRangeTo > nBlockTo )
+            idxBlockSubRangeTo = nBlockTo;
+        try {
+            details.write(
+                cc.debug( "Iterative scan of " ) +
+                cc.info( idxBlockSubRangeFrom ) + cc.debug( "/" ) + cc.info( idxBlockSubRangeTo ) +
+                cc.debug( " block sub-range in " ) +
+                cc.info( nBlockFrom ) + cc.debug( "/" ) + cc.info( nBlockTo ) +
+                cc.debug( " block range..." ) + "\n" );
+            const joAllEventsInBlock = await get_web3_pastEvents( details, w3, attempts, joContract, strEventName, idxBlockSubRangeFrom, idxBlockSubRangeTo, joFilter );
+            if( joAllEventsInBlock && joAllEventsInBlock != "" && joAllEventsInBlock.length > 0 ) {
+                details.write(
+                    cc.success( "Result of " ) + cc.attention( "iterative" ) + cc.success( " scan in " ) +
+                    cc.info( nBlockFrom ) + cc.success( "/" ) + cc.info( nBlockTo ) +
+                    cc.success( " block range is " ) + cc.j( joAllEventsInBlock ) + "\n" );
+                return joAllEventsInBlock;
+            }
+        } catch ( err ) {}
+        idxBlockSubRangeFrom = idxBlockSubRangeTo;
+        if( idxBlockSubRangeFrom == nBlockTo )
+            break;
+    }
+    details.write(
+        cc.debug( "Result of " ) + cc.attention( "iterative" ) + cc.debug( " scan in " ) +
+        cc.info( nBlockFrom ) + cc.debug( "/" ) + cc.info( nBlockTo ) +
+        cc.debug( " block range is " ) + cc.warning( "empty" ) + "\n" );
+    return "";
+}
+
+let g_bIsEnabledProgressiveEventsScan = true;
+
+function getEnabledProgressiveEventsScan() {
+    return g_bIsEnabledProgressiveEventsScan ? true : false;
+}
+function setEnabledProgressiveEventsScan( isEnabled ) {
+    g_bIsEnabledProgressiveEventsScan = isEnabled ? true : false;
+}
+
+function create_progressive_events_scan_plan( details, nLatestBlockNumber ) {
+    // assume Main Net mines 6 blocks per minute
+    const blks_in_1_minute = 6;
+    const blks_in_1_hour = blks_in_1_minute * 60;
+    const blks_in_1_day = blks_in_1_hour * 24;
+    const blks_in_1_week = blks_in_1_day * 7;
+    const blks_in_1_month = blks_in_1_day * 31;
+    const blks_in_1_year = blks_in_1_day * 366;
+    const blks_in_3_years = blks_in_1_year * 3;
+    const arr_progressive_events_scan_plan_A = [
+        { nBlockFrom: nLatestBlockNumber - blks_in_1_day, nBlockTo: "latest", type: "1 day" },
+        { nBlockFrom: nLatestBlockNumber - blks_in_1_week, nBlockTo: "latest", type: "1 week" },
+        { nBlockFrom: nLatestBlockNumber - blks_in_1_month, nBlockTo: "latest", type: "1 month" },
+        { nBlockFrom: nLatestBlockNumber - blks_in_1_year, nBlockTo: "latest", type: "1 year" },
+        { nBlockFrom: nLatestBlockNumber - blks_in_3_years, nBlockTo: "latest", type: "3 years" }
+    ];
+    const arr_progressive_events_scan_plan = [];
+    for( let idxPlan = 0; idxPlan < arr_progressive_events_scan_plan_A.length; ++idxPlan ) {
+        const joPlan = arr_progressive_events_scan_plan_A[idxPlan];
+        if( joPlan.nBlockFrom >= 0 )
+            arr_progressive_events_scan_plan.push( joPlan );
+    }
+    if( arr_progressive_events_scan_plan.length > 0 ) {
+        const joLastPlan = arr_progressive_events_scan_plan[arr_progressive_events_scan_plan.length - 1];
+        if( ! ( joLastPlan.nBlockFrom == 0 && joLastPlan.nBlockTo == "latest" ) )
+            arr_progressive_events_scan_plan.push( { nBlockFrom: 0, nBlockTo: "latest", type: "entire block range" } );
+    } else
+        arr_progressive_events_scan_plan.push( { nBlockFrom: 0, nBlockTo: "latest", type: "entire block range" } );
+    return arr_progressive_events_scan_plan;
+}
+
+async function get_web3_pastEventsProgressive( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ) {
+    if( ! g_bIsEnabledProgressiveEventsScan ) {
+        details.write(
+            cc.fatal( "IMPORTANT NOTICE:" ) + " " +
+            cc.warning( "Will skip " ) + cc.attention( "progressive" ) + cc.warning( " events scan in block range from " ) +
+            cc.info( nBlockFrom ) + cc.warning( " to " ) + cc.info( nBlockTo ) +
+            cc.warning( " because it's " ) + cc.error( "DISABLED" ) + "\n" );
+        return await get_web3_pastEvents( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter );
+    }
+    if( ! ( nBlockFrom == 0 && nBlockTo == "latest" ) ) {
+        details.write(
+            cc.debug( "Will skip " ) + cc.attention( "progressive" ) + cc.debug( " scan and use scan in block range from " ) +
+            cc.info( nBlockFrom ) + cc.debug( " to " ) + cc.info( nBlockTo ) + "\n" );
+        return await get_web3_pastEvents( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter );
+    }
+    details.write( cc.debug( "Will run " ) + cc.attention( "progressive" ) + cc.debug( " scan..." ) + "\n" );
+    const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3 );
+    details.write( cc.debug( "Current latest block number is " ) + cc.info( nLatestBlockNumber ) + "\n" );
+    const arr_progressive_events_scan_plan = create_progressive_events_scan_plan( details, nLatestBlockNumber );
+    details.write( cc.debug( "Composed " ) + cc.attention( "progressive" ) + cc.debug( " scan plan is: " ) + cc.j( arr_progressive_events_scan_plan ) + "\n" );
+    let joLastPlan = { nBlockFrom: 0, nBlockTo: "latest", type: "entire block range" };
+    for( let idxPlan = 0; idxPlan < arr_progressive_events_scan_plan.length; ++idxPlan ) {
+        const joPlan = arr_progressive_events_scan_plan[idxPlan];
+        if( joPlan.nBlockFrom < 0 )
+            continue;
+        joLastPlan = joPlan;
+        details.write(
+            cc.debug( "Progressive scan of " ) + cc.attention( "getPastEvents" ) + cc.debug( "/" ) + cc.info( strEventName ) +
+            cc.debug( ", from block " ) + cc.info( joPlan.nBlockFrom ) +
+            cc.debug( ", to block " ) + cc.info( joPlan.nBlockTo ) +
+            cc.debug( ", block range is " ) + cc.info( joPlan.type ) +
+            cc.debug( "..." ) + "\n" );
+        try {
+            const joAllEventsInBlock = await get_web3_pastEventsIterative( details, w3, attempts, joContract, strEventName, joPlan.nBlockFrom, joPlan.nBlockTo, joFilter );
+            if( joAllEventsInBlock && joAllEventsInBlock.length > 0 ) {
+                details.write(
+                    cc.success( "Progressive scan of " ) + cc.attention( "getPastEvents" ) + cc.debug( "/" ) + cc.info( strEventName ) +
+                    cc.success( ", from block " ) + cc.info( joPlan.nBlockFrom ) +
+                    cc.success( ", to block " ) + cc.info( joPlan.nBlockTo ) +
+                    cc.success( ", block range is " ) + cc.info( joPlan.type ) +
+                    cc.success( ", found " ) + cc.info( joAllEventsInBlock.length ) +
+                    cc.success( " event(s)" ) + "\n" );
+                return joAllEventsInBlock;
+            }
+        } catch ( err ) {}
+    }
+    // throw new Error(
+    //     "Could not not get Event \"" + strEventName +
+    //     "\", from block " + joLastPlan.nBlockFrom + ", to block " + joLastPlan.nBlockTo +
+    //     ", using progressive event scan"
+    // );
+    details.write(
+        cc.error( "Could not not get Event \"" ) + cc.info( strEventName ) +
+        cc.error( "\", from block " ) + cc.info( joLastPlan.nBlockFrom ) +
+        cc.error( ", to block " ) + cc.info( joLastPlan.nBlockTo ) +
+        cc.debug( ", block range is " ) + cc.info( joLastPlan.type ) +
+        cc.error( ", using " ) + cc.attention( "progressive" ) + cc.error( " event scan" ) + "\n" );
+    return [];
+}
+
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 async function get_contract_call_events( details, w3, joContract, strEventName, nBlockNumber, strTxHash, joFilter ) {
     joFilter = joFilter || {};
     let nBlockFrom = nBlockNumber - 10, nBlockTo = nBlockNumber + 10;
-    const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3 ); // await get_web3_universal_call( 10, "BlockNumber", w3, null, null );
+    const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3 );
     if( nBlockFrom < 0 )
         nBlockFrom = 0;
     if( nBlockTo > nLatestBlockNumber )
         nBlockTo = nLatestBlockNumber;
-    const joAllEventsInBlock = await get_web3_pastEvents( details, 10, joContract, strEventName, nBlockFrom, nBlockTo, joFilter );
+    const joAllEventsInBlock = await get_web3_pastEventsIterative( details, w3, 10, joContract, strEventName, nBlockFrom, nBlockTo, joFilter );
     const joAllTransactionEvents = []; let i;
     for( i = 0; i < joAllEventsInBlock.length; ++i ) {
         const joEvent = joAllEventsInBlock[i];
@@ -390,11 +581,12 @@ async function dry_run_call( details, w3, methodWithArguments, joAccount, strDRC
     strLogPrefix += cc.attention( ":" ) + " ";
     if( ! dry_run_is_enabled() ) {
         details.write( strLogPrefix + cc.success( "Skipped, dry run is disabled" ) + "\n" );
-        return;
+        return null;
     }
     try {
         const addressFrom = joAccount.address( w3 );
-        details.write( strLogPrefix + cc.debug( " will call method" ) +
+        details.write(
+            strLogPrefix + cc.debug( " will call method" ) +
             // cc.debug( " with data " ) + cc.normal( cc.safeStringifyJSON( methodWithArguments ) ) +
             cc.debug( " from address " ) + cc.sunny( addressFrom ) +
             "\n" );
@@ -413,9 +605,15 @@ async function dry_run_call( details, w3, methodWithArguments, joAccount, strDRC
             strErrorMessage += cc.fatal( "CRITICAL DRY RUN FAIL:" );
         strErrorMessage += " " + cc.error( err ) + "\n";
         details.write( strErrorMessage );
-        if( ! ( isIgnore || dry_run_is_ignored() ) )
-            throw new Error( "CRITICAL DRY RUN FAIL invoking the \"" + strMethodName + "\" method: " + err.toString() );
+        if( ! ( isIgnore || dry_run_is_ignored() ) ) {
+            details.write(
+                strLogPrefix + cc.fatal( "CRITICAL DRY RUN FAIL" ) + " " +
+                cc.error( " invoking the " ) + cc.info( strMethodName ) + cc.error( " method: " ) +
+                cc.warning( err.toString() ) + "\n" );
+            return "CRITICAL DRY RUN FAIL invoking the \"" + strMethodName + "\" method: " + err.toString();
+        }
     }
+    return null;
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -506,8 +704,11 @@ async function tm_wait( details, tx_id, w3 ) {
     let hash;
     while( hash === undefined ) {
         const r = await tm_get_record( tx_id );
-        if( tm_is_finished( r ) )
-            hash = r.tx_hash;
+        if( tm_is_finished( r ) ) {
+            if( r.status == "DROPPED" )
+                return null;
+        }
+        hash = r.tx_hash;
     }
     details.write( cc.debug( "TM - TX hash is " ) + cc.info( hash ) + "\n" );
     // return await w3.eth.getTransactionReceipt( hash );
@@ -517,6 +718,30 @@ async function tm_wait( details, tx_id, w3 ) {
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
+async function tm_ensure_transaction( details, w3, priority, txAdjusted, cntAttempts, sleepMilliseconds ) {
+    cntAttempts = cntAttempts || 10;
+    sleepMilliseconds = sleepMilliseconds || 3000;
+    let tx_id = "";
+    let joReceipt = null;
+    let idxAttempt = 0;
+    for( ; idxAttempt < cntAttempts; ++idxAttempt ) {
+        tx_id = await tm_send( details, txAdjusted, priority );
+        details.write( cc.debug( "TM - generated TX ID: " ) + cc.info( tx_id ) + "\n" );
+        joReceipt = await tm_wait( details, tx_id, w3 );
+        if( joReceipt )
+            break;
+        details.write( cc.warning( "TM - unsuccessful TX sending attempt " ) + cc.info( idxAttempt ) + cc.warning( " of " ) + cc.info( cntAttempts ) + "\n" );
+        await sleep( sleepMilliseconds );
+    }
+    if( !joReceipt ) {
+        details.write( cc.fatal( "BAD ERROR:" ) + " " + cc.error( "TM transaction " ) + cc.info( tx_id ) + cc.error( " transaction has been dropped" ) + "\n" );
+        log.write( cc.fatal( "BAD ERROR:" ) + " " + cc.error( "TM transaction " ) + cc.info( tx_id ) + cc.error( " transaction has been dropped" ) + "\n" );
+        throw new Error( "TM transaction " + tx_id + " transaction has been dropped" );
+    }
+    details.write( cc.success( "TM - successful TX sending attempt " ) + cc.info( idxAttempt ) + cc.success( " of " ) + cc.info( cntAttempts ) + "\n" );
+    return [ tx_id, joReceipt ];
+}
+
 async function safe_sign_transaction_with_account( details, w3, tx, rawTx, joAccount ) {
     const joSR = {
         joACI: get_account_connectivity_info( joAccount ),
@@ -599,11 +824,16 @@ async function safe_sign_transaction_with_account( details, w3, tx, rawTx, joAcc
         if( redis == null )
             redis = new Redis( joAccount.strTransactionManagerURL );
         const priority = joAccount.tm_priority || 5;
-        const tx_id = await tm_send( details, txAdjusted, priority );
-        const joReceipt = await tm_wait( details, tx_id, w3 );
-        joSR.txHashSent = "" + joReceipt.transactionHash;
-        joSR.joReceipt = joReceipt;
-        joSR.tm_tx_id = tx_id;
+        try {
+            const [ tx_id, joReceipt ] = await tm_ensure_transaction( details, w3, priority, txAdjusted );
+            joSR.txHashSent = "" + joReceipt.transactionHash;
+            joSR.joReceipt = joReceipt;
+            joSR.tm_tx_id = tx_id;
+        } catch ( err ) {
+            details.write( cc.fatal( "BAD ERROR:" ) + " " + cc.error( "TM - transaction was not sent, underlying error is: " ) + cc.warning( err.toString() ) + "\n" );
+            log.write( cc.fatal( "BAD ERROR:" ) + " " + cc.error( "TM - transaction was not sent, underlying error is: " ) + cc.warning( err.toString() ) + "\n" );
+            // throw err;
+        }
     } break;
     case "sgx": {
         details.write(
@@ -651,10 +881,10 @@ async function safe_sign_transaction_with_account( details, w3, tx, rawTx, joAcc
                 }
                 details.write( cc.debug( "SGX wallet ECDSA sign result is: " ) + cc.j( joOut ) + "\n" );
                 const joNeededResult = {
-                    // "v": Buffer.from( parseInt( joOut.result.signature_v, 10 ).toString( "hex" ), "utf8" ),
+                    // "v": Buffer.from( parseIntOrHex( joOut.result.signature_v ).toString( "hex" ), "utf8" ),
                     // "r": Buffer.from( "" + joOut.result.signature_r, "utf8" ),
                     // "s": Buffer.from( "" + joOut.result.signature_s, "utf8" )
-                    "v": parseInt( joOut.result.signature_v, 10 ),
+                    "v": parseIntOrHex( joOut.result.signature_v, 10 ),
                     "r": "" + joOut.result.signature_r,
                     "s": "" + joOut.result.signature_s
                 };
@@ -891,7 +1121,9 @@ async function register_s_chain_in_deposit_boxes( // step 1
         //
         const isIgnore = false;
         const strDRC = "register_s_chain_in_deposit_boxes, step 1, connectSchain";
-        await dry_run_call( details, w3_main_net, methodWithArguments, joAccount_main_net, strDRC, isIgnore, gasPrice, estimatedGas, "0" );
+        const strErrorOfDryRun = await dry_run_call( details, w3_main_net, methodWithArguments, joAccount_main_net, strDRC, isIgnore, gasPrice, estimatedGas, "0" );
+        if( strErrorOfDryRun )
+            throw new Error( strErrorOfDryRun );
         //
         const rawTx = {
             chainId: cid_main_net,
@@ -1021,9 +1253,11 @@ async function reimbursement_wallet_recharge(
         details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" );
         //
         //
+        const addressReceiver = joAccount_main_net.address( w3_main_net );
         const methodWithArguments = jo_community_pool.methods.rechargeUserWallet(
             // call params, last is destination account on S-chain
-            strReimbursementChain
+            strReimbursementChain,
+            addressReceiver
         );
         const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method
         //
@@ -1034,7 +1268,9 @@ async function reimbursement_wallet_recharge(
         //
         const isIgnore = false;
         const strDRC = "reimbursement_wallet_recharge";
-        await dry_run_call( details, w3_main_net, methodWithArguments, joAccount_main_net, strDRC, isIgnore, gasPrice, estimatedGas, nReimbursementRecharge );
+        const strErrorOfDryRun = await dry_run_call( details, w3_main_net, methodWithArguments, joAccount_main_net, strDRC, isIgnore, gasPrice, estimatedGas, nReimbursementRecharge );
+        if( strErrorOfDryRun )
+            throw new Error( strErrorOfDryRun );
         //
         const rawTx = {
             chainId: cid_main_net,
@@ -1118,7 +1354,9 @@ async function reimbursement_wallet_withdraw(
         //
         const isIgnore = false;
         const strDRC = "reimbursement_wallet_withdraw";
-        await dry_run_call( details, w3_main_net, methodWithArguments, joAccount_main_net, strDRC, isIgnore, gasPrice, estimatedGas, wei_how_much );
+        const strErrorOfDryRun = await dry_run_call( details, w3_main_net, methodWithArguments, joAccount_main_net, strDRC, isIgnore, gasPrice, estimatedGas, wei_how_much );
+        if( strErrorOfDryRun )
+            throw new Error( strErrorOfDryRun );
         //
         const rawTx = {
             chainId: cid_main_net,
@@ -1200,7 +1438,9 @@ async function reimbursement_set_range(
         //
         const isIgnore = false;
         const strDRC = "reimbursement_set_range";
-        await dry_run_call( details, w3_s_chain, methodWithArguments, joAccount_s_chain, strDRC, isIgnore, gasPrice, estimatedGas, wei_how_much );
+        const strErrorOfDryRun = await dry_run_call( details, w3_s_chain, methodWithArguments, joAccount_s_chain, strDRC, isIgnore, gasPrice, estimatedGas, wei_how_much );
+        if( strErrorOfDryRun )
+            throw new Error( strErrorOfDryRun );
         //
         const rawTx = {
             chainId: cid_s_chain,
@@ -1285,7 +1525,7 @@ async function do_eth_payment_from_main_net(
         //
         const methodWithArguments = jo_deposit_box.methods.deposit(
             // call params, last is destination account on S-chain
-            chain_id_s_chain, joAccountDst.address( w3_main_net )
+            chain_id_s_chain
         );
         const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method
         //
@@ -1296,7 +1536,9 @@ async function do_eth_payment_from_main_net(
         //
         const isIgnore = false;
         const strDRC = "do_eth_payment_from_main_net, deposit";
-        await dry_run_call( details, w3_main_net, methodWithArguments, joAccountSrc, strDRC, isIgnore, gasPrice, estimatedGas, wei_how_much );
+        const strErrorOfDryRun = await dry_run_call( details, w3_main_net, methodWithArguments, joAccountSrc, strDRC, isIgnore, gasPrice, estimatedGas, wei_how_much );
+        if( strErrorOfDryRun )
+            throw new Error( strErrorOfDryRun );
         //
         const rawTx = {
             chainId: cid_main_net,
@@ -1401,7 +1643,6 @@ async function do_eth_payment_from_s_chain(
         strActionName = "jo_token_manager_eth.methods.exitToMain()/do_eth_payment_from_s_chain";
         const methodWithArguments = jo_token_manager_eth.methods.exitToMain(
             // call params, last is destination account on S-chain
-            joAccountDst.address( w3_s_chain ),
             "0x" + w3_s_chain.utils.toBN( wei_how_much ).toString( 16 )
         );
         const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method
@@ -1414,7 +1655,9 @@ async function do_eth_payment_from_s_chain(
         //
         const isIgnore = true;
         const strDRC = "do_eth_payment_from_s_chain, exitToMain";
-        await dry_run_call( details, w3_s_chain, methodWithArguments, joAccountSrc, strDRC, isIgnore, gasPrice, estimatedGas, "0" );
+        const strErrorOfDryRun = await dry_run_call( details, w3_s_chain, methodWithArguments, joAccountSrc, strDRC, isIgnore, gasPrice, estimatedGas, "0" );
+        if( strErrorOfDryRun )
+            throw new Error( strErrorOfDryRun );
         //
         const rawTx = {
             chainId: cid_s_chain,
@@ -1504,7 +1747,9 @@ async function receive_eth_payment_from_s_chain_on_main_net(
         //
         const isIgnore = false;
         const strDRC = "receive_eth_payment_from_s_chain_on_main_net, getMyEth";
-        await dry_run_call( details, w3_main_net, methodWithArguments, joAccount_main_net, strDRC, isIgnore, gasPrice, estimatedGas, "0" );
+        const strErrorOfDryRun = await dry_run_call( details, w3_main_net, methodWithArguments, joAccount_main_net, strDRC, isIgnore, gasPrice, estimatedGas, "0" );
+        if( strErrorOfDryRun )
+            throw new Error( strErrorOfDryRun );
         //
         const rawTx = {
             chainId: cid_main_net,
@@ -1630,7 +1875,6 @@ async function do_erc721_payment_from_main_net(
         const contractERC721 = new w3_main_net.eth.Contract( erc721ABI, erc721Address_main_net );
         // prepare the smart contract function deposit(string schainName, address to)
         const depositBoxAddress = jo_deposit_box_erc721.options.address;
-        const accountForSchain = joAccountDst.address( w3_s_chain );
         const methodWithArguments_approve = contractERC721.methods.approve( // same as approve in 20
             // joAccountSrc.address( w3_main_net ),
             depositBoxAddress,
@@ -1641,7 +1885,6 @@ async function do_erc721_payment_from_main_net(
         const methodWithArguments_rawDepositERC721 = jo_deposit_box_erc721.methods.depositERC721(
             chain_id_s_chain,
             erc721Address_main_net,
-            accountForSchain,
             "0x" + w3_main_net.utils.toBN( token_id ).toString( 16 )
         );
         dataTxDeposit = methodWithArguments_rawDepositERC721.encodeABI();
@@ -1658,7 +1901,9 @@ async function do_erc721_payment_from_main_net(
         //
         const isIgnore_approve = false;
         const strDRC_approve = "do_erc721_payment_from_main_net, approve";
-        await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        const strErrorOfDryRun_approve = await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        if( strErrorOfDryRun_approve )
+            throw new Error( strErrorOfDryRun_approve );
         //
         const rawTxApprove = {
             chainId: cid_main_net,
@@ -1702,7 +1947,9 @@ async function do_erc721_payment_from_main_net(
         //
         const isIgnore_rawDepositERC721 = true;
         const strDRC_rawDepositERC721 = "do_erc721_payment_from_main_net, rawDepositERC721";
-        await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC721, joAccountSrc, strDRC_rawDepositERC721, isIgnore_rawDepositERC721, gasPrice, estimatedGas_deposit, "0" );
+        const strErrorOfDryRun_rawDepositERC721 = await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC721, joAccountSrc, strDRC_rawDepositERC721, isIgnore_rawDepositERC721, gasPrice, estimatedGas_deposit, "0" );
+        if( strErrorOfDryRun_rawDepositERC721 )
+            throw new Error( strErrorOfDryRun_rawDepositERC721 );
         //
         const rawTxDeposit = {
             chainId: cid_main_net,
@@ -1817,7 +2064,6 @@ async function do_erc20_payment_from_main_net(
         const contractERC20 = new w3_main_net.eth.Contract( erc20ABI, erc20Address_main_net );
         // prepare the smart contract function deposit(string schainName, address to)
         const depositBoxAddress = jo_deposit_box_erc20.options.address;
-        const accountForSchain = joAccountDst.address( w3_s_chain );
         const methodWithArguments_approve = contractERC20.methods.approve(
             depositBoxAddress, "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 )
         );
@@ -1826,7 +2072,6 @@ async function do_erc20_payment_from_main_net(
         const methodWithArguments_rawDepositERC20 = jo_deposit_box_erc20.methods.depositERC20(
             chain_id_s_chain,
             erc20Address_main_net,
-            accountForSchain,
             "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 )
         );
         dataTxDeposit = methodWithArguments_rawDepositERC20.encodeABI();
@@ -1843,7 +2088,9 @@ async function do_erc20_payment_from_main_net(
         //
         const isIgnore_approve = false;
         const strDRC_approve = "do_erc20_payment_from_main_net, approve";
-        await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        const strErrorOfDryRun_approve = await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        if( strErrorOfDryRun_approve )
+            throw new Error( strErrorOfDryRun_approve );
         //
         const rawTxApprove = {
             chainId: cid_main_net,
@@ -1886,7 +2133,9 @@ async function do_erc20_payment_from_main_net(
         //
         const isIgnore_rawDepositERC20 = true;
         const strDRC_rawDepositERC20 = "do_erc20_payment_from_main_net, rawDepositERC20";
-        await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC20, joAccountSrc, strDRC_rawDepositERC20, isIgnore_rawDepositERC20, gasPrice, estimatedGas_deposit, "0" );
+        const strErrorOfDryRun_rawDepositERC20 = await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC20, joAccountSrc, strDRC_rawDepositERC20, isIgnore_rawDepositERC20, gasPrice, estimatedGas_deposit, "0" );
+        if( strErrorOfDryRun_rawDepositERC20 )
+            throw new Error( strErrorOfDryRun_rawDepositERC20 );
         //
         tcnt += 1;
         const rawTxDeposit = {
@@ -1995,7 +2244,6 @@ async function do_erc1155_payment_from_main_net(
         const contractERC1155 = new w3_main_net.eth.Contract( erc1155ABI, erc1155Address_main_net );
         // prepare the smart contract function deposit(string schainName, address to)
         const depositBoxAddress = jo_deposit_box_erc1155.options.address;
-        const accountForSchain = joAccountDst.address( w3_s_chain );
         const methodWithArguments_approve = contractERC1155.methods.setApprovalForAll( // same as approve in 20
             // joAccountSrc.address( w3_main_net ),
             depositBoxAddress,
@@ -2006,7 +2254,6 @@ async function do_erc1155_payment_from_main_net(
         const methodWithArguments_rawDepositERC1155 = jo_deposit_box_erc1155.methods.depositERC1155(
             chain_id_s_chain,
             erc1155Address_main_net,
-            accountForSchain,
             "0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ),
             "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 )
         );
@@ -2024,7 +2271,9 @@ async function do_erc1155_payment_from_main_net(
         //
         const isIgnore_approve = false;
         const strDRC_approve = "do_erc1155_payment_from_main_net, approve";
-        await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        const strErrorOfDryRun_approve = await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        if( strErrorOfDryRun_approve )
+            throw new Error( strErrorOfDryRun_approve );
         //
         const rawTxApprove = {
             chainId: cid_main_net,
@@ -2068,7 +2317,9 @@ async function do_erc1155_payment_from_main_net(
         //
         const isIgnore_rawDepositERC1155 = true;
         const strDRC_rawDepositERC1155 = "do_erc1155_payment_from_main_net, rawDepositERC1155";
-        await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC1155, joAccountSrc, strDRC_rawDepositERC1155, isIgnore_rawDepositERC1155, gasPrice, estimatedGas_deposit, "0" );
+        const strErrorOfDryRun_rawDepositERC1155 = await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC1155, joAccountSrc, strDRC_rawDepositERC1155, isIgnore_rawDepositERC1155, gasPrice, estimatedGas_deposit, "0" );
+        if( strErrorOfDryRun_rawDepositERC1155 )
+            throw new Error( strErrorOfDryRun_rawDepositERC1155 );
         //
         const rawTxDeposit = {
             chainId: cid_main_net,
@@ -2177,7 +2428,6 @@ async function do_erc1155_batch_payment_from_main_net(
         const contractERC1155 = new w3_main_net.eth.Contract( erc1155ABI, erc1155Address_main_net );
         // prepare the smart contract function deposit(string schainName, address to)
         const depositBoxAddress = jo_deposit_box_erc1155.options.address;
-        const accountForSchain = joAccountDst.address( w3_s_chain );
         const methodWithArguments_approve = contractERC1155.methods.setApprovalForAll( // same as approve in 20
             // joAccountSrc.address( w3_main_net ),
             depositBoxAddress,
@@ -2188,7 +2438,6 @@ async function do_erc1155_batch_payment_from_main_net(
         const methodWithArguments_rawDepositERC1155Batch = jo_deposit_box_erc1155.methods.depositERC1155Batch(
             chain_id_s_chain,
             erc1155Address_main_net,
-            accountForSchain,
             token_ids, //"0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ),
             token_amounts //"0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 )
         );
@@ -2206,7 +2455,9 @@ async function do_erc1155_batch_payment_from_main_net(
         //
         const isIgnore_approve = false;
         const strDRC_approve = "do_erc1155_batch_payment_from_main_net, approve";
-        await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        const strErrorOfDryRun_approve = await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        if( strErrorOfDryRun_approve )
+            throw new Error( strErrorOfDryRun_approve );
         //
         const rawTxApprove = {
             chainId: cid_main_net,
@@ -2250,7 +2501,9 @@ async function do_erc1155_batch_payment_from_main_net(
         //
         const isIgnore_rawDepositERC1155Batch = true;
         const strDRC_rawDepositERC1155Batch = "do_erc1155_batch_payment_from_main_net, rawDepositERC1155Batch";
-        await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC1155Batch, joAccountSrc, strDRC_rawDepositERC1155Batch, isIgnore_rawDepositERC1155Batch, gasPrice, estimatedGas_deposit, "0" );
+        const strErrorOfDryRun_rawDepositERC1155Batch = await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC1155Batch, joAccountSrc, strDRC_rawDepositERC1155Batch, isIgnore_rawDepositERC1155Batch, gasPrice, estimatedGas_deposit, "0" );
+        if( strErrorOfDryRun_rawDepositERC1155Batch )
+            throw new Error( strErrorOfDryRun_rawDepositERC1155Batch );
         //
         const rawTxDeposit = {
             chainId: cid_main_net,
@@ -2353,7 +2606,6 @@ async function do_erc20_payment_from_s_chain(
         //
         //
         strActionName = "ERC20 prepare S->M";
-        const accountForMainnet = joAccountDst.address( w3_main_net );
         const accountForSchain = joAccountSrc.address( w3_s_chain );
         const erc20ABI = joErc20_s_chain[strCoinNameErc20_s_chain + "_abi"];
         const erc20Address_s_chain = joErc20_s_chain[strCoinNameErc20_s_chain + "_address"];
@@ -2370,7 +2622,6 @@ async function do_erc20_payment_from_s_chain(
         const erc20Address_main_net = joErc20_main_net[strCoinNameErc20_main_net + "_address"];
         const methodWithArguments_rawExitToMainERC20 = jo_token_manager_erc20.methods.exitToMainERC20(
             erc20Address_main_net,
-            accountForMainnet,
             "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 )
             // "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 )
         );
@@ -2389,9 +2640,11 @@ async function do_erc20_payment_from_s_chain(
         //
         const isIgnore_approve = false;
         const strDRC_approve = "do_erc20_payment_from_s_chain, approve";
-        await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        const strErrorOfDryRun_approve = await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        if( strErrorOfDryRun_approve )
+            throw new Error( strErrorOfDryRun_approve );
         //
-        let tcnt = parseInt( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
+        let tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
         details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" );
         const rawTxApprove = {
             chainId: cid_s_chain,
@@ -2434,7 +2687,7 @@ async function do_erc20_payment_from_s_chain(
         strActionName = "create ERC20/exitToMain transaction S->M";
         const estimatedGas_rawExitToMainERC20 = await tc_s_chain.computeGas( methodWithArguments_rawExitToMainERC20, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" );
         details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_rawExitToMainERC20 ) + "\n" );
-        tcnt = parseInt( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
+        tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
         details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" );
         //
         gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 );
@@ -2442,7 +2695,9 @@ async function do_erc20_payment_from_s_chain(
         //
         const isIgnore_rawExitToMainERC20 = true;
         const strDRC_rawExitToMainERC20 = "do_erc20_payment_from_s_chain, rawExitToMainERC20";
-        await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC20, joAccountSrc, strDRC_rawExitToMainERC20, isIgnore_rawExitToMainERC20, gasPrice, estimatedGas_rawExitToMainERC20, "0" );
+        const strErrorOfDryRun_rawExitToMainERC20 = await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC20, joAccountSrc, strDRC_rawExitToMainERC20, isIgnore_rawExitToMainERC20, gasPrice, estimatedGas_rawExitToMainERC20, "0" );
+        if( strErrorOfDryRun_rawExitToMainERC20 )
+            throw new Error( strErrorOfDryRun_rawExitToMainERC20 );
         //
         const rawTxExitToMainERC20 = {
             chainId: cid_s_chain,
@@ -2530,7 +2785,6 @@ async function do_erc721_payment_from_s_chain(
         //
         //
         strActionName = "ERC721 prepare S->M";
-        const accountForMainnet = joAccountDst.address( w3_main_net );
         const accountForSchain = joAccountSrc.address( w3_s_chain );
         const erc721ABI = joErc721_s_chain[strCoinNameErc721_s_chain + "_abi"];
         const erc721Address_s_chain = joErc721_s_chain[strCoinNameErc721_s_chain + "_address"];
@@ -2548,7 +2802,6 @@ async function do_erc721_payment_from_s_chain(
         const erc721Address_main_net = joErc721_main_net[strCoinNameErc721_main_net + "_address"];
         const methodWithArguments_rawExitToMainERC721 = jo_token_manager_erc721.methods.exitToMainERC721(
             erc721Address_main_net,
-            accountForMainnet,
             "0x" + w3_main_net.utils.toBN( token_id ).toString( 16 )
             // "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 )
         );
@@ -2561,7 +2814,7 @@ async function do_erc721_payment_from_s_chain(
         //
         //
         strActionName = "create ERC721/approve transaction S->M";
-        let tcnt = parseInt( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
+        let tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
         details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" );
         //
         const estimatedGas_approve = await tc_s_chain.computeGas( methodWithArguments_approve, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" );
@@ -2569,7 +2822,9 @@ async function do_erc721_payment_from_s_chain(
         //
         const isIgnore_approve = false;
         const strDRC_approve = "erc721_payment_from_s_chain, approve";
-        await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve,isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        const strErrorOfDryRun_approve = await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve,isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        if( strErrorOfDryRun_approve )
+            throw new Error( strErrorOfDryRun_approve );
         //
         const rawTxApprove = {
             chainId: cid_s_chain,
@@ -2610,7 +2865,7 @@ async function do_erc721_payment_from_s_chain(
         //
         //
         strActionName = "create ERC721/rawExitToMain transaction S->M";
-        tcnt = parseInt( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
+        tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
         details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" );
         //
         gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 );
@@ -2621,7 +2876,9 @@ async function do_erc721_payment_from_s_chain(
         //
         const isIgnore_rawExitToMainERC721 = true;
         const strDRC_rawExitToMainERC721 = "erc721_payment_from_s_chain, rawExitToMainERC721";
-        await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC721, joAccountSrc, strDRC_rawExitToMainERC721, isIgnore_rawExitToMainERC721, gasPrice, estimatedGas_exitToMainERC721, "0" );
+        const strErrorOfDryRun_rawExitToMainERC721 = await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC721, joAccountSrc, strDRC_rawExitToMainERC721, isIgnore_rawExitToMainERC721, gasPrice, estimatedGas_exitToMainERC721, "0" );
+        if( strErrorOfDryRun_rawExitToMainERC721 )
+            throw new Error( strErrorOfDryRun_rawExitToMainERC721 );
         //
         const rawTxExitToMainERC721 = compose_tx_instance(
             details,
@@ -2712,7 +2969,6 @@ async function do_erc1155_payment_from_s_chain(
         //
         //
         strActionName = "ERC1155 prepare S->M";
-        const accountForMainnet = joAccountDst.address( w3_main_net );
         const accountForSchain = joAccountSrc.address( w3_s_chain );
         const erc1155ABI = joErc1155_s_chain[strCoinNameErc1155_s_chain + "_abi"];
         const erc1155Address_s_chain = joErc1155_s_chain[strCoinNameErc1155_s_chain + "_address"];
@@ -2730,7 +2986,6 @@ async function do_erc1155_payment_from_s_chain(
         const erc1155Address_main_net = joErc1155_main_net[strCoinNameErc1155_main_net + "_address"];
         const methodWithArguments_rawExitToMainERC1155 = jo_token_manager_erc1155.methods.exitToMainERC1155(
             erc1155Address_main_net,
-            accountForMainnet,
             "0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ),
             "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 )
             // "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 )
@@ -2744,7 +2999,7 @@ async function do_erc1155_payment_from_s_chain(
         //
         //
         strActionName = "create ERC1155/approve transaction S->M";
-        let tcnt = parseInt( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
+        let tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
         details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" );
         //
         const estimatedGas_approve = await tc_s_chain.computeGas( methodWithArguments_approve, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" );
@@ -2752,7 +3007,9 @@ async function do_erc1155_payment_from_s_chain(
         //
         const isIgnore_approve = false;
         const strDRC_approve = "erc1155_payment_from_s_chain, approve";
-        await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve,isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        const strErrorOfDryRun_approve = await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve,isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        if( strErrorOfDryRun_approve )
+            throw new Error( strErrorOfDryRun_approve );
         //
         const rawTxApprove = {
             chainId: cid_s_chain,
@@ -2793,7 +3050,7 @@ async function do_erc1155_payment_from_s_chain(
         //
         //
         strActionName = "create ERC1155/rawExitToMain transaction S->M";
-        tcnt = parseInt( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
+        tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
         details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" );
         //
         gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 );
@@ -2804,7 +3061,9 @@ async function do_erc1155_payment_from_s_chain(
         //
         const isIgnore_rawExitToMainERC1155 = true;
         const strDRC_rawExitToMainERC1155 = "erc1155_payment_from_s_chain, rawExitToMainERC1155";
-        await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC1155, joAccountSrc, strDRC_rawExitToMainERC1155, isIgnore_rawExitToMainERC1155, gasPrice, estimatedGas_exitToMainERC1155, "0" );
+        const strErrorOfDryRun_rawExitToMainERC1155 = await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC1155, joAccountSrc, strDRC_rawExitToMainERC1155, isIgnore_rawExitToMainERC1155, gasPrice, estimatedGas_exitToMainERC1155, "0" );
+        if( strErrorOfDryRun_rawExitToMainERC1155 )
+            throw new Error( strErrorOfDryRun_rawExitToMainERC1155 );
         //
         const rawTxExitToMainERC1155 = compose_tx_instance(
             details,
@@ -2895,7 +3154,6 @@ async function do_erc1155_batch_payment_from_s_chain(
         //
         //
         strActionName = "ERC1155 Batch prepare S->M";
-        const accountForMainnet = joAccountDst.address( w3_main_net );
         const accountForSchain = joAccountSrc.address( w3_s_chain );
         const erc1155ABI = joErc1155_s_chain[strCoinNameErc1155_s_chain + "_abi"];
         const erc1155Address_s_chain = joErc1155_s_chain[strCoinNameErc1155_s_chain + "_address"];
@@ -2913,7 +3171,6 @@ async function do_erc1155_batch_payment_from_s_chain(
         const erc1155Address_main_net = joErc1155_main_net[strCoinNameErc1155_main_net + "_address"];
         const methodWithArguments_rawExitToMainERC1155Batch = jo_token_manager_erc1155.methods.exitToMainERC1155Batch(
             erc1155Address_main_net,
-            accountForMainnet,
             token_ids, //"0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ),
             token_amounts //"0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 )
             // "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 )
@@ -2927,7 +3184,7 @@ async function do_erc1155_batch_payment_from_s_chain(
         //
         //
         strActionName = "create ERC1155 Batch/approve transaction S->M";
-        let tcnt = parseInt( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
+        let tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
         details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" );
         //
         const estimatedGas_approve = await tc_s_chain.computeGas( methodWithArguments_approve, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" );
@@ -2935,7 +3192,9 @@ async function do_erc1155_batch_payment_from_s_chain(
         //
         const isIgnore_approve = false;
         const strDRC_approve = "erc1155_payment_from_s_chain, approve";
-        await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve,isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        const strErrorOfDryRun_approve = await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve,isIgnore_approve, gasPrice, estimatedGas_approve, "0" );
+        if( strErrorOfDryRun_approve )
+            throw new Error( strErrorOfDryRun_approve );
         //
         const rawTxApprove = {
             chainId: cid_s_chain,
@@ -2976,7 +3235,7 @@ async function do_erc1155_batch_payment_from_s_chain(
         //
         //
         strActionName = "create ERC1155 Batch/rawExitToMain transaction S->M";
-        tcnt = parseInt( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
+        tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) );
         details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" );
         //
         gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 );
@@ -2987,7 +3246,9 @@ async function do_erc1155_batch_payment_from_s_chain(
         //
         const isIgnore_rawExitToMainERC1155Batch = true;
         const strDRC_rawExitToMainERC1155Batch = "erc1155_batch_payment_from_s_chain, rawExitToMainERC1155Batch";
-        await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC1155Batch, joAccountSrc, strDRC_rawExitToMainERC1155Batch, isIgnore_rawExitToMainERC1155Batch, gasPrice, estimatedGas_exitToMainERC1155Batch, "0" );
+        const strErrorOfDryRun_rawExitToMainERC1155Batch = await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC1155Batch, joAccountSrc, strDRC_rawExitToMainERC1155Batch, isIgnore_rawExitToMainERC1155Batch, gasPrice, estimatedGas_exitToMainERC1155Batch, "0" );
+        if( strErrorOfDryRun_rawExitToMainERC1155Batch )
+            throw new Error( strErrorOfDryRun_rawExitToMainERC1155Batch );
         //
         const rawTxExitToMainERC1155Batch = compose_tx_instance(
             details,
@@ -3080,6 +3341,18 @@ function w3_2_url( w3 ) {
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
+function parseIntOrHex( s ) {
+    if( typeof s != "string" )
+        return parseInt( s );
+    s = s.trim();
+    if( s.length > 2 && s[0] == "0" && ( s[1] == "x" || s[1] == "X" ) )
+        return parseInt( s, 16 );
+    return parseInt( s, 10 );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
 async function async_pending_tx_start( details, w3, w3_opposite, chain_id, chain_id_opposite, txHash ) {
     const strLogPrefix = "";
     try {
@@ -3375,10 +3648,10 @@ async function init_ima_state_file( details, w3, strDirection, optsStateFile ) {
     try {
         nBlockFrom = await w3.eth.getBlockNumber();
     } catch ( err ) { }
+    const strKeyName = ( strDirection == "M2S" ) ? "lastSearchedStartBlockM2S" : "lastSearchedStartBlockS2M";
     try {
         const joStateForLogsSearch = {};
         details.write( strLogPrefix + cc.normal( "(FIRST TIME) Saving next forecasted block number for logs search value " ) + cc.info( blockNumberNextForecast ) + "\n" );
-        const strKeyName = ( strDirection == "M2S" ) ? "lastSearchedStartBlockM2S" : "lastSearchedStartBlockS2M";
         joStateForLogsSearch[strKeyName] = nBlockFrom;
         const s = JSON.stringify( joStateForLogsSearch, null, 4 );
         fs.writeFileSync( optsStateFile.path, s );
@@ -3523,16 +3796,33 @@ async function do_transfer(
             let nBlockFrom = 0;
             const nBlockTo = "latest";
             let joStateForLogsSearch = {};
-            const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3_src ); // await get_web3_universal_call( 10, "BlockNumber", w3, null, null );
+            // const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3_src );
             if( optsStateFile && optsStateFile.isEnabled && "path" in optsStateFile && typeof optsStateFile.path == "string" && optsStateFile.path.length > 0 ) {
+                const strKeyName = ( strDirection == "M2S" ) ? "lastSearchedStartBlockM2S" : "lastSearchedStartBlockS2M";
                 try {
                     const s = fs.readFileSync( optsStateFile.path );
                     joStateForLogsSearch = JSON.parse( s );
-                    const strKeyName = ( strDirection == "M2S" ) ? "lastSearchedStartBlockM2S" : "lastSearchedStartBlockS2M";
-                    if( strKeyName in joStateForLogsSearch && typeof joStateForLogsSearch[strKeyName] == "string" )
+                    if( strKeyName in joStateForLogsSearch && typeof joStateForLogsSearch[strKeyName] == "string" ) {
                         nBlockFrom = "0x" + w3_src.utils.toBN( joStateForLogsSearch[strKeyName] ).toString( 16 );
+                        details.write( strLogPrefix +
+                            cc.normal( "Loaded nearest previously forecasted " ) +
+                            cc.bright( strDirection ) + cc.debug( "/" ) + cc.attention( strKeyName ) +
+                            cc.normal( " block number for logs search value " ) +
+                            cc.info( nBlockFrom ) + "\n" );
+                    } else {
+                        details.write( strLogPrefix +
+                            cc.normal( "Was not found nearest previously forecasted " ) +
+                            cc.bright( strDirection ) + cc.debug( "/" ) + cc.attention( strKeyName ) +
+                            cc.normal( " block number for logs search value " ) +
+                            cc.info( nBlockFrom ) + "\n" );
+                    }
                 } catch ( err ) {
                     nBlockFrom = 0;
+                    details.write( strLogPrefix +
+                        cc.error( "Was reset nearest previously forecasted " ) +
+                        cc.bright( strDirection ) + cc.debug( "/" ) + cc.attention( strKeyName ) +
+                        cc.error( " block number for logs search value " ) +
+                        cc.error( nBlockFrom ) + cc.error( " due to error: " ) + cc.warning( err ) + "\n" );
                 }
             }
             // blockNumberNextForecast = nBlockFrom;
@@ -3543,13 +3833,12 @@ async function do_transfer(
                     break;
                 //
                 //
-                strActionName = "src-chain.MessageProxy.getPastEvents()";
+                strActionName = "src-chain->MessageProxy->scan-past-events()";
                 details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) +
-                cc.debug( " for " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event, starting block number is " ) +
-                cc.info( nBlockFrom ) + cc.debug( ", current latest block number is ~ " ) + cc.info( nLatestBlockNumber ) +
-                cc.debug( "..." ) + "\n" );
-                r = await get_web3_pastEvents(
+                cc.debug( " for " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event..." ) + "\n" );
+                r = await get_web3_pastEventsProgressive(
                     details,
+                    w3_src,
                     10,
                     jo_message_proxy_src,
                     "OutgoingMessage",
@@ -3891,7 +4180,9 @@ async function do_transfer(
                 //
                 const isIgnore_postIncomingMessages = false;
                 const strDRC_postIncomingMessages = "postIncomingMessages in message signer";
-                await dry_run_call( details, w3_dst, methodWithArguments_postIncomingMessages, joAccountDst, strDRC_postIncomingMessages,isIgnore_postIncomingMessages, gasPrice, estimatedGas_postIncomingMessages, "0" );
+                const strErrorOfDryRun = await dry_run_call( details, w3_dst, methodWithArguments_postIncomingMessages, joAccountDst, strDRC_postIncomingMessages,isIgnore_postIncomingMessages, gasPrice, estimatedGas_postIncomingMessages, "0" );
+                if( strErrorOfDryRun )
+                    throw new Error( strErrorOfDryRun );
                 //
                 const raw_tx_postIncomingMessages = {
                     chainId: cid_dst,
@@ -3961,9 +4252,13 @@ async function do_transfer(
 
                 if( optsStateFile && optsStateFile.isEnabled && "path" in optsStateFile && typeof optsStateFile.path == "string" && optsStateFile.path.length > 0 ) {
                     if( blockNumberNextForecast !== nBlockFrom ) {
+                        const strKeyName = ( strDirection == "M2S" ) ? "lastSearchedStartBlockM2S" : "lastSearchedStartBlockS2M";
                         try {
-                            details.write( strLogPrefix + cc.normal( "Saving next forecasted block number for logs search value " ) + cc.info( blockNumberNextForecast ) + "\n" );
-                            const strKeyName = ( strDirection == "M2S" ) ? "lastSearchedStartBlockM2S" : "lastSearchedStartBlockS2M";
+                            details.write( strLogPrefix +
+                                cc.normal( "Saving next forecasted " +
+                                cc.bright( strDirection ) + cc.debug( "/" ) + cc.attention( strKeyName ) +
+                                " block number for logs search value " ) +
+                                cc.info( blockNumberNextForecast ) + "\n" );
                             joStateForLogsSearch[strKeyName] = blockNumberNextForecast;
                             const s = JSON.stringify( joStateForLogsSearch, null, 4 );
                             fs.writeFileSync( optsStateFile.path, s );
@@ -3978,6 +4273,10 @@ async function do_transfer(
                 if( expose_details_get() )
                     details.exposeDetailsTo( log, "do_transfer", true );
                 details.close();
+            } ).catch( ( err ) => {
+                bErrorInSigningMessages = true;
+                if( verbose_get() >= RV_VERBOSE.fatal )
+                    log.write( strLogPrefix + cc.error( "Problem in transfer handler: " ) + cc.warning( err ) + "\n" );
             } );
             if( bErrorInSigningMessages )
                 break;
@@ -4038,9 +4337,9 @@ class TransactionCustomizer {
         this.gasMultiplier = gasMultiplier ? ( 0.0 + gasMultiplier ) : 1.25;
     }
     async computeGasPrice( w3, maxGasPrice ) {
-        const gasPrice = parseInt( await w3.eth.getGasPrice() );
+        const gasPrice = parseIntOrHex( await w3.eth.getGasPrice() );
         if( gasPrice == 0 || gasPrice == null || gasPrice == undefined || gasPrice <= 1000000000 )
-            return parseInt( "1000000000" );
+            return parseIntOrHex( "1000000000" );
         else if(
             this.gasPriceMultiplier != null &&
             this.gasPriceMultiplier != undefined &&
@@ -4049,9 +4348,9 @@ class TransactionCustomizer {
             maxGasPrice != undefined
         ) {
             if( gasPrice * this.gasPriceMultiplier > maxGasPrice )
-                return parseInt( maxGasPrice );
+                return parseIntOrHex( maxGasPrice );
             else
-                return gasPrice * this.gasPriceMultiplier;
+                return parseIntOrHex( ( gasPrice * this.gasPriceMultiplier ).toString() );
         } else
             return gasPrice;
     }
@@ -4073,7 +4372,7 @@ class TransactionCustomizer {
             estimatedGas = 0;
         }
         estimatedGas *= this.gasMultiplier;
-        estimatedGas = parseInt( "" + estimatedGas ); // avoid using floating point
+        estimatedGas = parseIntOrHex( "" + estimatedGas ); // avoid using floating point
         if( estimatedGas == 0 )
             estimatedGas = recommendedGas;
         return estimatedGas;
@@ -4252,6 +4551,16 @@ module.exports.getWaitForNextBlockOnSChain = getWaitForNextBlockOnSChain;
 module.exports.setWaitForNextBlockOnSChain = setWaitForNextBlockOnSChain;
 module.exports.get_web3_blockNumber = get_web3_blockNumber;
 module.exports.get_web3_pastEvents = get_web3_pastEvents;
+module.exports.get_web3_pastEventsIterative = get_web3_pastEventsIterative;
+module.exports.get_web3_pastEventsProgressive = get_web3_pastEventsProgressive;
+module.exports.getBlocksCountInInIterativeStepOfEventsScan = getBlocksCountInInIterativeStepOfEventsScan;
+module.exports.setBlocksCountInInIterativeStepOfEventsScan = setBlocksCountInInIterativeStepOfEventsScan;
+module.exports.getMaxIterationsInAllRangeEventsScan = getMaxIterationsInAllRangeEventsScan;
+module.exports.setMaxIterationsInAllRangeEventsScan = setMaxIterationsInAllRangeEventsScan;
+module.exports.getEnabledProgressiveEventsScan = getEnabledProgressiveEventsScan;
+module.exports.setEnabledProgressiveEventsScan = setEnabledProgressiveEventsScan;
+
+module.exports.parseIntOrHex = parseIntOrHex;
 
 module.exports.balanceETH = balanceETH;
 module.exports.balanceERC20 = balanceERC20;
diff --git a/npms/skale-ima/package.json b/npms/skale-ima/package.json
index 8b932fa01..d592a88b5 100644
--- a/npms/skale-ima/package.json
+++ b/npms/skale-ima/package.json
@@ -34,7 +34,7 @@
         "colors": "^1.4.0",
         "ethereumjs-tx": "1.3.7",
         "ethereumjs-wallet": "1.0.1",
-        "ethereumjs-util": "7.0.10",
+        "ethereumjs-util": "7.1.0",
         "web3": "^1.4.0",
         "ioredis": "^4.27.5"
     },
diff --git a/npms/skale-ima/yarn.lock b/npms/skale-ima/yarn.lock
index 5291467c0..c4d4877d9 100644
--- a/npms/skale-ima/yarn.lock
+++ b/npms/skale-ima/yarn.lock
@@ -996,10 +996,10 @@ ethereumjs-tx@1.3.7:
     ethereum-common "^0.0.18"
     ethereumjs-util "^5.0.0"
 
-ethereumjs-util@7.0.10, ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2:
-  version "7.0.10"
-  resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz#5fb7b69fa1fda0acc59634cf39d6b0291180fc1f"
-  integrity sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==
+ethereumjs-util@7.1.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz#e2b43a30bfcdbcb432a4eb42bd5f2393209b3fd5"
+  integrity sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw==
   dependencies:
     "@types/bn.js" "^5.1.0"
     bn.js "^5.1.2"
@@ -1021,6 +1021,18 @@ ethereumjs-util@^5.0.0:
     rlp "^2.0.0"
     safe-buffer "^5.1.1"
 
+ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2:
+  version "7.0.10"
+  resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz#5fb7b69fa1fda0acc59634cf39d6b0291180fc1f"
+  integrity sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==
+  dependencies:
+    "@types/bn.js" "^5.1.0"
+    bn.js "^5.1.2"
+    create-hash "^1.1.2"
+    ethereum-cryptography "^0.1.3"
+    ethjs-util "0.1.6"
+    rlp "^2.2.4"
+
 ethereumjs-wallet@1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-1.0.1.tgz#664a4bcacfc1291ca2703de066df1178938dba1c"
diff --git a/proxy/contracts/mainnet/CommunityPool.sol b/proxy/contracts/mainnet/CommunityPool.sol
index e619e91d2..6b7b078d0 100644
--- a/proxy/contracts/mainnet/CommunityPool.sol
+++ b/proxy/contracts/mainnet/CommunityPool.sol
@@ -84,19 +84,27 @@ contract CommunityPool is Twin {
         node.sendValue(amount);
     }
 
-    function rechargeUserWallet(string calldata schainName) external payable {
+    /**
+     * @dev Allows `msg.sender` to recharge their wallet for further gas reimbursement.
+     * 
+     * Requirements:
+     * 
+     * - 'msg.sender` should recharge their gas wallet for amount that enough to reimburse any 
+     *   transaction from schain to mainnet.
+     */
+    function rechargeUserWallet(string calldata schainName, address user) external payable {
         bytes32 schainHash = keccak256(abi.encodePacked(schainName));
         require(
-            msg.value + _userWallets[msg.sender][schainHash] >= minTransactionGas * tx.gasprice,
+            msg.value + _userWallets[user][schainHash] >= minTransactionGas * tx.gasprice,
             "Not enough ETH for transaction"
         );
-        _userWallets[msg.sender][schainHash] = _userWallets[msg.sender][schainHash] + msg.value;
-        if (!activeUsers[msg.sender][schainHash]) {
-            activeUsers[msg.sender][schainHash] = true;
+        _userWallets[user][schainHash] = _userWallets[user][schainHash] + msg.value;
+        if (!activeUsers[user][schainHash]) {
+            activeUsers[user][schainHash] = true;
             messageProxy.postOutgoingMessage(
                 schainHash,
                 schainLinks[schainHash],
-                Messages.encodeActivateUserMessage(msg.sender)
+                Messages.encodeActivateUserMessage(user)
             );
         }
     }
@@ -125,7 +133,7 @@ contract CommunityPool is Twin {
         minTransactionGas = newMinTransactionGas;
     }
 
-    function getBalance(string calldata schainName) external view returns (uint) {
-        return _userWallets[msg.sender][keccak256(abi.encodePacked(schainName))];
+    function getBalance(address user, string calldata schainName) external view returns (uint) {
+        return _userWallets[user][keccak256(abi.encodePacked(schainName))];
     }
 }
diff --git a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol
index 482e033ef..116b17934 100644
--- a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol
+++ b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol
@@ -79,12 +79,11 @@ contract DepositBoxERC1155 is DepositBox, ERC1155ReceiverUpgradeable {
     function depositERC1155(
         string calldata schainName,
         address erc1155OnMainnet,
-        address to,
         uint256 id,
         uint256 amount
     )
         external
-        rightTransaction(schainName, to)
+        rightTransaction(schainName, msg.sender)
         whenNotKilled(keccak256(abi.encodePacked(schainName)))
     {
         bytes32 schainHash = keccak256(abi.encodePacked(schainName));
@@ -97,7 +96,7 @@ contract DepositBoxERC1155 is DepositBox, ERC1155ReceiverUpgradeable {
         bytes memory data = _receiveERC1155(
             schainName,
             erc1155OnMainnet,
-            to,
+            msg.sender,
             id,
             amount
         );
@@ -114,12 +113,11 @@ contract DepositBoxERC1155 is DepositBox, ERC1155ReceiverUpgradeable {
     function depositERC1155Batch(
         string calldata schainName,
         address erc1155OnMainnet,
-        address to,
         uint256[] calldata ids,
         uint256[] calldata amounts
     )
         external
-        rightTransaction(schainName, to)
+        rightTransaction(schainName, msg.sender)
         whenNotKilled(keccak256(abi.encodePacked(schainName)))
     {
         bytes32 schainHash = keccak256(abi.encodePacked(schainName));
@@ -132,7 +130,7 @@ contract DepositBoxERC1155 is DepositBox, ERC1155ReceiverUpgradeable {
         bytes memory data = _receiveERC1155Batch(
             schainName,
             erc1155OnMainnet,
-            to,
+            msg.sender,
             ids,
             amounts
         );
diff --git a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC20.sol b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC20.sol
index 50e30cacf..2d85e78f4 100644
--- a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC20.sol
+++ b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC20.sol
@@ -50,11 +50,10 @@ contract DepositBoxERC20 is DepositBox {
     function depositERC20(
         string calldata schainName,
         address erc20OnMainnet,
-        address to,
         uint256 amount
     )
         external
-        rightTransaction(schainName, to)
+        rightTransaction(schainName, msg.sender)
         whenNotKilled(keccak256(abi.encodePacked(schainName)))
     {
         bytes32 schainHash = keccak256(abi.encodePacked(schainName));
@@ -67,7 +66,7 @@ contract DepositBoxERC20 is DepositBox {
         bytes memory data = _receiveERC20(
             schainName,
             erc20OnMainnet,
-            to,
+            msg.sender,
             amount
         );
         if (!linker.interchainConnections(schainHash))
diff --git a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC721.sol b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC721.sol
index 359acca43..96d638f3d 100644
--- a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC721.sol
+++ b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC721.sol
@@ -45,11 +45,10 @@ contract DepositBoxERC721 is DepositBox {
     function depositERC721(
         string calldata schainName,
         address erc721OnMainnet,
-        address to,
         uint256 tokenId
     )
         external
-        rightTransaction(schainName, to)
+        rightTransaction(schainName, msg.sender)
         whenNotKilled(keccak256(abi.encodePacked(schainName)))
     {
         bytes32 schainHash = keccak256(abi.encodePacked(schainName));
@@ -62,7 +61,7 @@ contract DepositBoxERC721 is DepositBox {
         bytes memory data = _receiveERC721(
             schainName,
             erc721OnMainnet,
-            to,
+            msg.sender,
             tokenId
         );
         if (!linker.interchainConnections(schainHash))
diff --git a/proxy/contracts/mainnet/DepositBoxes/DepositBoxEth.sol b/proxy/contracts/mainnet/DepositBoxes/DepositBoxEth.sol
index 1cfbe6d82..7373b2c8a 100644
--- a/proxy/contracts/mainnet/DepositBoxes/DepositBoxEth.sol
+++ b/proxy/contracts/mainnet/DepositBoxes/DepositBoxEth.sol
@@ -40,10 +40,10 @@ contract DepositBoxEth is DepositBox {
         revert("Use deposit function");
     }
 
-    function deposit(string memory schainName, address to)
+    function deposit(string memory schainName)
         external
         payable
-        rightTransaction(schainName, to)
+        rightTransaction(schainName, msg.sender)
         whenNotKilled(keccak256(abi.encodePacked(schainName)))
     {
         bytes32 schainHash = keccak256(abi.encodePacked(schainName));
@@ -54,7 +54,7 @@ contract DepositBoxEth is DepositBox {
         messageProxy.postOutgoingMessage(
             schainHash,
             contractReceiver,
-            Messages.encodeTransferEthMessage(to, msg.value)
+            Messages.encodeTransferEthMessage(msg.sender, msg.value)
         );
     }
 
diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol
index 45d099cbf..991857e51 100644
--- a/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol
+++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol
@@ -42,6 +42,12 @@ contract TokenManagerERC1155 is TokenManager {
     // address of ERC1155 on Mainnet => ERC1155 on Schain
     mapping(address => ERC1155OnChain) public clonesErc1155;
 
+    // address clone on schain => added or not
+    mapping(ERC1155OnChain => bool) public addedClones;
+
+    /**
+     * @dev Emitted when schain owner register new ERC1155 clone.
+     */
     event ERC1155TokenAdded(address indexed erc1155OnMainnet, address indexed erc1155OnSchain);
 
     event ERC1155TokenCreated(address indexed erc1155OnMainnet, address indexed erc1155OnSchain);
@@ -55,54 +61,50 @@ contract TokenManagerERC1155 is TokenManager {
 
     function exitToMainERC1155(
         address contractOnMainnet,
-        address to,
         uint256 id,
         uint256 amount
     )
         external
     {
-        communityLocker.checkAllowedToSendMessage(to);
-        _exit(MAINNET_HASH, depositBox, contractOnMainnet, to, id, amount);
+        communityLocker.checkAllowedToSendMessage(msg.sender);
+        _exit(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, id, amount);
     }
 
     function exitToMainERC1155Batch(
         address contractOnMainnet,
-        address to,
         uint256[] memory ids,
         uint256[] memory amounts
     )
         external
     {
-        communityLocker.checkAllowedToSendMessage(to);
-        _exitBatch(MAINNET_HASH, depositBox, contractOnMainnet, to, ids, amounts);
+        communityLocker.checkAllowedToSendMessage(msg.sender);
+        _exitBatch(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, ids, amounts);
     }
 
     function transferToSchainERC1155(
         string calldata targetSchainName,
         address contractOnMainnet,
-        address to,
         uint256 id,
         uint256 amount
     ) 
         external
-        rightTransaction(targetSchainName, to)
+        rightTransaction(targetSchainName, msg.sender)
     {
         bytes32 targetSchainHash = keccak256(abi.encodePacked(targetSchainName));
-        _exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, to, id, amount);
+        _exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, id, amount);
     }
 
     function transferToSchainERC1155Batch(
         string calldata targetSchainName,
         address contractOnMainnet,
-        address to,
         uint256[] memory ids,
         uint256[] memory amounts
     ) 
         external
-        rightTransaction(targetSchainName, to)
+        rightTransaction(targetSchainName, msg.sender)
     {
         bytes32 targetSchainHash = keccak256(abi.encodePacked(targetSchainName));
-        _exitBatch(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, to, ids, amounts);
+        _exitBatch(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, ids, amounts);
     }
 
     /**
@@ -156,7 +158,10 @@ contract TokenManagerERC1155 is TokenManager {
         onlyTokenRegistrar
     {
         require(address(erc1155OnSchain).isContract(), "Given address is not a contract");
+        require(address(clonesErc1155[erc1155OnMainnet]) == address(0), "Could not relink clone");
+        require(!addedClones[erc1155OnSchain], "Clone was already added");
         clonesErc1155[erc1155OnMainnet] = erc1155OnSchain;
+        addedClones[erc1155OnSchain] = true;
         emit ERC1155TokenAdded(erc1155OnMainnet, address(erc1155OnSchain));
     }
 
@@ -211,6 +216,7 @@ contract TokenManagerERC1155 is TokenManager {
                 require(automaticDeploy, "Automatic deploy is disabled");
                 contractOnSchain = new ERC1155OnChain(message.tokenInfo.uri);
                 clonesErc1155[token] = contractOnSchain;
+                addedClones[contractOnSchain] = true;
                 emit ERC1155TokenCreated(token, address(contractOnSchain));
             }
         }
diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol
index 43ae197f7..a72c3a2e4 100644
--- a/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol
+++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol
@@ -51,6 +51,12 @@ contract TokenManagerERC20 is TokenManager {
     // address of clone on schain => totalSupplyOnMainnet
     mapping(IERC20Upgradeable => uint) public totalSupplyOnMainnet;
 
+    // address clone on schain => added or not
+    mapping(ERC20OnChain => bool) public addedClones;
+
+    /**
+     * @dev Emitted when schain owner register new ERC20 clone.
+     */
     event ERC20TokenAdded(address indexed erc20OnMainnet, address indexed erc20OnSchain);
 
     event ERC20TokenCreated(address indexed erc20OnMainnet, address indexed erc20OnSchain);
@@ -59,26 +65,24 @@ contract TokenManagerERC20 is TokenManager {
 
     function exitToMainERC20(
         address contractOnMainnet,
-        address to,
         uint256 amount
     )
         external
     {
-        communityLocker.checkAllowedToSendMessage(to);
-        _exit(MAINNET_HASH, depositBox, contractOnMainnet, to, amount);
+        communityLocker.checkAllowedToSendMessage(msg.sender);
+        _exit(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, amount);
     }
 
     function transferToSchainERC20(
         string calldata targetSchainName,
         address contractOnMainnet,
-        address to,
         uint256 amount
     )
         external
-        rightTransaction(targetSchainName, to)
+        rightTransaction(targetSchainName, msg.sender)
     {
         bytes32 targetSchainHash = keccak256(abi.encodePacked(targetSchainName));
-        _exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, to, amount);
+        _exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, amount);
     }
 
     /**
@@ -128,7 +132,10 @@ contract TokenManagerERC20 is TokenManager {
     {
         require(address(erc20OnSchain).isContract(), "Given address is not a contract");
         require(erc20OnSchain.totalSupply() == 0, "TotalSupply is not zero");
+        require(address(clonesErc20[erc20OnMainnet]) == address(0), "Could not relink clone");
+        require(!addedClones[erc20OnSchain], "Clone was already added");
         clonesErc20[erc20OnMainnet] = erc20OnSchain;
+        addedClones[erc20OnSchain] = true;
         emit ERC20TokenAdded(erc20OnMainnet, address(erc20OnSchain));
     }
 
@@ -185,6 +192,7 @@ contract TokenManagerERC20 is TokenManager {
                 require(automaticDeploy, "Automatic deploy is disabled");
                 contractOnSchain = new ERC20OnChain(message.tokenInfo.name, message.tokenInfo.symbol);
                 clonesErc20[token] = contractOnSchain;
+                addedClones[contractOnSchain] = true;
                 emit ERC20TokenCreated(token, address(contractOnSchain));
             }
         }
diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol
index 1279971d2..efabebfe5 100644
--- a/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol
+++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol
@@ -41,6 +41,12 @@ contract TokenManagerERC721 is TokenManager {
     // address of ERC721 on Mainnet => ERC721 on Schain
     mapping(address => ERC721OnChain) public clonesErc721;
 
+    // address clone on schain => added or not
+    mapping(ERC721OnChain => bool) public addedClones;
+
+    /**
+     * @dev Emitted when schain owner register new ERC721 clone.
+     */
     event ERC721TokenAdded(address indexed erc721OnMainnet, address indexed erc721OnSchain);
 
     event ERC721TokenCreated(address indexed erc721OnMainnet, address indexed erc721OnSchain);
@@ -49,26 +55,24 @@ contract TokenManagerERC721 is TokenManager {
 
     function exitToMainERC721(
         address contractOnMainnet,
-        address to,
         uint256 tokenId
     )
         external
     {
-        communityLocker.checkAllowedToSendMessage(to);
-        _exit(MAINNET_HASH, depositBox, contractOnMainnet, to, tokenId);
+        communityLocker.checkAllowedToSendMessage(msg.sender);
+        _exit(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, tokenId);
     }
 
     function transferToSchainERC721(
         string calldata targetSchainName,
         address contractOnMainnet,
-        address to,
         uint256 tokenId
     ) 
         external
-        rightTransaction(targetSchainName, to)
+        rightTransaction(targetSchainName, msg.sender)
     {
         bytes32 targetSchainHash = keccak256(abi.encodePacked(targetSchainName));
-        _exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, to, tokenId);
+        _exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, tokenId);
     }
 
     /**
@@ -117,7 +121,10 @@ contract TokenManagerERC721 is TokenManager {
         onlyTokenRegistrar
     {
         require(address(erc721OnSchain).isContract(), "Given address is not a contract");
+        require(address(clonesErc721[erc721OnMainnet]) == address(0), "Could not relink clone");
+        require(!addedClones[erc721OnSchain], "Clone was already added");
         clonesErc721[erc721OnMainnet] = erc721OnSchain;
+        addedClones[erc721OnSchain] = true;
         emit ERC721TokenAdded(erc721OnMainnet, address(erc721OnSchain));
     }
 
@@ -169,6 +176,7 @@ contract TokenManagerERC721 is TokenManager {
                 require(automaticDeploy, "Automatic deploy is disabled");
                 contractOnSchain = new ERC721OnChain(message.tokenInfo.name, message.tokenInfo.symbol);           
                 clonesErc721[token] = contractOnSchain;
+                addedClones[contractOnSchain] = true;
                 emit ERC721TokenCreated(token, address(contractOnSchain));
             }
         }
diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol b/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol
index 967865b98..633fc620c 100644
--- a/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol
+++ b/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol
@@ -53,21 +53,20 @@ contract TokenManagerEth is TokenManager {
     /**
      * @dev Performs an exit (post outgoing message) to Mainnet.
      */
-    function exitToMain(address to, uint256 amount) external {
-        communityLocker.checkAllowedToSendMessage(to);
-        _exit(MAINNET_HASH, depositBox, to, amount);
+    function exitToMain(uint256 amount) external {
+        communityLocker.checkAllowedToSendMessage(msg.sender);
+        _exit(MAINNET_HASH, depositBox, msg.sender, amount);
     }
 
     function transferToSchain(
         string memory targetSchainName,
-        address to,
         uint256 amount
     )
         external
-        rightTransaction(targetSchainName, to)
+        rightTransaction(targetSchainName, msg.sender)
     {
         bytes32 targetSchainHash = keccak256(abi.encodePacked(targetSchainName));
-        _exit(targetSchainHash, tokenManagers[targetSchainHash], to, amount);
+        _exit(targetSchainHash, tokenManagers[targetSchainHash], msg.sender, amount);
     }
 
     /**
diff --git a/proxy/gas/calculateGas.ts b/proxy/gas/calculateGas.ts
index fa7ab1f63..6012da2e3 100644
--- a/proxy/gas/calculateGas.ts
+++ b/proxy/gas/calculateGas.ts
@@ -276,7 +276,7 @@ describe("Gas calculation", () => {
         // IMA registration
         await messageProxyForMainnet.grantRole(await messageProxyForMainnet.CHAIN_CONNECTOR_ROLE(), imaLinker.address);
         await imaLinker.connectSchain(schainName, [tokenManagerLinker.address, communityLocker.address, tokenManagerEth.address, tokenManagerERC20.address, tokenManagerERC721.address, tokenManagerERC1155.address]);
-        await communityPool.connect(user).rechargeUserWallet(schainName, { value: 1e18.toString() });
+        await communityPool.connect(user).rechargeUserWallet(schainName, user.address, { value: 1e18.toString() });
         // await lockAndDataForSchain.addDepositBox(depositBoxEth.address);
         // await lockAndDataForSchain.addDepositBox(depositBoxERC20.address);
         // await lockAndDataForSchain.addDepositBox(depositBoxERC721.address);
@@ -321,19 +321,19 @@ describe("Gas calculation", () => {
         await ERC1155TokenOnSchain.grantRole(minterRoleERC1155, tokenManagerERC1155.address);
 
         // register user
-        await communityPool.connect(user).rechargeUserWallet(schainName, {value: "1000000000000000000"});
+        await communityPool.connect(user).rechargeUserWallet(schainName, user.address, {value: "1000000000000000000"});
     });
 
     it("calculate eth deposits", async () => {
-        let res = await (await depositBoxEth.connect(user).deposit(schainName, user.address, {value: "1000000000000000000"})).wait();
+        let res = await (await depositBoxEth.connect(user).deposit(schainName, {value: "1000000000000000000"})).wait();
         console.log("First deposit eth cost:", res.gasUsed.toNumber());
-        res = await (await depositBoxEth.connect(user).deposit(schainName, user.address, {value: "1000000000000000000"})).wait();
+        res = await (await depositBoxEth.connect(user).deposit(schainName, {value: "1000000000000000000"})).wait();
         console.log("Second deposit eth cost:", res.gasUsed.toNumber());
-        res = await (await depositBoxEth.connect(user).deposit(schainName, user.address, {value: "1000000000000000000"})).wait();
+        res = await (await depositBoxEth.connect(user).deposit(schainName, {value: "1000000000000000000"})).wait();
         console.log("Third deposit eth cost:", res.gasUsed.toNumber());
-        res = await (await depositBoxEth.connect(user).deposit(schainName, user.address, {value: "1000000000000000000"})).wait();
+        res = await (await depositBoxEth.connect(user).deposit(schainName, {value: "1000000000000000000"})).wait();
         console.log("Forth deposit eth cost:", res.gasUsed.toNumber());
-        res = await (await depositBoxEth.connect(user).deposit(schainName, user.address, {value: "1000000000000000000"})).wait();
+        res = await (await depositBoxEth.connect(user).deposit(schainName, {value: "1000000000000000000"})).wait();
         console.log("Fifth deposit eth cost:", res.gasUsed.toNumber());
     });
 
@@ -355,22 +355,22 @@ describe("Gas calculation", () => {
         it("calculate erc20 deposits without eth without automatic deploy", async () => {
             await ERC20TokenOnMainnet.connect(user).approve(depositBoxERC20.address, 5);
 
-            let res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, user.address, 1)).wait();
+            let res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, 1)).wait();
             console.log("First deposit erc20 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, user.address, 1)).wait();
+            res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, 1)).wait();
             console.log("Second deposit erc20 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, user.address, 1)).wait();
+            res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, 1)).wait();
             console.log("Third deposit erc20 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, user.address, 1)).wait();
+            res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, 1)).wait();
             console.log("Forth deposit erc20 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, user.address, 1)).wait();
+            res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, 1)).wait();
             console.log("Deposit all remaining approved erc20 tokens cost:", res.gasUsed.toNumber());
         });
 
         it("calculate erc20 deposits of all approved tokens without eth without automatic deploy", async () => {
             await ERC20TokenOnMainnet.connect(user).approve(depositBoxERC20.address, 5);
 
-            const res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, user.address, 5)).wait();
+            const res = await (await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, 5)).wait();
             console.log("Deposit all approved erc20 tokens at once cost:", res.gasUsed.toNumber());
         });
     });
@@ -418,68 +418,68 @@ describe("Gas calculation", () => {
             await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 9);
             await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 10);
 
-            let res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 1)).wait();
+            let res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 1)).wait();
             console.log("First deposit erc721 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 2)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 2)).wait();
             console.log("Second deposit erc721 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 3)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 3)).wait();
             console.log("Third deposit erc721 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 4)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 4)).wait();
             console.log("Forth deposit erc721 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 5)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 5)).wait();
             console.log("Fifth deposit erc721 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 6)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 6)).wait();
             console.log("Sixth deposit erc721 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 7)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 7)).wait();
             console.log("Seventh deposit erc721 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 8)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 8)).wait();
             console.log("Eighth deposit erc721 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 9)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 9)).wait();
             console.log("Ninth deposit erc721 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 10)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 10)).wait();
             console.log("Tenth deposit erc721 cost:", res.gasUsed.toNumber());
         });
 
         it("calculate erc721 deposits without eth without automatic deploy and approve each time", async () => {
             let res = await (await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 1)).wait();
             console.log("First approve of ERC721 token cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 1)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 1)).wait();
             console.log("First deposit erc721 cost:", res.gasUsed.toNumber());
             res = await (await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 2)).wait();
             console.log("Second approve of ERC721 token cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 2)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 2)).wait();
             console.log("Second deposit erc721 cost:", res.gasUsed.toNumber());
             res = await (await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 3)).wait();
             console.log("Third approve of ERC721 token cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 3)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 3)).wait();
             console.log("Third deposit erc721 cost:", res.gasUsed.toNumber());
             res = await (await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 4)).wait();
             console.log("Forth approve of ERC721 token cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 4)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 4)).wait();
             console.log("Forth deposit erc721 cost:", res.gasUsed.toNumber());
             res = await (await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 5)).wait();
             console.log("Fifth approve of ERC721 token cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 5)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 5)).wait();
             console.log("Fifth deposit erc721 cost:", res.gasUsed.toNumber());
             res = await (await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 6)).wait();
             console.log("Sixth approve of ERC721 token cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 6)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 6)).wait();
             console.log("Sixth deposit erc721 cost:", res.gasUsed.toNumber());
             res = await (await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 7)).wait();
             console.log("Seventh approve of ERC721 token cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 7)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 7)).wait();
             console.log("Seventh deposit erc721 cost:", res.gasUsed.toNumber());
             res = await (await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 8)).wait();
             console.log("Eighth approve of ERC721 token cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 8)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 8)).wait();
             console.log("Eighth deposit erc721 cost:", res.gasUsed.toNumber());
             res = await (await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 9)).wait();
             console.log("Ninth approve of ERC721 token cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 9)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 9)).wait();
             console.log("Ninth deposit erc721 cost:", res.gasUsed.toNumber());
             res = await (await ERC721TokenOnMainnet.connect(user).approve(depositBoxERC721.address, 10)).wait();
             console.log("Tenth approve of ERC721 token cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, 10)).wait();
+            res = await (await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, 10)).wait();
             console.log("Tenth deposit erc721 cost:", res.gasUsed.toNumber());
         });
     });
@@ -500,50 +500,50 @@ describe("Gas calculation", () => {
         it("calculate erc1155 deposits without eth without automatic deploy", async () => {
             await ERC1155TokenOnMainnet.connect(user).setApprovalForAll(depositBoxERC1155.address, true);
 
-            let res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, 1, 1)).wait();
+            let res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, 1, 1)).wait();
             console.log("First deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, 2, 2)).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, 2, 2)).wait();
             console.log("Second deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, 3, 3)).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, 3, 3)).wait();
             console.log("Third deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, 4, 4)).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, 4, 4)).wait();
             console.log("Forth deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, 5, 5)).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, 5, 5)).wait();
             console.log("Fifth deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, 6, 6)).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, 6, 6)).wait();
             console.log("Sixth deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, 7, 7)).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, 7, 7)).wait();
             console.log("Seventh deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, 8, 8)).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, 8, 8)).wait();
             console.log("Eighth deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, 9, 9)).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, 9, 9)).wait();
             console.log("Ninth deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, 10, 10)).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, 10, 10)).wait();
             console.log("Tenth deposit erc1155 cost:", res.gasUsed.toNumber());
         });
 
         it("calculate erc1155 deposits batches without eth without automatic deploy", async () => {
             await ERC1155TokenOnMainnet.connect(user).setApprovalForAll(depositBoxERC1155.address, true);
 
-            let res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])).wait();
+            let res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1])).wait();
             console.log("First deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, [2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 1, 1, 1, 1, 1, 1, 1, 1])).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, [2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 1, 1, 1, 1, 1, 1, 1, 1])).wait();
             console.log("Second deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, [3, 4, 5, 6, 7, 8, 9, 10], [1, 1, 1, 1, 1, 1, 1, 1])).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, [3, 4, 5, 6, 7, 8, 9, 10], [1, 1, 1, 1, 1, 1, 1, 1])).wait();
             console.log("Third deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, [4, 5, 6, 7, 8, 9, 10], [1, 1, 1, 1, 1, 1, 1])).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, [4, 5, 6, 7, 8, 9, 10], [1, 1, 1, 1, 1, 1, 1])).wait();
             console.log("Forth deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, [5, 6, 7, 8, 9, 10], [1, 1, 1, 1, 1, 1])).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, [5, 6, 7, 8, 9, 10], [1, 1, 1, 1, 1, 1])).wait();
             console.log("Fifth deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, [6, 7, 8, 9, 10], [1, 1, 1, 1, 1])).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, [6, 7, 8, 9, 10], [1, 1, 1, 1, 1])).wait();
             console.log("Sixth deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, [7, 8, 9, 10], [1, 1, 1, 1])).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, [7, 8, 9, 10], [1, 1, 1, 1])).wait();
             console.log("Seventh deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, [8, 9, 10], [1, 1, 1])).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, [8, 9, 10], [1, 1, 1])).wait();
             console.log("Eighth deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, [9, 10], [1, 1])).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, [9, 10], [1, 1])).wait();
             console.log("Ninth deposit erc1155 cost:", res.gasUsed.toNumber());
-            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, [10], [1])).wait();
+            res = await (await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, [10], [1])).wait();
             console.log("Tenth deposit erc1155 cost:", res.gasUsed.toNumber());
         });
     });
@@ -584,7 +584,7 @@ describe("Gas calculation", () => {
             }
 
             async function sendEth() {
-                await depositBoxEth.connect(user).deposit(schainName, user.address, {value: "1000000000000000000"});
+                await depositBoxEth.connect(user).deposit(schainName, {value: "1000000000000000000"});
             }
 
             async function getMyEth(action: string) {
@@ -813,7 +813,7 @@ describe("Gas calculation", () => {
 
         describe("ERC20 Token registered and approved", async () => {
 
-            // prepare exit message of erc20 token - await TokenManager.exitToMainERC20(ERC20TokenOnMainnet.address, user.address, amount, {from: user});
+            // prepare exit message of erc20 token - await TokenManager.exitToMainERC20(ERC20TokenOnMainnet.address, amount, {from: user});
             async function getERC20Message(amount: number) {
                 return {
                     data: await messages.encodeTransferErc20Message(ERC20TokenOnMainnet.address, user.address, amount),
@@ -823,7 +823,7 @@ describe("Gas calculation", () => {
             }
 
             async function sendERC20(amount: number) {
-                await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, user.address, amount);
+                await depositBoxERC20.connect(user).depositERC20(schainName, ERC20TokenOnMainnet.address, amount);
             }
 
             async function checkBalance() {
@@ -920,7 +920,7 @@ describe("Gas calculation", () => {
 
         describe("ERC721 Token registered and approved", async() => {
 
-            // prepare exit message of erc721 token - await TokenManager.exitToMainERC721(ERC721TokenOnMainnet.address, user.address, tokenId, {from: user});
+            // prepare exit message of erc721 token - await TokenManager.exitToMainERC721(ERC721TokenOnMainnet.address, tokenId, {from: user});
             async function getERC721Message(tokenId: number) {
                 return {
                     data: await messages.encodeTransferErc721Message(ERC721TokenOnMainnet.address, user.address, tokenId),
@@ -930,7 +930,7 @@ describe("Gas calculation", () => {
             }
 
             async function sendERC721(tokenId: number) {
-                await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, user.address, tokenId);
+                await depositBoxERC721.connect(user).depositERC721(schainName, ERC721TokenOnMainnet.address, tokenId);
             }
 
             async function checkBalance() {
@@ -1055,7 +1055,7 @@ describe("Gas calculation", () => {
 
         describe("ERC1155 Token registered and approved", async() => {
 
-            // prepare exit message of erc1155 token - await TokenManager.exitToMainERC721(ERC721TokenOnMainnet.address, user.address, tokenId, amount, {from: user});
+            // prepare exit message of erc1155 token - await TokenManager.exitToMainERC721(ERC721TokenOnMainnet.address, tokenId, amount, {from: user});
             async function getERC1155Message(tokenId: number, amount: number) {
                 return {
                     data: await messages.encodeTransferErc1155Message(ERC1155TokenOnMainnet.address, user.address, tokenId, amount),
@@ -1064,7 +1064,7 @@ describe("Gas calculation", () => {
                 };
             }
 
-            // prepare exit batch message of erc1155 token - await TokenManager.exitToMainERC721(ERC721TokenOnMainnet.address, user.address, tokenId, amounts, {from: user});
+            // prepare exit batch message of erc1155 token - await TokenManager.exitToMainERC721(ERC721TokenOnMainnet.address, tokenId, amounts, {from: user});
             async function getERC1155BatchMessage(tokenIds: number[], amounts: number[]) {
                 return {
                     data: await messages.encodeTransferErc1155BatchMessage(ERC1155TokenOnMainnet.address, user.address, tokenIds, amounts),
@@ -1074,11 +1074,11 @@ describe("Gas calculation", () => {
             }
 
             async function sendERC1155(tokenId: number, amount: number) {
-                await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, user.address, tokenId, amount);
+                await depositBoxERC1155.connect(user).depositERC1155(schainName, ERC1155TokenOnMainnet.address, tokenId, amount);
             }
 
             async function sendERC1155Batch(tokenIds: number[], amounts: number[]) {
-                await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, user.address, tokenIds, amounts);
+                await depositBoxERC1155.connect(user).depositERC1155Batch(schainName, ERC1155TokenOnMainnet.address, tokenIds, amounts);
             }
 
             async function checkBalance() {
diff --git a/proxy/hardhat.config.ts b/proxy/hardhat.config.ts
index 3210cf9dc..226ae67ef 100644
--- a/proxy/hardhat.config.ts
+++ b/proxy/hardhat.config.ts
@@ -48,6 +48,7 @@ const config: HardhatUserConfig = {
   },
   networks: {
     hardhat: {
+      hardfork: "berlin",
       blockGasLimit: 12000000,
       allowUnlimitedContractSize: true
     },
diff --git a/proxy/package.json b/proxy/package.json
index 7d26d611d..3316263ca 100644
--- a/proxy/package.json
+++ b/proxy/package.json
@@ -22,13 +22,13 @@
     "dependencies": {
         "@nomiclabs/hardhat-ethers": "^2.0.2",
         "@nomiclabs/hardhat-web3": "^2.0.0",
-        "@openzeppelin/contracts-upgradeable": "^4.1.0",
+        "@openzeppelin/contracts-upgradeable": "^4.2.0",
         "@openzeppelin/hardhat-upgrades": "^1.9.0",
         "@skalenetwork/skale-manager-interfaces": "^0.1.1",
         "dotenv": "^10.0.0",
         "ethereumjs-tx": "2.1.2",
         "ethers": "^5.4.1",
-        "hardhat": "^2.4.1",
+        "hardhat": "^2.1.2",
         "path": "^0.12.7",
         "web3": "^1.4.0"
     },
diff --git a/proxy/yarn.lock b/proxy/yarn.lock
index 8d8a7f800..ed06b8f2c 100644
--- a/proxy/yarn.lock
+++ b/proxy/yarn.lock
@@ -92,32 +92,32 @@
     patch-package "^6.2.2"
     postinstall-postinstall "^2.1.0"
 
-"@ethereumjs/block@^3.2.1", "@ethereumjs/block@^3.3.0":
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.3.0.tgz#a1b3baec831c71c0d9e7f6145f25e919cff4939c"
-  integrity sha512-WoefY9Rs4W8vZTxG9qwntAlV61xsSv0NPoXmHO7x3SH16dwJQtU15YvahPCz4HEEXbu7GgGgNgu0pv8JY7VauA==
-  dependencies:
-    "@ethereumjs/common" "^2.3.0"
-    "@ethereumjs/tx" "^3.2.0"
-    ethereumjs-util "^7.0.10"
+"@ethereumjs/block@^3.4.0":
+  version "3.4.0"
+  resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.4.0.tgz#4747b0c06220ee10cbdfe1cbde8cbb0677b1b074"
+  integrity sha512-umKAoTX32yXzErpIksPHodFc/5y8bmZMnOl6hWy5Vd8xId4+HKFUOyEiN16Y97zMwFRysRpcrR6wBejfqc6Bmg==
+  dependencies:
+    "@ethereumjs/common" "^2.4.0"
+    "@ethereumjs/tx" "^3.3.0"
+    ethereumjs-util "^7.1.0"
     merkle-patricia-tree "^4.2.0"
 
-"@ethereumjs/blockchain@^5.2.1", "@ethereumjs/blockchain@^5.3.0":
-  version "5.3.0"
-  resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.3.0.tgz#206936e30a4320d87a26e58d157eadef21ef6ff1"
-  integrity sha512-B0Y5QDZcRDQISPilv3m8nzk97QmC98DnSE9WxzGpCxfef22Mw7xhwGipci5Iy0dVC2Np2Cr5d3F6bHAR7+yVmQ==
+"@ethereumjs/blockchain@^5.4.0":
+  version "5.4.0"
+  resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.4.0.tgz#28d712627d3442b2bb1f50dd5acba7cde1021993"
+  integrity sha512-wAuKLaew6PL52kH8YPXO7PbjjKV12jivRSyHQehkESw4slSLLfYA6Jv7n5YxyT2ajD7KNMPVh7oyF/MU6HcOvg==
   dependencies:
-    "@ethereumjs/block" "^3.3.0"
-    "@ethereumjs/common" "^2.3.0"
+    "@ethereumjs/block" "^3.4.0"
+    "@ethereumjs/common" "^2.4.0"
     "@ethereumjs/ethash" "^1.0.0"
     debug "^2.2.0"
-    ethereumjs-util "^7.0.10"
+    ethereumjs-util "^7.1.0"
     level-mem "^5.0.1"
     lru-cache "^5.1.1"
     rlp "^2.2.4"
     semaphore-async-await "^1.5.1"
 
-"@ethereumjs/common@^2.2.0", "@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.3.1":
+"@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.3.1":
   version "2.3.1"
   resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.3.1.tgz#d692e3aff5adb35dd587dd1e6caab69e0ed2fa0b"
   integrity sha512-V8hrULExoq0H4HFs3cCmdRGbgmipmlNzak6Xg34nHYfQyqkSdrCuflvYjyWmsNpI8GtrcZhzifAbgX/1C1Cjwg==
@@ -125,6 +125,14 @@
     crc-32 "^1.2.0"
     ethereumjs-util "^7.0.10"
 
+"@ethereumjs/common@^2.4.0":
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.4.0.tgz#2d67f6e6ba22246c5c89104e6b9a119fb3039766"
+  integrity sha512-UdkhFWzWcJCZVsj1O/H8/oqj/0RVYjLc1OhPjBrQdALAkQHpCp8xXI4WLnuGTADqTdJZww0NtgwG+TRPkXt27w==
+  dependencies:
+    crc-32 "^1.2.0"
+    ethereumjs-util "^7.1.0"
+
 "@ethereumjs/ethash@^1.0.0":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@ethereumjs/ethash/-/ethash-1.0.0.tgz#4e77f85b37be1ade5393e8719bdabac3e796ddaa"
@@ -135,7 +143,7 @@
     ethereumjs-util "^7.0.7"
     miller-rabin "^4.0.0"
 
-"@ethereumjs/tx@^3.1.3", "@ethereumjs/tx@^3.2.0", "@ethereumjs/tx@^3.2.1":
+"@ethereumjs/tx@^3.2.1":
   version "3.2.1"
   resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.2.1.tgz#65f5f1c11541764f08377a94ba4b0dcbbd67739e"
   integrity sha512-i9V39OtKvwWos1uVNZxdVhd7zFOyzFLjgt69CoiOY0EmXugS0HjO3uxpLBSglDKFMRriuGqw6ddKEv+RP1UNEw==
@@ -143,22 +151,30 @@
     "@ethereumjs/common" "^2.3.1"
     ethereumjs-util "^7.0.10"
 
-"@ethereumjs/vm@^5.3.2":
-  version "5.3.2"
-  resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.3.2.tgz#b4d83a3d50a7ad22d6d412cc21bbde221b3e2871"
-  integrity sha512-QmCUQrW6xbhgEbQh9njue4kAJdM056C+ytBFUTF/kDYa3kNDm4Qxp9HUyTlt1OCSXvDhws0qqlh8+q+pmXpN7g==
+"@ethereumjs/tx@^3.3.0":
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.0.tgz#14ed1b7fa0f28e1cd61e3ecbdab824205f6a4378"
+  integrity sha512-yTwEj2lVzSMgE6Hjw9Oa1DZks/nKTWM8Wn4ykDNapBPua2f4nXO3qKnni86O6lgDj5fVNRqbDsD0yy7/XNGDEA==
+  dependencies:
+    "@ethereumjs/common" "^2.4.0"
+    ethereumjs-util "^7.1.0"
+
+"@ethereumjs/vm@^5.5.2":
+  version "5.5.2"
+  resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.5.2.tgz#918a2c1000aaa9fdbe6007a4fdc2c62833122adf"
+  integrity sha512-AydZ4wfvZAsBuFzs3xVSA2iU0hxhL8anXco3UW3oh9maVC34kTEytOfjHf06LTEfN0MF9LDQ4ciLa7If6ZN/sg==
   dependencies:
-    "@ethereumjs/block" "^3.2.1"
-    "@ethereumjs/blockchain" "^5.2.1"
-    "@ethereumjs/common" "^2.2.0"
-    "@ethereumjs/tx" "^3.1.3"
+    "@ethereumjs/block" "^3.4.0"
+    "@ethereumjs/blockchain" "^5.4.0"
+    "@ethereumjs/common" "^2.4.0"
+    "@ethereumjs/tx" "^3.3.0"
     async-eventemitter "^0.2.4"
     core-js-pure "^3.0.1"
     debug "^2.2.0"
-    ethereumjs-util "^7.0.10"
+    ethereumjs-util "^7.1.0"
     functional-red-black-tree "^1.0.1"
     mcl-wasm "^0.7.1"
-    merkle-patricia-tree "^4.1.0"
+    merkle-patricia-tree "^4.2.0"
     rustbn.js "~0.2.0"
     util.promisify "^1.0.1"
 
@@ -916,10 +932,10 @@
   dependencies:
     "@types/bignumber.js" "^5.0.0"
 
-"@openzeppelin/contracts-upgradeable@^4.1.0":
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.1.0.tgz#36a6113ceeda278ae14f740280e5388161dfd383"
-  integrity sha512-QZSvbYqNpU/x60vARhq/jghh97VWjml3NAlKfu4u1XehvpEBbHVXJyKTBSZtZY7jviG305jOczEisnN8VeOMcw==
+"@openzeppelin/contracts-upgradeable@^4.2.0":
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.2.0.tgz#3b12d6fe9d51e563c8a6ae39c96c1d32c5d0fa4a"
+  integrity sha512-vn0hoUqQzgOLzLZwFgh+w/D5hzJHX8F7X/7t/gZdSQYIEXMyGpXUwkr5A3eoAeoc42f/n7yDhwusvBmNknM41Q==
 
 "@openzeppelin/hardhat-upgrades@^1.9.0":
   version "1.9.0"
@@ -3984,6 +4000,18 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.0.3, ethereu
     ethjs-util "0.1.6"
     rlp "^2.2.4"
 
+ethereumjs-util@^7.1.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz#e2b43a30bfcdbcb432a4eb42bd5f2393209b3fd5"
+  integrity sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw==
+  dependencies:
+    "@types/bn.js" "^5.1.0"
+    bn.js "^5.1.2"
+    create-hash "^1.1.2"
+    ethereum-cryptography "^0.1.3"
+    ethjs-util "0.1.6"
+    rlp "^2.2.4"
+
 ethereumjs-vm@4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab"
@@ -4894,16 +4922,16 @@ hardhat-typechain@^0.3.5:
   resolved "https://registry.yarnpkg.com/hardhat-typechain/-/hardhat-typechain-0.3.5.tgz#8e50616a9da348b33bd001168c8fda9c66b7b4af"
   integrity sha512-w9lm8sxqTJACY+V7vijiH+NkPExnmtiQEjsV9JKD1KgMdVk2q8y+RhvU/c4B7+7b1+HylRUCxpOIvFuB3rE4+w==
 
-hardhat@^2.4.1:
-  version "2.4.1"
-  resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.4.1.tgz#2cd1e86ee6ca3a6a473eeb0f55bd3124c8c59250"
-  integrity sha512-vwllrFypukeE/Q+4ZfWj7j7nUo4ncUhRpsAYUM0Ruuuk6pQlKmRa0A6c0kxRSvvVgQsMud6j+/weYhbMX1wPmQ==
-  dependencies:
-    "@ethereumjs/block" "^3.3.0"
-    "@ethereumjs/blockchain" "^5.3.0"
-    "@ethereumjs/common" "^2.3.1"
-    "@ethereumjs/tx" "^3.2.1"
-    "@ethereumjs/vm" "^5.3.2"
+hardhat@^2.1.2:
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.6.0.tgz#a00a44d36559a880c170dca6363cc33f7545364b"
+  integrity sha512-NEM2pe11QXWXB7k49heOLQA9vxihG4DJ0712KjMT9NYSZgLOMcWswJ3tvn+/ND6vzLn6Z4pqr2x/kWSfllWFuw==
+  dependencies:
+    "@ethereumjs/block" "^3.4.0"
+    "@ethereumjs/blockchain" "^5.4.0"
+    "@ethereumjs/common" "^2.4.0"
+    "@ethereumjs/tx" "^3.3.0"
+    "@ethereumjs/vm" "^5.5.2"
     "@ethersproject/abi" "^5.1.2"
     "@sentry/node" "^5.18.1"
     "@solidity-parser/parser" "^0.11.0"
@@ -4921,7 +4949,7 @@ hardhat@^2.4.1:
     eth-sig-util "^2.5.2"
     ethereum-cryptography "^0.1.2"
     ethereumjs-abi "^0.6.8"
-    ethereumjs-util "^7.0.10"
+    ethereumjs-util "^7.1.0"
     find-up "^2.1.0"
     fp-ts "1.19.3"
     fs-extra "^7.0.1"
@@ -6354,7 +6382,7 @@ merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2:
     rlp "^2.0.0"
     semaphore ">=1.0.1"
 
-merkle-patricia-tree@^4.1.0, merkle-patricia-tree@^4.2.0:
+merkle-patricia-tree@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-4.2.0.tgz#a204b9041be5c25e8d14f0ff47021de090e811a1"
   integrity sha512-0sBVXs7z1Q1/kxzWZ3nPnxSPiaHKF/f497UQzt9O7isRcS10tel9jM/4TivF6Jv7V1yFq4bWyoATxbDUOen5vQ==


Test patch:
diff --git a/proxy/test/CommunityPool.ts b/proxy/test/CommunityPool.ts
index 46f647857..b60448f46 100644
--- a/proxy/test/CommunityPool.ts
+++ b/proxy/test/CommunityPool.ts
@@ -68,7 +68,7 @@ describe("CommunityPool", () => {
         await messageProxy.registerExtraContractForAll(communityPool.address);
         const tx = await messageProxy.addConnectedChain(schainName);
         const wei = minTransactionGas.mul(tx.gasPrice);
-        await communityPool.connect(user).rechargeUserWallet(schainName, { value: wei.toString() });
+        await communityPool.connect(user).rechargeUserWallet(schainName, user.address, { value: wei.toString() });
         await messageProxy.removeExtraContractForAll(communityPool.address);
         await communityPool.connect(user).withdrawFunds(schainName, wei.toString())
             .should.be.eventually.rejectedWith("Sender contract is not registered");
@@ -83,7 +83,7 @@ describe("CommunityPool", () => {
 
         it("should not allow to withdraw from user wallet if CommunityPool is not registered", async () => {
             const amount = minTransactionGas.mul(gasPrice);
-            await communityPool.connect(user).rechargeUserWallet(schainName, { value: amount.toString() });
+            await communityPool.connect(user).rechargeUserWallet(schainName, user.address, { value: amount.toString() });
             await messageProxy.removeExtraContract(schainName, communityPool.address);
             await communityPool.connect(user).withdrawFunds(schainName, amount.toString())
                 .should.be.eventually.rejectedWith("Sender contract is not registered");
@@ -91,24 +91,24 @@ describe("CommunityPool", () => {
 
         it("should revert if user recharged not enough money for most costly transaction", async () => {
             const amount = minTransactionGas.mul(gasPrice).sub(1);
-            await communityPool.connect(user).rechargeUserWallet(schainName, { value: amount.toString(), gasPrice })
+            await communityPool.connect(user).rechargeUserWallet(schainName, user.address, { value: amount.toString(), gasPrice })
                 .should.be.eventually.rejectedWith("Not enough ETH for transaction");
         });
 
         it("should recharge wallet if user passed enough money", async () => {
             const amount = minTransactionGas.mul(gasPrice);
-            await communityPool.connect(user).rechargeUserWallet(schainName, { value: amount.toString(), gasPrice });
-            let userBalance = await communityPool.connect(user).getBalance(schainName);
+            await communityPool.connect(user).rechargeUserWallet(schainName, user.address, { value: amount.toString(), gasPrice });
+            let userBalance = await communityPool.getBalance(user.address, schainName);
             userBalance.should.be.deep.equal(amount);
-            await communityPool.connect(user).rechargeUserWallet(schainName, { value: amount.toString(), gasPrice });
-            userBalance = await communityPool.connect(user).getBalance(schainName);
+            await communityPool.connect(user).rechargeUserWallet(schainName, user.address, { value: amount.toString(), gasPrice });
+            userBalance = await communityPool.getBalance(user.address, schainName);
             userBalance.should.be.deep.equal(amount.mul(2));
             expect(BigNumber.from(await messageProxy.getOutgoingMessagesCounter(schainName)).toString()).to.be.equal(BigNumber.from(1).toString());
         });
 
         it("should allow to withdraw money", async () => {
             const amount = minTransactionGas.mul(gasPrice).toNumber();
-            await communityPool.connect(user).rechargeUserWallet(schainName, { value: (amount + 1).toString(), gasPrice });
+            await communityPool.connect(user).rechargeUserWallet(schainName, user.address, { value: (amount + 1).toString(), gasPrice });
             expect(BigNumber.from(await messageProxy.getOutgoingMessagesCounter(schainName)).toString()).to.be.equal(BigNumber.from(1).toString());
 
             await communityPool.connect(user).withdrawFunds(schainName, amount + 2 )
@@ -170,11 +170,11 @@ describe("CommunityPool", () => {
         const gasPrice = tx.gasPrice;
         const wei = minTransactionGas.mul(gasPrice);
         const wei2 = minTransactionGas.mul(gasPrice).mul(2);
-        const res1 = await (await communityPool.connect(user).rechargeUserWallet(schainName, { value: wei.toString(), gasPrice })).wait();
-        const res2 = await (await communityPool.connect(user).rechargeUserWallet("schainName2", { value: wei2.toString(), gasPrice })).wait();
-        const userBalance = await communityPool.connect(user).getBalance(schainName);
+        const res1 = await (await communityPool.connect(user).rechargeUserWallet(schainName, user.address, { value: wei.toString(), gasPrice })).wait();
+        const res2 = await (await communityPool.connect(user).rechargeUserWallet("schainName2", user.address, { value: wei2.toString(), gasPrice })).wait();
+        const userBalance = await communityPool.getBalance(user.address, schainName);
         userBalance.should.be.deep.equal(wei);
-        const userBalance2 = await communityPool.connect(user).getBalance("schainName2");
+        const userBalance2 = await communityPool.getBalance(user.address, "schainName2");
         userBalance2.should.be.deep.equal(wei2);
 
         if (!res1.events) {
@@ -195,7 +195,7 @@ describe("CommunityPool", () => {
             expect(BigNumber.from(res2.events[last]?.topics[2]).toString()).to.equal("0");
         }
 
-        const res3 = await (await communityPool.connect(user).rechargeUserWallet(schainName, { value: wei.toString(), gasPrice })).wait();
+        const res3 = await (await communityPool.connect(user).rechargeUserWallet(schainName, user.address, { value: wei.toString(), gasPrice })).wait();
         expect(res3.events).to.be.empty;
     });
 
@@ -203,7 +203,7 @@ describe("CommunityPool", () => {
         await messageProxy.registerExtraContract(schainName, communityPool.address);
         const gasPrice = (await messageProxy.addConnectedChain(schainName)).gasPrice;
         const wei = minTransactionGas.mul(gasPrice).toNumber();
-        await communityPool.connect(user).rechargeUserWallet(schainName, { value: wei.toString(), gasPrice });
+        await communityPool.connect(user).rechargeUserWallet(schainName, user.address, { value: wei.toString(), gasPrice });
     });
 
     it("should add and remove link to contract on schain as LINKER_ROLE", async () => {
diff --git a/proxy/test/DepositBoxERC1155.ts b/proxy/test/DepositBoxERC1155.ts
index 7cbc7746c..3cbe5c23d 100644
--- a/proxy/test/DepositBoxERC1155.ts
+++ b/proxy/test/DepositBoxERC1155.ts
@@ -153,7 +153,7 @@ describe("DepositBoxERC1155", () => {
                 // execution/expectation
                 await depositBoxERC1155
                     .connect(deployer)
-                    .depositERC1155(schainName, contractHere, to, id, amount)
+                    .depositERC1155(schainName, contractHere, id, amount)
                     .should.be.eventually.rejectedWith(error);
             });
 
@@ -176,14 +176,14 @@ describe("DepositBoxERC1155", () => {
                 // execution
                 await depositBoxERC1155
                     .connect(deployer)
-                    .depositERC1155(schainName, contractHere, to, id, amount).should.be.eventually.rejectedWith("Whitelist is enabled");
+                    .depositERC1155(schainName, contractHere, id, amount).should.be.eventually.rejectedWith("Whitelist is enabled");
                 await depositBoxERC1155.connect(user).disableWhitelist(schainName);
                 await depositBoxERC1155
                     .connect(deployer)
-                    .depositERC1155(schainName, contractHere, to, id, amount);
+                    .depositERC1155(schainName, contractHere, id, amount);
                 await (await depositBoxERC1155
                     .connect(deployer)
-                    .depositERC1155(schainName, contractHere, to, id2, amount2)).wait();
+                    .depositERC1155(schainName, contractHere, id2, amount2)).wait();
                 // console.log("Gas for depositERC1155:", res.receipt.gasUsed);
                 // expectation
                 expect(BigNumber.from(await erc1155.balanceOf(depositBoxERC1155.address, id)).toNumber()).to.equal(amount);
@@ -208,7 +208,7 @@ describe("DepositBoxERC1155", () => {
                 // execution/expectation
                 await depositBoxERC1155
                     .connect(deployer)
-                    .depositERC1155Batch(schainName, contractHere, to, ids, amounts)
+                    .depositERC1155Batch(schainName, contractHere, ids, amounts)
                     .should.be.eventually.rejectedWith(error);
             });
 
@@ -231,14 +231,14 @@ describe("DepositBoxERC1155", () => {
                 // execution
                 await depositBoxERC1155
                     .connect(deployer)
-                    .depositERC1155Batch(schainName, contractHere, to, ids, amounts).should.be.eventually.rejectedWith("Whitelist is enabled");
+                    .depositERC1155Batch(schainName, contractHere, ids, amounts).should.be.eventually.rejectedWith("Whitelist is enabled");
                 await depositBoxERC1155.connect(user).disableWhitelist(schainName);
                 await depositBoxERC1155
                     .connect(deployer)
-                    .depositERC1155Batch(schainName, contractHere, to, ids, amounts);
+                    .depositERC1155Batch(schainName, contractHere, ids, amounts);
                 const res = await (await depositBoxERC1155
                     .connect(deployer)
-                    .depositERC1155Batch(schainName, contractHere, to, ids2, amounts2)).wait();
+                    .depositERC1155Batch(schainName, contractHere, ids2, amounts2)).wait();
                 // console.log("Gas for depositERC1155:", res.receipt.gasUsed);
                 // expectation
                 const balanceIds = await erc1155.balanceOfBatch([depositBoxERC1155.address, depositBoxERC1155.address, depositBoxERC1155.address], ids);
@@ -265,7 +265,7 @@ describe("DepositBoxERC1155", () => {
             await depositBoxERC1155.connect(user).disableWhitelist(schainName);
             await depositBoxERC1155
                 .connect(deployer)
-                .depositERC1155(schainName, erc1155.address, deployer.address, 4, 50);
+                .depositERC1155(schainName, erc1155.address, 4, 50);
             await depositBoxERC1155.connect(user).getFunds(schainName, erc1155.address, user.address, [4], [50]).should.be.eventually.rejectedWith("Schain is not killed");
             await linker.connect(deployer).kill(schainName);
             await linker.connect(user).kill(schainName);
@@ -331,7 +331,7 @@ describe("DepositBoxERC1155", () => {
                 .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]);
             await communityPool
                 .connect(user)
-                .rechargeUserWallet(schainName, { value: wei });
+                .rechargeUserWallet(schainName, user.address, { value: wei });
 
             // mint some ERC1155 of  for `deployer` address
             await erc1155.connect(deployer).mint(deployer.address, id, amount, "0x");
@@ -342,7 +342,7 @@ describe("DepositBoxERC1155", () => {
             await depositBoxERC1155.connect(user2).disableWhitelist(schainName);
             await depositBoxERC1155
                 .connect(deployer)
-                .depositERC1155(schainName, contractHere, to, id, amount);
+                .depositERC1155(schainName, contractHere, id, amount);
             // execution
             // to avoid `Incorrect sender` error
             const balanceBefore = await getBalance(deployer.address);
@@ -387,7 +387,7 @@ describe("DepositBoxERC1155", () => {
                 .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]);
             await communityPool
                 .connect(user)
-                .rechargeUserWallet(schainName, { value: wei });
+                .rechargeUserWallet(schainName, user.address, { value: wei });
 
             // mint some ERC1155 of  for `deployer` address
             await erc1155.connect(deployer).mintBatch(deployer.address, ids, amounts, "0x");
@@ -398,7 +398,7 @@ describe("DepositBoxERC1155", () => {
             await depositBoxERC1155.connect(user2).disableWhitelist(schainName);
             await depositBoxERC1155
                 .connect(deployer)
-                .depositERC1155Batch(schainName, contractHere, to, ids, amounts);
+                .depositERC1155Batch(schainName, contractHere, ids, amounts);
             // execution
             // to avoid `Incorrect sender` error
             const balanceBefore = await getBalance(deployer.address);
diff --git a/proxy/test/DepositBoxERC20.ts b/proxy/test/DepositBoxERC20.ts
index e2306e9c4..a98fa16e6 100644
--- a/proxy/test/DepositBoxERC20.ts
+++ b/proxy/test/DepositBoxERC20.ts
@@ -127,7 +127,7 @@ describe("DepositBoxERC20", () => {
                 // execution/expectation
                 await depositBoxERC20
                     .connect(deployer)
-                    .depositERC20(schainName, erc20.address, deployer.address, 100)
+                    .depositERC20(schainName, erc20.address, 100)
                     .should.be.eventually.rejectedWith(error);
             });
 
@@ -140,7 +140,7 @@ describe("DepositBoxERC20", () => {
                 // execution/expectation
                 await depositBoxERC20
                     .connect(deployer)
-                    .depositERC20(schainName, erc20.address, deployer.address, 100)
+                    .depositERC20(schainName, erc20.address, 100)
                     .should.be.eventually.rejectedWith(error);
             });
 
@@ -153,14 +153,14 @@ describe("DepositBoxERC20", () => {
                 // execution
                 await depositBoxERC20
                     .connect(deployer)
-                    .depositERC20(schainName, erc20.address, deployer.address, 1).should.be.eventually.rejectedWith("Whitelist is enabled");
+                    .depositERC20(schainName, erc20.address, 1).should.be.eventually.rejectedWith("Whitelist is enabled");
                 await depositBoxERC20.connect(user).disableWhitelist(schainName);
                 await depositBoxERC20
                     .connect(deployer)
-                    .depositERC20(schainName, erc20.address, deployer.address, 1);
+                    .depositERC20(schainName, erc20.address, 1);
                 await depositBoxERC20
                     .connect(deployer)
-                    .depositERC20(schainName, erc20.address, deployer.address, 1);
+                    .depositERC20(schainName, erc20.address, 1);
                 // console.log("Gas for depositERC20:", res.receipt.gasUsed);
             });
 
@@ -174,25 +174,9 @@ describe("DepositBoxERC20", () => {
                 await depositBoxERC20.connect(user).disableWhitelist(schainName);
                 await depositBoxERC20
                     .connect(deployer)
-                    .depositERC20(schainName, erc20.address, deployer.address, amount + 1)
+                    .depositERC20(schainName, erc20.address, amount + 1)
                     .should.be.eventually.rejectedWith("Amount is incorrect");
             });
-
-            it("should rejected with `Receiver address cannot be null`", async () => {
-                // preparation
-                // mint some quantity of ERC20 tokens for `deployer` address
-                const amount = 10;
-                const to0 = "0x0000000000000000000000000000000000000000";
-
-                await erc20.connect(deployer).mint(deployer.address, amount);
-                await erc20.connect(deployer).approve(depositBoxERC20.address, amount);
-
-                await depositBoxERC20.connect(user).disableWhitelist(schainName);
-                await depositBoxERC20
-                    .connect(deployer)
-                    .depositERC20(schainName, erc20.address, to0, amount)
-                    .should.be.eventually.rejectedWith("Receiver address cannot be null");
-            });
         });
 
         it("should get funds after kill", async () => {
@@ -201,7 +185,7 @@ describe("DepositBoxERC20", () => {
             await depositBoxERC20.connect(user).disableWhitelist(schainName);
             await depositBoxERC20
                 .connect(deployer)
-                .depositERC20(schainName, erc20.address, deployer.address, 1);
+                .depositERC20(schainName, erc20.address, 1);
             await depositBoxERC20.connect(user).getFunds(schainName, erc20.address, user.address, 1).should.be.eventually.rejectedWith("Schain is not killed");
             await linker.connect(deployer).kill(schainName);
             await linker.connect(user).kill(schainName);
@@ -286,7 +270,7 @@ describe("DepositBoxERC20", () => {
             await initializeSchain(contractManager, schainName, deployer.address, 1, 1);
             await setCommonPublicKey(contractManager, schainName);
 
-            await depositBoxERC20.connect(user).depositERC20(schainName, erc20.address, user.address, amount)
+            await depositBoxERC20.connect(user).depositERC20(schainName, erc20.address, amount)
                 .should.be.eventually.rejectedWith("Unconnected chain");
 
             await linker
@@ -295,16 +279,16 @@ describe("DepositBoxERC20", () => {
 
             await communityPool
                 .connect(user)
-                .rechargeUserWallet(schainName, { value: wei });
+                .rechargeUserWallet(schainName, user.address, { value: wei });
 
             await depositBoxERC20.disableWhitelist(schainName);
             await erc20.connect(deployer).mint(user.address, amount * 2);
 
-            await depositBoxERC20.connect(user).depositERC20(schainName, erc20.address, user.address, amount)
+            await depositBoxERC20.connect(user).depositERC20(schainName, erc20.address, amount)
                 .should.be.eventually.rejectedWith("DepositBox was not approved for ERC20 token");
             await erc20.connect(user).approve(depositBoxERC20.address, amount * 2);
 
-            await depositBoxERC20.connect(user).depositERC20(schainName, erc20.address, user.address, amount);
+            await depositBoxERC20.connect(user).depositERC20(schainName, erc20.address, amount);
 
             const res = await (await messageProxy.connect(deployer).postIncomingMessages(schainName, 0, [messageWithWrongTokenAddress, messageWithNotMintedToken], sign)).wait();
             if (res.events) {
@@ -323,7 +307,7 @@ describe("DepositBoxERC20", () => {
             balance.should.be.almost(balanceBefore);
 
             await linker.allowInterchainConnections(schainName);
-            await depositBoxERC20.connect(user).depositERC20(schainName, erc20.address, user.address, amount);
+            await depositBoxERC20.connect(user).depositERC20(schainName, erc20.address, amount);
             await messageProxy.connect(deployer).postIncomingMessages(schainName, 3, [message], sign);
             expect(BigNumber.from(await depositBoxERC20.transferredAmount(schainHash, erc20.address)).toString()).to.be.equal(BigNumber.from(0).toString());
 
diff --git a/proxy/test/DepositBoxERC721.ts b/proxy/test/DepositBoxERC721.ts
index dbc4be882..ce5003388 100644
--- a/proxy/test/DepositBoxERC721.ts
+++ b/proxy/test/DepositBoxERC721.ts
@@ -123,7 +123,7 @@ describe("DepositBoxERC721", () => {
                 //  preparation
                 const amount = 10;
 
-                await depositBoxERC721.connect(user).depositERC721(schainName, erc721.address, user.address, amount)
+                await depositBoxERC721.connect(user).depositERC721(schainName, erc721.address, amount)
                     .should.be.eventually.rejectedWith("Unconnected chain");
             });
 
@@ -144,7 +144,7 @@ describe("DepositBoxERC721", () => {
                 // execution/expectation
                 await depositBoxERC721
                     .connect(deployer)
-                    .depositERC721(schainName, contractHere, to, tokenId)
+                    .depositERC721(schainName, contractHere, tokenId)
                     .should.be.eventually.rejectedWith(error);
             });
 
@@ -166,14 +166,14 @@ describe("DepositBoxERC721", () => {
                 // execution
                 await depositBoxERC721
                     .connect(deployer)
-                    .depositERC721(schainName, contractHere, to, tokenId).should.be.eventually.rejectedWith("Whitelist is enabled");
+                    .depositERC721(schainName, contractHere, tokenId).should.be.eventually.rejectedWith("Whitelist is enabled");
                 await depositBoxERC721.connect(user).disableWhitelist(schainName);
                 await depositBoxERC721
                     .connect(deployer)
-                    .depositERC721(schainName, contractHere, to, tokenId);
+                    .depositERC721(schainName, contractHere, tokenId);
                 await (await depositBoxERC721
                     .connect(deployer)
-                    .depositERC721(schainName, contractHere, to, tokenId2)).wait();
+                    .depositERC721(schainName, contractHere, tokenId2)).wait();
                 // console.log("Gas for depositERC721:", res.receipt.gasUsed);
                 // expectation
                 expect(await erc721OnChain.ownerOf(tokenId)).to.equal(depositBoxERC721.address);
@@ -192,7 +192,7 @@ describe("DepositBoxERC721", () => {
             await depositBoxERC721.connect(user).disableWhitelist(schainName);
             await depositBoxERC721
                 .connect(deployer)
-                .depositERC721(schainName, erc721OnChain.address, deployer.address, tokenId);
+                .depositERC721(schainName, erc721OnChain.address, tokenId);
             await depositBoxERC721.connect(user).getFunds(schainName, erc721OnChain.address, user.address, tokenId).should.be.eventually.rejectedWith("Schain is not killed");
             await linker.connect(deployer).kill(schainName);
             await linker.connect(user).kill(schainName);
@@ -246,7 +246,7 @@ describe("DepositBoxERC721", () => {
                 .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]);
             await communityPool
                 .connect(user)
-                .rechargeUserWallet(schainName, { value: weiAmount });
+                .rechargeUserWallet(schainName, user.address, { value: weiAmount });
         });
 
         it("should transfer ERC721 token", async () => {
@@ -341,7 +341,7 @@ describe("DepositBoxERC721", () => {
             await erc721.approve(depositBoxERC721.address, tokenId);
 
             await depositBoxERC721
-                .depositERC721(schainName, erc721.address, deployer.address, tokenId);
+                .depositERC721(schainName, erc721.address, tokenId);
 
             const balanceBefore = await getBalance(deployer.address);
             await messageProxy.connect(deployer).postIncomingMessages(schainName, 0, [message], sign);
diff --git a/proxy/test/DepositBoxEth.ts b/proxy/test/DepositBoxEth.ts
index 5f56b9db0..ecfad676d 100644
--- a/proxy/test/DepositBoxEth.ts
+++ b/proxy/test/DepositBoxEth.ts
@@ -115,7 +115,7 @@ describe("DepositBoxEth", () => {
             // execution/expectation
             await depositBoxEth
                 .connect(deployer)
-                .deposit(schainName, user.address)
+                .deposit(schainName)
                 .should.be.eventually.rejectedWith(error);
         });
 
@@ -126,7 +126,7 @@ describe("DepositBoxEth", () => {
             // execution/expectation
             await depositBoxEth
                 .connect(deployer)
-                .deposit(newSchainName, user.address)
+                .deposit(newSchainName)
                 .should.be.eventually.rejectedWith(error);
         });
 
@@ -143,7 +143,7 @@ describe("DepositBoxEth", () => {
             // execution
             await depositBoxEth
                 .connect(deployer)
-                .deposit(schainName, deployer.address, { value: wei });
+                .deposit(schainName, { value: wei });
             // console.log("Gas for deposit:", tx.receipt.gasUsed);
 
             const lockAndDataBalance = await web3.eth.getBalance(depositBoxEth.address);
@@ -168,7 +168,7 @@ describe("DepositBoxEth", () => {
                 .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]);
             await depositBoxEth
                 .connect(deployer)
-                .deposit(schainName, deployer.address, { value: wei });
+                .deposit(schainName, { value: wei });
             await depositBoxEth.connect(user2).getFunds(schainName, user.address, wei).should.be.eventually.rejectedWith("Schain is not killed");
             await linker.connect(deployer).kill(schainName);
             await linker.connect(user2).kill(schainName);
@@ -231,7 +231,7 @@ describe("DepositBoxEth", () => {
             await setCommonPublicKey(contractManager, schainName);
             await communityPool
                 .connect(user)
-                .rechargeUserWallet(schainName, { value: wei });
+                .rechargeUserWallet(schainName, user.address, { value: wei });
             // execution
 
             const res = await (await messageProxy.connect(deployer).postIncomingMessages(schainName, 0, [message], sign)).wait();
@@ -277,7 +277,7 @@ describe("DepositBoxEth", () => {
                 await setCommonPublicKey(contractManager, schainName);
                 await communityPool
                     .connect(user)
-                    .rechargeUserWallet(schainName, { value: wei });
+                    .rechargeUserWallet(schainName, user.address, { value: wei });
                 // execution
                 const res = await (await messageProxy.connect(deployer).postIncomingMessages(schainName, 0, [message], sign)).wait();
 
@@ -306,7 +306,7 @@ describe("DepositBoxEth", () => {
                 .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]);
             await communityPool
                 .connect(user)
-                .rechargeUserWallet(schainName, { value: wei });
+                .rechargeUserWallet(schainName, user.address, { value: wei });
 
             const sign = {
                 blsSignature: BlsSignature,
@@ -351,7 +351,7 @@ describe("DepositBoxEth", () => {
                 .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]);
             await communityPool
                 .connect(user)
-                .rechargeUserWallet(schainName, { value: wei });
+                .rechargeUserWallet(schainName, user.address, { value: wei });
 
             const sign = {
                 blsSignature: BlsSignature,
@@ -371,7 +371,7 @@ describe("DepositBoxEth", () => {
             // add wei to contract through `receiveEth` because `receiveEth` have `payable` parameter
             await depositBoxEth
                 .connect(deployer)
-                .deposit(schainName, user.address, { value: wei });
+                .deposit(schainName, { value: wei });
             // execution
             const res = await (await messageProxy.connect(deployer).postIncomingMessages(schainName, 0, [message], sign)).wait();
 
@@ -416,11 +416,11 @@ describe("DepositBoxEth", () => {
 
             await communityPool
                 .connect(user)
-                .rechargeUserWallet(schainName, { value: wei });
+                .rechargeUserWallet(schainName, user.address, { value: wei });
 
             await depositBoxEth
                 .connect(deployer)
-                .deposit(schainName, user.address, { value: wei });
+                .deposit(schainName, { value: wei });
 
             expect(BigNumber.from(await depositBoxEth.transferredAmount(schainHash)).toString()).to.be.equal(BigNumber.from(0).toString());
 
diff --git a/proxy/test/MessageProxy.ts b/proxy/test/MessageProxy.ts
index cb16aca3f..ef6f12700 100644
--- a/proxy/test/MessageProxy.ts
+++ b/proxy/test/MessageProxy.ts
@@ -284,7 +284,7 @@ describe("MessageProxy", () => {
                     sign
                     ).should.be.eventually.rejectedWith("Too many messages");
 
-            await communityPool.connect(client).rechargeUserWallet(schainName, {value: amountWei.toString()});
+            await communityPool.connect(client).rechargeUserWallet(schainName, client.address, {value: amountWei.toString()});
 
             await messageProxyForMainnet
                 .connect(deployer)
diff --git a/proxy/test/TokenManagerERC1155.ts b/proxy/test/TokenManagerERC1155.ts
index c4e57b705..efe0df906 100644
--- a/proxy/test/TokenManagerERC1155.ts
+++ b/proxy/test/TokenManagerERC1155.ts
@@ -74,6 +74,10 @@ describe("TokenManagerERC1155", () => {
     let messages: MessagesTester;
     let messageProxyForSchain: MessageProxyForSchainTester;
     let communityLocker: CommunityLocker;
+    let token2: ERC1155OnChain;
+    let tokenClone2: ERC1155OnChain;
+    let token3: ERC1155OnChain;
+    let tokenClone3: ERC1155OnChain;
 
     before(async () => {
         [deployer, user, schainOwner] = await ethers.getSigners();
@@ -103,6 +107,10 @@ describe("TokenManagerERC1155", () => {
 
         tokenClone = await deployERC1155OnChain("ELVIS Multi Token");
         token = await deployERC1155OnChain("ELVIS Multi Token");
+        tokenClone2 = await deployERC1155OnChain("ELVIS2 Multi Token");
+        token2 = await deployERC1155OnChain("ELVIS2 Multi Token");
+        tokenClone3 = await deployERC1155OnChain("ELVIS3 Multi Token");
+        token3 = await deployERC1155OnChain("ELVIS3 Multi Token");
 
         to = user.address;
 
@@ -124,19 +132,19 @@ describe("TokenManagerERC1155", () => {
     });
 
     it("should successfully call exitToMainERC1155", async () => {
-        await tokenManagerERC1155.connect(user).exitToMainERC1155(token.address, to, id, amount)
+        await tokenManagerERC1155.connect(user).exitToMainERC1155(token.address, id, amount)
             .should.be.eventually.rejectedWith("No token clone on schain");
 
         await tokenManagerERC1155.connect(schainOwner).addERC1155TokenByOwner(token.address, tokenClone.address);
-        await tokenManagerERC1155.connect(user).exitToMainERC1155(token.address, to, id, amount)
+        await tokenManagerERC1155.connect(user).exitToMainERC1155(token.address, id, amount)
             .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
 
         await tokenClone.connect(deployer).mint(user.address, id, amount, "0x");
-        await tokenManagerERC1155.connect(user).exitToMainERC1155(token.address, to, id, amount)
+        await tokenManagerERC1155.connect(user).exitToMainERC1155(token.address, id, amount)
             .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
 
         await tokenClone.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
-        await tokenManagerERC1155.connect(user).exitToMainERC1155(token.address, to, id, amount);
+        await tokenManagerERC1155.connect(user).exitToMainERC1155(token.address, id, amount);
 
         const outgoingMessagesCounterMainnet = BigNumber.from(
             await messageProxyForSchain.getOutgoingMessagesCounter("Mainnet")
@@ -145,19 +153,19 @@ describe("TokenManagerERC1155", () => {
     });
 
     it("should successfully call exitToMainERC1155Batch", async () => {
-        await tokenManagerERC1155.connect(user).exitToMainERC1155Batch(token.address, to, ids, amounts)
+        await tokenManagerERC1155.connect(user).exitToMainERC1155Batch(token.address, ids, amounts)
             .should.be.eventually.rejectedWith("No token clone on schain");
 
         await tokenManagerERC1155.connect(schainOwner).addERC1155TokenByOwner(token.address, tokenClone.address);
-        await tokenManagerERC1155.connect(user).exitToMainERC1155Batch(token.address, to, ids, amounts)
+        await tokenManagerERC1155.connect(user).exitToMainERC1155Batch(token.address, ids, amounts)
             .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
 
         await tokenClone.connect(deployer).mintBatch(user.address, ids, amounts, "0x");
-        await tokenManagerERC1155.connect(user).exitToMainERC1155Batch(token.address, to, ids, amounts)
+        await tokenManagerERC1155.connect(user).exitToMainERC1155Batch(token.address, ids, amounts)
             .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
 
         await tokenClone.connect(user).setApprovalForAll(tokenManagerERC1155.address, true);
-        await tokenManagerERC1155.connect(user).exitToMainERC1155Batch(token.address, to, ids, amounts);
+        await tokenManagerERC1155.connect(user).exitToMainERC1155Batch(token.address, ids, amounts);
 
         const outgoingMessagesCounterMainnet = BigNumber.from(
             await messageProxyForSchain.getOutgoingMessagesCounter("Mainnet")
@@ -173,6 +181,12 @@ describe("TokenManagerERC1155", () => {
             .should.be.eventually.rejectedWith("Given address is not a contract");
 
         await tokenManagerERC1155.connect(schainOwner).addERC1155TokenByOwner(token.address, tokenClone.address);
+
+        await tokenManagerERC1155.connect(schainOwner).addERC1155TokenByOwner(token2.address, tokenClone.address)
+            .should.be.eventually.rejectedWith("Clone was already added");
+
+        await tokenManagerERC1155.connect(schainOwner).addERC1155TokenByOwner(token.address, tokenClone2.address)
+            .should.be.eventually.rejectedWith("Could not relink clone");
     });
 
     it("should successfully call transferToSchainERC1155", async () => {
@@ -183,7 +197,7 @@ describe("TokenManagerERC1155", () => {
 
         await tokenManagerERC1155
             .connect(deployer)
-            .transferToSchainERC1155(newSchainName, token.address, to, id, amount)
+            .transferToSchainERC1155(newSchainName, token.address, id, amount)
             .should.be.eventually.rejectedWith("Incorrect Token Manager address");
 
         await tokenManagerERC1155.addTokenManager(newSchainName, deployer.address);
@@ -192,7 +206,7 @@ describe("TokenManagerERC1155", () => {
 
         await tokenManagerERC1155
             .connect(deployer)
-            .transferToSchainERC1155(newSchainName, token.address, to, id, amount)
+            .transferToSchainERC1155(newSchainName, token.address, id, amount)
             .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
 
         await tokenClone.connect(deployer).setApprovalForAll(tokenManagerERC1155.address, true);
@@ -200,7 +214,7 @@ describe("TokenManagerERC1155", () => {
         // execution:
         await tokenManagerERC1155
             .connect(deployer)
-            .transferToSchainERC1155(newSchainName, token.address, to, id, amount);
+            .transferToSchainERC1155(newSchainName, token.address, id, amount);
         // expectation:
         const outgoingMessagesCounter = BigNumber.from(
             await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)
@@ -217,7 +231,7 @@ describe("TokenManagerERC1155", () => {
 
         await tokenManagerERC1155
             .connect(deployer)
-            .transferToSchainERC1155Batch(newSchainName, token.address, to, ids, amounts)
+            .transferToSchainERC1155Batch(newSchainName, token.address, ids, amounts)
             .should.be.eventually.rejectedWith("Incorrect Token Manager address");
 
         await tokenManagerERC1155.addTokenManager(newSchainName, deployer.address);
@@ -226,7 +240,7 @@ describe("TokenManagerERC1155", () => {
 
         await tokenManagerERC1155
             .connect(deployer)
-            .transferToSchainERC1155Batch(newSchainName, token.address, to, ids, amounts)
+            .transferToSchainERC1155Batch(newSchainName, token.address, ids, amounts)
             .should.be.eventually.rejectedWith("Not allowed ERC1155 Token");
 
         await tokenClone.connect(deployer).setApprovalForAll(tokenManagerERC1155.address, true);
@@ -234,7 +248,7 @@ describe("TokenManagerERC1155", () => {
         // execution:
         await tokenManagerERC1155
             .connect(deployer)
-            .transferToSchainERC1155Batch(newSchainName, token.address, to, ids, amounts);
+            .transferToSchainERC1155Batch(newSchainName, token.address, ids, amounts);
         // expectation:
         const outgoingMessagesCounter = BigNumber.from(
             await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)
diff --git a/proxy/test/TokenManagerERC20.ts b/proxy/test/TokenManagerERC20.ts
index e0002846b..69cbd8027 100644
--- a/proxy/test/TokenManagerERC20.ts
+++ b/proxy/test/TokenManagerERC20.ts
@@ -117,7 +117,7 @@ describe("TokenManagerERC20", () => {
         const to = user.address;
         const amount = 10;
         // execution/expectation
-        await tokenManagerErc20.connect(deployer).exitToMainERC20(deployer.address, to, amount)
+        await tokenManagerErc20.connect(user).exitToMainERC20(deployer.address, amount)
             .should.be.eventually.rejectedWith(error);
     });
 
@@ -162,7 +162,7 @@ describe("TokenManagerERC20", () => {
         await erc20OnChain.connect(user).approve(tokenManagerErc20.address, amount);
         await tokenManagerErc20
             .connect(user)
-            .exitToMainERC20(erc20OnMainnet.address, user.address, amount)
+            .exitToMainERC20(erc20OnMainnet.address, amount)
             .should.be.eventually.rejectedWith(error);
     });
 
@@ -179,10 +179,12 @@ describe("TokenManagerERC20", () => {
             await tokenManagerErc20.connect(schainOwner).enableAutomaticDeploy();
         }
 
-        await tokenManagerErc20.connect(schainOwner).addERC20TokenByOwner(addressERC201, addressERC20);
+        await tokenManagerErc20.connect(schainOwner).addERC20TokenByOwner(addressERC201, addressERC20).should.be.eventually.rejectedWith("Could not relink clone");
 
         eRC20OnChain2 = await deployERC20OnChain("NewToken", "NTN");
+        const eRC20OnChain3 = await deployERC20OnChain("NewToken2", "NTN2");
         eRC20OnMainnet2 = await deployERC20OnChain("NewToken", "NTN");
+        const eRC20OnMainnet3 = await deployERC20OnChain("NewToken2", "NTN2");
 
         if (automaticDeploy) {
             await tokenManagerErc20.connect(schainOwner).enableAutomaticDeploy();
@@ -196,8 +198,12 @@ describe("TokenManagerERC20", () => {
             .should.be.eventually.rejectedWith("Given address is not a contract");
 
         await eRC20OnChain2.mint(user.address, 1);
+        await eRC20OnChain3.mint(user.address, 1);
+
+        await tokenManagerErc20.connect(schainOwner).addERC20TokenByOwner(eRC20OnMainnet3.address, addressERC20)
+            .should.be.eventually.rejectedWith("Clone was already added");
 
-        await tokenManagerErc20.connect(schainOwner).addERC20TokenByOwner(eRC20OnMainnet2.address, eRC20OnChain2.address)
+        await tokenManagerErc20.connect(schainOwner).addERC20TokenByOwner(eRC20OnMainnet3.address, eRC20OnChain3.address)
             .should.be.eventually.rejectedWith("TotalSupply is not zero");
 
     });
@@ -214,7 +220,7 @@ describe("TokenManagerERC20", () => {
         //
         await erc20OnChain.connect(user).approve(tokenManagerErc20.address, amount / 2);
         // execution/expectation
-        await tokenManagerErc20.connect(user).exitToMainERC20(erc20OnMainnet.address, user.address, amount)
+        await tokenManagerErc20.connect(user).exitToMainERC20(erc20OnMainnet.address, amount)
             .should.be.eventually.rejectedWith(error);
     });
 
@@ -233,7 +239,7 @@ describe("TokenManagerERC20", () => {
         // execution:
         await tokenManagerErc20
             .connect(user)
-            .exitToMainERC20(erc20OnMainnet.address, user.address, amountReduceCost);
+            .exitToMainERC20(erc20OnMainnet.address, amountReduceCost);
 
         // // expectation:
         const outgoingMessagesCounterMainnet = BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter("Mainnet"));
@@ -256,12 +262,12 @@ describe("TokenManagerERC20", () => {
 
         await tokenManagerErc20
             .connect(user)
-            .transferToSchainERC20(newSchainName, erc20OnMainnet.address, user.address, amountReduceCost)
+            .transferToSchainERC20(newSchainName, erc20OnMainnet.address, amountReduceCost)
             .should.be.eventually.rejectedWith("Incorrect Token Manager address");
 
         await tokenManagerErc20
             .connect(user)
-            .transferToSchainERC20("Mainnet", erc20OnMainnet.address, user.address, amountReduceCost)
+            .transferToSchainERC20("Mainnet", erc20OnMainnet.address, amountReduceCost)
             .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet");
 
         await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc20.address);
@@ -269,7 +275,7 @@ describe("TokenManagerERC20", () => {
         // execution:
         await tokenManagerErc20
             .connect(user)
-            .transferToSchainERC20(newSchainName, erc20OnMainnet.address, user.address, amountReduceCost);
+            .transferToSchainERC20(newSchainName, erc20OnMainnet.address, amountReduceCost);
 
         // expectation:
         const outgoingMessagesCounter = BigNumber.from(
diff --git a/proxy/test/TokenManagerERC721.ts b/proxy/test/TokenManagerERC721.ts
index 0622a30ad..855f298ed 100644
--- a/proxy/test/TokenManagerERC721.ts
+++ b/proxy/test/TokenManagerERC721.ts
@@ -70,6 +70,10 @@ describe("TokenManagerERC721", () => {
     let messages: MessagesTester;
     let messageProxyForSchain: MessageProxyForSchainTester;
     let communityLocker: CommunityLocker;
+    let token2: ERC721OnChain;
+    let tokenClone2: ERC721OnChain;
+    let token3: ERC721OnChain;
+    let tokenClone3: ERC721OnChain;
 
     before(async () => {
         [deployer, user, schainOwner] = await ethers.getSigners();
@@ -99,6 +103,10 @@ describe("TokenManagerERC721", () => {
 
         tokenClone = await deployERC721OnChain("ELVIS", "ELV");
         token = await deployERC721OnChain("SKALE", "SKL");
+        tokenClone2 = await deployERC721OnChain("ELVIS2", "ELV");
+        token2 = await deployERC721OnChain("SKALE2", "SKL");
+        tokenClone3 = await deployERC721OnChain("ELVIS3", "ELV");
+        token3 = await deployERC721OnChain("SKALE3", "SKL");
 
         to = user.address;
 
@@ -122,29 +130,29 @@ describe("TokenManagerERC721", () => {
     });
 
     it("should successfully call exitToMainERC721", async () => {
-        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, to, tokenId)
+        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, tokenId)
             .should.be.eventually.rejectedWith("No token clone on schain");
 
         await tokenManagerERC721.connect(schainOwner).addERC721TokenByOwner(token.address, tokenClone.address);
-        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, to, tokenId)
+        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, tokenId)
             .should.be.eventually.rejectedWith("ERC721: approved query for nonexistent token");
 
         await tokenClone.connect(deployer).mint(user.address, tokenId);
-        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, to, tokenId)
+        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, tokenId)
             .should.be.eventually.rejectedWith("Not allowed ERC721 Token");
 
         await tokenClone.connect(user).approve(tokenManagerERC721.address, tokenId);
-        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, to, tokenId)
+        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, tokenId)
             .should.be.eventually.rejectedWith("Sender contract is not registered");
 
         await messageProxyForSchain.registerExtraContract("Mainnet", tokenManagerERC721.address);
-        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, to, tokenId);
+        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, tokenId);
 
         await messageProxyForSchain.removeExtraContract("Mainnet", tokenManagerERC721.address);
         await tokenClone.connect(deployer).mint(user.address, tokenId);
         await tokenClone.connect(user).approve(tokenManagerERC721.address, tokenId);
 
-        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, to, tokenId)
+        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, tokenId)
             .should.be.eventually.rejectedWith("Sender contract is not registered");
 
         const outgoingMessagesCounterMainnet = BigNumber.from(
@@ -159,13 +167,13 @@ describe("TokenManagerERC721", () => {
         await tokenClone.connect(user).approve(tokenManagerERC721.address, tokenId);
         await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721.address);
 
-        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, to, tokenId);
+        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, tokenId);
 
         await messageProxyForSchain.removeExtraContractForAll(tokenManagerERC721.address);
         await tokenClone.connect(deployer).mint(user.address, tokenId);
         await tokenClone.connect(user).approve(tokenManagerERC721.address, tokenId);
 
-        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, to, tokenId)
+        await tokenManagerERC721.connect(user).exitToMainERC721(token.address, tokenId)
             .should.be.eventually.rejectedWith("Sender contract is not registered");
 
         const outgoingMessagesCounterMainnet = BigNumber.from(
@@ -182,21 +190,23 @@ describe("TokenManagerERC721", () => {
             .should.be.eventually.rejectedWith("Given address is not a contract");
 
         await tokenManagerERC721.connect(schainOwner).addERC721TokenByOwner(token.address, tokenClone.address);
+
+        await tokenManagerERC721.connect(schainOwner).addERC721TokenByOwner(token2.address, tokenClone.address)
+            .should.be.eventually.rejectedWith("Clone was already added");
+
+        await tokenManagerERC721.connect(schainOwner).addERC721TokenByOwner(token.address, tokenClone2.address)
+            .should.be.eventually.rejectedWith("Could not relink clone");
     });
 
     it("should successfully call transferToSchainERC721", async () => {
         const newSchainName = randomString(10);
 
-        const to0 = "0x0000000000000000000000000000000000000000";
-        await tokenManagerERC721.connect(user).transferToSchainERC721(newSchainName, token.address, to0, tokenId)
-            .should.be.eventually.rejectedWith("Incorrect receiver address");
-
         await messageProxyForSchain.grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address);
         await messageProxyForSchain.addConnectedChain(newSchainName);
 
         await tokenManagerERC721
             .connect(deployer)
-            .transferToSchainERC721(newSchainName, token.address, to, tokenId)
+            .transferToSchainERC721(newSchainName, token.address, tokenId)
             .should.be.eventually.rejectedWith("Incorrect Token Manager address");
 
         await tokenManagerERC721.addTokenManager(newSchainName, deployer.address);
@@ -205,14 +215,14 @@ describe("TokenManagerERC721", () => {
 
         await tokenManagerERC721
             .connect(deployer)
-            .transferToSchainERC721(newSchainName, token.address, to, tokenId)
+            .transferToSchainERC721(newSchainName, token.address, tokenId)
             .should.be.eventually.rejectedWith("Not allowed ERC721 Token");
 
         await tokenClone.connect(deployer).approve(tokenManagerERC721.address, tokenId);
 
         await tokenManagerERC721
             .connect(deployer)
-            .transferToSchainERC721(newSchainName, token.address, to, tokenId)
+            .transferToSchainERC721(newSchainName, token.address, tokenId)
             .should.be.eventually.rejectedWith("Sender contract is not registered");
 
         await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address);
@@ -221,7 +231,7 @@ describe("TokenManagerERC721", () => {
         // execution:
         await tokenManagerERC721
             .connect(deployer)
-            .transferToSchainERC721(newSchainName, token.address, to, tokenId);
+            .transferToSchainERC721(newSchainName, token.address, tokenId);
         // expectation:
         const outgoingMessagesCounter = BigNumber.from(
             await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)
diff --git a/proxy/test/TokenManagerEth.ts b/proxy/test/TokenManagerEth.ts
index c282d8860..037252135 100644
--- a/proxy/test/TokenManagerEth.ts
+++ b/proxy/test/TokenManagerEth.ts
@@ -204,13 +204,19 @@ describe("TokenManagerEth", () => {
         await ethERC20.mint(user.address, amount);
 
         // send Eth to a client on Mainnet:
-        await tokenManagerEth.connect(user).exitToMain(to, amountTo);
+        await tokenManagerEth.connect(user).exitToMain(amountTo);
         expect(BigNumber.from(await ethERC20.balanceOf(user.address)).toString()).to.be.equal(amountAfter.toString());
 
-        await tokenManagerEth.connect(user).exitToMain(deployer.address, amountTo)
+        let data1 = await messages.encodeLockUserMessage(user.address);
+        await messageProxyForSchain.postMessage(communityLocker.address, mainnetHash, fakeCommunityPool, data1);
+
+        await tokenManagerEth.connect(user).exitToMain(amountTo)
             .should.be.eventually.rejectedWith("Recipient must be active");
 
-        await tokenManagerEth.connect(user).exitToMain(to, amountTo)
+        data1 = await messages.encodeActivateUserMessage(user.address);
+        await messageProxyForSchain.postMessage(communityLocker.address, mainnetHash, fakeCommunityPool, data1);
+
+        await tokenManagerEth.connect(user).exitToMain(amountTo)
             .should.be.eventually.rejectedWith("Trying to send messages too often");
 
     });
@@ -240,7 +246,7 @@ describe("TokenManagerEth", () => {
         await tokenManagerEth.connect(deployer).addTokenManager(newSchainName, user.address);
 
         // send Eth and data to a client on schain:
-        await tokenManagerEth.connect(user).transferToSchain(newSchainName, to, amountTo);
+        await tokenManagerEth.connect(user).transferToSchain(newSchainName, amountTo);
 
         const balanceAfter = BigNumber.from(await ethERC20.balanceOf(user.address));
         balanceAfter.should.be.deep.equal(amountAfter);
diff --git a/test/agent/agent.py b/test/agent/agent.py
index 4fafc43cf..9dd26326b 100644
--- a/test/agent/agent.py
+++ b/test/agent/agent.py
@@ -53,7 +53,7 @@ def stop(self):
             self.agent_service = None
 
     def transfer_eth_from_mainnet_to_schain(self, from_key, to_key, amount_wei, timeout=0):
-        destination_address = self.blockchain.key_to_address(to_key)
+        destination_address = self.blockchain.key_to_address(from_key)
         balance, initial_balance = None, None
         start = time()
         if timeout > 0:
@@ -78,7 +78,7 @@ def transfer_eth_from_mainnet_to_schain(self, from_key, to_key, amount_wei, time
                     sleep(1)
 
     def transfer_eth_from_schain_to_mainnet(self, from_key, to_key, amount_wei, timeout=0):
-        destination_address = self.blockchain.key_to_address(to_key)
+        destination_address = self.blockchain.key_to_address(from_key)
         initial_approved, approved, balance, initial_balance = None, None, None, None
         start = time()
         if timeout > 0:
@@ -108,7 +108,7 @@ def transfer_eth_from_schain_to_mainnet(self, from_key, to_key, amount_wei, time
             start = time()
             debug(f'Initial balance: {initial_balance}')
 
-        self._execute_command('s2m-receive', {'key-main-net': to_key})
+        self._execute_command('s2m-receive', {'key-main-net': from_key})
 
         if timeout > 0:
             approximate_gas_spends = 3 * 10 ** 15
@@ -246,7 +246,7 @@ def transfer_erc20_from_schain_to_mainnet(self, token_contract, token_contract_o
         with open(erc20_config_filename, 'w') as erc20_file:
             json.dump(config_mainnet_json, erc20_file)
 
-        destination_address = self.blockchain.key_to_address(to_key)
+        destination_address = self.blockchain.key_to_address(from_key)
         erc20 = token_contract_on_mainnet
         balance = erc20.functions.balanceOf(destination_address).call()
         # balance = erc20.functions.balanceOf(destination_address)
@@ -330,7 +330,7 @@ def transfer_erc1155_from_schain_to_mainnet(self, token_contract, token_contract
             json.dump(config_mainnet_json, erc1155_file)
 
         erc1155 = token_contract_on_mainnet
-        destination_address = self.blockchain.key_to_address(to_key)
+        destination_address = self.blockchain.key_to_address(from_key)
         # destination_address = erc1155.functions.balanceOf(token_id).call()
         # destination_address = self.blockchain.key_to_address(to_key)
         # tx_count = self.blockchain.get_transactions_count_on_mainnet(destination_address)
@@ -372,7 +372,7 @@ def transfer_erc1155_batch_from_schain_to_mainnet(self, token_contract, token_co
             json.dump(config_mainnet_json, erc1155_file)
 
         erc1155 = token_contract_on_mainnet
-        destination_address = self.blockchain.key_to_address(to_key)
+        destination_address = self.blockchain.key_to_address(from_key)
         # destination_address = erc1155.functions.balanceOf(token_id).call()
         # destination_address = self.blockchain.key_to_address(to_key)
         # tx_count = self.blockchain.get_transactions_count_on_mainnet(destination_address)
diff --git a/test/test_cases/a_lot_of_send_ether_to_schain.py b/test/test_cases/a_lot_of_send_ether_to_schain.py
index d8953357a..0e26e7a76 100644
--- a/test/test_cases/a_lot_of_send_ether_to_schain.py
+++ b/test/test_cases/a_lot_of_send_ether_to_schain.py
@@ -31,7 +31,7 @@ def _execute(self):
         #
         range_int = 5
         #
-        address = self.blockchain.key_to_address(self.config.schain_key)
+        address = self.blockchain.key_to_address(self.config.mainnet_key)
         balance = self.blockchain.get_balance_on_schain(address)
         initial_balance = balance
         # 2 ether (2 000 000 000 000 000 000 wei)
diff --git a/test/test_cases/load_send_ether_from_mainnet_to_schain_and_back.py b/test/test_cases/load_send_ether_from_mainnet_to_schain_and_back.py
index c08867256..92d57d664 100644
--- a/test/test_cases/load_send_ether_from_mainnet_to_schain_and_back.py
+++ b/test/test_cases/load_send_ether_from_mainnet_to_schain_and_back.py
@@ -38,7 +38,7 @@ def _execute(self):
         # ETH
         eth_amount = 12 * 10 ** 18
         #
-        address = self.blockchain.key_to_address(self.config.schain_key)
+        address = self.blockchain.key_to_address(self.config.mainnet_key)
         #  transfer to schain
         self.agent.transfer_eth_from_mainnet_to_schain(self.config.mainnet_key,
                                                        self.config.schain_key,
@@ -61,8 +61,8 @@ def _execute(self):
                                                            self.timeout)
             time.sleep(2)
             # back to mainnet
-            self.agent.transfer_eth_from_schain_to_mainnet(self.config.schain_key,
-                                                           self.config.mainnet_key,
+            self.agent.transfer_eth_from_schain_to_mainnet(self.config.mainnet_key,
+                                                           self.config.schain_key,
                                                            amount_from_schain,
                                                            self.timeout)
             self.blockchain.get_balance_on_schain(address)
diff --git a/test/test_cases/send_erc1155_batch_from_mainnet_to_schain.py b/test/test_cases/send_erc1155_batch_from_mainnet_to_schain.py
index 648a09da9..e415cdbe4 100644
--- a/test/test_cases/send_erc1155_batch_from_mainnet_to_schain.py
+++ b/test/test_cases/send_erc1155_batch_from_mainnet_to_schain.py
@@ -64,7 +64,7 @@ def _execute(self):
         )
 
         erc1155 = self.blockchain.get_erc1155_on_schain("Mainnet", self.erc1155.address)
-        destination_address = self.blockchain.key_to_address(self.config.schain_key)
+        destination_address = self.blockchain.key_to_address(self.config.mainnet_key)
         new_amounts = erc1155.functions.balanceOfBatch([destination_address] * len(self.tokenIds), self.tokenIds).call()
         if self.tokenAmounts == new_amounts:
             self._mark_passed()
diff --git a/test/test_cases/send_erc1155_batch_from_schain_to_mainnet.py b/test/test_cases/send_erc1155_batch_from_schain_to_mainnet.py
index 99b1818fa..13104ff38 100644
--- a/test/test_cases/send_erc1155_batch_from_schain_to_mainnet.py
+++ b/test/test_cases/send_erc1155_batch_from_schain_to_mainnet.py
@@ -81,7 +81,7 @@ def _prepare(self):
         self.erc1155_clone = self.blockchain.get_erc1155_on_schain("Mainnet", self.erc1155.address)
 
     def _execute(self):
-        source_address = self.blockchain.key_to_address(self.config.schain_key)
+        source_address = self.blockchain.key_to_address(self.config.mainnet_key)
         destination_address = self.blockchain.key_to_address(self.config.mainnet_key)
 
         if self.erc1155_clone.functions.balanceOfBatch([source_address] * len(self.token_ids), self.token_ids).call() != self.token_amounts:
@@ -92,8 +92,8 @@ def _execute(self):
         self.agent.transfer_erc1155_batch_from_schain_to_mainnet(
             self.erc1155_clone,
             self.erc1155,
-            self.config.schain_key,
             self.config.mainnet_key,
+            self.config.schain_key,
             self.token_ids,
             self.token_amounts,
             6 * 10 ** 16,
diff --git a/test/test_cases/send_erc1155_from_mainnet_to_schain.py b/test/test_cases/send_erc1155_from_mainnet_to_schain.py
index 5b75fe0c9..2184e4ceb 100644
--- a/test/test_cases/send_erc1155_from_mainnet_to_schain.py
+++ b/test/test_cases/send_erc1155_from_mainnet_to_schain.py
@@ -64,7 +64,7 @@ def _execute(self):
         )
 
         erc1155 = self.blockchain.get_erc1155_on_schain("Mainnet", self.erc1155.address)
-        destination_address = self.blockchain.key_to_address(self.config.schain_key)
+        destination_address = self.blockchain.key_to_address(self.config.mainnet_key)
         new_amount = erc1155.functions.balanceOf(destination_address, self.tokenId).call()
         if self.tokenAmount == new_amount:
             self._mark_passed()
diff --git a/test/test_cases/send_erc1155_from_schain_to_mainnet.py b/test/test_cases/send_erc1155_from_schain_to_mainnet.py
index 777722f43..9c4de177a 100644
--- a/test/test_cases/send_erc1155_from_schain_to_mainnet.py
+++ b/test/test_cases/send_erc1155_from_schain_to_mainnet.py
@@ -81,7 +81,7 @@ def _prepare(self):
         self.erc1155_clone = self.blockchain.get_erc1155_on_schain("Mainnet", self.erc1155.address)
 
     def _execute(self):
-        source_address = self.blockchain.key_to_address(self.config.schain_key)
+        source_address = self.blockchain.key_to_address(self.config.mainnet_key)
         destination_address = self.blockchain.key_to_address(self.config.mainnet_key)
 
         if self.erc1155_clone.functions.balanceOf(source_address, self.token_id).call() != self.token_amount:
@@ -92,8 +92,8 @@ def _execute(self):
         self.agent.transfer_erc1155_from_schain_to_mainnet(
             self.erc1155_clone,
             self.erc1155,
-            self.config.schain_key,
             self.config.mainnet_key,
+            self.config.schain_key,
             self.token_id,
             self.token_amount,
             6 * 10 ** 16,
diff --git a/test/test_cases/send_erc20_from_mainnet_to_schain.py b/test/test_cases/send_erc20_from_mainnet_to_schain.py
index a4197e45c..20c248293 100644
--- a/test/test_cases/send_erc20_from_mainnet_to_schain.py
+++ b/test/test_cases/send_erc20_from_mainnet_to_schain.py
@@ -58,7 +58,7 @@ def _execute(self):
         )
 
         erc20 = self.blockchain.get_erc20_on_schain("Mainnet", self.erc20.address)
-        destination_address = self.blockchain.key_to_address(self.config.schain_key)
+        destination_address = self.blockchain.key_to_address(self.config.mainnet_key)
         balance = erc20.functions.balanceOf(destination_address).call()
         if balance == amount:
             self._mark_passed()
diff --git a/test/test_cases/send_erc20_from_schain_to_mainnet.py b/test/test_cases/send_erc20_from_schain_to_mainnet.py
index 4ebe79812..2b059e2c5 100644
--- a/test/test_cases/send_erc20_from_schain_to_mainnet.py
+++ b/test/test_cases/send_erc20_from_schain_to_mainnet.py
@@ -79,7 +79,7 @@ def _prepare(self):
         self.erc20_clone = self.blockchain.get_erc20_on_schain("Mainnet", self.erc20.address)
 
     def _execute(self):
-        source_address = self.blockchain.key_to_address(self.config.schain_key)
+        source_address = self.blockchain.key_to_address(self.config.mainnet_key)
         destination_address = self.blockchain.key_to_address(self.config.mainnet_key)
 
         if self.erc20_clone.functions.balanceOf(source_address).call() < self.amount:
@@ -90,8 +90,8 @@ def _execute(self):
         self.agent.transfer_erc20_from_schain_to_mainnet(
             self.erc20_clone, # token
             self.erc20, # token on mainnet
-            self.config.schain_key, # from
-            self.config.mainnet_key, # to
+            self.config.mainnet_key, # from
+            self.config.schain_key, # to
             (self.amount - 2), # 2 tokens
             6 * 10 ** 16,
             self.timeout
diff --git a/test/test_cases/send_erc721_from_mainnet_to_schain.py b/test/test_cases/send_erc721_from_mainnet_to_schain.py
index 8c7ab6e6c..4ab36eb52 100644
--- a/test/test_cases/send_erc721_from_mainnet_to_schain.py
+++ b/test/test_cases/send_erc721_from_mainnet_to_schain.py
@@ -63,7 +63,7 @@ def _execute(self):
         )
 
         erc721 = self.blockchain.get_erc721_on_schain("Mainnet", self.erc721.address)
-        destination_address = self.blockchain.key_to_address(self.config.schain_key)
+        destination_address = self.blockchain.key_to_address(self.config.mainnet_key)
         new_owner_address = erc721.functions.ownerOf(self.tokenId).call()
         if destination_address == new_owner_address:
             self._mark_passed()
diff --git a/test/test_cases/send_erc721_from_schain_to_mainnet.py b/test/test_cases/send_erc721_from_schain_to_mainnet.py
index 41398aad7..67c7ea2b2 100644
--- a/test/test_cases/send_erc721_from_schain_to_mainnet.py
+++ b/test/test_cases/send_erc721_from_schain_to_mainnet.py
@@ -79,7 +79,7 @@ def _prepare(self):
         self.erc721_clone = self.blockchain.get_erc721_on_schain("Mainnet", self.erc721.address)
 
     def _execute(self):
-        source_address = self.blockchain.key_to_address(self.config.schain_key)
+        source_address = self.blockchain.key_to_address(self.config.mainnet_key)
         destination_address = self.blockchain.key_to_address(self.config.mainnet_key)
 
         if self.erc721_clone.functions.ownerOf(self.token_id).call() != source_address:
@@ -90,8 +90,8 @@ def _execute(self):
         self.agent.transfer_erc721_from_schain_to_mainnet(
             self.erc721_clone,
             self.erc721,
-            self.config.schain_key,
             self.config.mainnet_key,
+            self.config.schain_key,
             self.token_id,
             6 * 10 ** 16,
             self.timeout
diff --git a/test/test_cases/send_ether_from_schain_to_mainnet.py b/test/test_cases/send_ether_from_schain_to_mainnet.py
index 53946ea58..c390a98c7 100644
--- a/test/test_cases/send_ether_from_schain_to_mainnet.py
+++ b/test/test_cases/send_ether_from_schain_to_mainnet.py
@@ -48,7 +48,7 @@ def _prepare(self):
             self.blockchain.send_ether_on_mainnet(self.config.mainnet_key, self.config.mainnet_key, min_transaction_fee)
 
     def _execute(self):
-        source_address = self.blockchain.key_to_address(self.config.schain_key)
+        source_address = self.blockchain.key_to_address(self.config.mainnet_key)
         if self.blockchain.get_balance_on_schain(source_address) < self.amount:
             return
 
@@ -60,8 +60,8 @@ def _execute(self):
         
         debug('Destination balance:', balance)
 
-        self.agent.transfer_eth_from_schain_to_mainnet(self.config.schain_key,
-                                                       self.config.mainnet_key,
+        self.agent.transfer_eth_from_schain_to_mainnet(self.config.mainnet_key,
+                                                       self.config.schain_key,
                                                        self.amount,
                                                        self.timeout)
 
diff --git a/test/test_cases/send_ether_to_schain.py b/test/test_cases/send_ether_to_schain.py
index ab0fdb81e..007fa19c7 100644
--- a/test/test_cases/send_ether_to_schain.py
+++ b/test/test_cases/send_ether_to_schain.py
@@ -27,7 +27,7 @@ def __init__(self, config):
         super().__init__('Send ether to schain', config)
 
     def _execute(self):
-        address = self.blockchain.key_to_address(self.config.schain_key)
+        address = self.blockchain.key_to_address(self.config.mainnet_key)
         balance = self.blockchain.get_balance_on_schain(address)
         initial_balance = balance
         amount = 2 * 10 ** 15 # 2 finney
diff --git a/test/tools/blockchain.py b/test/tools/blockchain.py
index ed9eb2b30..211334278 100644
--- a/test/tools/blockchain.py
+++ b/test/tools/blockchain.py
@@ -235,7 +235,7 @@ def send_ether_on_mainnet(self, from_key, to_key, amount_wei):
     def recharge_user_wallet(self, from_key, schainName, amount_wei):
         sender_address = self.key_to_address(from_key)
         community_pool = self._get_contract_on_mainnet('community_pool')
-        recharge_abi = community_pool.encodeABI(fn_name="rechargeUserWallet", args=[schainName])
+        recharge_abi = community_pool.encodeABI(fn_name="rechargeUserWallet", args=[schainName, sender_address])
         signed_txn = self.web3_mainnet.eth.account.signTransaction(dict(
                 nonce=self.web3_mainnet.eth.getTransactionCount(sender_address),
                 gasPrice=self.web3_mainnet.eth.gasPrice,