fix(event): decode uint event parameters as unsigned
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:
EventParserTestcovers2^255-1,2^255and2^256-1foruint256,uintandtrcTokenthrough bothparseDataBytesandparseTopic, withint256(-1)as the control, plus an end-to-endContractEventParserAbicase fortopicMapanddataMap. The new tests fail on the currentrelease_v4.8.3head. - Manual Testing: on a single-witness private chain, replayed the USDT
Approvallog above through a contract that emits the sameowner,spenderandvalue; the private-chain logtopicsanddataare byte-identical to the mainnet log. With therelease_v4.8.3build the native-queuecontractEventTriggermessage carriedvalue = "-1"; with this build the same transaction decoded to the positive value on both the realtime path and theversion = 1history replay path, and the two indexed addresses decoded identically on both builds. A second probe contract covering2^255-1,2^255,2^256-1andint256(-1)gave the same picture.
Follow up
None.
Extra details
Breaking changes (release-note items):
uint256event parameters at or above2^255are published as positive decimal strings intopicMapanddataMap. Consumers that compare the decoded value to"-1"to detect an unlimited approval must compare to115792089237316195423570985008687907853269984665640564039457584007913129639935instead.event.subscribe.filter.contractTopicmatchescontracteventtriggers 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
uint256parameters at or above2^255are now published as positive decimal strings, so consumers matching an unlimited approval against"-1"must compare against115792089237316195423570985008687907853269984665640564039457584007913129639935instead.event.subscribe.filter.contractTopicfilters written for such parameters must use the positive value.
Raw event data and all JSON-RPC, HTTP, and gRPC responses are unchanged.