diff --git a/docs/images/testing/reverting-call-trace.svg b/docs/images/testing/reverting-call-trace.svg new file mode 100644 index 000000000..f9e56bcd1 --- /dev/null +++ b/docs/images/testing/reverting-call-trace.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + Rich + + + + + + + + + + Reverting.<constructor>('0x9a6a6920008318b3556702b5115680e048c2c8db')[CREATE] +└── Unknown(0x9a6a6920008318b3556702b5115680e048c2c8db).<???>(b'\x18\x16\r\xdd')[STATICCALL] + + + + diff --git a/docs/testing-framework/troubleshooting.md b/docs/testing-framework/troubleshooting.md new file mode 100644 index 000000000..0d0494264 --- /dev/null +++ b/docs/testing-framework/troubleshooting.md @@ -0,0 +1,70 @@ +# Troubleshooting + +## `UnknownTransactionRevertedError(data=b'')` + +In many different cases, a development chain or compiler auto-generated code does not provide any useful information about the revert reason. +This section describes the most common cases and how to debug them. + +### ABI decoding error + +Failed ABI decoding reverts without reason data. The decoding can be explicit (e.g. `abi.decode(data, (uint256))`) or implicit when performing an external call, for example: + +```solidity +contract Reverting { + uint256 public immutable initialTotalSupply; + + constructor(address token) { + initialTotalSupply = IERC20(token).totalSupply(); + } +} +``` + +To debug this error, print a call trace of the failing transaction. The trace should contain the failing call in a malformed way. + +```python +from woke.testing import * +from pytypes.contracts.Reverting import Reverting + +def revert_handler(e: TransactionRevertedError): + if e.tx is not None: + print(e.tx.call_trace) + +@default_chain.connect() +@on_revert(revert_handler) +def test_reverting(): + a = default_chain.accounts[0] + r = Reverting.deploy( + Address("0x9a6A6920008318b3556702b5115680E048c2c8dB"), + from_=a + ) +``` + +
+--8<-- "docs/images/testing/reverting-call-trace.svg" +
+ +### Contract code size limit + +The Spurious Dragon hard fork introduced a limit on the size of a contract. The limit is 24,576 bytes of bytecode. +Due to the limit, a deployment transaction may fail with the `UnknownTransactionRevertedError` error without any reason data. +In this case, the transaction call trace contains **all contain green ticks**, but the transaction itself still fails. + +To debug this error, compile the project and search for a warning message similar to the following: + +``` +Warning: Contract code size exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on mainnet. +Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries. +``` + +### Invalid opcode + +When EVM encounters an invalid opcode, it reverts without any reason data. +Under normal circumstances, an invalid opcode should never be encountered unless explicitly triggered by the contract code. + +However, the `PUSH0` opcode may behave as invalid if the chain is not configured for the Shanghai hard fork or later. +To debug this issue, try to set a different pre-Shanghai EVM version in the Woke config file. + +```yaml +[compiler.solc] +evm_version = "paris" +``` diff --git a/mkdocs.yml b/mkdocs.yml index fbc8f4531..51ffe3946 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -54,6 +54,7 @@ nav: - Performance considerations: 'testing-framework/performance-considerations.md' - Migrating from Ape & Brownie: 'testing-framework/migrating-from-ape-and-brownie.md' - Migrating from Woke 2.x: 'testing-framework/migrating-from-woke-2.md' + - Troubleshooting: 'testing-framework/troubleshooting.md' - Detectors: 'detectors.md' - LSP server: 'language-server.md' - Solc Version Manager: 'solc-version-manager.md'