# Python Blockchain Development & Review Guidelines ## Overview This document outlines the standards for writing, reviewing, and deploying Python scripts that interact with EVM-based blockchains (Ethereum, Arbitrum, etc.). These guidelines prioritize **capital preservation**, **transaction robustness**, and **system stability**. --- ## 1. Transaction Handling & Lifecycle *High-reliability transaction management is the core of a production bot. Never "fire and forget."* ### 1.1. Timeout & Receipt Management - **Requirement:** Never send a transaction without immediately waiting for its receipt or tracking its hash. - **Why:** The RPC might accept the tx, but it could be dropped from the mempool or stuck indefinitely. - **Code Standard:** ```python # BAD w3.eth.send_raw_transaction(signed_txn.rawTransaction) # GOOD tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction) try: receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=120) except TimeExhausted: # Handle stuck transaction (bump gas or cancel) handle_stuck_transaction(tx_hash) ``` ### 1.2. Verification of Success - **Requirement:** Explicitly check `receipt.status == 1`. - **Why:** A transaction can be mined (success=True) but execution can revert (status=0). - **Code Standard:** ```python if receipt.status != 1: raise TransactionRevertedError(f"Tx {tx_hash.hex()} reverted on-chain") ``` ### 1.3. Gas Management & Stuck Transactions - **Requirement:** Do not hardcode gas prices. Use dynamic estimation. - **Mechanism:** - For EIP-1559 chains (Arbitrum/Base/Mainnet), use `maxFeePerGas` and `maxPriorityFeePerGas`. - Implement a "Gas Bumping" mechanism: If a tx is not mined in $X$ seconds, resubmit with 10-20% higher gas using the **same nonce**. ### 1.4. Nonce Management - **Requirement:** In high-frequency loops, track the nonce locally. - **Why:** `w3.eth.get_transaction_count(addr, 'pending')` is often slow or eventually consistent on some RPCs, leading to "Nonce too low" or "Replacement transaction underpriced" errors. --- ## 2. Financial Logic & Precision ### 2.1. No Floating Point Math for Token Amounts - **Requirement:** NEVER use standard python `float` for calculating token amounts or prices involved in protocol interactions. - **Standard:** Use `decimal.Decimal` or integer math (Wei). - **Why:** `0.1 + 0.2 != 0.3` in floating point. This causes dust errors and "Insufficient Balance" reverts. ```python # BAD amount = balance * 0.5 # GOOD amount = int(Decimal(balance) * Decimal("0.5")) ``` ### 2.2. Slippage Protection - **Requirement:** Never use `0` for `amountOutMinimum` or `sqrtPriceLimitX96` in production. - **Standard:** Calculate expected output and apply a config-defined slippage (e.g., 0.1%). - **Why:** Front-running and sandwich attacks will drain value from `amountOutMin: 0` trades. ### 2.3. Approval Handling - **Requirement:** Check allowance before approving. - **Standard:** - Verify `allowance >= amount`. - If `allowance == 0`, approve. - **Note:** Some tokens (USDT) require approving `0` before approving a new amount if an allowance already exists. --- ## 3. Security & Safety ### 3.1. Secrets Management - **Requirement:** No private keys or mnemonics in source code. - **Standard:** Use `.env` files (loaded via `python-dotenv`) or proper secrets managers. - **Review Check:** `grep -r "0x..." .` to ensure no keys were accidentally committed. ### 3.2. Address Validation - **Requirement:** All addresses must be checksummed before use. - **Standard:** ```python # Input target_address = "0xc364..." # Validation if not Web3.is_address(target_address): raise ValueError("Invalid address") checksum_address = Web3.to_checksum_address(target_address) ``` ### 3.3. Simulation (Dry Run) - **Requirement:** For complex logic (like batch swaps), use `contract.functions.method().call()` before `.build_transaction()`. - **Why:** If the `.call()` fails (reverts), the transaction will definitely fail. Save gas by catching logic errors off-chain. --- ## 4. Coding Style & Observability ### 4.1. Logging - **Requirement:** No `print()` statements. Use `logging` module. - **Standard:** - `INFO`: High-level state changes (e.g., "Position Opened"). - `DEBUG`: API responses, specific calc steps. - `ERROR`: Stack traces and critical failures. - **Traceability:** Log the Transaction Hash **immediately** upon sending, not after waiting. If the script crashes while waiting, you need the hash to check the chain manually. ### 4.2. Idempotency & State Recovery - **Requirement:** Scripts must be restartable without double-spending. - **Standard:** Before submitting a "Open Position" transaction, read the chain (or `hedge_status.json`) to ensure a position isn't already open. ### 4.3. Type Hinting - **Requirement:** Use Python type hints for clarity. - **Standard:** ```python def execute_swap( token_in: str, amount: int, slippage_pct: float = 0.5 ) -> str: # Returns tx_hash ``` --- ## 5. Review Checklist (Copy-Paste for PRs) - [ ] **Secrets:** No private keys in code? - [ ] **Math:** Is `Decimal` or Integer math used for all financial calcs? - [ ] **Slippage:** Is `amountOutMinimum` > 0? - [ ] **Timeouts:** Does `wait_for_transaction_receipt` have a timeout? - [ ] **Status Check:** Is `receipt.status` checked for success/revert? - [ ] **Gas:** Are gas limits and prices dynamic/reasonable? - [ ] **Addresses:** Are all addresses Checksummed? - [ ] **Restartability:** What happens if the script dies halfway through?