Skip to content

Commit

Permalink
Merge branch 'main' into feat/fork/add-sepolia
Browse files Browse the repository at this point in the history
  • Loading branch information
fubuloubu committed Mar 8, 2024
2 parents 16c6e6f + 5c3ca5e commit 02c829f
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 20 deletions.
9 changes: 9 additions & 0 deletions ape_foundry/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ def providers():
yield "polygon", "mainnet-fork", FoundryForkProvider
yield "polygon", "mumbai-fork", FoundryForkProvider

yield "base", LOCAL_NETWORK_NAME, FoundryProvider
yield "base", "mainnet-fork", FoundryForkProvider
yield "base", "goerli-fork", FoundryForkProvider
yield "base", "sepolia-fork", FoundryForkProvider

yield "blast", LOCAL_NETWORK_NAME, FoundryProvider
yield "blast", "mainnet-fork", FoundryForkProvider
yield "blast", "sepolia-fork", FoundryForkProvider


__all__ = [
"FoundryNetworkConfig",
Expand Down
44 changes: 29 additions & 15 deletions ape_foundry/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,31 +718,47 @@ def get_virtual_machine_error(self, exception: Exception, **kwargs) -> VirtualMa
if not message:
return VirtualMachineError(base_err=exception, **kwargs)

def _handle_execution_reverted(
exception: Exception, revert_message: Optional[str] = None, **kwargs
):
if revert_message in ("", "0x", None):
revert_message = TransactionError.DEFAULT_MESSAGE

enriched = self.compiler_manager.enrich_error(
ContractLogicError(base_err=exception, revert_message=message, **kwargs)
)

# Show call trace if availble
if enriched.txn:
# Unlikely scenario where a transaction is on the error even though a receipt
# exists.
if isinstance(enriched.txn, TransactionAPI) and enriched.txn.receipt:
enriched.txn.receipt.show_trace()
elif isinstance(enriched.txn, ReceiptAPI):
enriched.txn.show_trace()

return enriched

# Handle `ContactLogicError` similarly to other providers in `ape`.
# by stripping off the unnecessary prefix that foundry has on reverts.
foundry_prefix = (
"Error: VM Exception while processing transaction: reverted with reason string "
)
if message.startswith(foundry_prefix):
message = message.replace(foundry_prefix, "").strip("'")
err = ContractLogicError(base_err=exception, revert_message=message, **kwargs)
return self.compiler_manager.enrich_error(err)
return _handle_execution_reverted(exception, message, **kwargs)

elif "Transaction reverted without a reason string" in message:
err = ContractLogicError(base_err=exception, **kwargs)
return self.compiler_manager.enrich_error(err)
return _handle_execution_reverted(exception, **kwargs)

elif message.lower() == "execution reverted":
err = ContractLogicError(TransactionError.DEFAULT_MESSAGE, base_err=exception, **kwargs)
message = TransactionError.DEFAULT_MESSAGE
if isinstance(exception, Web3ContractLogicError) and (
msg := _extract_custom_error(self, **kwargs)
):
err.message = msg

err.message = (
TransactionError.DEFAULT_MESSAGE if err.message in ("", "0x", None) else err.message
)
return self.compiler_manager.enrich_error(err)
if msg not in ("", "0x", None):
message = msg
return _handle_execution_reverted(exception, revert_message=message, **kwargs)

elif message == "Transaction ran out of gas" or "OutOfGas" in message:
return OutOfGasError(base_err=exception, **kwargs)
Expand All @@ -752,14 +768,12 @@ def get_virtual_machine_error(self, exception: Exception, **kwargs) -> VirtualMa
message.replace("execution reverted: ", "").strip()
or TransactionError.DEFAULT_MESSAGE
)
err = ContractLogicError(message, base_err=exception, **kwargs)
return self.compiler_manager.enrich_error(err)
return _handle_execution_reverted(exception, revert_message=message, **kwargs)

elif isinstance(exception, ContractCustomError):
# Is raw hex (custom exception)
message = TransactionError.DEFAULT_MESSAGE if message in ("", None, "0x") else message
err = ContractLogicError(message, base_err=exception, **kwargs)
return self.compiler_manager.enrich_error(err)
return _handle_execution_reverted(exception, revert_message=message, **kwargs)

return VirtualMachineError(message, **kwargs)

Expand Down
17 changes: 16 additions & 1 deletion tests/test_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,26 @@ def test_base_fee(connected_provider, temp_config, networks, accounts):
data = {"foundry": {"base_fee": new_base_fee, "host": "http://127.0.0.1:8555"}}
with temp_config(data):
with networks.ethereum.local.use_provider("foundry") as provider:
assert provider.base_fee == new_base_fee
# Verify the block has the right base fee
block_one = provider.get_block("latest")
assert block_one.base_fee == new_base_fee

# Make sure the command has the right base fee
cmd = provider.build_command()
idx = -1
for i, part in enumerate(cmd):
if part == "--block-base-fee-per-gas":
idx = i + 1
assert idx > -1 # option was found
assert cmd[idx] == str(new_base_fee) # option val is correct

# Show can transact with this base_fee
acct1.transfer(acct2, "1 eth")

# Verify the block still has the right base fee
block_two = provider.get_block("latest")
assert block_two.base_fee == new_base_fee


def test_auto_mine(connected_provider):
assert connected_provider.auto_mine is True
Expand Down
14 changes: 10 additions & 4 deletions tests/test_pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ def run_gas_test(result, expected_report: str = EXPECTED_GAS_REPORT):


@pytest.mark.fork
def test_gas_flag_in_tests(ape_pytester):
result = ape_pytester.runpytest("--gas")
def test_gas_flag_in_tests(ape_pytester, sender):
result = ape_pytester.runpytest("--gas", "--network", "ethereum:local:foundry")
run_gas_test(result)

# Verify can happen more than once.
Expand All @@ -101,7 +101,13 @@ def test_gas_flag_exclude_method_using_cli_option(ape_pytester):
expected = filter_expected_methods("fooAndBar", "myNumber")
# Also ensure can filter out whole class
expected = expected.replace(TOKEN_B_GAS_REPORT, "")
result = ape_pytester.runpytest("--gas", "--gas-exclude", "*:fooAndBar,*:myNumber,tokenB:*")
result = ape_pytester.runpytest(
"--gas",
"--gas-exclude",
"*:fooAndBar,*:myNumber,tokenB:*",
"--network",
"ethereum:local:foundry",
)
run_gas_test(result, expected_report=expected)


Expand All @@ -112,7 +118,7 @@ def test_coverage(ape_pytester):
verifying Foundry in coverage.
TODO: Write + Run tests in an env with both vyper and foundry.
"""
result = ape_pytester.runpytest("--coverage")
result = ape_pytester.runpytest("--coverage", "--network", "ethereum:local:foundry")
result.assert_outcomes(passed=NUM_TESTS)
assert any("Coverage Profile" in ln for ln in result.outlines)
assert any("WARNING: No coverage data found." in ln for ln in result.outlines)

0 comments on commit 02c829f

Please sign in to comment.