-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Bug: OverflowError: Python int too large to convert to C ssize_t #1634
Comments
@zinootje Can you provide a minimum reproducible example of what you're trying to do? |
sure , do i also need to provide contract source code or is there another way |
Just the snippet of the contract code that is throwing the error would be good, and any background needed to put it in context. |
Here is my minimal example i also uploaded the source code to ether scan to make it easier. As you will see when you call the function "buysellmultiple" from etherscan it works as expected. I hope i didn't miss something obvious .
|
It looks like the |
@kclowes interestingly this is an
I think that's the place to investigate as it isn't exactly clear to me why or how that is happening. |
If you can reproduce the above error in CI then dropping into a pdb might be the most informative way to try and figure out which value is exceeding the limit and then how eth-abi is encountering a that value. |
I'm having a similar sort of issue as well, it seems this comes from an issue with
So, it seems part of the issue is that As a note, this is for decoding a function that returns a struct of the following format:
|
NOTE: This works in reality (see ethereum/web3.py#1634 (comment)) however our test suite currently can't handle it because of a bug in Web3.py
NOTE: This works in reality (see ethereum/web3.py#1634 (comment)) however our test suite currently can't handle it because of a bug in Web3.py
Dumping what I figured out thus far. Taking the value provided by @fubuloubu it looks like we can correctly perform a round trip encode/decode on the provided value. >>> abi = '(uint256,int128[7],bytes,int128[3][3],uint256,uint256)'
>>> value = (11, (0, 0, 13, 0, 0, 0, 0), b'horse', ((0, 0, 0), (0, 0, 0), (0, 0, 0)), 0, 0)
>>> data = eth_abi.encode_abi((abi,), (value,))
>>> assert value == eth_abi.decode_abi((abi,), data) The original example also works if we split the ABI up into it's component parts rather than providing as a tuple-type
So I think the problem here is that when a function returns a singular tuple ABI type we aren't handling it properly. I think we need to look at doing two things.
|
Having this issue as well with the Uniswap v2 contracts 🙁 Is it known when/where this regression (I assume) occurred? Is it in web3.py or eth-abi? I have a thing in prod which I can't update until this is fixed :/ |
@ErikBjare can you expand a little, which function, what inputs are resulting in this error? |
At present, the code example provided in #1634 (comment) works correctly for me, and brief exploration into the uniswap v5 contract @ 0x7665fecb393ca45061a6338662751d6cf45a854d didn't appear to have any functions that used tuples for output values. I'm going to close this because we currently don't have a reproducible example that uses web3.py code paths. If someone has a contract call that they know of that causes this bug, please let us know what contract address, ABI, function name, function inputs, and Currently, it is possible this was a bug in an older version of web3.py/eth-abi but has since been fixed. |
@pipermerriam were you able to run the test case mentioned in #1634 (comment) We currently have an outstanding failure in Vyper that could be a good target to check if this is fixed in the latest version: |
@fubuloubu I started poking around your example this morning. I'm not well-versed in this part of the code base, but the
Do you remember one of these failing or have I got the context wrong? |
Yeah, one of those was failing before ( |
Nope, still an issue: $ python --version
Python 3.8.4
$ pip freeze | grep web3
web3==5.12.0
# I removed the `xfail` for the test case here
$ pytest tests/parser/globals/test_getters.py
...
def test_getter_code(get_contract_with_gas_estimation_for_constants):
getter_code = """
struct W:
a: uint256
b: int128[7]
c: Bytes[100]
e: int128[3][3]
f: uint256
g: uint256
x: public(uint256)
y: public(int128[5])
z: public(Bytes[100])
w: public(HashMap[int128, W])
@external
def __init__():
self.x = as_wei_value(7, "wei")
self.y[1] = 9
self.z = b"cow"
self.w[1].a = 11
self.w[1].b[2] = 13
self.w[1].c = b"horse"
self.w[2].e[1][2] = 17
self.w[3].f = 750
self.w[3].g = 751
"""
c = get_contract_with_gas_estimation_for_constants(getter_code)
assert c.x() == 7
assert c.y(1) == 9
assert c.z() == b"cow"
> assert c.w(1)[0] == 11 # W.a
tests/parser/globals/test_getters.py:54:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/base_conftest.py:24: in __call__
return self.__prepared_function(*args, **kwargs)
tests/base_conftest.py:42: in __prepared_function
return getattr(self._function(*args), modifier)(modifier_dict)
site-packages/web3/contract.py:954: in call
return call_contract_function(
site-packages/web3/contract.py:1507: in call_contract_function
output_data = web3.codec.decode_abi(output_types, return_data)
site-packages/eth_abi/codec.py:181: in decode_abi
return decoder(stream)
site-packages/eth_abi/decoding.py:127: in __call__
return self.decode(stream)
site-packages/eth_utils/functional.py:45: in inner
return callback(fn(*args, **kwargs))
site-packages/eth_abi/decoding.py:173: in decode
yield decoder(stream)
site-packages/eth_abi/decoding.py:127: in __call__
return self.decode(stream)
site-packages/eth_abi/decoding.py:145: in decode
value = self.tail_decoder(stream)
site-packages/eth_abi/decoding.py:127: in __call__
return self.decode(stream)
site-packages/eth_utils/functional.py:45: in inner
return callback(fn(*args, **kwargs))
site-packages/eth_abi/decoding.py:173: in decode
yield decoder(stream)
site-packages/eth_abi/decoding.py:127: in __call__
return self.decode(stream)
site-packages/eth_abi/decoding.py:144: in decode
stream.push_frame(start_pos)
site-packages/eth_abi/decoding.py:95: in push_frame
self.seek_in_frame(0)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <eth_abi.decoding.ContextFramesBytesIO object at 0x7f1a9cd3a860>, pos = 0, args = (), kwargs = {}
def seek_in_frame(self, pos, *args, **kwargs):
"""
Seeks relative to the total offset of the current contextual frames.
"""
> self.seek(self._total_offset + pos, *args, **kwargs)
E OverflowError: Python int too large to convert to C ssize_t
site-packages/eth_abi/decoding.py:84: OverflowError |
@fubuloubu did you see my analysis of that issue here: #1634 (comment) From what I could tell, it looks like the ABI type is incorrect but what I can't tell is whether that is a web3.py problem or the ABI itself is not correct. I'm curious if we can get the ABI produced by that contract so that we can verify/reproduce this using web3 code. |
ABI:
|
Here is what I know so far..... In [35]: w3.codec.encode_single('uint256', 1234)
Out[35]: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xd2'
In [36]: w3.codec.encode_abi(['uint256',], [1234,])
Out[36]: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xd2' Here we see the behavior for fixed size value encoding. The singular/plural encodings are identical. Next lets look at variable length encodings. In [41]: w3.codec.encode_single('uint256[]', [1234, 4321])
Out[41]: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xd2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\xe1'
In [42]: w3.codec.encode_abi(['uint256[]',], [[1234, 4321]])
Out[42]: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xd2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\xe1' If we try to decode the output from the In [45]: w3.codec.decode_abi(['uint256[]'], w3.codec.encode_single('uint256[]', [1234, 4321]))
---------------------------------------------------------------------------
InsufficientDataBytes Traceback (most recent call last)
... <STACKTRACE OMITTED HERE> So now looking at the tuple example, what I believe we are seeing is an incorrectly encoded output from the smart contract. If we take a look at a simple example, like the Now looking at the provided
So I think that what we are seeing is vyper not correctly encoding the return value for this function. But maybe I'm incorrectI did not look to see what solidity does for singular tuple type returns so I think that is the next step needed before a decision can be made on what the correct behavior here should be. |
@pipermerriam Turns out you were right, in a way. Same contract in Solidity: // SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.19 <0.7.0;
pragma experimental ABIEncoderV2;
contract Test {
struct W {
uint a;
int128[7] b;
bytes c;
int128[3][3] e;
uint f;
uint g;
}
uint256 public x;
int128[5] public y;
bytes public z;
mapping(int128 => W) public w;
constructor() public {
x = 7 wei;
y[1] = 9;
z = "cow";
w[1].a = 11;
w[1].b[2] = 13;
w[1].c = "horse";
w[2].e[1][2] = 17;
w[3].f = 750;
w[3].g = 751;
}
} ABI:
The difference is that Solidity doesn't even use struct Y {
uint a;
uint b;
bytes c;
}
struct X {
Y y;
}
X public x; ABI (modified):
function return_all_in_w(int128 idx)
public
returns (
uint a,
int128[7] memory b,
bytes memory c,
int128[3][3] memory e,
uint f,
uint g,
)
{
a = w[idx].a;
b = w[idx].b;
c = w[idx].c;
e = w[idx].e;
f = w[idx].f;
g = w[idx].g;
} NOTE: The ABI for this method correctly returns all of the members of So, for Vyper we indeed have a bug in not showing the proper ABI, but I would argue that it is still legitimate for a contract to return a I would also say broadly that the error message for this bug is still an issue that deserves to be solved in it's own right. |
Definitely, this needs to be fixed regardless of what decision gets made on how to handle singular tuple types. As for what to do about methods that return singular tuple types with variable size elements, are we in agreement that the output encoding produced by vyper is missing the "wrapper" that other variable size return values exhibit when returned from the EVM? |
Actually, I figured out that it is actually the opposite: if the value returned is a complex type (such as a EDIT: Sorry I edited the previous comments one too many times lol |
Issue for better exception messaging in |
It appears this issue is not a problem with web3.py and I am now re-closing this. Happy to re-visit/re-open if someone feels differently or there is something that web3.py could be doing in this case to mitigate. |
Would also like to note that a function returning a tuple directly is most likely untested behavior, because no Ethereum smart contract language implements it (unless it is tested separately in |
how to set amount to buy...everything works fine but it stops at approving then preparing bot |
Got this error as well while trying to call the name() method of this contract, the value as seen by etherscan is i think the value should be decoded as "Maker", but i'm not very knowledgeable in the whole spec, so not sure what goes wrong in getting us there, or if the contract is just wrong and should be ignored. |
@tshirtman The MKR contract uses a different (old?) version of the ERC20 spec where See this PR for how we handle it in uniswap-python: uniswap-python/uniswap-python#191 |
@ErikBjare Will look into it, thanks for the tip! |
pip freeze
outputWhat was wrong?
I get a overflow error when calling a specific view function which returns a int256[];
When i call te same function online using a site like https://justsmartcontracts.dev the function works fine
I know this isn't enough information. If you tell me what else you need i will try to provide is as quickly as posible
The text was updated successfully, but these errors were encountered: