-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: transaction with CONTRACT_NEGATIVE_VALUE
breaks some routes
#3387
base: main
Are you sure you want to change the base?
feat: transaction with CONTRACT_NEGATIVE_VALUE
breaks some routes
#3387
Conversation
Signed-off-by: nikolay <[email protected]>
Test Results 18 files - 7 236 suites - 151 33m 2s ⏱️ - 40m 3s Results for commit fa9f894. ± Comparison against base commit 67b61c6. This pull request removes 3 tests.
♻️ This comment has been updated with latest results. |
Signed-off-by: nikolay <[email protected]>
Signed-off-by: nikolay <[email protected]>
Signed-off-by: nikolay <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work overall. Blocking as one warning needed to be addressed.
Also, is it feasible to add an e2e test to avoid regression?
|
||
// we're using 64 bits integer because that the type returned by the mirror node - int64 | ||
const bits = 64; | ||
return numberTo0x((BigInt(input.toString()) + (BigInt(1) << BigInt(bits))) % (BigInt(1) << BigInt(bits))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: do we expect number
bigger than 53
bits? so it's not automatically coerced to double https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I don't know how often it will happen but we definitely must handle values bigger than Number.MAX_SAFE_INTEGER
.
The max Int64 positive value is 0x7fffffffffffffff
which has 63 "usable" bits.
0111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
That's why we always convert the incoming value to BigInt here 👇
BigInt(input.toString())
Hope that makes sense or am I wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mmm, I'm not sure that BigInt(input.toString())
works as expected when input
being a number
uses more than 53
bits. Say
> const x = 0x7fffffffffffffff
> typeof(x)
'number'
> BigInt(x.toString()) - 0x7fffffffffffffffn
193n
but the difference should be zero, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, the difference should be zero. Nice catch 👏 and thank you. That's something I must add more unit tests tomorrow.
Here are some more quick tests, it seems that .toString()
messed things up, also using a shadow conversion like postfixing n
doesn't seem to work as expected.
> const x = 0x7fffffffffffffff
undefined
> typeof(x)
'number'
> BigInt(x.toString()) - 0x7fffffffffffffffn
193n
> BigInt(x) - 0x7fffffffffffffffn
1n
> BigInt(x) - BigInt(0x7fffffffffffffff)
0n
> BigInt(x) - BigInt(9223372036854776000)
0n
Do you have an idea how this can be completely fixed? I think removing .toString()
is enough but that will be confirmed when I push the unit tests covering wide-bit range numbers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think removing .toString() is enough
The problem is with number
altogether.
> BigInt(0x7fffffffffffffff) - 0x7fffffffffffffffn
1n
The only way I see to proper fix it completely would be to not use number
, and use bigint
everywhere for values that are int64
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Will try to refactor it in an elegant way and once I'm done will ping you again for review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @acuarica,
Richard Moore has the same thoughts as you ethers-io/ethers.js#452 (comment). Today I managed to resolve it but what do you think about the implementation?
What I've done:
- decided to use json-bigint
- hooked up into axios's transformResponse method
- parsed the json string before it's been parsed by the default
JSON.parse
where the number will be rounded and lost forever
Here are the two mainnet transactions I tested with:
- negative number - https://hashscan.io/mainnet/transaction/1735241436.856862230
- positive 62 bits number - https://hashscan.io/mainnet/transaction/1735223396.774976000
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would be the advantage of using json-bigint
over bigint
? Only parsing? doesn't bigint
already comes with parsing capabilities?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
json-bigint
is doing JSONBigInt.parse(data)
but under the hood, it transforms numeric values to bigint
instead of JS Number.
If we're doing JSON.parse()
and then manually transforming numeric values to bigint, JSON.parse()
already rounded the number and we lost it.
json-bigint
doesn't replace bigint
and they are not correlated. json-bigint
is used instead of JSON.parse()
due to its capability of converting string json input directly to bigint
instead of JS Number.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification.
Signed-off-by: nikolay <[email protected]>
Adding an e2e test is not a straightforward process because that kind of revert can't be reproduced with an I have no problem adding that test if you insist 🚀 🙏. |
Ah I see. Just curious how would you reproduice the problem? |
Signed-off-by: nikolay <[email protected]>
Quality Gate failedFailed conditions |
Sending a negative amount via ContractCallTransaction will be enough while it accepts int64 (not uint64). Here is the link to the doc https://docs.hedera.com/hedera/sdks-and-apis/hedera-api/readme-1-1/contractcall#contractcalltransactionbody. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3387 +/- ##
===========================================
- Coverage 84.87% 64.10% -20.77%
===========================================
Files 69 65 -4
Lines 4742 4550 -192
Branches 1067 1043 -24
===========================================
- Hits 4025 2917 -1108
- Misses 400 1106 +706
- Partials 317 527 +210
Flags with carried forward coverage won't be shown. Click here to find out more.
|
Ah I see. So if it's feasible and do not take crazy amount of time, I would encourage we have an e2e just to make sure no regression later. Thanks much Nikki! |
Description:
It seems like
eth_getBlockByNumber
fails because one of the transactions in the block was a CONTRACT_NEGATIVE_VALUE failure. The expectation is for the block to be successfully returned.Steps to reproduce:
eth_getBlockByNumber
on block 73298898The problematic transaction is here
Related issue(s):
Fixes #3367
Notes for reviewer:
Checklist