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

[v6] Rename Contract.encodeABI -> Contract.encode_abi #3280

Merged
merged 3 commits into from
Mar 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/overview.rst
Original file line number Diff line number Diff line change
@@ -258,7 +258,7 @@ API
- :attr:`Contract.events <web3.contract.Contract.events>`
- :attr:`Contract.fallback <web3.contract.Contract.fallback.call>`
- :meth:`Contract.constructor() <web3.contract.Contract.constructor>`
- :meth:`Contract.encodeABI() <web3.contract.Contract.encodeABI>`
- :meth:`Contract.encode_abi() <web3.contract.Contract.encode_abi>`
- :attr:`web3.contract.ContractFunction <web3.contract.ContractFunction>`
- :attr:`web3.contract.ContractEvents <web3.contract.ContractEvents>`

17 changes: 11 additions & 6 deletions docs/web3.contract.rst
Original file line number Diff line number Diff line change
@@ -302,17 +302,22 @@ Each Contract Factory exposes the following methods.
filter_builder.fromBlock = 0 # raises a ValueError
.. py:classmethod:: Contract.encodeABI(fn_name, args=None, kwargs=None, data=None)
.. py:classmethod:: Contract.encode_abi(fn_name, args=None, kwargs=None, data=None)
Encodes the arguments using the Ethereum ABI for the contract function that
matches the given ``fn_name`` and arguments ``args``. The ``data`` parameter
defaults to the function selector.
Encodes the arguments using the Ethereum ABI for the contract function that
matches the given ``fn_name`` and arguments ``args``. The ``data`` parameter
defaults to the function selector.

.. code-block:: python
.. code-block:: python
>>> contract.encodeABI(fn_name="register", args=["rainbows", 10])
>>> contract.encode_abi(fn_name="register", args=["rainbows", 10])
"0xea87152b0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000087261696e626f7773000000000000000000000000000000000000000000000000"
.. py:classmethod:: Contract.encodeABI(fn_name, args=None, kwargs=None, data=None)
.. deprecated:: 7.0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nice! TIL

Use :meth:`Contract.encode_abi` instead.

.. py:classmethod:: Contract.all_functions()
Returns a list of all the functions present in a Contract where every function is
2 changes: 1 addition & 1 deletion ens/async_ens.py
Original file line number Diff line number Diff line change
@@ -490,7 +490,7 @@ async def _resolve(
):
contract_func_with_args = (fn_name, [node])

calldata = resolver.encodeABI(*contract_func_with_args)
calldata = resolver.encode_abi(*contract_func_with_args)
contract_call_result = await resolver.caller.resolve(
ens_encode_name(normal_name),
calldata,
2 changes: 1 addition & 1 deletion ens/ens.py
Original file line number Diff line number Diff line change
@@ -475,7 +475,7 @@ def _resolve(
if _resolver_supports_interface(resolver, ENS_EXTENDED_RESOLVER_INTERFACE_ID):
contract_func_with_args = (fn_name, [node])

calldata = resolver.encodeABI(*contract_func_with_args)
calldata = resolver.encode_abi(*contract_func_with_args)
contract_call_result = resolver.caller.resolve(
ens_encode_name(normal_name),
calldata,
1 change: 1 addition & 0 deletions newsfragments/3280.deprecation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deprecated ``Contract.encodeABI()`` in favor of ``Contract.encode_abi()``.
44 changes: 39 additions & 5 deletions tests/core/contracts/test_contract_method_abi_encoding.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import json
import pytest
from unittest.mock import (
patch,
)

from web3 import (
constants,
@@ -64,7 +67,7 @@
)
def test_contract_abi_encoding(w3, abi, arguments, data, expected):
contract = w3.eth.contract(abi=abi)
actual = contract.encodeABI("a", arguments, data=data)
actual = contract.encode_abi("a", arguments, data=data)
assert actual == expected


@@ -116,7 +119,7 @@ def test_contract_abi_encoding_non_strict(
w3_non_strict_abi, abi, arguments, data, expected
):
contract = w3_non_strict_abi.eth.contract(abi=abi)
actual = contract.encodeABI("a", arguments, data=data)
actual = contract.encode_abi("a", arguments, data=data)
assert actual == expected


@@ -128,7 +131,7 @@ def test_contract_abi_encoding_kwargs(w3):
"0x6f8d2fa18448afbfe4f82143c384484ad09a0271f3a3c0eb9f629e703f883125",
],
}
actual = contract.encodeABI("byte_array", kwargs=kwargs)
actual = contract.encode_abi("byte_array", kwargs=kwargs)
assert (
actual
== "0xf166d6f8000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025595c210956e7721f9b692e702708556aa9aabb14ea163e96afa56ffbe9fa8096f8d2fa18448afbfe4f82143c384484ad09a0271f3a3c0eb9f629e703f883125" # noqa: E501
@@ -146,7 +149,7 @@ def test_contract_abi_encoding_kwargs(w3):
def test_contract_abi_encoding_strict_with_error(w3, arguments):
contract = w3.eth.contract(abi=ABI_C)
with pytest.raises(Web3ValidationError):
contract.encodeABI("a", arguments, data=None)
contract.encode_abi("a", arguments, data=None)


@pytest.mark.parametrize(
@@ -195,5 +198,36 @@ def test_contract_abi_encoding_strict_with_error(w3, arguments):
)
def test_contract_abi_encoding_strict(w3, abi, arguments, data, expected):
contract = w3.eth.contract(abi=abi)
actual = contract.encodeABI("a", arguments, data=data)
actual = contract.encode_abi("a", arguments, data=data)
assert actual == expected


def test_contract_encodeABI_deprecated(w3):
expected = "0xf0fdf8340000000000000000000000000000000000000000000000000000000000000000" # noqa: E501

abi = ABI_B
arguments = [0]
data = None

contract = w3.eth.contract(abi=abi)

with pytest.warns(DeprecationWarning):
actual = contract.encodeABI("a", arguments, data=data)
assert actual == expected


@patch("web3.eth.Contract.encodeABI", lambda w3, *args, **kwargs: (args, kwargs))
def test_contract_encodeABI_deprecated_calls_encode_abi_with_args(w3):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this test add any new test vector? It looks like the test above tests kwargs already?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test expects the new method to be called with all the arguments. The @patch wraps the encode function to be able to check values for each argument.

abi = ABI_B
arguments = [0]
kwargs = {"x": 1}
data = {"secret_code": "12345"}

contract = w3.eth.contract(abi=abi)

# DeprecationWarning raised inside patched function
passed_on_args, passed_on_kwargs = contract.encodeABI(
"a", arguments, kwargs, data=data
)
assert passed_on_args == ([0], {"x": 1})
assert passed_on_kwargs == {"data": {"secret_code": "12345"}}
12 changes: 6 additions & 6 deletions web3/_utils/module_testing/eth_module.py
Original file line number Diff line number Diff line change
@@ -1340,7 +1340,7 @@ async def test_eth_call_revert_custom_error_with_msg(
async_revert_contract: "Contract",
async_unlocked_account: ChecksumAddress,
) -> None:
data = async_revert_contract.encodeABI(
data = async_revert_contract.encode_abi(
fn_name="UnauthorizedWithMessage", args=["You are not authorized"]
)
txn_params = async_revert_contract._prepare_transaction(
@@ -1360,7 +1360,7 @@ async def test_eth_call_revert_custom_error_without_msg(
async_revert_contract: "Contract",
async_unlocked_account: ChecksumAddress,
) -> None:
data = async_revert_contract.encodeABI(fn_name="Unauthorized")
data = async_revert_contract.encode_abi(fn_name="Unauthorized")
txn_params = async_revert_contract._prepare_transaction(
fn_name="customErrorWithoutMessage",
transaction={
@@ -3826,7 +3826,7 @@ def test_eth_call_custom_error_revert_with_msg(
revert_contract: "Contract",
unlocked_account: ChecksumAddress,
) -> None:
data = revert_contract.encodeABI(
data = revert_contract.encode_abi(
fn_name="UnauthorizedWithMessage", args=["You are not authorized"]
)
txn_params = revert_contract._prepare_transaction(
@@ -3846,7 +3846,7 @@ def test_eth_call_custom_error_revert_without_msg(
revert_contract: "Contract",
unlocked_account: ChecksumAddress,
) -> None:
data = revert_contract.encodeABI(fn_name="Unauthorized")
data = revert_contract.encode_abi(fn_name="Unauthorized")
txn_params = revert_contract._prepare_transaction(
fn_name="customErrorWithoutMessage",
transaction={
@@ -4135,7 +4135,7 @@ def test_eth_estimate_gas_custom_error_revert_with_msg(
revert_contract: "Contract",
unlocked_account: ChecksumAddress,
) -> None:
data = revert_contract.encodeABI(
data = revert_contract.encode_abi(
fn_name="UnauthorizedWithMessage", args=["You are not authorized"]
)
txn_params = revert_contract._prepare_transaction(
@@ -4155,7 +4155,7 @@ def test_eth_estimate_gas_custom_error_revert_without_msg(
revert_contract: "Contract",
unlocked_account: ChecksumAddress,
) -> None:
data = revert_contract.encodeABI(fn_name="Unauthorized")
data = revert_contract.encode_abi(fn_name="Unauthorized")
txn_params = revert_contract._prepare_transaction(
fn_name="customErrorWithoutMessage",
transaction={
14 changes: 14 additions & 0 deletions web3/contract/base_contract.py
Original file line number Diff line number Diff line change
@@ -56,6 +56,9 @@
from web3._utils.datatypes import (
PropertyCheckingFactory,
)
from web3._utils.decorators import (
deprecated_for,
)
from web3._utils.empty import (
empty,
)
@@ -724,12 +727,23 @@ class BaseContract:
# Public API
#
@combomethod
@deprecated_for("encode_abi()")
def encodeABI(
cls,
fn_name: str,
args: Optional[Any] = None,
kwargs: Optional[Any] = None,
data: Optional[HexStr] = None,
) -> HexStr:
return cls.encode_abi(fn_name, args, kwargs, data)

@combomethod
def encode_abi(
cls,
fn_name: str,
args: Optional[Any] = None,
kwargs: Optional[Any] = None,
data: Optional[HexStr] = None,
) -> HexStr:
"""
Encodes the arguments using the Ethereum ABI for the contract function