Issue with recognizing multi-sig deposits

Overview

Some exchanges may have an issue where deposits made using msig propose and then msig exec are not properly recognized.

The issue

EOS

For EOS deposits Sample Exchange instructs all users to send funds to a single EOS account. Each user is given a unique id and is required to enter it into the memo field.

Sample Exchange monitors that single account for inbound transfers and reads the memo to know which internal user account to credit.

FIO

FIO does not use native token transfer action and instead uses custom trnsfiopubky action.

For that reason, and as recommended in Exchange Listing Guide Sample Exchange creates a unique FIO Public Key for each user’s deposit. It then monitors the chain calling get_block at every block height and inspects the transactions looking for a transfer to one of the accounts that belong to a Sample Exchange customer.

Here’s an example of get_block response where such token transfer transaction occurred:

{ "timestamp": "2020-07-31T06:09:39.500", "producer": "gtgkdpybvdnb", "confirmed": 0, "previous": "01520e8fe0340182ade7eaa9d723a2f2a0a913c4e9ef784c2114122ecfb88ad8", "transaction_mroot": "2021b36e3f2d590e1834770bf0c78ff63fead575bc7cebf24920f2bc0015c38c", "action_mroot": "9ea1465b0e5b8414855a859a1e34c2bfa1cd4ce74b061e782eb7dd220acd75db", "schedule_version": 24, "new_producers": null, "header_extensions": [], "producer_signature": "SIG_K1_KgavTqbubwBTnC3XHYRQdmVVgKPGZwRHpDxP1a1t1bn33ounF32PomK3PuKSqHseiv7sVxRvhxnnfro4TaHuMAzdfmNoFM", "transactions": [ { "status": "executed", "cpu_usage_us": 7626, "net_usage_words": 22, "trx": { "id": "87632dca83653c1e803082a62452c5fe48610555fc8b94f669810c06ab94f6fe", "signatures": ["SIG_K1_Kk16nfVM3VeQ2iytgfmubiYJtxKLLagtQqyRefXAZPVo9nZESJobLmQk9JZH8fsfYquBuj7J6Q9iivqW37DCJun9bFzEjd"], "compression": "none", "packed_context_free_data": "", "context_free_data": [], "packed_trx": "c0b5235f8e0e055ec6e600000000010000980ad20ca85be0e1d195ba85e7cd0190b6af0f71943f5500000000a8ed32324f3546494f34764a6d4c645831365247524841336e654848564a61636a736b7a43723362616566467a5350647366514471565a45743579000cdc0f21000000009435770000000090b6af0f71943f550000", "transaction": { "expiration": "2020-07-31T06:10:08", "ref_block_num": 3726, "ref_block_prefix": 3871759877, "max_net_usage_words": 0, "max_cpu_usage_ms": 0, "delay_sec": 0, "context_free_actions": [], "actions": [ { "account": "fio.token", "name": "trnsfiopubky", "authorization": [ { "actor": "eoztcwcjpyvd", "permission": "active" }], "data": { "payee_public_key": "FIO4vJmLdX16RGRHA3neHHVJacjskzCr3baefFzSPdsfQDqVZEt5y", "amount": 142000000000, "max_fee": 2000000000, "actor": "eoztcwcjpyvd", "tpid": "" }, "hex_data": "3546494f34764a6d4c645831365247524841336e654848564a61636a736b7a43723362616566467a5350647366514471565a45743579000cdc0f21000000009435770000000090b6af0f71943f5500" }], "transaction_extensions": [] } } }], "block_extensions": [], "id": "01520e908ee3b30aabc3bdffb6d2fd6029e2d0d02b15a4325b9d1b75a75fced2", "block_num": 22154896, "ref_block_prefix": 4290626475 }

Transfer via multi-sig

When funds are transferred via multi-sig, the actual transfer transaction occurs in the block when it is proposed as part of msig propose and is executed as an in-line action when msig exec transaction is submitted, or more specifically in next block.

Here’s an example of get_block response where such msig propose transaction occurred:

{ "timestamp": "2020-07-31T12:06:19.500", "producer": "c5aeqmc1trd2", "confirmed": 0, "previous": "0152b5bfa97b704180c7f50ef3a94eb40f6f1921141e9ded77341324baa57518", "transaction_mroot": "a2a4839248a04c041c3a402dffdf9eb90b04473f068e7996c2b8872a2bd709f2", "action_mroot": "c444676979fa63dfecdde29aeede16e01b3165eac9414b27bb1509f721eec047", "schedule_version": 24, "new_producers": null, "header_extensions": [], "producer_signature": "SIG_K1_JyS2rUd53P4ZYq7qmEYamfXDVoYG6Vf7Q196dZiLJ7eUu3jST5k6SkuQUntC86SAe2Zk7H9iEpGBwHRrZSvS2RdUshr55S", "transactions": [ { "status": "executed", "cpu_usage_us": 7477, "net_usage_words": 35, "trx": { "id": "ec54a8c9804a05e7e78fa2254f301df72d74e64e0ef2eae63772d8dbc20561c4", "signatures": ["SIG_K1_KcvxJojjiyFvxyuARCfsnC9NKZ1EjTzMN4aYsM7kUBBuFGf8uERDHsKgh9n4hH8EnDEbuV3u2kQfnMsrDESkNpN77M4rXh"], "compression": "none", "packed_context_free_data": "", "context_free_data": [], "packed_trx": "5809245f78b4616e0aa500000000010000735802ea305500000040615ae9ad0140d8813d4242387900000000a8ed3232ba0140d8813d42423879000000000000883902b0f40d0bf180dfe200000000a8ed32328097804c1d59f21000000000a8ed3232002f68590000000008ce245f6cb4f9c8e6ec00000000010000980ad20ca85be0e1d195ba85e7cd01d09f12c2116f0e5400000000a8ed32324f3546494f36424436694e5572444d74756e73584152484c4b744573737074366639504c427354677a7573316f7a5452695132503744620080c6a47e8d03000094357700000000d09f12c2116f0e54000000", "transaction": { "expiration": "2020-07-31T12:06:48", "ref_block_num": 46200, "ref_block_prefix": 2768924257, "max_net_usage_words": 0, "max_cpu_usage_ms": 0, "delay_sec": 0, "context_free_actions": [], "actions": [ { "account": "eosio.msig", "name": "propose", "authorization": [ { "actor": "j4w44klxkbg4", "permission": "active" }], "data": { "proposer": "j4w44klxkbg4", "proposal_name": "ba4", "requested": [ { "actor": "wfjs1wcf1ruf", "permission": "active" }, { "actor": "23t5mbegk2fs", "permission": "active" } ], "max_fee": 1500000000, "trx": { "expiration": "2020-08-01T02:06:00", "ref_block_num": 46188, "ref_block_prefix": 3974547705, "max_net_usage_words": 0, "max_cpu_usage_ms": 0, "delay_sec": 0, "context_free_actions": [], "actions": [ { "account": "fio.token", "name": "trnsfiopubky", "authorization": [ { "actor": "ekbay4i22ejx", "permission": "active" }], "data": "3546494f36424436694e5572444d74756e73584152484c4b744573737074366639504c427354677a7573316f7a5452695132503744620080c6a47e8d03000094357700000000d09f12c2116f0e5400" }], "transaction_extensions": [] } }, "hex_data": "40d8813d42423879000000000000883902b0f40d0bf180dfe200000000a8ed32328097804c1d59f21000000000a8ed3232002f68590000000008ce245f6cb4f9c8e6ec00000000010000980ad20ca85be0e1d195ba85e7cd01d09f12c2116f0e5400000000a8ed32324f3546494f36424436694e5572444d74756e73584152484c4b744573737074366639504c427354677a7573316f7a5452695132503744620080c6a47e8d03000094357700000000d09f12c2116f0e540000" }], "transaction_extensions": [] } } }], "block_extensions": [], "id": "0152b5c0f62bc87e549a6e8dce26d08c6ab6b6d26ec177894b6c019a62d464c8", "block_num": 22197696, "ref_block_prefix": 2372835924 }

As you can see the transaction’s action is propose but it has a trx parameter which contains the actual trnsfiopubky transaction. The data de-serializes to:

{ "payee_public_key": "FIO6BD6iNUrDMtunsXARHLKtEsspt6f9PLBsTgzus1ozTRiQ2P7Db", "amount": 1000000000000000, "max_fee": 2000000000, "actor": "ekbay4i22ejx", "tpid": "" }

Here’s an example of get_block response where such msig exec transaction occurred:

Here’s an example of get_block response where the actual transfer occurred (next block):

As you can see there is no reference to the original msig propose. The actual transfer shows up in action traces for the above transaction, but action traces are not returned in get_block.

Solutions

When transaction with status executed is encountered:

Fetch inline traces for that transaction using /v1/history/get_transaction

Here’s an example of /v1/history/get_transaction response for trx id above:

Please note that there are 12 action traces for this transaction and trnsfiopubky shows up in several of them. It’s best to identify the correct action trace using the receiver field, which includes the actor which was hashed down from the Payee Public Key, i.e. ddgh44qzfyxo for FIO6BD6iNUrDMtunsXARHLKtEsspt6f9PLBsTgzus1ozTRiQ2P7Db.