diff --git a/docs/basics/debugging.md b/docs/basics/debugging.md
index ade427b9bb..64c1540f6c 100644
--- a/docs/basics/debugging.md
+++ b/docs/basics/debugging.md
@@ -9,6 +9,7 @@ hide_title: true
# Contract Debugging
There are three ways to debug your ink! contract currently:
+
* You can write tests using one of the mechanisms described on the
[Contract Testing](/basics/contract-testing) page.
* You can interact with your contract via a UI or command-line. This is
@@ -19,6 +20,7 @@ There are three ways to debug your ink! contract currently:
### How do I print to the terminal console from ink!?
You can use those two macros:
+
* [`ink::env::debug_println!`](https://docs.rs/ink_env/4.0.0/ink_env/macro.debug_println.html)
* [`ink::env::debug_print!`](https://docs.rs/ink_env/4.0.0/ink_env/macro.debug_print.html)
@@ -30,6 +32,7 @@ There are things you could do to enable debug messages on the client console:
1. __Set the log level of your node to `runtime::contracts=debug`.__
For example, to have only errors and debug output show up for the `substrate-contracts-node`:
+
```
substrate-contracts-node -lerror,runtime::contracts=debug
```
@@ -37,6 +40,7 @@ There are things you could do to enable debug messages on the client console:
1. __Set the log level of your node to `runtime::contracts::strace` to trace host function calls.__
These function calls logs will also be displayed in the `Debug message` panel of [Contracts UI](https://github.com/paritytech/contracts-ui).
For example, to view these traces in addition to the logs described above:
+
```
substrate-contracts-node -lerror,runtime::contracts=debug,runtime::contracts::strace=trace
```
@@ -61,9 +65,98 @@ fn print(&self) {
}
```
-
:::note
Debug output is not printed for transactions!
It is only printed for RPC calls or off-chain tests.
:::
+
+# Decode Data Payload
+
+You can use a block explorer or an app like PolkadotJs to retrieve the data payload of a contract transaction, and then use [cargo-contract](https://github.com/paritytech/cargo-contract) to decode it.
+
+```bash
+# From your contract directory
+cargo contract decode message -d fe5bd8ea01000000
+```
+
+This command will output the method name and parameters encoded in the data payload:
+
+```
+Decoded data: inc_by { n: 1 }
+```
+
+If the contract was called through a cross-contract interaction, the payload will not be available in the transaction. In such cases, you can use the approach described in the next section to access it.
+
+# Replay and Debug a Block
+
+To replay a transaction, you can use [Chopstick](https://github.com/AcalaNetwork/chopsticks) to create a local fork of the chain and replay the block with trace-level logging.
+
+Assuming you have a node that you can connect to at `$ENDPOINT` and the transaction you want to replay is in block `$BLOCK_HASH`, you can use the following command:
+
+```bash
+npx @acala-network/chopsticks@latest run-block \
+--endpoint $ENDPOINT \
+--block $BLOCK_HASH \
+--runtime-log-level 5 \
+| grep runtime::contracts
+```
+
+This command replays the block with trace-level logging enabled. By filtering the output with `runtime::contracts`, you can view all the contract calls in the block:
+
+```
+runtime::contracts TRACE: call ExportedFunction::Call account: , input_data: [246, 118, 44, 201]
+runtime::contracts TRACE: call ExportedFunction::Call account: , input_data: [254, 91, 216, 234, 1, 0, 0, 0]
+runtime::contracts TRACE: call result ExecReturnValue { flags: (empty), data: [0] }
+runtime::contracts TRACE: call result ExecReturnValue { flags: (empty), data: [0] }
+```
+
+From here, you can identify the call you are interested in and decode the data payload:
+
+```bash
+echo 254, 91, 216, 234, 1, 0, 0, 0 \
+| tr ',' ' ' \
+| xargs printf '%02x' \
+| xargs cargo contract decode message -d
+```
+
+This command will output the following:
+
+```
+Decoded data: inc_by { n: 1 }
+```
+
+# Fork Node and Replay Transactions
+
+You can also use [Chopstick](https://github.com/AcalaNetwork/chopsticks) to start a local fork of your chain.
+
+This command starts a fork beginning at block `$BLOCK_HASH`. You can connect to this fork using `ws://localhost:8000` to submit extrinsics via PolkadotJs or `cargo contract`:
+
+```bash
+npx @acala-network/chopsticks@latest \
+--endpoint $ENDPOINT \
+--block $BLOCK_HASH \
+--runtime-log-level 5
+```
+
+Here, for example, you can re-run the transaction that we decoded in the previous section:
+
+```bash
+cargo contract call \
+--contract $CONTRACT_ADDR \
+--message inc_by --args 1 \
+--suri //Alice \
+--url ws://localhost:8000
+```
+
+Since trace-level logging is used, you will receive detailed information about all the host functions called during the execution of the contract:
+
+```
+runtime::contracts TRACE: call ExportedFunction::Call account: , input_data: [254, 91, 216, 234, 2, 0, 0, 0]
+runtime::contracts TRACE: call result ExecReturnValue { flags: (empty), data: [0] }
+runtime::contracts DEBUG: Execution finished with debug buffer: seal0::value_transferred(out_ptr: 65488, out_len_ptr: 65516) = Ok(())
+seal0::input(out_ptr: 65536, out_len_ptr: 65524) = Ok(())
+seal1::get_storage(key_ptr: 65536, key_len: 4, out_ptr: 65540, out_len_ptr: 65524) = Ok(Success)
+seal2::set_storage(key_ptr: 65536, key_len: 4, value_ptr: 65540, value_len: 4) = Ok(4)
+seal0::seal_return(flags: 0, data_ptr: 65536, data_len: 1) = Err(TrapReason::Return(ReturnData { flags: 0, data: [0] }))
+```