neo-modules icon indicating copy to clipboard operation
neo-modules copied to clipboard

getnep11balances in TokensTrakcer doesn't return correct result compared with invoking tokensOf

Open superboyiii opened this issue 2 years ago • 6 comments

Describe the bug getnep11balances in TokensTrakcer doesn't return correct result compared with invoking tokensOf

To Reproduce Steps to reproduce the behavior:

  1. invoke getnep11balances on a T5 node like:
{
  "jsonrpc": "2.0",
  "method": "getnep11balances",
  "params": ["NfcCRKpDUKGZDjz3wQFg8G2x1kh25TCpaq", 0],
  "id": 1
}

return:

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "address": "NfcCRKpDUKGZDjz3wQFg8G2x1kh25TCpaq",
        "balance": [
            {
                "assethash": "0xaa3ee1db78a9791a80ccc4fd1befe63c468096ab",
                "name": "ilex",
                "symbol": "ilex",
                "decimals": "0",
                "tokens": [
                    {
                        "tokenid": "0b",
                        "amount": "1",
                        "lastupdatedblock": 617871
                    }
                ]
            }
        ]
    }
}

Only 1 NEP-11 token is returned. 2. invoke tokensOf like:

{{
  "jsonrpc": "2.0",
  "method": "invokefunction",
  "params": [
    "0x6a2893f97401e2b58b757f59d71238d91339856a",
    "tokensOf",
    [
        {
        "type": "Hash160",
        "value": "0x833ac279fa278098b9dbe65d5cfb64a9541306d8"
        }
    ]
  ],
  "id": 3
}

return:

{
    "jsonrpc": "2.0",
    "id": 3,
    "result": {
        "script": "DBTYBhNUqWT7XF3m27mYgCf6ecI6gxHAHwwIdG9rZW5zT2YMFGqFORPZOBLXWX91i7XiAXT5kyhqQWJ9W1I=",
        "state": "HALT",
        "gasconsumed": "278448",
        "exception": null,
        "notifications": [],
        "stack": [
            {
                "type": "InteropInterface",
                "interface": "IIterator",
                "id": "c0a7d84f-53dd-4f4c-b8e2-9b17e697087b"
            }
        ],
        "session": "b5348a69-b756-4cd9-af3f-05b485678df8"
    }
}

Go to traverseiterator and invoke

{
  "jsonrpc": "2.0",
  "method": "traverseiterator",
  "params": ["b5348a69-b756-4cd9-af3f-05b485678df8", "c0a7d84f-53dd-4f4c-b8e2-9b17e697087b", 100],
  "id": 3
}

return:

{
    "jsonrpc": "2.0",
    "id": 3,
    "result": [
        {
            "type": "ByteString",
            "value": "SEFTSCAjMDE="
        },
        {
            "type": "ByteString",
            "value": "SEFTSCAjMDI="
        },
        {
            "type": "ByteString",
            "value": "SEFTSCAjMDM="
        },
        {
            "type": "ByteString",
            "value": "V0VCICMwMQ=="
        },
        {
            "type": "ByteString",
            "value": "V0VCICMwMg=="
        },
        {
            "type": "ByteString",
            "value": "V0VCICMwMw=="
        }
    ]
}
  1. You can see absolutely different result

Expected behavior Should return the same amount of tokenid

Platform:

  • Version v3.4.0

superboyiii avatar Aug 31 '22 03:08 superboyiii

NeoGo 0.99.2:

invoke getnep11balances on a T5 node like:
{
   "jsonrpc" : "2.0",
   "id" : 1,
   "result" : {
      "balance" : [
         {
            "symbol" : "ILEX GENESIS",
            "decimals" : "0",
            "assethash" : "0x6a2893f97401e2b58b757f59d71238d91339856a",
            "name" : "ILEX GENESIS",
            "tokens" : [
               {
                  "amount" : "1",
                  "lastupdatedblock" : 617588,
                  "tokenid" : "4841534820233031"
               },
               {
                  "tokenid" : "4841534820233032",
                  "lastupdatedblock" : 617588,
                  "amount" : "1"
               },
               {
                  "tokenid" : "4841534820233033",
                  "amount" : "1",
                  "lastupdatedblock" : 617588
               },
               {
                  "amount" : "1",
                  "lastupdatedblock" : 617588,
                  "tokenid" : "57454220233031"
               },
               {
                  "amount" : "1",
                  "lastupdatedblock" : 617588,
                  "tokenid" : "57454220233032"
               },
               {
                  "tokenid" : "57454220233033",
                  "amount" : "1",
                  "lastupdatedblock" : 617588
               }
            ]
         }
      ],
      "address" : "NfcCRKpDUKGZDjz3wQFg8G2x1kh25TCpaq"
   }
}
  1. invoke tokensOf like:
{
   "result" : {
      "state" : "HALT",
      "stack" : [
         {
            "type" : "InteropInterface",
            "iterator" : [
               {
                  "type" : "ByteString",
                  "value" : "SEFTSCAjMDE="
               },
               {
                  "type" : "ByteString",
                  "value" : "SEFTSCAjMDI="
               },
               {
                  "value" : "SEFTSCAjMDM=",
                  "type" : "ByteString"
               },
               {
                  "type" : "ByteString",
                  "value" : "V0VCICMwMQ=="
               },
               {
                  "value" : "V0VCICMwMg==",
                  "type" : "ByteString"
               },
               {
                  "type" : "ByteString",
                  "value" : "V0VCICMwMw=="
               }
            ]
         }
      ],
      "script" : "DBTYBhNUqWT7XF3m27mYgCf6ecI6gxHAHwwIdG9rZW5zT2YMFGqFORPZOBLXWX91i7XiAXT5kyhqQWJ9W1I=",
      "exception" : null,
      "gasconsumed" : "278448",
      "notifications" : []
   },
   "id" : 3,
   "jsonrpc" : "2.0"
}

roman-khimov avatar Aug 31 '22 06:08 roman-khimov

Notice that the symbol is different too if we're to ask 0x6a2893f97401e2b58b757f59d71238d91339856a for it:

$ curl -sd '{"jsonrpc": "2.0", "method": "invokefunction", "params": ["0x6a2893f97401e2b58b757f59d71238d91339856a", "symbol", []],"id": 3}' https://rpc.t5.n3.nspcc.ru:20331
{"id":3,"jsonrpc":"2.0","result":{"state":"HALT","gasconsumed":"167256","script":"wh8MBnN5bWJvbAwUaoU5E9k4EtdZf3WLteIBdPmTKGpBYn1bUg==","stack":[{"type":"ByteString","value":"SUxFWCBHRU5FU0lT"}],"exception":null,"notifications":[]}}
$ echo "SUxFWCBHRU5FU0lT" | base64 -d
ILEX GENESIS

roman-khimov avatar Aug 31 '22 06:08 roman-khimov

Notice that the symbol is different too if we're to ask 0x6a2893f97401e2b58b757f59d71238d91339856a for it:

TokensTracker will deocde that Base64 ByteString.

superboyiii avatar Aug 31 '22 08:08 superboyiii

Notice that the symbol is different too if we're to ask 0x6a2893f97401e2b58b757f59d71238d91339856a for it:

TokensTracker will deocde that Base64 ByteString.

That's not the point, in your output you have

                "name": "ilex",
                "symbol": "ilex",

While NeoGo returns

            "symbol" : "ILEX GENESIS",
            "name" : "ILEX GENESIS",

And that's the correct answer (even though the symbol is bad, we're expecting something short (3-8 characters is recommended), with no whitespace characters or new-lines). I'm not sure why this happens, though.

roman-khimov avatar Aug 31 '22 08:08 roman-khimov

That's not the point, in your output you have.....

These are two absolutely different contracts, I find tokenid in 0x6a2893f97401e2b58b757f59d71238d91339856a was in Intger while tokenid in 0xaa3ee1db78a9791a80ccc4fd1befe63c468096ab was in ByteString, that's why TokenTracker can't catch 0x6a2893f97401e2b58b757f59d71238d91339856a.

superboyiii avatar Sep 01 '22 06:09 superboyiii

Huh, thanks for clarification. I was then somewhat surprised that I don't see any tokens listed for 0xaa3ee1db78a9791a80ccc4fd1befe63c468096ab in my output, but looks like they're gone now:

$ curl -sd '{"jsonrpc": "2.0", "method": "invokefunction", "params": ["0xaa3ee1db78a9791a80ccc4fd1befe63c468096ab", "tokensOf", [{"type": "Hash160", "value": "0x833ac279fa278098b9dbe65d5cfb64a9541306d8"}]],"id": 3}' https://rpc.t5.n3.nspcc.ru:20331 |json_pp
{
   "id" : 3,
   "jsonrpc" : "2.0",
   "result" : {
      "notifications" : [],
      "script" : "DBTYBhNUqWT7XF3m27mYgCf6ecI6gxHAHwwIdG9rZW5zT2YMFKuWgEY85u8b/cTMgBp5qXjb4T6qQWJ9W1I=",
      "gasconsumed" : "382635",
      "state" : "HALT",
      "exception" : null,
      "stack" : [
         {
            "type" : "InteropInterface"
         }
      ]
   }
}

While there was something (the same token as in your getnep11balances) at 617871:

$ curl -sd '{"jsonrpc": "2.0", "method": "invokefunctionhistoric", "params": [617871, "0xaa3ee1db78a9791a80ccc4fd1befe63c468096ab", "tokensOf", [{"type": "Hash160", "value": "0x833ac279fa278098b9dbe65d5cfb64a9541306d8"}]],"id": 3}' https://rpc.t5.n3.nspcc.ru:20331 |json_pp
{
   "id" : 3,
   "result" : {
      "notifications" : [],
      "exception" : null,
      "state" : "HALT",
      "gasconsumed" : "382635",
      "script" : "DBTYBhNUqWT7XF3m27mYgCf6ecI6gxHAHwwIdG9rZW5zT2YMFKuWgEY85u8b/cTMgBp5qXjb4T6qQWJ9W1I=",
      "stack" : [
         {
            "type" : "InteropInterface",
            "iterator" : [
               {
                  "value" : "Cw==",
                  "type" : "ByteString"
               }
            ]
         }
      ]
   },
   "jsonrpc" : "2.0"
}

roman-khimov avatar Sep 01 '22 09:09 roman-khimov

TokenId should be ByteString, I will close this.

superboyiii avatar Sep 05 '22 03:09 superboyiii

Hey guys, why if i do the rpc call "getnep11balances" on NEO-GO nodes i get a result with a set of data and if i do the same request to C# nodes i get it different?

Example:

  • NEO-GO: https://rpc10.n3.nspcc.ru:10331/
  • C#: https://n3seed1.ngd.network:10332/

Request body: { "jsonrpc": "2.0", "method": "getnep11balances", "params": ["Nhiqz5HqKyicYiwnMTgeujmBjRjWvcBQYr"], "id": 1 }

The contracts that are returning different data here are BlackStoneShard and BoredDoge NFTs. @superboyiii @roman-khimov

mfbz avatar Dec 09 '22 17:12 mfbz

@mfbz, I don't have any obvious answer for this one. Take this token for example:

         {
            "assethash" : "0x7bd7b0af7f9085bb4f6f2e3f956ec9ff5a494645",
            "tokens" : [
               {
                  "tokenid" : "546865446f67655761734e6f74416e496d706f73746f722020233532",
                  "lastupdatedblock" : 1680095,
                  "amount" : "1"
               }
            ],
            "symbol" : "BoredDoge",
            "name" : "DogeRift_NFTS",
            "decimals" : "0"
         },

Block 1680095 really has one transaction, 0xb878b2ad81078522b5d2e98f5be89d635223ecf1aea5e43a0ed3a3e57c9b9122 and it has this event generated during the execution:

               {
                  "contract" : "0x7bd7b0af7f9085bb4f6f2e3f956ec9ff5a494645",
                  "eventname" : "Transfer",
                  "state" : {
                     "value" : [
                        {
                           "value" : "7zguJBMYuAgxO8Vzkm7OIq+tTyI=",
                           "type" : "ByteString"
                        },
                        {
                           "value" : "ZHOD/efBT66ngyCMMHdOesko/0I=",
                           "type" : "ByteString"
                        },
                        {
                           "type" : "Integer",
                           "value" : "1"
                        },
                        {
                           "type" : "ByteString",
                           "value" : "VGhlRG9nZVdhc05vdEFuSW1wb3N0b3IgICM1Mg=="
                        }
                     ],
                     "type" : "Array"
                  }
               }

Which seems to be a valid event, so it should be processed correctly by TokensTracker.

roman-khimov avatar Dec 09 '22 20:12 roman-khimov

Yes, i agree with you.

Another strange thing is that I just tried also with another contract (https://explorer.onegate.space/contractinfo/0xc09af9967175faca47d610716900f075bd8bf18a) that has basically the same Transfer method and NEP11 handling of the BlackStoneShard contract (https://explorer.onegate.space/contractinfo/0xdd191554eb403669221137aee0c424c27670cb2b) and it's correctly returned from getnep11balances.

I think this issue should be reopened

mfbz avatar Dec 09 '22 21:12 mfbz

Thanks to NeoLine devs we found the cause of the problem.

Basically BlackStoneShard Nft contract at the beginning had 2 balanceOf methods because i coded it with an overload to handle the case of requesting the balance of a key of a nft like in Ethereum EIP-1155 (https://eips.ethereum.org/EIPS/eip-1155). The fact of having 2 balanceOf methods caused the problem on the c# node.

Now i removed the overload and saw that everything is working correctly.

mfbz avatar Dec 10 '22 07:12 mfbz

Reminds me of neo-project/neo#2355. In fact NeoGo uses balanceOf signature check to distinguish between divisible/non-divisble NEP-11 and it was probably using balanceOf(owner, token) in your case, but if that works (returning 1), it's OK. Still I'd say the plugin should be improved, because your additional balanceOf doesn't break compliance with NEP-11 non-divisible spec, the contract can have as many additional methods as it needs to with any kind of signatures, it shouldn't be a problem.

In absence of neo-project/neo#2355 we probably should check for ownerOf signature to separate divisible/non-divisible NFTs, one can't have both versions of it in the same contract.

roman-khimov avatar Dec 10 '22 08:12 roman-khimov