-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Docs and refactoring from discussions on PR #2457
- Add documentation - Refactor out the provider flag since there is no support for sending transactions w/ CCIP Read support - Refactor some around the way the ``eth_call`` is made, add flag directly to ``eth_call`` and make ``durin_call()`` and internal ``_durin_call()`` - Refactor data back into post request after linting issues went away - Make CCIP Read max redirects configurable and add tests - OffchainLookup should extend from ContractLogicError - Add some more testing and refactor some more; use web3 ValidationError instead of importing from eth_utils - Add MultipleFailedRequests if multiple failed requests for similar / same data - Reconcile changes with rebased async contract - Raise an exception if CCIP Read urls do not contain expected keyword - Add tests for ENS offchain resolution via CCIP Read functionality - CCIP Read support for EthereumTesterProvider / eth-tester
- Loading branch information
Showing
44 changed files
with
1,750 additions
and
239 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,6 +67,7 @@ Table of Contents | |
web3.miner | ||
web3.geth | ||
web3.parity | ||
web3.utils | ||
gas_price | ||
ens | ||
constants | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
Utils | ||
===== | ||
|
||
.. py:module:: web3.utils | ||
The ``utils`` module houses public utility and helper functions. | ||
|
||
|
||
.. py:method:: Utils.handle_offchain_lookup(offchain_lookup_payload, transaction) | ||
Handle ``OffchainLookup`` reverts on contract function calls manually. For an example, see :ref:`ccip-read-example` | ||
within the examples section. | ||
|
||
|
||
.. py:method:: Utils.async_handle_offchain_lookup(offchain_lookup_payload, transaction) | ||
The async version of the ``handle_offchain_lookup()`` utility method described above. |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import pytest | ||
|
||
from eth_abi import ( | ||
decode_abi, | ||
) | ||
|
||
from web3._utils.module_testing.module_testing_utils import ( | ||
mock_offchain_lookup_request_response, | ||
) | ||
from web3._utils.module_testing.offchain_lookup_contract import ( | ||
OFFCHAIN_LOOKUP_ABI, | ||
OFFCHAIN_LOOKUP_BYTECODE, | ||
OFFCHAIN_LOOKUP_BYTECODE_RUNTIME, | ||
) | ||
from web3._utils.type_conversion import ( | ||
to_hex_if_bytes, | ||
) | ||
from web3.exceptions import ( | ||
TooManyRequests, | ||
ValidationError, | ||
) | ||
|
||
# "test offchain lookup" as an abi-encoded string | ||
OFFCHAIN_LOOKUP_TEST_DATA = '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001474657374206f6666636861696e206c6f6f6b7570000000000000000000000000' # noqa: E501 | ||
# "web3py" as an abi-encoded string | ||
WEB3PY_AS_HEXBYTES = '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000067765623370790000000000000000000000000000000000000000000000000000' # noqa: E501 | ||
|
||
|
||
@pytest.fixture | ||
def OffchainLookup(w3): | ||
# compiled from `web3/_utils/module_testing/contract_sources/OffchainLookup.sol` | ||
return w3.eth.contract( | ||
abi=OFFCHAIN_LOOKUP_ABI, | ||
bytecode=OFFCHAIN_LOOKUP_BYTECODE, | ||
bytecode_runtime=OFFCHAIN_LOOKUP_BYTECODE_RUNTIME, | ||
) | ||
|
||
|
||
@pytest.fixture | ||
def offchain_lookup_contract( | ||
w3, wait_for_block, OffchainLookup, wait_for_transaction, address_conversion_func, | ||
): | ||
wait_for_block(w3) | ||
deploy_txn_hash = OffchainLookup.constructor().transact({'gas': 10000000}) | ||
deploy_receipt = wait_for_transaction(w3, deploy_txn_hash) | ||
contract_address = address_conversion_func(deploy_receipt['contractAddress']) | ||
|
||
bytecode = w3.eth.get_code(contract_address) | ||
assert bytecode == OffchainLookup.bytecode_runtime | ||
deployed_offchain_lookup = OffchainLookup(address=contract_address) | ||
assert deployed_offchain_lookup.address == contract_address | ||
return deployed_offchain_lookup | ||
|
||
|
||
def test_offchain_lookup_functionality( | ||
offchain_lookup_contract, monkeypatch, | ||
): | ||
normalized_address = to_hex_if_bytes(offchain_lookup_contract.address) | ||
mock_offchain_lookup_request_response( | ||
monkeypatch, | ||
mocked_request_url=f'https://web3.py/gateway/{normalized_address}/{OFFCHAIN_LOOKUP_TEST_DATA}.json', # noqa: E501 | ||
mocked_json_data=WEB3PY_AS_HEXBYTES, | ||
) | ||
response = offchain_lookup_contract.caller.testOffchainLookup(OFFCHAIN_LOOKUP_TEST_DATA) | ||
assert decode_abi(['string'], response)[0] == 'web3py' | ||
|
||
|
||
def test_offchain_lookup_raises_for_improperly_formatted_rest_request_response( | ||
offchain_lookup_contract, monkeypatch, | ||
): | ||
normalized_address = to_hex_if_bytes(offchain_lookup_contract.address) | ||
mock_offchain_lookup_request_response( | ||
monkeypatch, | ||
mocked_request_url=f'https://web3.py/gateway/{normalized_address}/{OFFCHAIN_LOOKUP_TEST_DATA}.json', # noqa: E501 | ||
mocked_json_data=WEB3PY_AS_HEXBYTES, | ||
json_data_field='not_data', | ||
) | ||
with pytest.raises(ValidationError, match="missing 'data' field"): | ||
offchain_lookup_contract.caller.testOffchainLookup(OFFCHAIN_LOOKUP_TEST_DATA) | ||
|
||
|
||
@pytest.mark.parametrize('status_code_non_4xx_error', [100, 300, 500, 600]) | ||
def test_eth_call_offchain_lookup_tries_next_url_for_non_4xx_error_status_and_tests_POST( | ||
offchain_lookup_contract, monkeypatch, status_code_non_4xx_error, | ||
) -> None: | ||
normalized_contract_address = to_hex_if_bytes(offchain_lookup_contract.address).lower() | ||
|
||
# The next url in our test contract doesn't contain '{data}', triggering the POST request | ||
# logic. The idea here is to return a bad status for the first url (GET) and a success | ||
# status from the second call (POST) to test both that we move on to the next url with | ||
# non 4xx status and that the POST logic is also working as expected. | ||
mock_offchain_lookup_request_response( | ||
monkeypatch, | ||
mocked_request_url=f'https://web3.py/gateway/{normalized_contract_address}/{OFFCHAIN_LOOKUP_TEST_DATA}.json', # noqa: E501 | ||
mocked_status_code=status_code_non_4xx_error, | ||
mocked_json_data=WEB3PY_AS_HEXBYTES, | ||
) | ||
mock_offchain_lookup_request_response( | ||
monkeypatch, | ||
http_method='POST', | ||
mocked_request_url=f'https://web3.py/gateway/{normalized_contract_address}.json', | ||
mocked_status_code=200, | ||
mocked_json_data=WEB3PY_AS_HEXBYTES, | ||
sender=normalized_contract_address, | ||
calldata=OFFCHAIN_LOOKUP_TEST_DATA, | ||
) | ||
response = offchain_lookup_contract.caller.testOffchainLookup(OFFCHAIN_LOOKUP_TEST_DATA) | ||
assert decode_abi(['string'], response)[0] == 'web3py' | ||
|
||
|
||
@pytest.mark.parametrize('status_code_4xx_error', [400, 410, 450, 499]) | ||
def test_eth_call_offchain_lookup_calls_raise_for_status_for_4xx_status_code( | ||
offchain_lookup_contract, monkeypatch, status_code_4xx_error, | ||
) -> None: | ||
normalized_contract_address = to_hex_if_bytes(offchain_lookup_contract.address).lower() | ||
mock_offchain_lookup_request_response( | ||
monkeypatch, | ||
mocked_request_url=f'https://web3.py/gateway/{normalized_contract_address}/{OFFCHAIN_LOOKUP_TEST_DATA}.json', # noqa: E501 | ||
mocked_status_code=status_code_4xx_error, | ||
mocked_json_data=WEB3PY_AS_HEXBYTES, | ||
) | ||
with pytest.raises(Exception, match="called raise_for_status\\(\\)"): | ||
offchain_lookup_contract.caller.testOffchainLookup(OFFCHAIN_LOOKUP_TEST_DATA) | ||
|
||
|
||
def test_offchain_lookup_raises_on_continuous_redirect( | ||
offchain_lookup_contract, monkeypatch, | ||
): | ||
normalized_address = to_hex_if_bytes(offchain_lookup_contract.address) | ||
mock_offchain_lookup_request_response( | ||
monkeypatch, | ||
mocked_request_url=f'https://web3.py/gateway/{normalized_address}/0x.json', | ||
) | ||
with pytest.raises(TooManyRequests, match="Too many CCIP read redirects"): | ||
offchain_lookup_contract.caller.continuousOffchainLookup() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.