Skip to content
This repository has been archived by the owner on Sep 20, 2023. It is now read-only.

Fix USDT payment #4306

Closed
wants to merge 17 commits into from
Closed

Fix USDT payment #4306

wants to merge 17 commits into from

Conversation

shahthepro
Copy link
Collaborator

@shahthepro shahthepro commented Jan 28, 2020

Should fix #4304

Link to test build

Checklist:

@micahalcorn micahalcorn requested a review from tomlinton January 28, 2020 22:41
tomlinton
tomlinton previously approved these changes Jan 29, 2020
@tomlinton tomlinton dismissed their stale review January 29, 2020 02:34

Test failures

@tomlinton
Copy link
Contributor

Thanks @shahthepro, looks like a lot of test failures that are probably related to these changes. I'll update the branch to run them again but would you mind checking them out if it still fails?

@shahthepro
Copy link
Collaborator Author

@tomlinton Thanks. PR is not yet ready for review. Yeah, will be fixing the tests

@tomlinton
Copy link
Contributor

Sorry @shahthepro, someone (cough @micahalcorn) requested review 👺 😂

Copy link
Member

@sparrowDom sparrowDom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left one comment otherwise LGTM.
Since you have separated it so nicely into a class could be beneficial to add a few unit tests maybe.


const zeroCount = valueInWei.length - valueInWei.replace(/0/g, '').length

return zeroCount === decimals
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT web3 units for each zero count don't exist. Sometimes there are 3 zeros between the 2 closest units. So the above function might miss the correct unit in case its' decimal count is between 2 units. (for example between szabo -> 12 zeros and nano -> 9 zeros)

Maybe one suggestion as how to amend the above implementation:

let biggestUnit = 'wei'
let c = 0
const unit = Object.keys(web3.utils.unitMap).forEach(unit => {
    const valueInWei = web3.utils.unitMap[unit]

    const zeroCount = valueInWei.length - valueInWei.replace(/0/g, '').length
    if (zeroCount <= decimals && zeroCount > biggestUnitZeros) {
        biggestUnit = unit
        biggestUnitZeros = zeroCount
    }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this @sparrowDom, Will fix this

@mikeshultz
Copy link
Contributor

mikeshultz commented Jan 29, 2020

Sorry, it's early and I may have missed something but I don't get why we're doing string operations here instead of using BN.js? Here's a conversion from "human units" to an 8-decimal token value:

const ONE_TOKEN = new BN('100000000') // 1e8
function toReal(v) {
  return v.mul(ONE_TOKEN)
}

Seems a bit more accurate and straight forward than trying to do math this way?

EDIT: Converting a decimal to a real token value:

> (new BN(1.032435245*1e8)).toString()
'103243524'

Copy link
Contributor

@franckc franckc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Agreed with @sparrowDom that adding some simple unit tests would be nice.
So that next time we had a new currency we can easily make sure it works.

@tomlinton
Copy link
Contributor

Ethersjs has great utility functions for this kind of thing. Maybe we should add it as a dependency and slowly try to move away from web3js. Tough job though 😞

@shahthepro
Copy link
Collaborator Author

shahthepro commented Jan 29, 2020

@mikeshultz

Seems a bit more accurate and straight forward than trying to do math this way?

Agreed. This seems simple. Will update it. Thanks

@franckc

Agreed with @sparrowDom that adding some simple unit tests would be nice.

Thanks. Will do it

@tomlinton

Ethersjs has great utility functions for this kind of thing. Maybe we should add it as a dependency and slowly try to move away from web3js. Tough job though 😞

We could but Mike's solution should reduce the complexity of the code right now. I'm not sure if we should add a dependency right now. But thanks, let me check this

@shahthepro
Copy link
Collaborator Author

@mikeshultz
I tried that but it doesn't work well. new web3.utils.BN('123.12345').toString() results in 122812345 which is way off.

However, I did some other change that will simply it more (more like treating it as a string).

@sparrowDom @franckc The issue with decimal places (that are not multiples of 3) is fixed now and have also added a couple of simple unit tests

@tomlinton Tried ether.js, but the potential that Domen reported was still reproducible (i.e the function not working with decimals which are not multiples of 3). I managed to fix this without ether.js or even using web3. So skipping adding ether.js for now

@mikeshultz
Copy link
Contributor

mikeshultz commented Jan 29, 2020

@shahthepro you can't feed BN a decimal. In fact, I'm surprised that didn't error. Here's a slightly more comprehensive example using your given numbers starting with a string:

> x = new BN(parseInt(parseFloat('123.12345') * 1e6)) // for 6-decimal, use 1e8 for 8-decimal, etc
<BN: 756b6fa>
> x.toString()
'123123450'

EDIT: This also assumes relatively small numbers as user input that won't overflow in JS. Might want to add some checks if you expect extremely large numbers(N > Number.MAX_SAFE_INTEGER / 1e8).

@shahthepro
Copy link
Collaborator Author

shahthepro commented Jan 30, 2020

@shahthepro you can't feed BN a decimal. In fact, I'm surprised that didn't error. Here's a slightly more comprehensive example using your given numbers starting with a string:

EDIT: This also assumes relatively small numbers as user input that won't overflow in JS. Might want to add some checks if you expect extremely large numbers(N > Number.MAX_SAFE_INTEGER / 1e8).

Yep, this is what I'm concerned about. We had code to truncate anything longer than 18 decimals (before passing that to toWei). There is a possibility, albeit rare, that it can fail. Also, even with 18 decimals, JS seems to round off digits.

I'm probably gonna merge this change in and will fix forward, if we ever any issue with the present implementation

Thanks @mikeshultz

@shahthepro shahthepro closed this Feb 24, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

USDT incorrectly configured
5 participants