Skip to content
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

option to keep padding for quantities #4444

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

passabilities
Copy link

Allows to optionally keep the leading 0s when converting a value to a Quantity.

@ricmoo
Copy link
Member

ricmoo commented Oct 31, 2023

That’s what hexlify does; it doesn’t remove leading 0’s. A “quantity” type forbids leading 0’s, which is the purpose of that function, but if you use hexlify it will retain the zeros.

What do you need this functionality for?

@passabilities
Copy link
Author

passabilities commented Nov 3, 2023

for instance when a number needs to be represented by all 32 bytes but there are leading 0s in the hex number
take this example:

> num = BigInt('0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d')
1937035142596246788172577232054709726386880441279550832067530347910661804397n
> ethers.hexlify(num)
Uncaught:
TypeError: invalid BytesLike value (argument="value", value=1937035142596246788172577232054709726386880441279550832067530347910661804397, code=INVALID_ARGUMENT, version=6.8.0)
    at makeError (./node_modules/ethers/lib.commonjs/utils/errors.js:122:21)
    at assert (./node_modules/ethers/lib.commonjs/utils/errors.js:149:15)
    at assertArgument (./node_modules/ethers/lib.commonjs/utils/errors.js:161:5)
    at _getBytes (./node_modules/ethers/lib.commonjs/utils/data.js:27:36)
    at getBytes (./node_modules/ethers/lib.commonjs/utils/data.js:37:12)
    at Object.hexlify (./node_modules/ethers/lib.commonjs/utils/data.js:84:19) {
  code: 'INVALID_ARGUMENT',
  argument: 'value',
  value: 1937035142596246788172577232054709726386880441279550832067530347910661804397n,
  shortMessage: 'invalid BytesLike value'
}
> ethers.toQuantity(num)
'0x44852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d'
  • hexlify throws an error because its an odd number of bytes (leading 0)
  • toQuantity strips the 0 making the number an odd number of bytes

I need all 32 bytes to be populated when converting an ENS token ID from a decimal number into a hex which represents the token's labelhash

this is not trivial to ensure I have the correct value but becomes annoying when you need to remember this 1 edge case and reproduce the following code to work:

    const q = ethers.toQuantity(opts.tokenId)
    const labelhash = ethers.zeroPadValue(q.length % 2 ? `0x0${q.substring(2)}` : q, 32)
    const url = 'https://api.thegraph.com/subgraphs/name/ensdomains/ens'
    const res: { registrations: [ { domain: { name: string } } | undefined ] } = await request(url, gql`
        query {
            registrations(
              where: { domain_: { labelhash: "${labelhash}" } }
            ) { domain { name } }
        }`,
    )

@passabilities
Copy link
Author

iirc in v5 hexlify did not throw an error and did exactly want I wanted

@ricmoo
Copy link
Member

ricmoo commented Nov 3, 2023

In v5, hexlify accepted a numeric type; the equivalent in v6 is toBeArray, to be more explicit about how input types should be processed.

It also isn’t safe to use v5 hexlify to get a 32-byte value from a bigint; it might usually work out (because of how hashing works, often having non-zero values in high-order bits), but if for example the hex string were to begin with 0x000 the final string would be only 31 bytes wide.

For now, I think you would want zeroPadValue(toBeArray(value), 32) to ensure you get a 32 byte (64 nibble) hex string.

It may make sense for zeroPadValue to accept a BigInt or number as well, though.

@ricmoo
Copy link
Member

ricmoo commented Nov 3, 2023

You can also use abiCoder.encode([ "uint" ], [ value ]). Whatever best conveys the intention of the code, is best. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants