From 5795429e18cd79d6258e55e368af3c1d3ccd4869 Mon Sep 17 00:00:00 2001 From: def-Param Date: Fri, 30 Oct 2026 20:43:34 +0530 Subject: [PATCH 1/4] fix(solidity_keccak): pad bytesN values to their full size --- web3/_utils/encoding.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web3/_utils/encoding.py b/web3/_utils/encoding.py index c6d9f72639..593aeb9e8f 100644 --- a/web3/_utils/encoding.py +++ b/web3/_utils/encoding.py @@ -85,6 +85,9 @@ def hex_encode_abi_type( return pad_hex(value, data_size) elif is_bytes_type(abi_type): if is_bytes(value): + # Pad fixed-size bytesN to their full size (Solidity right-pads to N bytes) + if abi_type != "bytes" and data_size is not None: + return pad_hex(encode_hex(value), data_size) return encode_hex(value) else: return value From f7acfaab54f25c6a83b6cf842210261752eeea41 Mon Sep 17 00:00:00 2001 From: def-Param Date: Fri, 30 Oct 2026 23:27:37 +0530 Subject: [PATCH 2/4] fix(solidity_keccak): right-pad bytesN values to 32 bytes --- tests/core/web3-module/test_keccak.py | 8 ++++++++ web3/_utils/encoding.py | 9 ++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/core/web3-module/test_keccak.py b/tests/core/web3-module/test_keccak.py index 25fcc1f090..e49f44517f 100644 --- a/tests/core/web3-module/test_keccak.py +++ b/tests/core/web3-module/test_keccak.py @@ -119,3 +119,11 @@ def test_keccak_raise_if_hexstr_and_text(): def test_keccak_raise_if_no_args(): with pytest.raises(TypeError): Web3.keccak() + + +def test_solidity_keccak_bytes_padding(): + # bytes1 value 0x01 should be padded to 32 bytes in Solidity + result = Web3.solidity_keccak(["bytes1"], [b"\x01"]) + # The padded value is 0x01 followed by 31 zero bytes + expected = Web3.keccak(hexstr="0x01" + "00" * 31) + assert result == expected diff --git a/web3/_utils/encoding.py b/web3/_utils/encoding.py index 593aeb9e8f..11c9ff702f 100644 --- a/web3/_utils/encoding.py +++ b/web3/_utils/encoding.py @@ -85,9 +85,12 @@ def hex_encode_abi_type( return pad_hex(value, data_size) elif is_bytes_type(abi_type): if is_bytes(value): - # Pad fixed-size bytesN to their full size (Solidity right-pads to N bytes) - if abi_type != "bytes" and data_size is not None: - return pad_hex(encode_hex(value), data_size) + # Pad fixed-size bytesN to 32 bytes (Solidity right-pads to 32 bytes in abi.encode) + if abi_type != "bytes": + hex_val = remove_0x_prefix(encode_hex(value)) + # Right-pad to 32 bytes (64 hex chars) + padded = hex_val.ljust(64, "0") + return add_0x_prefix(HexStr(padded)) return encode_hex(value) else: return value From d50a56cc7bfbd53eb7a91c3ce5ea30ac3e64fe9a Mon Sep 17 00:00:00 2001 From: def-Param Date: Fri, 30 Oct 2026 23:51:29 +0530 Subject: [PATCH 3/4] fix(http): conditionally pass enable_cleanup_closed for older Python --- web3/_utils/http_session_manager.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/web3/_utils/http_session_manager.py b/web3/_utils/http_session_manager.py index 913ea550f1..ef021c29b2 100644 --- a/web3/_utils/http_session_manager.py +++ b/web3/_utils/http_session_manager.py @@ -187,11 +187,20 @@ async def async_cache_and_return_session( async with async_lock(self.session_pool, self._lock): if cache_key not in self.session_cache: if session is None: + connector_kwargs = {"force_close": True} + # enable_cleanup_closed is only needed on Python < 3.12.8 / 3.13.1 + # where CPython bug #118960 is not fixed; on newer versions it + # triggers a DeprecationWarning. + import sys + if sys.version_info < (3, 12, 8) or ( + sys.version_info.major == 3 + and sys.version_info.minor == 13 + and sys.version_info.micro < 1 + ): + connector_kwargs["enable_cleanup_closed"] = True session = ClientSession( raise_for_status=True, - connector=TCPConnector( - force_close=True, enable_cleanup_closed=True - ), + connector=TCPConnector(**connector_kwargs), ) cached_session, evicted_items = self.session_cache.cache( @@ -236,9 +245,7 @@ async def async_cache_and_return_session( # replace stale session with a new session at the cache key _session = ClientSession( raise_for_status=True, - connector=TCPConnector( - force_close=True, enable_cleanup_closed=True - ), + connector=TCPConnector(**connector_kwargs), ) cached_session, evicted_items = self.session_cache.cache( cache_key, _session From df5ff61e4948fc0c60f2e4e84cef8cc113eb3512 Mon Sep 17 00:00:00 2001 From: def-Param Date: Sat, 31 Oct 2026 12:05:41 +0530 Subject: [PATCH 4/4] fix(http): conditionally pass enable_cleanup_closed to TCPConnector (#3900) Only pass enable_cleanup_closed=True to aiohttp's TCPConnector on Python versions that need it (< 3.12.8 or 3.13.x < 3.13.1). On newer versions, aiohttp ignores the parameter and emits a DeprecationWarning, which breaks tests run with -W error. Fixes #3900. --- web3/_utils/http_session_manager.py | 38 +++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/web3/_utils/http_session_manager.py b/web3/_utils/http_session_manager.py index ef021c29b2..703d619f3d 100644 --- a/web3/_utils/http_session_manager.py +++ b/web3/_utils/http_session_manager.py @@ -1,4 +1,5 @@ import asyncio +import sys from concurrent.futures import ( ThreadPoolExecutor, ) @@ -19,6 +20,14 @@ from eth_typing import ( URI, ) + +# aiohttp's `enable_cleanup_closed` parameter is deprecated on Python 3.12.8+ +# and 3.13.1+ (CPython bug fix https://github.com/python/cpython/pull/118960). +# Passing it triggers a DeprecationWarning on those versions. +_ENABLE_CLEANUP_CLOSED = ( + sys.version_info < (3, 12, 8) + or (3, 13) <= sys.version_info < (3, 13, 1) +) import requests from web3._utils.async_caching import ( @@ -187,20 +196,16 @@ async def async_cache_and_return_session( async with async_lock(self.session_pool, self._lock): if cache_key not in self.session_cache: if session is None: - connector_kwargs = {"force_close": True} - # enable_cleanup_closed is only needed on Python < 3.12.8 / 3.13.1 - # where CPython bug #118960 is not fixed; on newer versions it - # triggers a DeprecationWarning. - import sys - if sys.version_info < (3, 12, 8) or ( - sys.version_info.major == 3 - and sys.version_info.minor == 13 - and sys.version_info.micro < 1 - ): - connector_kwargs["enable_cleanup_closed"] = True session = ClientSession( raise_for_status=True, - connector=TCPConnector(**connector_kwargs), + connector=TCPConnector( + force_close=True, + **( + {"enable_cleanup_closed": True} + if _ENABLE_CLEANUP_CLOSED + else {} + ), + ), ) cached_session, evicted_items = self.session_cache.cache( @@ -245,7 +250,14 @@ async def async_cache_and_return_session( # replace stale session with a new session at the cache key _session = ClientSession( raise_for_status=True, - connector=TCPConnector(**connector_kwargs), + connector=TCPConnector( + force_close=True, + **( + {"enable_cleanup_closed": True} + if _ENABLE_CLEANUP_CLOSED + else {} + ), + ), ) cached_session, evicted_items = self.session_cache.cache( cache_key, _session