fix(event): decode uint event parameters as unsigned

0X
8d ago
+64-2

What does this PR do?

ContractEventParser classified int, uint and trcToken together as INT_NUMBER and decoded all of them as signed two's complement. Any uint256 event parameter with bit 255 set was therefore published as a negative number, in both topicMap (indexed) and dataMap (non-indexed).

This PR adds a UINT_NUMBER type for uint* and trcToken and decodes it with a new DataWord.bigUIntValue helper (new BigInteger(1, bytes)), mirroring the existing DataWord.bigIntValue. Signed decoding is unchanged.

Why are these changes required?

Unlimited TRC20 approvals hit this every day. Mainnet USDT transaction f2e9b6cc2df49316122f28e974b28d1e160bcf49db84a04827b1b49cea38cfb4 (block 87664803) emits Approval(owner, spender, type(uint256).max); the event plugin publishes dataMap.value = "-1" instead of 115792089237316195423570985008687907853269984665640564039457584007913129639935. Every other decoder in the ecosystem, including TronGrid, trident, web3.js and ethers, treats uint256 as unsigned; the java-tron event plugin is the only producer emitting negative values.

A fix for the same defect was proposed in #2297 (2019) but was closed unmerged.

This PR has been tested by:

  • Unit Tests: EventParserTest covers 2^255-1, 2^255 and 2^256-1 for uint256, uint and trcToken through both parseDataBytes and parseTopic, with int256(-1) as the control, plus an end-to-end ContractEventParserAbi case for topicMap and dataMap. The new tests fail on the current release_v4.8.3 head.
  • Manual Testing: on a single-witness private chain, replayed the USDT Approval log above through a contract that emits the same owner, spender and value; the private-chain log topics and data are byte-identical to the mainnet log. With the release_v4.8.3 build the native-queue contractEventTrigger message carried value = "-1"; with this build the same transaction decoded to the positive value on both the realtime path and the version = 1 history replay path, and the two indexed addresses decoded identically on both builds. A second probe contract covering 2^255-1, 2^255, 2^256-1 and int256(-1) gave the same picture.

Follow up

None.

Extra details

Breaking changes (release-note items):

  • uint256 event parameters at or above 2^255 are published as positive decimal strings in topicMap and dataMap. Consumers that compare the decoded value to "-1" to detect an unlimited approval must compare to 115792089237316195423570985008687907853269984665640564039457584007913129639935 instead.
  • event.subscribe.filter.contractTopic matches contractevent triggers against decoded indexed values. A filter written as "-1" for such a parameter must be rewritten as the positive value.

Raw topics and data, contractlog triggers, and all JSON-RPC, HTTP and gRPC responses are unchanged.


Summary by cubic

Fixes uint* and trcToken event parameters being decoded as signed values, publishing uint256 values at or above 2^255 as negative numbers in topicMap and dataMap.

Breaking changes

  • uint256 parameters at or above 2^255 are now published as positive decimal strings, so consumers matching an unlimited approval against "-1" must compare against 115792089237316195423570985008687907853269984665640564039457584007913129639935 instead.
  • event.subscribe.filter.contractTopic filters written for such parameters must use the positive value.

Raw event data and all JSON-RPC, HTTP, and gRPC responses are unchanged.