> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tenderly.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Foundry Cheatcode Tutorial

> Virtual Environment पर एक cheatcode playground deploy करें और transactions से balances, nonces, storage, और event logs को manipulate करने के लिए cast send का उपयोग करें।

यह ट्यूटोरियल Foundry में एक modular cheatcode playground बनाता है। आप एक ही contract को Virtual Environment पर deploy करते हैं, फिर transactions के अंदर से हर [Solidity precompile cheatcode](/virtual-environments/precompiles) का अभ्यास करने के लिए इसके functions को `cast send` के साथ कॉल करते हैं।

## आप क्या बनाएंगे

तीन files:

* `src/IVnetPrecompile.sol`: precompile interface।
* `src/MyTestSetup.sol`: एक playground contract। प्रत्येक function एक precompile call को wrap करता है, इसलिए आप एक बार deploy करते हैं और एक बार में state के एक टुकड़े को manipulate करने के लिए individual functions को कॉल करते हैं।
* `script/Deploy.s.sol`: एक `forge script` deploy।

### Function map

| श्रेणी  | Function                                | Wraps                                                 |
| ------- | --------------------------------------- | ----------------------------------------------------- |
| Balance | `forceBalance(account, newBalance)`     | `setBalance`                                          |
|         | `topUp(account, amount)`                | `addBalance`                                          |
| Nonce   | `forceNonce(account, newNonce)`         | `setNonce`                                            |
| Storage | `writeStorage(target, slot, value)`     | `setStorageAt`                                        |
|         | `readStorage(target, slot) → bytes32`   | `getStorageAt`                                        |
| Events  | `fireTransfer(token, from, to, amount)` | `emitEvent` (ERC-20 `Transfer`)                       |
|         | `fireEvent(target, topics[], data)`     | `emitEvent` (generic, 0–4 topics)                     |
| Demo    | `demoScenario(account)`                 | balance, nonce, storage, USDC `Transfer` को जोड़ता है |

## पूर्वापेक्षाएँ

* एक project के साथ Tenderly account।
* Foundry स्थापित (`curl -L https://foundry.paradigm.xyz | bash && foundryup`)।

<Steps>
  ### Virtual Environment बनाएं

  Tenderly Dashboard में, **Virtual Environments** पर जाएं और एक Virtual Environment बनाएं। **Admin RPC** URL कॉपी करें, public RPC funding और verification calls पर 401 लौटाता है, इसलिए इस ट्यूटोरियल में हमेशा Admin RPC का उपयोग करें।

  ### Foundry project को initialize करें

  ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  forge init tenderly-cheatcodes
  cd tenderly-cheatcodes
  ```

  ### precompile interface जोड़ें

  `src/IVnetPrecompile.sol` के रूप में save करें:

  ```solidity title="src/IVnetPrecompile.sol" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  interface IVnetPrecompile {
      function setStorageAt(address target, bytes32 slot, bytes32 value) external returns (bool);
      function getStorageAt(address target, bytes32 slot) external view returns (bytes32);
      function setBalance(address target, uint256 balance) external returns (bool);
      function addBalance(address target, uint256 amount) external returns (bool);
      function setNonce(address target, uint256 value) external returns (bool);

      function emitEvent(address target, bytes calldata data) external returns (bool);
      function emitEvent(address target, bytes32 topic1) external returns (bool);
      function emitEvent(address target, bytes32 topic1, bytes calldata data) external returns (bool);
      function emitEvent(address target, bytes32 topic1, bytes32 topic2) external returns (bool);
      function emitEvent(address target, bytes32 topic1, bytes32 topic2, bytes calldata data) external returns (bool);
      function emitEvent(address target, bytes32 topic1, bytes32 topic2, bytes32 topic3) external returns (bool);
      function emitEvent(address target, bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes calldata data) external returns (bool);
      function emitEvent(address target, bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4) external returns (bool);
      function emitEvent(address target, bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes calldata data) external returns (bool);
  }
  ```

  ### playground contract जोड़ें

  `src/MyTestSetup.sol` के रूप में save करें:

  ```solidity title="src/MyTestSetup.sol" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  import {IVnetPrecompile} from "./IVnetPrecompile.sol";

  contract MyTestSetup {
      IVnetPrecompile constant VNET = IVnetPrecompile(0xc100000000000000000000000000000000000000);

      bytes32 constant TRANSFER_TOPIC = keccak256("Transfer(address,address,uint256)");

      function forceBalance(address account, uint256 amount) external {
          VNET.setBalance(account, amount);
      }

      function topUp(address account, uint256 amount) external {
          VNET.addBalance(account, amount);
      }

      function forceNonce(address account, uint256 n) external {
          VNET.setNonce(account, n);
      }

      function writeStorage(address target, bytes32 slot, bytes32 value) external {
          VNET.setStorageAt(target, slot, value);
      }

      function readStorage(address target, bytes32 slot) external view returns (bytes32) {
          return VNET.getStorageAt(target, slot);
      }

      function fireTransfer(address token, address from, address to, uint256 amount) external {
          VNET.emitEvent(
              token,
              TRANSFER_TOPIC,
              bytes32(uint256(uint160(from))),
              bytes32(uint256(uint160(to))),
              abi.encode(amount)
          );
      }

      function fireEvent(address target, bytes32[] calldata topics, bytes calldata data) external {
          if (topics.length == 0)      VNET.emitEvent(target, data);
          else if (topics.length == 1) VNET.emitEvent(target, topics[0], data);
          else if (topics.length == 2) VNET.emitEvent(target, topics[0], topics[1], data);
          else if (topics.length == 3) VNET.emitEvent(target, topics[0], topics[1], topics[2], data);
          else                         VNET.emitEvent(target, topics[0], topics[1], topics[2], topics[3], data);
      }

      function demoScenario(address account) external {
          VNET.setBalance(account, 10 ether);
          VNET.setNonce(account, 5);
          VNET.setStorageAt(account, bytes32(uint256(0)), bytes32(uint256(0x1234)));
          VNET.addBalance(account, 2 ether);
          VNET.emitEvent(
              0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48,
              TRANSFER_TOPIC,
              bytes32(uint256(0)),
              bytes32(uint256(uint160(account))),
              abi.encode(uint256(1000e6))
          );
      }
  }
  ```

  ### deploy script जोड़ें

  `script/Deploy.s.sol` के रूप में save करें:

  ```solidity title="script/Deploy.s.sol" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  import {Script} from "forge-std/Script.sol";
  import {MyTestSetup} from "../src/MyTestSetup.sol";

  contract Deploy is Script {
      function run() external {
          vm.startBroadcast();
          new MyTestSetup();
          vm.stopBroadcast();
      }
  }
  ```

  ### environment variables कॉन्फ़िगर करें

  `.env` के रूप में save करें:

  ```bash title=".env" theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  VNET_RPC=https://virtual.mainnet.eu.rpc.tenderly.co/<your-virtual-env-uuid>
  PRIVATE_KEY=0x...
  DEPLOYER=0x...
  ```

  इसे source करें: `source .env`।

  ### deployer को fund करें

  ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  cast rpc tenderly_setBalance "[\"$DEPLOYER\"]" "0x56BC75E2D63100000" --rpc-url "$VNET_RPC"
  ```

  ### Deploy और verify

  ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  forge script script/Deploy.s.sol:Deploy \
      --rpc-url "$VNET_RPC" \
      --private-key "$PRIVATE_KEY" \
      --broadcast --slow \
      --verify \
      --verifier custom \
      --verifier-url "$VNET_RPC/verify"
  ```

  script output से deployed address को export करें:

  ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  export TEST_CONTRACT=0x...
  ```

  ### cheatcodes का अभ्यास करें

  प्रत्येक call एक अलग transaction है। किसी भी समय अलग arguments के साथ फिर से चलाएं, कोई redeployment आवश्यक नहीं।

  ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  # Set 999 ETH on an arbitrary account
  cast send "$TEST_CONTRACT" "forceBalance(address,uint256)" \
      0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 999000000000000000000 \
      --rpc-url "$VNET_RPC" --private-key "$PRIVATE_KEY"

  # Set vitalik.eth's nonce to 4242
  cast send "$TEST_CONTRACT" "forceNonce(address,uint256)" \
      0xd8da6bf26964af9d7eed9e03e53415d37aa96045 4242 \
      --rpc-url "$VNET_RPC" --private-key "$PRIVATE_KEY"

  # Write storage slot 0 of a contract
  cast send "$TEST_CONTRACT" "writeStorage(address,bytes32,bytes32)" \
      "$TARGET" \
      0x0000000000000000000000000000000000000000000000000000000000000000 \
      0x0000000000000000000000000000000000000000000000000000000000001234 \
      --rpc-url "$VNET_RPC" --private-key "$PRIVATE_KEY"

  # Spoof a 1 DAI Transfer from the real DAI contract
  cast send "$TEST_CONTRACT" "fireTransfer(address,address,address,uint256)" \
      0x6B175474E89094C44Da98b954EedeAC495271d0F \
      0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC \
      0xDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD \
      1000000000000000000 \
      --rpc-url "$VNET_RPC" --private-key "$PRIVATE_KEY"

  # Spoof a BAYC ERC-721 Transfer of token #1234 (all args indexed, data is empty)
  cast send "$TEST_CONTRACT" "fireEvent(address,bytes32[],bytes)" \
      0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D \
      '[0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,0x000000000000000000000000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC,0x000000000000000000000000DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD,0x00000000000000000000000000000000000000000000000000000000000004d2]' \
      0x \
      --rpc-url "$VNET_RPC" --private-key "$PRIVATE_KEY"
  ```

  ### state changes को verify करें

  ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  cast balance 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA --rpc-url "$VNET_RPC"
  cast nonce   0xd8da6bf26964af9d7eed9e03e53415d37aa96045 --rpc-url "$VNET_RPC"
  cast storage "$TARGET" 0                                --rpc-url "$VNET_RPC"
  ```

  ### spoofed log की पुष्टि करें

  receipt खींचें और `logs[]` में एक entry जाँचें जिसका `address` उस contract से match करता है जिसे आपने spoof किया है:

  ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  cast receipt <TX_HASH> --rpc-url "$VNET_RPC" --json | jq '.logs'
  ```

  BAYC उदाहरण के लिए, receipt में शामिल होना चाहिए:

  ```json theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  {
    "address": "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
    "topics": [
      "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
      "0x000000000000000000000000cccccccccccccccccccccccccccccccccccccccc",
      "0x000000000000000000000000dddddddddddddddddddddddddddddddddddddddd",
      "0x00000000000000000000000000000000000000000000000000000000000004d2"
    ],
    "data": "0x"
  }
  ```

  `address` BAYC contract से match करता है, `topics[0]` `Transfer` event signature hash है, और `topics[1–3]` indexed `from`, `to`, और `tokenId` को वहन करते हैं। BAYC transfers के लिए listen कर रहा एक indexer इस log को एक वास्तविक emission की तरह प्रोसेस करेगा।

  <Note>
    precompile `address` = `0xc100000000000000000000000000000000000000` के साथ diagnostic logs भी उत्सर्जित करता है, प्रत्येक state mutation रिकॉर्ड करता है। precompile की अपनी entries से spoofed log को अलग करने के लिए `logs[]` को target address द्वारा filter करें।
  </Note>
</Steps>

## यह भी देखें

* [Solidity Cheatcodes reference](/virtual-environments/precompiles), पूर्ण interface परिभाषा और function table।
* [Admin RPC](/virtual-environments/admin-rpc), JSON-RPC के माध्यम से transaction के बाहर से state manipulation।
