ethers-io / ethers.js

Complete Ethereum library and wallet implementation in JavaScript.
https://ethers.org/
MIT License
7.93k stars 1.84k forks source link

Call Data Encoding #2923

Closed Cryptverse closed 2 years ago

Cryptverse commented 2 years ago

Ethers Version

5.5.4

Search Terms

bytes encoding

Describe the Problem

I have been having a hard time using the high-level transaction methods. It seems when I populate a function that uses a bytes argument for call-back data it does not encode it properly. I have resulted to manually encoding the data in order to get the data to be reflected correctly on Etherscan.

It seems like if data is passed to a contract populate transaction function that contains bytes, the bytes aren't properly encoded. There may be an easy way to do this but I have ended up writing my own encoding and decoding functions for bytes data. This is very inefficient because many implementations need to be developed in order to deal with different functions calls whereas much fewer would be needed if the populate transaction function would work as expected.

If this truly is a bug then I'm sure I could be of assistance in adding this functionality as I have already developed my own methods to achieve the correct encodings.

Code Snippet

No response

Contract ABI

function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock

Errors

No response

Environment

No response

Environment (Other)

node

ricmoo commented 2 years ago

Can you please provide code examples of what you are passing in, what you are getting and what you are expecting?

Cryptverse commented 2 years ago

`const populatedTransaction = contract.populateTransaction.flash(recipient, amount0, amount1, bytesData) const data = populatedTransaction.data const parsedTransactionData = contract.interface.parseTransaction({data}) console.log(parseTransactionData) /... recipient: 'address is fine', amount0: BigNumber { _hex: '0x00', _isBigNumber: true }, amount1: BigNumber { _hex: '0x1acc97c07fffffff', _isBigNumber: true }, data: '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000... I guess the data is also fine above, as well, since the parser is supposed to return the arguments as they were passed in. / console,log(data) / 0x490e6cbc0000000000000000000000000000addressIsFine000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001acc97c07fffffff000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000000000000002a90... I've never looked directly at the data like this before and I can see the encoding is done properly here. So, my issue might be more related to bytes decoding and, perhaps, this may be a too specific use-case for ethers to have to resolve. However, the issue I've had to solve came from when I tried to decode this data as a uint256[] like so: /

const decoded data = defaultABICoder.decode(['uint256[]', [data]) //throws: Argument of type 'string[]' is not assignable to parameter of type 'BytesLike'. Type 'string[]' is not assignable to type 'string'. ` The 'bytesData' was a uint256[] that was encoded before being passed to the flash populator. I haven't succeeded in decoding 'bytesData' back into a uint256[] using ethers. Yet, I require being able to decode all of 'data' into a uint256[]. I've succeeded in doing so by writing a splitDataHexString function. However, I had thought that this would have been something that ethers would be able to do. Perhaps, I am using it incorrectly or, as I've mentioned, this might be too specific a use case.

To prevent any confusion or fix my incorrect labelling of types, I mean a BigNumber[] or string[] when I say uint256[]. Thanks for the fast reply @ricmoo.