Repository: ethereum/web3.py

Issue:
Function `create_access_list` - incorrect behavior and documentation
### What happened?

These are the input and output of function `create_access_list` according to [the official documentation](https://web3py.readthedocs.io/en/stable/web3.eth.html#web3.eth.Eth.create_access_list):

**Input Example**:
```
{'from': '0x0', 'data': '0x0', 'type': '0x1'}
```
**Output Example**:
```
{
    'accessList': (
        {
            'address': '0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae',
            'storageKeys': (
                '0x0000000000000000000000000000000000000000000000000000000000000003',
                '0x0000000000000000000000000000000000000000000000000000000000000007',
            )
        },
        {
            'address': '0xbb9bc244d798123fde783fcc1c72d3bb8c189413',
            'storageKeys': ()
        },
    ),
    'gas': '21000'
}
```
There are several problems here, both in the documentation, and in the actual behavior of the function.

**Problem 1 (should be fixed in the documentation)**:

The input should be the entire transaction dictionary, and not just the keys in the example, including:
   - 'gas'
   - 'chainId'
   - 'from'
   - 'to'
   - 'data'
   - 'value'
   - 'nonce'
   - 'type'
   - 'gasPrice' in the case of type 1, or 'maxPriorityFeePerGas' and 'maxFeePerGas' in the case of type 2

It is possible that some of them, like 'from' and 'chainId', can be omitted.
But it seems that at least the majority of them **should** be included.
Otherwise, the function throws errors such as `intrinsic gas too low`, etc.

**Problem 2 (should be fixed either in the documentation or in the code)**:

The output dictionary does not have a key named 'gas', but a key named 'gasUsed'.

**Problem 3 (should be fixed in the code)**:

The value of the output 'accessList' is not a list of `dict` items, but a list of `AttributeDict` items.
Moreover, the value of each 'storageKeys' is not a list of `str` items, but a list of `HexBytes` items.
This makes it impossible to just take the output 'accessList' and add it to the input transaction like this:
```
result = web3.eth.create_access_list(tx)
if tx['gas'] > result['gasUsed']:
    tx['gas'] = result['gasUsed']
    tx['accessList'] = result['accessList']
```
Instead, one needs to do something like:
```
result = web3.eth.create_access_list(tx)
if tx['gas'] > result['gasUsed']:
    tx['gas'] = result['gasUsed']
    tx['accessList'] = [
        {
            'address': item['address'],
            'storageKeys': [key.hex() for key in item['storageKeys']]
        }
        for item in result['accessList']
    ]
```

### Code that produced the error

_No response_

### Full error output

_No response_

### Fill this section in if you know how this could or should be fixed

_No response_

### web3 Version

6.16.0

### Python Version

3.9.13

### Operating System

MacOS

### Output from `pip freeze`

```shell
aiofiles==22.1.0
aiohttp==3.8.1
aiosignal==1.2.0
aiosqlite==0.18.0
alabaster==0.7.12
alchemy-sdk==0.1.1
anyio==3.6.1
appnope==0.1.3
argon2-cffi==21.3.0
argon2-cffi-bindings==21.2.0
arrow==1.2.2
async-timeout==4.0.2
attrs==21.4.0
Babel==2.10.3
backcall==0.2.0
backoff==2.2.1
bancor-research==2.0.3
base58==2.1.1
beautifulsoup4==4.11.1
binaryornot==0.4.4
bitarray==2.6.0
black==22.6.0
bleach==5.0.1
branca==0.5.0
cachetools==5.2.0
cairo-lang==0.9.1
carbon-simulator==2.0
certifi==2022.6.15
cffi==1.15.1
chardet==5.0.0
charset-normalizer==2.1.0
click==8.1.3
cloudpickle==2.1.0
colorama==0.4.5
contextvars==2.4
contourpy==1.2.0
cookiecutter==2.1.1
cramjam==2.5.0
cvxpy==1.3.2
cycler==0.11.0
cytoolz==0.12.0
dataclass-wizard==0.22.2
datascience==0.17.5
debugpy==1.6.2
decorator==5.1.1
defusedxml==0.7.1
docutils==0.17.1
ecdsa==0.18.0
ecos==2.0.12
entrypoints==0.4
eth-abi==4.1.0
eth-account==0.9.0
eth-hash==0.5.2
eth-keyfile==0.6.1
eth-keys==0.4.0
eth-rlp==0.3.0
eth-typing==3.4.0
eth-utils==2.2.0
fastecdsa==2.2.3
fastjsonschema==2.16.1
fastlane-bot==3.1.1
fastparquet==0.8.1
folium==0.12.1.post1
fonttools==4.34.4
fqdn==1.5.1
frozendict==1.2
frozenlist==1.3.1
fsspec==2022.7.1
gitdb==4.0.9
GitPython==3.1.27
greenlet==1.1.2
hexbytes==0.3.1
idna==3.3
imagesize==1.4.1
immutables==0.18
importlib-metadata==4.12.0
importlib-resources==6.1.1
iniconfig==1.1.1
ipfshttpclient==0.8.0a2
ipykernel==6.15.1
ipython==7.34.0
ipython-genutils==0.2.0
ipywidgets==7.7.1
isoduration==20.11.0
jedi==0.18.1
Jinja2==3.1.2
jinja2-time==0.2.0
joblib==1.2.0
json5==0.9.11
jsonpointer==2.3
jsonschema==4.17.3
jupyter==1.0.0
jupyter-black==0.3.1
jupyter-book==0.13.0
jupyter-cache==0.4.3
jupyter-console==6.4.4
jupyter-events==0.6.3
jupyter-server-mathjax==0.2.6
jupyter-sphinx==0.3.2
jupyter-ydoc==0.2.2
jupyter_client==8.0.3
jupyter_core==5.2.0
jupyter_server==2.3.0
jupyter_server_fileid==0.8.0
jupyter_server_terminals==0.4.4
jupyter_server_ydoc==0.6.1
jupyterlab==3.6.1
jupyterlab-pygments==0.2.2
jupyterlab-widgets==1.1.1
jupyterlab_server==2.19.0
jupytext==1.16.1
kiwisolver==1.4.4
lark-parser==0.12.0
latexcodec==2.0.1
linkify-it-py==1.0.3
lru-dict==1.1.8
markdown-it-py==1.1.0
MarkupSafe==2.1.1
marshmallow==3.17.0
marshmallow-dataclass==8.5.8
marshmallow-enum==1.5.1
marshmallow-oneofschema==3.0.1
matplotlib==3.7.4
matplotlib-inline==0.1.3
mdit-py-plugins==0.2.8
Mesa==1.0.0
mistune==0.8.4
mplfinance==0.12.10b0
mpmath==1.2.1
multiaddr==0.0.9
multidict==6.0.2
mypy-extensions==0.4.3
myst-nb==0.13.2
myst-parser==0.15.2
nbclassic==0.5.2
nbclient==0.5.13
nbconvert==6.5.0
nbdime==3.1.1
nbformat==5.4.0
nest-asyncio==1.5.8
netaddr==0.8.0
networkx==3.2.1
notebook==6.4.12
notebook_shim==0.2.2
numpy==1.23.1
orjson==3.9.10
osqp==0.6.3
packaging==21.3
pandas==1.5.3
pandocfilters==1.5.0
parsimonious==0.9.0
parso==0.8.3
pathspec==0.9.0
pexpect==4.8.0
pickleshare==0.7.5
Pillow==9.2.0
pipdeptree==2.2.1
platformdirs==2.5.2
plotly==5.9.0
pluggy==1.0.0
prometheus-client==0.14.1
prompt-toolkit==3.0.30
protobuf==4.24.4
psutil==5.9.7
ptyprocess==0.7.0
py==1.11.0
pyarrow==11.0.0
pybtex==0.24.0
pybtex-docutils==1.0.2
pycparser==2.21
pycryptodome==3.15.0
pydantic==1.9.1
pydata-sphinx-theme==0.8.1
Pygments==2.12.0
pyparsing==3.0.9
pyrsistent==0.18.1
pytest==7.1.2
pytest-asyncio==0.19.0
python-dateutil==2.8.2
python-dotenv==0.16.0
python-json-logger==2.0.7
python-slugify==6.1.2
pytz==2022.1
pyunormalize==15.0.0
PyYAML==6.0
pyzmq==25.0.0
qdldl==0.1.7.post0
qtconsole==5.4.0
QtPy==2.3.0
regex==2023.8.8
requests==2.31.0
rfc3339-validator==0.1.4
rfc3986-validator==0.1.1
rlp==3.0.0
scipy==1.9.0
scs==3.2.4.post1
Send2Trash==1.8.0
six==1.16.0
smmap==5.0.0
sniffio==1.2.0
snowballstemmer==2.2.0
soupsieve==2.3.2.post1
Sphinx==4.5.0
sphinx-book-theme==0.3.3
sphinx-comments==0.0.3
sphinx-copybutton==0.5.0
sphinx-external-toc==0.2.4
sphinx-jupyterbook-latex==0.4.6
sphinx-multitoc-numbering==0.1.3
sphinx-thebe==0.1.2
sphinx-togglebutton==0.3.2
sphinx_design==0.1.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-bibtex==2.4.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
SQLAlchemy==1.4.39
sympy==1.10.1
tabulate==0.9.0
tenacity==8.0.1
terminado==0.15.0
text-unidecode==1.3
tinycss2==1.1.1
tokenize-rt==4.2.1
toml==0.10.2
tomli==2.0.1
toolz==0.12.0
tornado==6.2
tqdm==4.64.1
traitlets==5.9.0
typeguard==2.13.3
typing-inspect==0.7.1
typing_extensions==4.7.1
uc-micro-py==1.0.1
uri-template==1.2.0
urllib3==1.26.11
varint==1.0.2
wcwidth==0.2.5
web3==6.16.0
webcolors==1.12
webencodings==0.5.1
websocket-client==1.3.3
websockets==11.0.3
widgetsnbextension==3.6.1
y-py==0.5.9
yarl==1.8.1
ypy-websocket==0.8.2
zipp==3.8.1
```



Discussion:
Alchemy node used for testing all of this.
See the relevant documentation [here](https://docs.alchemy.com/reference/eth-createaccesslist).

Resolving patch:
diff --git a/web3/_utils/method_formatters.py b/web3/_utils/method_formatters.py
--- a/web3/_utils/method_formatters.py
+++ b/web3/_utils/method_formatters.py
@@ -425,7 +425,22 @@ def apply_list_to_array_formatter(formatter: Any) -> Callable[..., Any]:
     )
 )
 
+ACCESS_LIST_REQUEST_FORMATTER = type_aware_apply_formatters_to_dict(
+    {
+        "accessList": apply_formatter_if(
+            is_not_null,
+            apply_list_to_array_formatter(
+                apply_formatters_to_dict(
+                    {
+                        "storageKeys": apply_list_to_array_formatter(to_hex_if_bytes),
+                    }
+                )
+            ),
+        ),
+    }
+)
 transaction_param_formatter = compose(
+    ACCESS_LIST_REQUEST_FORMATTER,
     remove_key_if("to", lambda txn: txn["to"] in {"", b"", None}),
     remove_key_if("gasPrice", lambda txn: txn["gasPrice"] in {"", b"", None}),
 )
diff --git a/web3/types.py b/web3/types.py
--- a/web3/types.py
+++ b/web3/types.py
@@ -165,6 +165,7 @@ class RPCError(TypedDict):
 TxParams = TypedDict(
     "TxParams",
     {
+        "accessList": AccessList,
         "chainId": int,
         "data": Union[bytes, HexStr],
         # addr or ens


Test patch:
diff --git a/web3/_utils/module_testing/eth_module.py b/web3/_utils/module_testing/eth_module.py
--- a/web3/_utils/module_testing/eth_module.py
+++ b/web3/_utils/module_testing/eth_module.py
@@ -139,7 +139,10 @@
 if TYPE_CHECKING:
     from _pytest.monkeypatch import MonkeyPatch  # noqa: F401
 
-    from web3.contract import Contract  # noqa: F401
+    from web3.contract import (  # noqa: F401
+        AsyncContract,
+        Contract,
+    )
     from web3.main import (  # noqa: F401
         AsyncWeb3,
         Web3,
@@ -147,7 +150,8 @@
 
 
 def abi_encoded_offchain_lookup_contract_address(
-    w3: Union["Web3", "AsyncWeb3"], offchain_lookup_contract: "Contract"
+    w3: Union["Web3", "AsyncWeb3"],
+    offchain_lookup_contract: Union["Contract", "AsyncContract"],
 ) -> HexAddress:
     return HexAddress(
         remove_0x_prefix(
@@ -834,7 +838,7 @@ async def test_eth_estimate_gas(
     async def test_eth_estimate_gas_with_override_param_type_check(
         self,
         async_w3: "AsyncWeb3",
-        async_math_contract: "Contract",
+        async_math_contract: "AsyncContract",
         params: StateOverrideParams,
     ) -> None:
         txn_params: TxParams = {"from": await async_w3.eth.coinbase}
@@ -1130,7 +1134,7 @@ async def test_eth_get_code(
     async def test_eth_get_code_invalid_address(
         self,
         async_w3: "AsyncWeb3",
-        async_math_contract: "Contract",
+        async_math_contract: "AsyncContract",
     ) -> None:
         with pytest.raises(InvalidAddress):
             await async_w3.eth.get_code(
@@ -1139,7 +1143,7 @@ async def test_eth_get_code_invalid_address(
 
     @pytest.mark.asyncio
     async def test_eth_get_code_with_block_identifier(
-        self, async_w3: "AsyncWeb3", async_emitter_contract: "Contract"
+        self, async_w3: "AsyncWeb3", async_emitter_contract: "AsyncContract"
     ) -> None:
         block_id = await async_w3.eth.block_number
         code = await async_w3.eth.get_code(async_emitter_contract.address, block_id)
@@ -1151,28 +1155,15 @@ async def test_eth_create_access_list(
         self,
         async_w3: "AsyncWeb3",
         async_unlocked_account_dual_type: ChecksumAddress,
-        async_math_contract: "Contract",
+        async_math_contract: "AsyncContract",
     ) -> None:
-        # Initialize transaction for gas estimation
-        txn_params: TxParams = {
-            "from": async_unlocked_account_dual_type,
-            "value": Wei(1),
-            "gas": 21000,
-        }
-        txn = async_math_contract._prepare_transaction(
-            fn_name="incrementCounter",
-            fn_args=[1],
-            transaction=txn_params,
+        # build txn
+        txn = await async_math_contract.functions.incrementCounter(1).build_transaction(
+            {"from": async_unlocked_account_dual_type}
         )
 
-        # create access list using data from transaction
-        response = await async_w3.eth.create_access_list(
-            {
-                "from": async_unlocked_account_dual_type,
-                "to": async_math_contract.address,
-                "data": txn["data"],
-            }
-        )
+        # create access list
+        response = await async_w3.eth.create_access_list(txn)
 
         assert is_dict(response)
         access_list = response["accessList"]
@@ -1182,6 +1173,13 @@ async def test_eth_create_access_list(
         assert len(access_list[0]["storageKeys"][0]) == 32
         assert int(response["gasUsed"]) >= 0
 
+        # assert the result can be used directly in a transaction dict
+        txn["accessList"] = response["accessList"]
+        txn["gas"] = response["gasUsed"]
+
+        # send txn with access list
+        await async_w3.eth.send_transaction(txn)
+
     @pytest.mark.asyncio
     async def test_eth_get_transaction_count(
         self, async_w3: "AsyncWeb3", async_unlocked_account_dual_type: ChecksumAddress
@@ -1194,7 +1192,7 @@ async def test_eth_get_transaction_count(
 
     @pytest.mark.asyncio
     async def test_eth_call(
-        self, async_w3: "AsyncWeb3", async_math_contract: "Contract"
+        self, async_w3: "AsyncWeb3", async_math_contract: "AsyncContract"
     ) -> None:
         coinbase = await async_w3.eth.coinbase
         txn_params = async_math_contract._prepare_transaction(
@@ -1211,7 +1209,7 @@ async def test_eth_call(
     async def test_eth_call_with_override_code(
         self,
         async_w3: "AsyncWeb3",
-        async_revert_contract: "Contract",
+        async_revert_contract: "AsyncContract",
     ) -> None:
         coinbase = await async_w3.eth.coinbase
         txn_params = async_revert_contract._prepare_transaction(
@@ -1267,7 +1265,7 @@ async def test_eth_call_with_override_code(
     async def test_eth_call_with_override_param_type_check(
         self,
         async_w3: "AsyncWeb3",
-        async_math_contract: "Contract",
+        async_math_contract: "AsyncContract",
         params: StateOverrideParams,
     ) -> None:
         coinbase = await async_w3.eth.coinbase
@@ -1280,7 +1278,7 @@ async def test_eth_call_with_override_param_type_check(
 
     @pytest.mark.asyncio
     async def test_eth_call_with_0_result(
-        self, async_w3: "AsyncWeb3", async_math_contract: "Contract"
+        self, async_w3: "AsyncWeb3", async_math_contract: "AsyncContract"
     ) -> None:
         coinbase = await async_w3.eth.coinbase
         txn_params = async_math_contract._prepare_transaction(
@@ -1297,7 +1295,7 @@ async def test_eth_call_with_0_result(
     async def test_eth_call_revert_with_msg(
         self,
         async_w3: "AsyncWeb3",
-        async_revert_contract: "Contract",
+        async_revert_contract: "AsyncContract",
         async_unlocked_account: ChecksumAddress,
     ) -> None:
         txn_params = async_revert_contract._prepare_transaction(
@@ -1316,7 +1314,7 @@ async def test_eth_call_revert_with_msg(
     async def test_eth_call_revert_without_msg(
         self,
         async_w3: "AsyncWeb3",
-        async_revert_contract: "Contract",
+        async_revert_contract: "AsyncContract",
         async_unlocked_account: ChecksumAddress,
     ) -> None:
         with pytest.raises(ContractLogicError, match="execution reverted"):
@@ -1333,7 +1331,7 @@ async def test_eth_call_revert_without_msg(
     async def test_eth_call_revert_custom_error_with_msg(
         self,
         async_w3: "AsyncWeb3",
-        async_revert_contract: "Contract",
+        async_revert_contract: "AsyncContract",
         async_unlocked_account: ChecksumAddress,
     ) -> None:
         data = async_revert_contract.encode_abi(
@@ -1353,7 +1351,7 @@ async def test_eth_call_revert_custom_error_with_msg(
     async def test_eth_call_revert_custom_error_without_msg(
         self,
         async_w3: "AsyncWeb3",
-        async_revert_contract: "Contract",
+        async_revert_contract: "AsyncContract",
         async_unlocked_account: ChecksumAddress,
     ) -> None:
         data = async_revert_contract.encode_abi(fn_name="Unauthorized")
@@ -1385,7 +1383,7 @@ async def test_eth_call_revert_custom_error_without_msg(
     async def test_contract_panic_errors(
         self,
         async_w3: "AsyncWeb3",
-        async_panic_errors_contract: "Contract",
+        async_panic_errors_contract: "AsyncContract",
         panic_error: str,
         params: List[Any],
     ) -> None:
@@ -1402,7 +1400,7 @@ async def test_contract_panic_errors(
     async def test_eth_call_offchain_lookup(
         self,
         async_w3: "AsyncWeb3",
-        async_offchain_lookup_contract: "Contract",
+        async_offchain_lookup_contract: "AsyncContract",
         async_unlocked_account: ChecksumAddress,
         monkeypatch: "MonkeyPatch",
     ) -> None:
@@ -1428,7 +1426,7 @@ async def test_eth_call_offchain_lookup(
     async def test_eth_call_offchain_lookup_raises_when_ccip_read_is_disabled(
         self,
         async_w3: "AsyncWeb3",
-        async_offchain_lookup_contract: "Contract",
+        async_offchain_lookup_contract: "AsyncContract",
     ) -> None:
         return_data = (
             OFFCHAIN_LOOKUP_4BYTE_DATA
@@ -1466,7 +1464,7 @@ async def test_eth_call_offchain_lookup_raises_when_ccip_read_is_disabled(
     async def test_eth_call_offchain_lookup_call_flag_overrides_provider_flag(
         self,
         async_w3: "AsyncWeb3",
-        async_offchain_lookup_contract: "Contract",
+        async_offchain_lookup_contract: "AsyncContract",
         async_unlocked_account: ChecksumAddress,
         monkeypatch: "MonkeyPatch",
     ) -> None:
@@ -1494,7 +1492,7 @@ async def test_eth_call_offchain_lookup_call_flag_overrides_provider_flag(
     async def test_eth_call_offchain_lookup_raises_if_max_redirects_is_less_than_4(
         self,
         async_w3: "AsyncWeb3",
-        async_offchain_lookup_contract: "Contract",
+        async_offchain_lookup_contract: "AsyncContract",
         max_redirects: int,
     ) -> None:
         default_max_redirects = async_w3.provider.ccip_read_max_redirects
@@ -1511,7 +1509,7 @@ async def test_eth_call_offchain_lookup_raises_if_max_redirects_is_less_than_4(
     async def test_eth_call_offchain_lookup_raises_for_improperly_formatted_rest_request_response(  # noqa: E501
         self,
         async_w3: "AsyncWeb3",
-        async_offchain_lookup_contract: "Contract",
+        async_offchain_lookup_contract: "AsyncContract",
         async_unlocked_account: ChecksumAddress,
         monkeypatch: "MonkeyPatch",
     ) -> None:
@@ -1535,7 +1533,7 @@ async def test_eth_call_offchain_lookup_raises_for_improperly_formatted_rest_req
     async def test_eth_call_offchain_lookup_tries_next_url_for_non_4xx_error_status_and_tests_POST(  # noqa: E501
         self,
         async_w3: "AsyncWeb3",
-        async_offchain_lookup_contract: "Contract",
+        async_offchain_lookup_contract: "AsyncContract",
         async_unlocked_account: ChecksumAddress,
         monkeypatch: "MonkeyPatch",
         status_code_non_4xx_error: int,
@@ -1573,7 +1571,7 @@ async def test_eth_call_offchain_lookup_tries_next_url_for_non_4xx_error_status_
     async def test_eth_call_offchain_lookup_calls_raise_for_status_for_4xx_status_code(
         self,
         async_w3: "AsyncWeb3",
-        async_offchain_lookup_contract: "Contract",
+        async_offchain_lookup_contract: "AsyncContract",
         async_unlocked_account: ChecksumAddress,
         monkeypatch: "MonkeyPatch",
     ) -> None:
@@ -1596,7 +1594,7 @@ async def test_eth_call_offchain_lookup_calls_raise_for_status_for_4xx_status_co
     async def test_eth_call_offchain_lookup_raises_when_all_supplied_urls_fail(
         self,
         async_w3: "AsyncWeb3",
-        async_offchain_lookup_contract: "Contract",
+        async_offchain_lookup_contract: "AsyncContract",
     ) -> None:
         # GET and POST requests should fail since responses are not mocked
         with pytest.raises(
@@ -1610,7 +1608,7 @@ async def test_eth_call_offchain_lookup_raises_when_all_supplied_urls_fail(
     async def test_eth_call_continuous_offchain_lookup_raises_with_too_many_requests(
         self,
         async_w3: "AsyncWeb3",
-        async_offchain_lookup_contract: "Contract",
+        async_offchain_lookup_contract: "AsyncContract",
         async_unlocked_account: ChecksumAddress,
         monkeypatch: "MonkeyPatch",
     ) -> None:
@@ -1685,7 +1683,7 @@ async def test_async_eth_get_transaction_receipt_with_log_entry(
         self,
         async_w3: "AsyncWeb3",
         async_block_with_txn_with_log: BlockData,
-        async_emitter_contract: "Contract",
+        async_emitter_contract: "AsyncContract",
         txn_hash_with_log: HexStr,
     ) -> None:
         receipt = await async_w3.eth.wait_for_transaction_receipt(txn_hash_with_log)
@@ -1752,7 +1750,7 @@ async def test_async_eth_wait_for_transaction_receipt_with_log_entry(
         self,
         async_w3: "AsyncWeb3",
         async_block_with_txn_with_log: BlockData,
-        async_emitter_contract: "Contract",
+        async_emitter_contract: "AsyncContract",
         txn_hash_with_log: HexStr,
     ) -> None:
         receipt = await async_w3.eth.wait_for_transaction_receipt(txn_hash_with_log)
@@ -1950,7 +1948,7 @@ async def test_async_eth_syncing(self, async_w3: "AsyncWeb3") -> None:
 
     @pytest.mark.asyncio
     async def test_async_eth_get_storage_at(
-        self, async_w3: "AsyncWeb3", async_storage_contract: "Contract"
+        self, async_w3: "AsyncWeb3", async_storage_contract: "AsyncContract"
     ) -> None:
         async_storage_contract_address = async_storage_contract.address
 
@@ -1978,7 +1976,7 @@ async def test_async_eth_get_storage_at(
     @pytest.mark.asyncio
     @pytest.mark.xfail
     async def test_async_eth_get_storage_at_ens_name(
-        self, async_w3: "AsyncWeb3", async_storage_contract: "Contract"
+        self, async_w3: "AsyncWeb3", async_storage_contract: "AsyncContract"
     ) -> None:
         with ens_addresses(async_w3, {"storage.eth": async_storage_contract.address}):
             storage = await async_w3.eth.get_storage_at(ENS("storage.eth"), 1)
@@ -2735,24 +2733,14 @@ def test_eth_create_access_list(
         unlocked_account_dual_type: ChecksumAddress,
         math_contract: "Contract",
     ) -> None:
-        # Initialize transaction for gas estimation
-        txn_params: TxParams = {
-            "from": unlocked_account_dual_type,
-            "value": Wei(1),
-            "gas": 21000,
-        }
-
-        txn = math_contract.functions.incrementCounter(1).build_transaction(txn_params)
-
-        # create access list using data from transaction
-        response = w3.eth.create_access_list(
-            {
-                "from": unlocked_account_dual_type,
-                "to": math_contract.address,
-                "data": txn["data"],
-            }
+        # build txn
+        txn = math_contract.functions.incrementCounter(1).build_transaction(
+            {"from": unlocked_account_dual_type}
         )
 
+        # create access list
+        response = w3.eth.create_access_list(txn)
+
         assert is_dict(response)
         access_list = response["accessList"]
         assert len(access_list) > 0
@@ -2761,6 +2749,13 @@ def test_eth_create_access_list(
         assert len(access_list[0]["storageKeys"][0]) == 32
         assert int(response["gasUsed"]) >= 0
 
+        # assert the result can be used directly in a transaction dict
+        txn["accessList"] = response["accessList"]
+        txn["gas"] = response["gasUsed"]
+
+        # send txn with access list
+        w3.eth.send_transaction(txn)
+
     def test_eth_sign(
         self, w3: "Web3", unlocked_account_dual_type: ChecksumAddress
     ) -> None: