ethereum / eth-abi

Ethereum ABI utilities for python
MIT License
248 stars 269 forks source link

fix: the zero-length bytestring encoding #191

Closed YanhuiJessica closed 2 years ago

YanhuiJessica commented 2 years ago

What was wrong?

When the length of the byte string is 0, there is zero-bytes after the encoded length.

Example

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.15;

contract Test {
    function test() public pure returns (bytes memory) {
        bytes memory btest = '';
        bytes memory serialized = abi.encode(btest);
        return serialized;
        // 0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000
    }
}
>>> import eth_abi
>>> eth_abi.encode(['bytes'], [b'']).hex()
'000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
# 32 bytes longer than the result given by abi.encode() in solidity

How was it fixed?

Only return the encoded_size when value_length is zero.

To-Do

Cute Animal Picture

put a cute animal picture link inside the parentheses

pacrob commented 2 years ago

What version of eth-abi and python are you using? Using python 3.9.10 and eth-abi 3.0.0, I get output that matches yours from Solidity:

>>> import eth_abi
>>> encoded = eth_abi.encode(['bytes'], [b'']).hex()
>>> len(encoded)
128
>>> encoded
'00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000'
yixun-alpha commented 2 years ago

this bug has been fixed in master https://github.com/ethereum/eth-abi/pull/158 but has not been merged into v3.0.1 which is what pip installs from pypi; I posted a comment earlier in the PR thread about this as didn't see this issue; could we get it merged into v3 as well? thanks

on a fresh virtualenv with python 3.7:

$ pip install eth-abi

$ pip list | grep eth-abi
eth-abi      3.0.1

$ python --version
Python 3.7.6

$ python -c "import eth_abi; print(len(eth_abi.encode(['bytes'], [b''])))"
96

$ python -c "import eth_abi; print((eth_abi.encode(['bytes'], [b''])).hex())"
000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

expecting a length of 64 (2x 32bytes)

fselmo commented 2 years ago

Hey @yixun-alpha, @YanhuiJessica. #158 is a decent change to the library that hopefully only fixes this bug and doesn't break anything. This change should be coming out in a beta v4 release. I need to check if there was anything else on the list before that but we can try to get that prioritized and release the beta asap.

yixun-alpha commented 2 years ago

Thanks for the update; would you know if v4 would make it into web3py v6?

Cheers

fselmo commented 2 years ago

Thanks for the update; would you know if v4 would make it into web3py v6?

Cheers

Yep! That's the plan. Beta v4 eth-abi on beta v6 web3.py until we can consider both stable.

fselmo commented 2 years ago

@YanhuiJessica @yixun-alpha just a quick update that I just pushed out 4.0.0-beta.1 with the change in it. I'm going to close this for now but if that version doesn't address the issues you were seeing then we can open this back up. I'm also going to PR pulling it into web3.py v6, so the next version of web3.py v6 should hopefully have this change too... keep an eye out there.