From 36003bc123d724e6915014dccc9971aa605a9965 Mon Sep 17 00:00:00 2001
From: krystal <56278409+theekrystallee@users.noreply.github.com>
Date: Thu, 14 May 2026 20:02:56 -0700
Subject: [PATCH 01/32] initial commit
Signed-off-by: krystal <56278409+theekrystallee@users.noreply.github.com>
---
evm/tools/foundry/forking-advanced-hts.mdx | 900 ------------------
hedera/core-concepts/accounts/hiero-hooks.mdx | 56 --
.../hiero-cli/feature-coverage-gap-report.mdx | 461 ---------
.../hiero-cli/plugins/batch-plugin.mdx | 134 ---
.../plugins/contract-erc20-plugin.mdx | 208 ----
.../plugins/contract-erc721-plugin.mdx | 294 ------
.../hiero-cli/plugins/contract-plugin.mdx | 187 ----
.../hiero-cli/plugins/schedule-plugin.mdx | 156 ---
.../hiero-cli/plugins/swap-plugin.mdx | 218 -----
...dera-network-with-foundry-advanced-hts.mdx | 900 ------------------
.../0.72_performance-measurement-results.png | Bin 1285490 -> 0 bytes
11 files changed, 3514 deletions(-)
delete mode 100644 evm/tools/foundry/forking-advanced-hts.mdx
delete mode 100644 hedera/core-concepts/accounts/hiero-hooks.mdx
delete mode 100644 hedera/open-source-solutions/hiero-cli/feature-coverage-gap-report.mdx
delete mode 100644 hedera/open-source-solutions/hiero-cli/plugins/batch-plugin.mdx
delete mode 100644 hedera/open-source-solutions/hiero-cli/plugins/contract-erc20-plugin.mdx
delete mode 100644 hedera/open-source-solutions/hiero-cli/plugins/contract-erc721-plugin.mdx
delete mode 100644 hedera/open-source-solutions/hiero-cli/plugins/contract-plugin.mdx
delete mode 100644 hedera/open-source-solutions/hiero-cli/plugins/schedule-plugin.mdx
delete mode 100644 hedera/open-source-solutions/hiero-cli/plugins/swap-plugin.mdx
delete mode 100644 hedera/tutorials/smart-contracts/foundry/how-to-fork-the-hedera-network-with-foundry-advanced-hts.mdx
delete mode 100644 images/networks/release-notes/services/0.72_performance-measurement-results.png
diff --git a/evm/tools/foundry/forking-advanced-hts.mdx b/evm/tools/foundry/forking-advanced-hts.mdx
deleted file mode 100644
index f0fa5733..00000000
--- a/evm/tools/foundry/forking-advanced-hts.mdx
+++ /dev/null
@@ -1,900 +0,0 @@
----
-title: "How to Fork the Hedera Network with Foundry - Advanced HTS Contract (Part 2)"
----
-
-In this advanced tutorial, you'll learn how to interact with the Hedera Token Service (HTS) using System Contracts precompiles on a forked network with Foundry. This guide covers creating HTS tokens, querying token info, and testing ERC-20 level interactions using the [hedera-forking](https://github.com/hashgraph/hedera-forking) emulation layer.
-
-This guide shows how to:
-
-- Create HTS fungible tokens using System Contracts precompiles
-- Query HTS token info (getTokenInfo, getFungibleTokenInfo) on a forked network
-- Read HTS token properties via the ERC-20 interface (name, symbol, decimals, balanceOf)
-- Transfer HTS tokens using ERC-20 methods through the HIP-719 proxy pattern
-
-References:
-
-- Repo: [hashgraph/hedera-forking](https://github.com/hashgraph/hedera-forking)
-- HTS System Contracts: [hiero-contracts](https://github.com/hiero-ledger/hiero-contracts)
-- Supported methods: [README - Supported Methods](https://github.com/hashgraph/hedera-forking#hedera-token-service-supported-methods)
-
-
- For a deeper understanding of how Hedera forking works and its limitations,
- see [Forking Hedera Network for Local
- Testing](/hedera/core-concepts/smart-contracts/forking-hedera-network-for-local-testing).
-
-
-
- You can take a look at the complete code in the [**advanced-hts-fork-test-foundry
- repository**](https://github.com/hedera-dev/tutorial-hedera-fork-testing/tree/main/foundry/advanced-hts-fork-test-foundry).
-
-
----
-
-## Prerequisites
-
-- Completed [Part 1](/hedera/tutorials/smart-contracts/foundry/how-to-fork-the-hedera-network-with-foundry-basic-erc20) of this tutorial series
-- [Foundry](https://book.getfoundry.sh/getting-started/installation) installed
-- ECDSA account from the [Hedera Portal](https://portal.hedera.com/) with at least **20 HBAR** (15 HBAR for HTS token creation fee + gas)
-- Familiarity with Hedera System Contracts - more specifically [HTS System Contracts precompiles](https://github.com/hiero-ledger/hiero-contracts/tree/main/contracts/token-service)
-- A Hedera JSON-RPC endpoint:
- - mainnet: `https://mainnet.hashio.io/api`
- - testnet: `https://testnet.hashio.io/api`
-
----
-
-## Table of Contents
-
-1. [Step 1: Project Setup](#step-1-project-setup)
-2. [Step 2: Create the HTS Contract and Deploy to Testnet](#step-2-create-the-hts-contract-and-deploy-to-testnet)
-3. [Step 3: Write Tests for the Forked Network](#step-3-write-tests-for-the-forked-network)
-4. [Step 4: Run Tests on the Forked Network](#step-4-run-tests-on-the-forked-network)
-
----
-
-## Step 1: Project Setup
-
-### Initialize Project
-
-Create a new directory and initialize the Foundry project:
-
-```bash
-mkdir advanced-hts-fork-test-foundry
-cd advanced-hts-fork-test-foundry
-forge init
-```
-
-### Install Dependencies
-
-Install OpenZeppelin contracts and the Hedera forking library:
-
-```bash
-forge install OpenZeppelin/openzeppelin-contracts
-forge install hashgraph/hedera-forking
-```
-
-
- The `hedera-forking` library requires `forge-std >= v1.8.0`. If you're on an
- older project, update it first with `forge update lib/forge-std`.
-
-
-### Configure Remappings
-
-Create or update `remappings.txt` in your project root:
-
-```txt remappings.txt
-@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
-hedera-forking/=lib/hedera-forking/contracts/
-forge-std/=lib/forge-std/src/
-```
-
-
- Note that we are updating the `remappings.txt` in our root directory of the
- project and not in the `lib` directory where the dependencies are installed.
-
-
-### Set Environment Variables
-
-Create a `.env` file in your project root:
-
-```bash .env
-HEDERA_RPC_URL=https://testnet.hashio.io/api
-HEDERA_PRIVATE_KEY=0x-your-private-key
-```
-
-
- Replace the `0x-your-private-key` environment variable with the **HEX Encoded
- Private Key** for your **ECDSA** **account.** Note that this account **MUST**
- exist on **testnet** and have at least **20 HBAR** for the token creation fee and gas.
-
-
-Load the environment variables:
-
-```bash
-source .env
-```
-
-### Configure Foundry
-
-Update your `foundry.toml` file:
-
-```toml foundry.toml
-[profile.default]
-src = "src"
-out = "out"
-libs = ["lib"]
-ffi = true
-solc = "0.8.33"
-
-# Add this section for Hedera testnet
-[rpc_endpoints]
-testnet = "${HEDERA_RPC_URL}"
-```
-
-
- **Why `ffi = true`?** The `hedera-forking` emulation layer uses Foundry's FFI
- cheatcode to shell out to `curl` and query the Hedera Mirror Node for real
- token data (balances, metadata, associations). Without `ffi = true`, the
- emulation cannot fetch data and HTS calls will fail.
-
- **Security note:** `ffi = true` allows Foundry to execute shell commands. Only
- enable this in test profiles, never in production deployment scripts.
-
-
-Remove the default contracts that come with `forge init`:
-
-```bash
-rm -f script/Counter.s.sol src/Counter.sol test/Counter.t.sol
-```
-
----
-
-## Step 2: Create the HTS Contract and Deploy to Testnet
-
-### Create the HTS Interaction Contract
-
-Create a new file `src/HTSTokenManager.sol`:
-
-```solidity src/HTSTokenManager.sol
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.33;
-
-import {IHederaTokenService} from "hedera-forking/IHederaTokenService.sol";
-
-/// @title HTSTokenManager
-/// @notice Manages HTS fungible tokens via the Hedera Token Service precompile (0x167).
-/// @dev The HTS precompile at address(0x167) is a Hedera-native system contract.
-/// In fork testing, the hedera-forking library provides a Solidity emulation
-/// layer that responds to the same function signatures at the same address.
-contract HTSTokenManager {
- address constant HTS_PRECOMPILE = address(0x167);
- int32 constant SUCCESS = 22;
-
- address public tokenAddress;
-
- event ResponseCode(int256 responseCode);
- event CreatedToken(address tokenAddress);
- event MintedToken(int64 newTotalSupply, int64[] serialNumbers);
- event TransferToken(address tokenAddress, address receiver, int64 amount);
- event TokenInfo(IHederaTokenService.TokenInfo tokenInfo);
- event FungibleTokenInfo(IHederaTokenService.FungibleTokenInfo tokenInfo);
-
- receive() external payable {}
-
- /// @notice Creates an HTS fungible token with this contract as treasury.
- function createFungibleTokenPublic(
- string memory _name,
- string memory _symbol
- ) public payable {
- IHederaTokenService.HederaToken memory token;
- token.name = _name;
- token.symbol = _symbol;
- token.treasury = address(this);
- token.memo = "Created via HTSTokenManager";
-
- // Assign supply key and admin key to this contract
- IHederaTokenService.TokenKey[]
- memory keys = new IHederaTokenService.TokenKey[](2);
-
- keys[0] = IHederaTokenService.TokenKey({
- keyType: 0x10, // SUPPLY
- key: IHederaTokenService.KeyValue({
- inheritAccountKey: false,
- contractId: address(this),
- ed25519: bytes(""),
- ECDSA_secp256k1: bytes(""),
- delegatableContractId: address(0)
- })
- });
-
- keys[1] = IHederaTokenService.TokenKey({
- keyType: 0x01, // ADMIN
- key: IHederaTokenService.KeyValue({
- inheritAccountKey: false,
- contractId: address(this),
- ed25519: bytes(""),
- ECDSA_secp256k1: bytes(""),
- delegatableContractId: address(0)
- })
- });
-
- token.tokenKeys = keys;
-
- token.expiry = IHederaTokenService.Expiry({
- second: 0,
- autoRenewAccount: address(this),
- autoRenewPeriod: 7_776_000 // 90 days
- });
-
- (int256 responseCode, address createdToken) = IHederaTokenService(
- HTS_PRECOMPILE
- ).createFungibleToken{value: msg.value}(token, 0, 8);
-
- emit ResponseCode(responseCode);
- if (responseCode != SUCCESS) {
- revert("HTS: token creation failed");
- }
-
- tokenAddress = createdToken;
- emit CreatedToken(createdToken);
- }
-
- /// @notice Mints additional fungible tokens.
- function mintTokenPublic(
- address token,
- int64 amount
- )
- public
- returns (
- int256 responseCode,
- int64 newTotalSupply,
- int64[] memory serialNumbers
- )
- {
- bytes[] memory metadata;
- (responseCode, newTotalSupply, serialNumbers) = IHederaTokenService(
- HTS_PRECOMPILE
- ).mintToken(token, amount, metadata);
-
- emit ResponseCode(responseCode);
- if (responseCode != SUCCESS) {
- revert("HTS: mint failed");
- }
- emit MintedToken(newTotalSupply, serialNumbers);
- }
-
- /// @notice Transfers HTS tokens between accounts.
- function transferTokenPublic(
- address token,
- address sender,
- address receiver,
- int64 amount
- ) public returns (int256 responseCode) {
- responseCode = IHederaTokenService(HTS_PRECOMPILE).transferToken(
- token, sender, receiver, amount
- );
-
- emit ResponseCode(responseCode);
- if (responseCode != SUCCESS) {
- revert("HTS: transfer failed");
- }
- emit TransferToken(token, receiver, amount);
- }
-
- /// @notice Gets full token info for an HTS token.
- function getTokenInfoPublic(
- address token
- )
- public
- returns (
- int256 responseCode,
- IHederaTokenService.TokenInfo memory tokenInfo
- )
- {
- (responseCode, tokenInfo) = IHederaTokenService(HTS_PRECOMPILE)
- .getTokenInfo(token);
- emit ResponseCode(responseCode);
- emit TokenInfo(tokenInfo);
- }
-
- /// @notice Gets fungible-specific token info.
- function getFungibleTokenInfoPublic(
- address token
- )
- public
- returns (
- int256 responseCode,
- IHederaTokenService.FungibleTokenInfo memory tokenInfo
- )
- {
- (responseCode, tokenInfo) = IHederaTokenService(HTS_PRECOMPILE)
- .getFungibleTokenInfo(token);
- emit ResponseCode(responseCode);
- emit FungibleTokenInfo(tokenInfo);
- }
-}
-```
-
-**Key features of this contract:**
-
-- `createFungibleTokenPublic` - Creates new HTS fungible tokens via the precompile at `0x167`
-- `mintTokenPublic` - Mints additional tokens (requires supply key)
-- `transferTokenPublic` - Transfers HTS tokens between accounts
-- `getTokenInfoPublic` / `getFungibleTokenInfoPublic` - Query token information
-- The contract assigns itself as both the **treasury** and the **supply/admin key holder**
-
-### Compile the Contract
-
-```bash
-forge build
-```
-
-### Create Deployment Script
-
-Create a new file `script/DeployHTS.s.sol`:
-
-```solidity script/DeployHTS.s.sol
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.33;
-
-import {Script, console} from "forge-std/Script.sol";
-import {HTSTokenManager} from "../src/HTSTokenManager.sol";
-
-/// @title DeployHTSScript
-/// @notice Deploys HTSTokenManager to Hedera testnet.
-/// @dev This script ONLY deploys the contract. HTS token creation must be done
-/// separately using `cast send` because forge script simulates locally first,
-/// and the HTS precompile at 0x167 has no EVM bytecode to simulate against.
-contract DeployHTSScript is Script {
- function run() external {
- uint256 deployerPrivateKey = vm.envUint("HEDERA_PRIVATE_KEY");
- address deployer = vm.addr(deployerPrivateKey);
-
- console.log("=== HTSTokenManager Deployment ===");
- console.log("Deployer address:", deployer);
- console.log("Deployer balance:", deployer.balance / 1e18, "HBAR");
-
- vm.startBroadcast(deployerPrivateKey);
- HTSTokenManager manager = new HTSTokenManager();
- vm.stopBroadcast();
-
- console.log("");
- console.log("=== Deployment Successful ===");
- console.log("HTSTokenManager deployed to:", address(manager));
- console.log("Block number:", block.number);
- }
-}
-```
-
-### Deploy to Testnet
-
-Deployment is a two-step process. The reason is that `forge script` simulates all transactions locally before broadcasting them to the network. Since the HTS precompile at `0x167` has no EVM bytecode (it's a native Hedera system contract), the local simulation fails with `InvalidFEOpcode` when trying to call `createFungibleTokenPublic`. By splitting the deployment, Step 1 deploys using `forge script` (standard EVM deploy), and Step 2 uses `cast send` which sends the transaction directly to the RPC without local simulation.
-
-**Step 1:** Deploy the HTSTokenManager contract:
-
-```bash
-forge script script/DeployHTS.s.sol:DeployHTSScript --rpc-url $HEDERA_RPC_URL --broadcast -vvv
-```
-
-You should see output similar to:
-
-```bash
-=== Deployment Successful ===
-HTSTokenManager deployed to: 0x22723B710D0A1Bdc83706Dd8085414c0570FaB8b
-Block number: 33427480
-```
-
-Save the contract address - you'll need it for the next step.
-
-**Step 2:** Create the HTS token using `cast send`:
-
-```bash
-export CONTRACT_ADDRESS=0x22723B710D0A1Bdc83706Dd8085414c0570FaB8b
-```
-
-```bash
-cast send $CONTRACT_ADDRESS \
- 'createFungibleTokenPublic(string,string)' 'DemoHTS' 'DHTS' \
- --value 15ether \
- --rpc-url $HEDERA_RPC_URL \
- --private-key $HEDERA_PRIVATE_KEY
-```
-
-This sends the transaction directly to Hedera (bypassing local simulation), so the HTS precompile at `0x167` is handled natively by the consensus nodes.
-
-**Step 3:** Get the token address:
-
-```bash
-cast abi-decode 'tokenAddress()(address)' $(cast call $CONTRACT_ADDRESS 'tokenAddress()' --rpc-url $HEDERA_RPC_URL)
-```
-
-**Step 4:** Note the block number for fork testing:
-
-```bash
-cast block-number --rpc-url $HEDERA_RPC_URL
-```
-
-
- Save the deployed contract address, token address, and block number! You'll need
- these for your fork tests. The contract must exist at the block you're forking from.
-
-
-We have already deployed this HTS contract on testnet at [https://hashscan.io/testnet/contract/0x22723B710D0A1Bdc83706Dd8085414c0570FaB8b](https://hashscan.io/testnet/contract/0x22723B710D0A1Bdc83706Dd8085414c0570FaB8b) so we will be using this for the remainder of this exercise.
-
----
-
-## Step 3: Write Tests for the Forked Network
-
-Now we'll write tests that interact with the deployed HTS contract on the forked testnet. The key difference from the basic ERC-20 tutorial is the `htsSetup()` call - this activates the HTS emulation layer at address `0x167` so that HTS precompile calls work in the forked environment.
-
-Create a new file `test/HTSForkTest.t.sol`:
-
-
- Make sure to update the `DEPLOYED_HTS_CONTRACT` and `HTS_TOKEN` constants
- below with the values from your deployment.
-
-
-```solidity test/HTSForkTest.t.sol
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.33;
-
-import {Test, console} from "forge-std/Test.sol";
-import {htsSetup} from "hedera-forking/htsSetup.sol";
-import {IHederaTokenService} from "hedera-forking/IHederaTokenService.sol";
-import {IERC20} from "hedera-forking/IERC20.sol";
-import {HTSTokenManager} from "../src/HTSTokenManager.sol";
-
-contract HTSForkTest is Test {
- int32 constant SUCCESS = 22;
-
- // UPDATE THESE with your deployed addresses
- address payable constant DEPLOYED_HTS_CONTRACT =
- payable(0x22723B710D0A1Bdc83706Dd8085414c0570FaB8b);
- address constant HTS_TOKEN =
- 0x000000000000000000000000000000000080d4f4;
-
- HTSTokenManager public htsManager;
- IERC20 public token;
- address public alice;
- address public bob;
-
- function setUp() public {
- // CRITICAL: Initialize the HTS emulation layer FIRST.
- // This deploys the emulation contract at 0x167 so HTS calls work.
- // Without this, all HTS calls revert with InvalidFEOpcode.
- htsSetup();
-
- // Bind to deployed contracts on the fork
- htsManager = HTSTokenManager(DEPLOYED_HTS_CONTRACT);
- token = IERC20(HTS_TOKEN);
-
- // Create and fund test accounts
- alice = makeAddr("alice");
- bob = makeAddr("bob");
- vm.deal(alice, 100 ether);
- vm.deal(bob, 100 ether);
- vm.deal(DEPLOYED_HTS_CONTRACT, 100 ether);
- }
-
- /* =========================
- Token Info Tests
- ========================= */
-
- function test_GetTokenInfo() public {
- (int256 responseCode, IHederaTokenService.TokenInfo memory info) =
- htsManager.getTokenInfoPublic(HTS_TOKEN);
-
- assertEq(responseCode, int256(SUCCESS), "getTokenInfo should succeed");
- assertTrue(bytes(info.token.name).length > 0, "name not empty");
- assertTrue(bytes(info.token.symbol).length > 0, "symbol not empty");
-
- console.log("Token name:", info.token.name);
- console.log("Token symbol:", info.token.symbol);
- }
-
- function test_GetFungibleTokenInfo() public {
- (int256 responseCode, IHederaTokenService.FungibleTokenInfo memory info) =
- htsManager.getFungibleTokenInfoPublic(HTS_TOKEN);
-
- assertEq(responseCode, int256(SUCCESS), "getFungibleTokenInfo should succeed");
- console.log("Fungible token decimals:", info.decimals);
- }
-
- /* =========================
- ERC-20 Interface Tests
- ========================= */
-
- function test_ReadNameAndSymbol() public view {
- string memory name = token.name();
- string memory symbol = token.symbol();
- console.log("Token name:", name);
- console.log("Token symbol:", symbol);
- assertEq(name, "DemoHTS");
- assertEq(symbol, "DHTS");
- }
-
- function test_ReadDecimals() public view {
- uint8 decimals = token.decimals();
- console.log("Token decimals:", decimals);
- assertEq(decimals, 8);
- }
-
- function test_ReadTotalSupply() public view {
- uint256 totalSupply = token.totalSupply();
- console.log("Total supply:", totalSupply);
- assertGe(totalSupply, 0);
- }
-
- function test_ReadTreasuryBalance() public view {
- uint256 balance = token.balanceOf(DEPLOYED_HTS_CONTRACT);
- console.log("Treasury balance:", balance);
- assertGe(balance, 0);
- }
-
- /* =========================
- Transfer Tests
- ========================= */
-
- function test_DealAndTransfer() public {
- // Give alice tokens using Foundry's deal cheatcode
- uint256 amount = 1000;
- deal(HTS_TOKEN, alice, amount);
- assertEq(token.balanceOf(alice), amount);
-
- // Alice transfers to bob via ERC-20 interface
- vm.prank(alice);
- token.transfer(bob, 400);
-
- assertEq(token.balanceOf(alice), 600);
- assertEq(token.balanceOf(bob), 400);
- }
-
- function test_ApproveAndTransferFrom() public {
- deal(HTS_TOKEN, alice, 2000);
-
- vm.prank(alice);
- token.approve(bob, 1000);
-
- vm.prank(bob);
- token.transferFrom(alice, bob, 500);
-
- assertEq(token.balanceOf(alice), 1500);
- assertEq(token.balanceOf(bob), 500);
- }
-
- function test_TransferToMultipleRecipients() public {
- deal(HTS_TOKEN, alice, 5000);
-
- vm.prank(alice);
- token.transfer(bob, 2000);
-
- address charlie = makeAddr("charlie");
- vm.prank(alice);
- token.transfer(charlie, 1000);
-
- assertEq(token.balanceOf(alice), 2000);
- assertEq(token.balanceOf(bob), 2000);
- assertEq(token.balanceOf(charlie), 1000);
- }
-
- /* =========================
- Fork State Verification
- ========================= */
-
- function test_ConnectedToForkedNetwork() public view {
- uint256 blockNumber = block.number;
- console.log("Fork block number:", blockNumber);
- assertGt(blockNumber, 0);
- }
-
- function test_ContractHasBytecode() public view {
- uint256 codeSize;
- address contractAddr = DEPLOYED_HTS_CONTRACT;
- assembly { codeSize := extcodesize(contractAddr) }
- assertGt(codeSize, 0, "HTSTokenManager should have bytecode");
- }
-
- function test_HTSPrecompileHasEmulation() public view {
- uint256 htsCodeSize;
- address hts = address(0x167);
- assembly { htsCodeSize := extcodesize(hts) }
- assertGt(htsCodeSize, 0, "0x167 should have emulation bytecode");
- }
-
- function test_TokenHasBytecode() public view {
- uint256 tokenCodeSize;
- address tokenAddr = HTS_TOKEN;
- assembly { tokenCodeSize := extcodesize(tokenAddr) }
- assertGt(tokenCodeSize, 0, "HTS token should have proxy bytecode");
- }
-}
-```
-
-**Key points about these tests:**
-
-- **`htsSetup()` is critical** - Must be the first call in `setUp()` before any HTS interaction. It deploys the Solidity emulation layer at `0x167` so that HTS precompile calls work.
-- **ERC-20 interface** - HTS tokens expose standard ERC-20 methods (`name`, `symbol`, `decimals`, `balanceOf`, `transfer`, `approve`, `transferFrom`) through the HIP-719 proxy pattern. The emulation layer fetches real data from the Hedera Mirror Node via FFI.
-- **`deal()` for balances** - Foundry's `deal()` cheatcode sets token balances directly, which works with HTS tokens because the emulation layer maps storage slots correctly.
-- **`vm.prank` for impersonation** - Act as any account without their private key.
-- **Fork verification** - Tests confirm the fork is connected, contracts have bytecode, and the HTS emulation layer is active at `0x167`.
-
-
- **Foundry vs. Hardhat approach:** The Hardhat advanced tutorial tests
- `mintToken` and `transferToken` directly through the HTS precompile because
- the Hardhat plugin intercepts at the JSON-RPC level. In Foundry, the emulation
- layer excels at **read operations** and **ERC-20 level interactions**. For
- setting balances in tests, use Foundry's `deal()` cheatcode and standard
- ERC-20 methods (`transfer`, `approve`, `transferFrom`) which work through the
- HIP-719 proxy redirect pattern.
-
-
----
-
-## Step 4: Run Tests on the Forked Network
-
-Run your tests against the forked Hedera testnet:
-
-```bash
-forge test --fork-url $HEDERA_RPC_URL -vvv
-```
-
-Pin to a specific block for reproducible tests:
-
-```bash
-forge test --fork-url $HEDERA_RPC_URL --fork-block-number 33427481 -vvv
-```
-
-You should see output similar to:
-
-```bash
-Ran 13 tests for test/HTSForkTest.t.sol:HTSForkTest
-[PASS] test_ApproveAndTransferFrom() (gas: 1788900)
-[PASS] test_ConnectedToForkedNetwork() (gas: 3768)
-[PASS] test_ContractHasBytecode() (gas: 6379)
-[PASS] test_DealAndTransfer() (gas: 1688928)
-[PASS] test_GetFungibleTokenInfo() (gas: 1413178)
-[PASS] test_GetTokenInfo() (gas: 1403795)
-[PASS] test_HTSPrecompileHasEmulation() (gas: 6422)
-[PASS] test_ReadDecimals() (gas: 1204125)
-[PASS] test_ReadNameAndSymbol() (gas: 1216338)
-[PASS] test_ReadTotalSupply() (gas: 1204165)
-[PASS] test_ReadTreasuryBalance() (gas: 2055646)
-[PASS] test_TokenHasBytecode() (gas: 6425)
-[PASS] test_TransferToMultipleRecipients() (gas: 1853280)
-Suite result: ok. 13 passed; 0 failed; 0 skipped
-```
-
-### Pin to a Specific Block
-
-For reproducible tests, use `--fork-block-number` with a block where your contract exists. If you try to fork at a block before your contract was deployed, `setUp()` will fail because the contract doesn't exist yet at that block.
-
----
-
-## Best Practices for HTS Fork Testing with Foundry
-
-1. **Always call `htsSetup()` first** - It must be the very first call in `setUp()`, before any HTS interaction
-
-2. **Use `ffi = true` only in test profiles** - FFI allows arbitrary shell execution; never enable it in production deployment scripts
-
-3. **Pin your block number** - Use `--fork-block-number` for deterministic, reproducible tests in CI/CD
-
-4. **Use supported methods** - Stick to the [currently supported HTS methods](https://github.com/hashgraph/hedera-forking#hedera-token-service-supported-methods)
-
-5. **Always verify on real network** - Fork testing is for development speed; always test on testnet/mainnet before production
-
----
-
-## Bonus: Real-World SaucerSwap Mainnet Fork Test
-
-The tutorial repository includes a bonus test that demonstrates one of the most powerful use cases for fork testing: interacting with **production DeFi contracts** on Hedera mainnet without spending real HBAR.
-
-The `SaucerSwapForkTest.t.sol` file forks Hedera mainnet and executes a **real token swap** through [SaucerSwap V2](https://www.saucerswap.finance/) - swapping WHBAR for USDC at the current mainnet exchange rate, using real liquidity pools.
-
-### Run the SaucerSwap Tests
-
-```bash
-forge test --match-contract SaucerSwapForkTest \
- --fork-url https://mainnet.hashio.io/api \
- -vvv
-```
-
-
- These tests use **mainnet** (not testnet). No `.env` configuration is needed -
- fork tests don't require a private key because all balances are created locally
- with Foundry cheatcodes.
-
-
-### The Real Swap Test
-
-The headline test (`test_SwapWHBARForUSDCViaSaucerSwap`) executes a real swap through SaucerSwap V2's `exactInput` function:
-
-```solidity
-function test_SwapWHBARForUSDCViaSaucerSwap() public {
- // Give the trader 10 WHBAR using deal() - no real tokens needed
- uint256 whbarAmount = 10 * 1e8;
- deal(WHBAR, trader, whbarAmount);
-
- // Approve the SaucerSwap router
- vm.startPrank(trader);
- whbar.approve(SAUCERSWAP_ROUTER, whbarAmount);
-
- // Encode the swap path: WHBAR -> 0.15% fee tier -> USDC
- bytes memory path = abi.encodePacked(
- WHBAR,
- uint24(1500), // 0.15% fee tier for WHBAR/USDC pool
- USDC
- );
-
- // Execute the swap
- ExactInputParams memory params = ExactInputParams({
- path: path,
- recipient: trader,
- deadline: block.timestamp + 300,
- amountIn: whbarAmount,
- amountOutMinimum: 0
- });
-
- (bool success, bytes memory returnData) = SAUCERSWAP_ROUTER.call(
- abi.encodeWithSignature(
- "exactInput((bytes,address,uint256,uint256,uint256))",
- params
- )
- );
- require(success, "Swap failed");
- uint256 amountOut = abi.decode(returnData, (uint256));
- vm.stopPrank();
-
- // Trader received real USDC at mainnet exchange rate
- assertGt(amountOut, 0, "Should have received USDC from swap");
-}
-```
-
-### How It Works
-
-**Where does the WHBAR come from if the test account doesn't exist on mainnet?**
-
-Foundry's `deal(token, account, amount)` writes directly to the token's storage slots on the forked EVM. It sets the balance for the given account without any real transfer. The account doesn't need to exist on mainnet. Similarly, `vm.deal(account, amount)` sets native HBAR balances locally. Both cheatcodes only affect the fork - mainnet is never touched.
-
-**How does the swap execute against real liquidity?**
-
-The fork is a snapshot of mainnet state. The SaucerSwap V2 Router has real bytecode, and the WHBAR/USDC pool has real liquidity deposited by real LPs. When the test calls `exactInput`, the router reads real pool state (liquidity, tick, price), pulls WHBAR from the trader, swaps through the pool, and sends USDC to the trader - all at the real exchange rate. The entire execution happens locally on the fork.
-
-**Can I impersonate a real mainnet account instead?**
-
-Yes. `vm.prank(realMainnetAddress)` makes the next call appear to come from any address - no private key needed. You could impersonate a whale with millions in HBAR and use their real balances for testing:
-
-```solidity
-address whale = 0x...; // A real mainnet account
-vm.prank(whale);
-whbar.transfer(trader, 50000 * 1e8); // Uses the whale's real balance
-```
-
-**Why does this need `htsSetup()`?**
-
-Both WHBAR and USDC are HTS tokens. When the SaucerSwap router calls `transferFrom` on these tokens during the swap, the call goes through the HIP-719 proxy to `0x167`. Without `htsSetup()`, that address returns `0xfe` and the entire swap reverts.
-
-### Mainnet Addresses
-
-| Contract/Token | Hedera ID | EVM Address | Decimals |
-| -------------- | --------- | ----------- | -------- |
-| SaucerSwap V2 Router | `0.0.3949434` | `0x00000000000000000000000000000000003c437A` | - |
-| WHBAR | `0.0.1456986` | `0x0000000000000000000000000000000000163B5a` | 8 |
-| USDC (Native) | `0.0.456858` | `0x000000000000000000000000000000000006f89a` | 6 |
-
-> **Source:** [SaucerSwap Contract Deployments](https://docs.saucerswap.finance/developerx/contract-deployments)
-
----
-
-## Bonus: Bonzo Finance Mainnet Fork Test (Lending/Borrowing)
-
-The tutorial repository also includes a test that forks Hedera mainnet and interacts with [Bonzo Finance](https://bonzo.finance/) - an Aave V2 fork and the first lending/borrowing protocol on Hedera. The test deposits WHBAR as collateral and borrows USDC against it, using real contracts with ~7M USDC in real liquidity.
-
-### Run the Bonzo Tests
-
-```bash
-forge test --match-contract BonzoForkTest \
- --fork-url https://mainnet.hashio.io/api \
- -vvv
-```
-
-### What It Tests
-
-| Test | What It Does |
-| ---- | ------------ |
-| `test_DepositWHBAR` | Deposits 5000 WHBAR as collateral, receives aWHBAR tokens |
-| `test_DepositWHBARAndBorrowUSDC` | Full flow: deposit collateral, check account data, borrow 10 USDC, verify debt position |
-| `test_ReadBonzoUSDCLiquidity` | Reads real USDC liquidity in Bonzo (~7M USDC) |
-
-### How the Deposit + Borrow Works
-
-```
-deal(WHBAR, depositor, 5000e8) → Create 5000 WHBAR on the fork
-whbar.approve(LENDING_POOL, amount) → Approve LendingPool to pull WHBAR
-LendingPool.deposit(WHBAR, ...) → Deposit as collateral → receive aWHBAR
-LendingPool.getUserAccountData(...) → Check collateral, LTV (62.72%), borrow capacity
-LendingPool.borrow(USDC, 10e6, 2, ..) → Borrow 10 USDC at variable rate
- → Receive USDC + variable debt token minted
-```
-
-The LendingPool uses Bonzo's real oracle pricing to calculate collateral value, LTV ratios, and health factors - all against production state on the fork.
-
-**Why this matters:** If you're building on top of Bonzo (or any Aave V2 fork on Hedera), fork testing lets you test your integration against real protocol state, verify borrowing logic against real oracle prices, and simulate liquidation scenarios - without risking real funds.
-
-### Bonzo Mainnet Addresses
-
-| Contract | Address |
-| -------- | ------- |
-| LendingPool | `0x236897c518996163E7b313aD21D1C9fCC7BA1afc` |
-| aWHBAR | `0x6e96a607F2F5657b39bf58293d1A006f9415aF32` |
-| Variable Debt USDC | `0x8a90C2f80Fc266e204cb37387c69EA2ed42A3cc1` |
-
-> **Source:** [Bonzo Lend Contracts](https://docs.bonzo.finance/hub/developer/bonzo-lend/lend-contracts)
-
----
-
-## Understanding HTS Fork Testing with Foundry
-
-### Why Standard Fork Testing Breaks on Hedera
-
-On standard EVM chains, every contract is on-chain bytecode. When you fork and call any contract, the fork fetches its bytecode and executes it locally. Hedera's system contracts (HTS at `0x167`, Exchange Rate at `0x168`, PRNG at `0x169`) are native services implemented in the consensus node software - they have no EVM bytecode. When your fork tries to fetch code at `0x167`, the JSON-RPC relay returns `0xfe` (the INVALID opcode), and your test crashes with `InvalidFEOpcode`.
-
-### How `htsSetup()` Fixes It
-
-The `htsSetup()` function from the `hedera-forking` library:
-
-1. Deploys the `HtsSystemContractJson` emulation contract at `0x167` using `vm.etch`
-2. Creates a `MirrorNodeFFI` instance that queries the Hedera Mirror Node via curl
-3. Calls `vm.allowCheatcodes(0x167)` so the emulation can use `vm.store`, `vm.ffi`, and `vm.parseJson`
-
-After `htsSetup()`, HTS calls work because they hit a Solidity contract that fetches real token data from the Mirror Node.
-
-### How the HIP-719 Proxy Pattern Works
-
-Every HTS token address on Hedera contains identical proxy bytecode (defined by [HIP-719](https://hips.hedera.com/hip/hip-719)). When you call `token.balanceOf()`, the proxy delegates the call to `0x167` via `redirectForToken`. The emulation contract at `0x167` receives the call, fetches the real balance from the Mirror Node via FFI, and returns it.
-
-### Foundry vs. Hardhat Comparison for HTS Fork Testing
-
-| Aspect | Foundry | Hardhat |
-| ------ | ------- | ------- |
-| Emulation approach | Proactive: deploys Solidity emulation via `htsSetup()` | Reactive: worker thread intercepts JSON-RPC calls |
-| Data fetch mechanism | FFI + curl to Mirror Node | Node.js fetch to Mirror Node |
-| Required config | `ffi = true` in `foundry.toml` | `chainId` + `workerPort` in hardhat config |
-| HTS read operations | Fully supported via emulation | Fully supported via interception |
-| HTS write operations | Use `deal()` + ERC-20 methods | Direct precompile calls work |
-| Test language | Solidity | TypeScript |
-
-### Local vs. Remote State
-
-| Action | Affects Local Fork | Affects Testnet |
-| -------------------------- | ------------------ | --------------- |
-| Read balances | ✅ (cached) | ❌ (read-only) |
-| Transfer tokens (ERC-20) | ✅ | ❌ |
-| Query token info (HTS) | ✅ | ❌ |
-| `deal()` set balances | ✅ | ❌ |
-| Impersonate accounts | ✅ | ❌ |
-| Changes persist after test | ❌ (reset) | N/A |
-
----
-
-## Further Learning & Next Steps
-
-1. [**Forking Hedera Network for Local Testing**](/hedera/core-concepts/smart-contracts/forking-hedera-network-for-local-testing)\
- Deep dive into how Hedera forking works under the hood
-
-2. [**How to Fork Hedera with Foundry (Part 1)**](/hedera/tutorials/smart-contracts/foundry/how-to-fork-the-hedera-network-with-foundry-basic-erc20)\
- Start with basic ERC-20 fork testing
-
-3. [**How to Fork Hedera with Hardhat - Advanced HTS**](/hedera/tutorials/smart-contracts/how-to-fork-the-hedera-network-with-hardhat-advanced-hts)\
- Compare the Hardhat approach to HTS fork testing
-
-4. [**hedera-forking Repository**](https://github.com/hashgraph/hedera-forking)\
- Explore examples and documentation
-
-5. [**Hiero Contracts Repository**](https://github.com/hiero-ledger/hiero-contracts)\
- Explore HTS System Contracts interfaces
-
-
-
- [GitHub](https://github.com/kpachhai) |
- [LinkedIn](https://www.linkedin.com/in/kiranpachhai/)
-
-
diff --git a/hedera/core-concepts/accounts/hiero-hooks.mdx b/hedera/core-concepts/accounts/hiero-hooks.mdx
deleted file mode 100644
index 6157d820..00000000
--- a/hedera/core-concepts/accounts/hiero-hooks.mdx
+++ /dev/null
@@ -1,56 +0,0 @@
----
-title: "Hiero Hooks"
----
-
-Hiero Hooks provide programmable extension points to inject Solidity-based logic directly into the network's transaction pipeline. Hooks attach to accounts to enforce custom rules on actions like token transfers, but they do not run automatically—a hook is triggered only when explicitly referenced in a `TransferTransaction` (e.g., `CryptoTransfer`).
-
-Unlike regular smart contracts, hooks execute in a special EVM context where `address(this)` is always the reserved system address `0x16d`, enabling them to act with the privileges of the account they're attached to. This model combines smart contract flexibility with native HAPI transaction efficiency, allowing custom validation without deploying full-scale contracts.
-
-## Core Concepts
-
-Hooks are a mechanism for [**Account Abstraction**](/hedera/support-and-community/glossary#account-abstraction) on Hedera, enabling custom validation and logic without migrating entire applications to the EVM. A hook is a small piece of Solidity logic that is **triggered only when referenced/specified in a `TransferTransaction`**—not automatically.
-
-Think of it like a webhook for the ledger itself. Instead of waiting for an off-chain call, the hook runs inside the network when a transaction explicitly references it. Hooks can check conditions before execution, update state, log data, or stop a transfer if validation fails.
-
-### Why Hooks?
-
-Before Hooks, developers faced two major limitations:
-
-1. **Protocol dependency**: New functionality required network-wide upgrades through HIPs (slow and heavyweight)
-2. **EVM migration**: Moving applications to smart contracts sacrificed the performance and cost-efficiency of native HAPI transactions
-
-Hooks solve this by allowing developers to inject custom logic directly into native flows, offering better performance and lower cost than general-purpose `ContractCall` operations.
-
-### Key Characteristics
-
-| Concept | Description |
-|:--------|:------------|
-| **Trigger Model** | **Triggered only when referenced/specified** in a `TransferTransaction`—not automatic event listeners. |
-| **Implementation** | EVM Hooks: Solidity contracts executed by the network's EVM. |
-| **Extension Point** | Account Allowance Hooks validate transfers during a `CryptoTransfer`. |
-| **Key Advantage** | Custom logic on native assets (HBAR and HTS tokens) without `ContractCall` overhead. |
-| **Use Cases** | Compliance rules, transfer constraints, one-time passcodes, receiver signature waivers. |
-
----
-
-## Extension Points
-
-Hooks attach to specific extension points in a transaction's lifecycle. An extension point defines the type of hook allowed for a transaction but doesn't specify when or why a hook is activated.
-
-Currently, the first supported extension point is the Account Allowance Hook (`ACCOUNT_ALLOWANCE_HOOK`). This hook runs when a `TransferTransaction` references the hook on a transfer entry, acting as a programmable replacement for traditional ERC-style allowances.
-
-Future extension points may include other native transaction types or entity lifecycle events, enabling hooks to validate or augment a wide range of on-chain operations.
-
----
-
-## Propose a New Hook
-
-Hooks are designed to be extended by the community. If you have a use case that would benefit from a new extension point — such as hooks for topic submissions, token minting, or scheduled transactions — you can propose it through the [Hiero Improvement Proposal (HIP) process](https://hips.hedera.com/).
-
-To get started:
-
-1. Review the [HIP-1195 specification](https://hips.hedera.com/hip/hip-1195) to understand the existing hooks architecture and extension point model
-2. Draft a new HIP that defines your proposed extension point, its trigger conditions, and the Solidity interface hooks would implement
-3. Submit your proposal to the [Hiero HIP repository](https://github.com/hiero-ledger/hiero-improvement-proposal) for community review and discussion
-
-The hooks framework is built to support new extension points without protocol-level changes to the core hook infrastructure.
\ No newline at end of file
diff --git a/hedera/open-source-solutions/hiero-cli/feature-coverage-gap-report.mdx b/hedera/open-source-solutions/hiero-cli/feature-coverage-gap-report.mdx
deleted file mode 100644
index c6234de8..00000000
--- a/hedera/open-source-solutions/hiero-cli/feature-coverage-gap-report.mdx
+++ /dev/null
@@ -1,461 +0,0 @@
----
-title: "Feature coverage and gaps"
-description: "Visual coverage map of Hedera network capabilities exposed through Hiero CLI, including known gaps and default plugin command inventory."
----
-
-## Purpose
-
-This page is a single “at a glance” view of which **Hedera network** capabilities are exposed through **Hiero CLI** command groups, and what is still missing or only partially covered.
-
-
- Rows reflect **registered commands on the Hiero CLI plugin manifests** (see
- the [`hiero-cli` repository](https://github.com/hiero-ledger/hiero-cli)).
- Confirm behaviour on your installed build with `hcli --help` and plugin
- subcommands (for example `hcli token --help`).
-
-
-## Status legend
-
-| Symbol | Meaning |
-| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **Yes** | Dedicated CLI commands cover this capability for typical workflows. |
-| **Partial** | Hedera exposes the capability on-chain, but Hiero CLI only publishes part of it. The **Notes / gap** column lists **only what is missing** - no recap of behaviour that already ships. |
-| **No** | No dedicated CLI command - you would need new commands or SDK integration beyond what the manifests expose. |
-
-## Coverage heatmap (by service area)
-
-Each **colored square** is one capability row in the detailed table below (left to right in the same order). Hover a square for the capability name and status.
-
-
-
-
-
Crypto & fees
-
-
-
-
-
-
-
-
Read / query
-
-
-
-
-
-
-
-
-
HTS - lifecycle
-
-
-
-
-
-
-
-
-
-
-
HTS - custody
-
-
-
-
-
-
-
- HTS - compliance & risk
-
-
-
-
-
-
-
-
-
-
- HTS - transfers & allowances
-
-
-
-
-
-
-
-
-
-
HTS - discovery
-
-
-
-
-
-
-
Smart contracts
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Network administration
-
-
-
-
-
-
-
-
-
-
-
-
- Yes
-
-
- {" "}
- Partial
-
-
- No
-
-
-
-## Summary by Hedera service area
-
-| Area | Capability | Status | Notes / gap |
-| -------------------------------- | ------------------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **Crypto & fees** | HBAR transfer (`CryptoTransfer`) | **Yes** | `hbar transfer` |
-| **Crypto & fees** | Account balance / info queries | **Partial** | No dedicated pending-staking-rewards readout. No command lists every allowance to or from an account. No explorer-grade `account view` (staking rewards, allowance inventory, token dashboards). Incomplete fungible token lists when the mirror paginates `/accounts/{id}/tokens` and `links.next` is not followed. Incomplete NFT lists after the first mirror page fetch. |
-| **Crypto & fees** | HBAR spending allowances (native `approveHbarAllowance` / allowance management) | **Yes** | `hbar allowance`, `hbar allowance-revoke` |
-| **Read / query** | Transaction receipt or status by user-provided transaction ID | **No** | No manifest command that takes **only** a transaction ID you type in afterward and prints its Hedera receipt, record, or final status (distinct from whatever that command emitted when it first submitted). |
-| **Read / query** | Network / node metadata (version, address book) as dedicated commands | **No** | Not exposed as dedicated CLI. Rely on a mirror explorer or HashScan instead. |
-| **Read / query** | Transaction history / blocks listing (“explorer” style mirror browsing) | **No** | No commands to list transactions by account, contract, or block range. Only entity-focused queries (`account view`, `token view`, `topic find-message`, …). |
-| **Accounts** | Create / update / delete accounts | **Yes** | `account create`, `account update`, `account delete` |
-| **Accounts** | Local wallet / alias bookkeeping | **Yes** | `account import`, `account list`, `account clear`, credentials helpers |
-| **Accounts** | Staking fields on account (`stakedAccountId`, `stakedNodeId`, `declineReward`) | **Yes** | On `account update` (and related options on `contract create`) |
-| **HTS - lifecycle** | Create fungible / NFT tokens | **Yes** | `token create-ft`, `token create-nft`, `token create-ft-from-file`, `token create-nft-from-file` |
-| **HTS - lifecycle** | Mint / burn | **Yes** | `token mint-ft`, `token mint-nft`, `token burn-ft`, `token burn-nft` |
-| **HTS - lifecycle** | Delete token | **Yes** | `token delete` |
-| **HTS - lifecycle** | Update token metadata / keys / treasury / expiry after creation (`TokenUpdate`) | **Yes** | `token update` exposes post-creation administration (including keys, treasury, memo, token metadata, fee schedule keys, auto-renew, expiration, etc., per CLI options). |
-| **HTS - lifecycle** | Update individual NFT metadata per-serial (`TokenUpdateNfts`) | **Yes** | `token update-metadata-nft` |
-| **HTS - lifecycle** | Update fee schedule (`TokenFeeScheduleUpdate`) | **Partial** | There is no command to replace the entire fee schedule for a token after it has been created. |
-| **HTS - custody** | Associate tokens | **Yes** | `token associate` |
-| **HTS - custody** | Dissociate tokens (`TokenDissociate`) | **Yes** | `token dissociate` |
-| **HTS - compliance & risk** | Freeze / unfreeze account on token | **Yes** | `token freeze`, `token unfreeze` |
-| **HTS - compliance & risk** | KYC grant / revoke (`TokenGrantKyc`, `TokenRevokeKyc`) | **Yes** | `token grant-kyc`, `token revoke-kyc` |
-| **HTS - compliance & risk** | Wipe (`TokenWipe`) | **Yes** | `token wipe-ft`, `token wipe-nft` |
-| **HTS - compliance & risk** | Pause / unpause network transfers (`TokenPause`, `TokenUnpause`) | **Yes** | `token pause`, `token unpause` |
-| **HTS - transfers & allowances** | FT / NFT transfers | **Yes** | `token transfer-ft`, `token transfer-nft` |
-| **HTS - transfers & allowances** | Allowances (approve / approve NFT / delete NFT allowance) | **Yes** | `token allowance-ft`, `token allowance-nft`, `token delete-allowance-nft` |
-| **HTS - swaps** | Multi-party token / HBAR swaps in a single transaction | **Yes** | `swap create`, `swap add-hbar`, `swap add-ft`, `swap add-nft`, `swap execute`, `swap list`, `swap view` (detailed transfer breakdown for a named swap in CLI state), `swap delete` |
-| **HTS - airdrops** | Airdrop, pending list, claim, cancel, reject | **Yes** | `token airdrop-ft`, `token airdrop-nft`, `token pending-airdrops`, `token claim-airdrop`, `token cancel-airdrop`, `token reject-airdrop` |
-| **HTS - discovery** | Token registry in CLI state & on-chain view | **Yes** | `token list`, `token view`, `token import` |
-| **HCS** | Topic create / update / delete | **Yes** | `topic create`, `topic update`, `topic delete` |
-| **HCS** | Submit message | **Yes** | `topic submit-message` |
-| **HCS** | Browse messages (mirror / filters) | **Yes** | `topic find-message` |
-| **HCS** | Topic registry in CLI state | **Yes** | `topic import`, `topic list` |
-| **HCS** | On-chain topic info (full **get topic** without message scan) | **Partial** | No command to view the full topic details (keys, memo, expiry) without scanning its messages. |
-| **Smart contracts** | Deploy (`ContractCreate` / create flow) | **Yes** | `contract create` |
-| **Smart contracts** | Delete contract | **Yes** | `contract delete` |
-| **Smart contracts** | Contract query via mirror (`ContractCall` read-only) | **Partial** | Querying a contract is only supported for ERC-20 and ERC-721. There is no command to call an arbitrary contract with a custom ABI. |
-| **Smart contracts** | Contract execute (`ContractExecute`) | **Partial** | Executing a contract is only supported for ERC-20 and ERC-721. There is no command to send a call to an arbitrary contract. |
-| **Smart contracts** | Contract update (`ContractUpdate`) | **Yes** | `contract update` — admin key, memo, auto-renew account and period, expiration, max automatic token associations, and staking fields (where applicable), per CLI options. |
-| **Smart contracts** | Ethereum transaction / EVM interoperability transactions | **No** | Not present in codebase survey |
-| **Scheduling** | Schedule create / sign / delete | **Yes** | `schedule create`, `schedule sign`, `schedule delete` |
-| **Scheduling** | Inspect / verify scheduled transaction | **Yes** | `schedule verify` — queries the mirror node and returns status, payer, expiry, memo, and execution timestamp. |
-| **Batching** | Atomic batch submission patterns | **Yes** | `batch create`, `batch execute`, `batch list`, `batch delete` (+ hooks on other commands) |
-| **File service** | File create / append / update / delete | **No** | Not exposed in `src/plugins`. Tracked in [issue #1645](https://github.com/hiero-ledger/hiero-cli/issues/1645) (epic). |
-| **Network administration** | Freeze / prepare upgrade / node admin transactions | **No** | Council / privileged ops not targeted by this CLI |
-| **Utilities** | PRNG / system contract utilities (`UtilPrng`, etc.) | **No** | No dedicated commands in `src/plugins` for these utilities. Outside the stated product scope for this CLI. |
-| **CLI platform** | Networks, operator, config, plugins | **Yes** | Switch networks and manage the active operator (`network`), read and write CLI settings (`config`), install and toggle plugins at runtime (`plugin-management`), view and remove stored credentials (`credentials`). |
-
-## Default plugins → commands (inventory)
-
-Plugins loaded by default (`DEFAULT_PLUGIN_STATE`) and their **command names** as registered in manifests:
-
-| Plugin | Commands |
-| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **account** | `create`, `update`, `balance`, `list`, `import`, `clear`, `delete`, `view` |
-| **batch** | `create`, `execute`, `list`, `delete` |
-| **schedule** | `create`, `sign`, `delete`, `verify` |
-| **token** | `airdrop-ft`, `airdrop-nft`, `allowance-ft`, `allowance-nft`, `associate`, `burn-ft`, `burn-nft`, `cancel-airdrop`, `claim-airdrop`, `create-ft`, `create-ft-from-file`, `create-nft`, `create-nft-from-file`, `delete`, `delete-allowance-nft`, `dissociate`, `freeze`, `grant-kyc`, `import`, `list`, `mint-ft`, `mint-nft`, `pause`, `pending-airdrops`, `reject-airdrop`, `revoke-kyc`, `transfer-ft`, `transfer-nft`, `unfreeze`, `unpause`, `update`, `update-metadata-nft`, `view`, `wipe-ft`, `wipe-nft` |
-| **network** | `list`, `use`, `get-operator`, `set-operator` |
-| **plugin-management** | `add`, `remove`, `enable`, `disable`, `list`, `reset`, `info` |
-| **credentials** | `list`, `remove` |
-| **topic** | `create`, `import`, `list`, `submit-message`, `update`, `delete`, `find-message` |
-| **hbar** | `transfer`, `allowance`, `allowance-revoke` |
-| **swap** | `create`, `add-hbar`, `add-ft`, `add-nft`, `execute`, `list`, `view`, `delete` |
-| **contract** | `create`, `list`, `import`, `delete`, `update` |
-| **config** | `list`, `get`, `set` |
-| **contract-erc20** | `name`, `symbol`, `decimals`, `allowance`, `balance-of`, `transfer`, `transfer-from`, `approve`, `total-supply` |
-| **contract-erc721** | `balance-of`, `approve`, `set-approval-for-all`, `is-approved-for-all`, `owner-of`, `get-approved`, `token-uri`, `name`, `symbol`, `safe-transfer-from`, `mint`, `transfer-from` |
-
-Non-default plugins (e.g. **test**) exist for development/integration and are omitted from the coverage tables above.
diff --git a/hedera/open-source-solutions/hiero-cli/plugins/batch-plugin.mdx b/hedera/open-source-solutions/hiero-cli/plugins/batch-plugin.mdx
deleted file mode 100644
index 691e8d20..00000000
--- a/hedera/open-source-solutions/hiero-cli/plugins/batch-plugin.mdx
+++ /dev/null
@@ -1,134 +0,0 @@
----
-title: "Batch Plugin"
----
-
-## Most Used Commands
-
-**Create a batch, queue two token creates, then execute**
-
-```sh
-hcli batch create --name my-batch --key alice
-
-hcli token create-ft \
- --token-name "Token A" --symbol "TA" \
- --treasury alice --decimals 8 \
- --initial-supply 1000 --supply-type FINITE --max-supply 10000 \
- --admin-key alice --supply-key alice --name token-a \
- --batch my-batch
-
-hcli token create-ft \
- --token-name "Token B" --symbol "TB" \
- --treasury alice --decimals 8 \
- --initial-supply 500 --supply-type INFINITE \
- --admin-key alice --supply-key alice --name token-b \
- --batch my-batch
-
-hcli batch execute --name my-batch
-```
-
-**List batches**
-
-```sh
-hcli batch list
-```
-
-**Remove one queued transaction or drop the whole batch**
-
-```sh
-hcli batch delete --name my-batch --order 2
-hcli batch delete --name my-batch
-```
-
-## Full Command Reference
-
-
- Create a named batch and choose which key will sign the batch transaction when you run **`batch execute`**.
-
-
- Name or alias for the batch.
-
-
-
- Key used to sign batched transactions. Defaults to the operator when omitted. Accepts `{accountId}:{privateKey}`, `{ed25519|ecdsa}:private:{private-key}`, key reference, or account alias.
-
-
-
- Key manager to use: `local` or `local_encrypted` (defaults to config setting).
-
-
- **Example**
-
- ```sh
- hcli batch create --name my-batch --key alice
- ```
-
-
-
- Sign and submit all transactions in the batch as one atomic batch transaction. The batch must already exist and contain at least one queued transaction. After a successful run, related plugins update local state (for example token or account hooks registered on this command).
-
-
- Name of the batch to execute.
-
-
- **Example**
-
- ```sh
- hcli batch execute --name my-batch
- ```
-
-
-
- List all batches stored in CLI state (name, size, execution status).
-
- **Example**
-
- ```sh
- hcli batch list
- ```
-
-
-
- Delete an entire batch, or remove a single queued transaction by its order index.
-
-
- Name of the batch.
-
-
-
- 1-based order of the transaction to remove. If omitted, the whole batch is deleted.
-
-
- **Examples**
-
- ```sh
- hcli batch delete --name my-batch --order 3
- hcli batch delete --name my-batch
- ```
-
-
-## Adding transactions to a batch (`-B` / `--batch`)
-
-The Batch plugin registers hooks that other commands use. When a command supports batching and you pass **`-B `** or **`--batch `** (same option), the CLI **does not** submit that transaction immediately. It serializes the signed inner transaction and appends it to the batch named ``. Run **`hcli --help`** on the command you care about. If batching is wired for that command, the help text includes **`-B` / `--batch`**.
-
-As of the current Hiero CLI manifests, batch hooks are registered on:
-
-- **Account:** `create`, `update`, `delete`
-- **HBAR:** `transfer`
-- **Topic:** `create`, `submit-message`, `update`, `delete`
-- **Token:** many HTS transaction subcommands under `token` (see `src/plugins/token/manifest.ts` for the full list). Examples include `create-ft`, `create-ft-from-file`, `create-nft`, `create-nft-from-file`, `associate`, `transfer-ft`, `transfer-nft`, and other operations that declare `batchify-set-batch-key` / `batchify-add-transaction`.
-
-**Rules and limits**
-
-- Create the batch with **`batch create`** before adding transactions.
-- A batch can hold at most **50** inner transactions (enforced in the batch hook implementation). Limits and atomic batch semantics on the network come from **[HIP-551: Batch transactions](https://github.com/hiero-ledger/hiero-improvement-proposals/blob/main/HIP/hip-551.md)** in the Hiero Improvement Proposals repository.
-- **`batch execute`** refuses to run if that batch name was already executed on the current network. Use **`batch list`** to inspect status and **`batch delete`** to remove a batch you no longer need (including freeing a name for reuse).
-
-
-#### **Operator key on `batch create`:**
-
-The **`--key` / `-k`** flag on **`batch create`** is **optional** in the CLI manifest. If you omit it, signing falls back to the **operator** key. Some older README text may say the key is required. Trust **`hcli batch create --help`** and this page.
-
-
-## Related
-
-For **Hedera scheduled transactions** (`--scheduled` / `-X`) instead of queued batch execution, see the [Schedule plugin](/hedera/open-source-solutions/hiero-cli/plugins/schedule-plugin).
diff --git a/hedera/open-source-solutions/hiero-cli/plugins/contract-erc20-plugin.mdx b/hedera/open-source-solutions/hiero-cli/plugins/contract-erc20-plugin.mdx
deleted file mode 100644
index 01581a47..00000000
--- a/hedera/open-source-solutions/hiero-cli/plugins/contract-erc20-plugin.mdx
+++ /dev/null
@@ -1,208 +0,0 @@
----
-title: "Contract ERC-20 Plugin"
----
-
-The **Contract ERC-20** plugin calls standard **EIP-20** methods on a contract already deployed on Hedera. Deploy or import the contract first with the [Contract plugin](/hedera/open-source-solutions/hiero-cli/plugins/contract-plugin).
-
-## Most Used Commands
-
-**Read token metadata and an account balance**
-
-```sh
-hcli contract-erc20 name --contract my-token
-hcli contract-erc20 decimals --contract my-token
-hcli contract-erc20 balance-of --contract my-token --account alice
-```
-
-**Transfer and approve (state-changing, signed by the operator)**
-
-```sh
-hcli contract-erc20 transfer --contract my-token --to bob --value 1000000
-hcli contract-erc20 approve --contract my-token --spender bob --value 500000
-```
-
-## Full Command Reference
-
-Commands use the **`contract-erc20`** namespace (for example **`hcli contract-erc20 name`**). **`--contract` / `-c`** accepts a local alias, Hedera contract ID (`0.0.xxx`), or EVM address (`0x…`) where the manifest says so.
-
-
- Call **`name()`** on the ERC-20 contract (read-only).
-
-
- Smart contract ID or local alias.
-
-
- **Example**
-
- ```sh
- hcli contract-erc20 name --contract my-token
- ```
-
-
-
- Call **`symbol()`** (read-only).
-
-
- Smart contract ID or local alias.
-
-
- **Example**
-
- ```sh
- hcli contract-erc20 symbol --contract my-token
- ```
-
-
-
- Call **`decimals()`** (read-only).
-
-
- Smart contract ID or local alias.
-
-
- **Example**
-
- ```sh
- hcli contract-erc20 decimals --contract my-token
- ```
-
-
-
- Call **`totalSupply()`** (read-only).
-
-
- Smart contract ID or local alias.
-
-
- **Example**
-
- ```sh
- hcli contract-erc20 total-supply --contract my-token
- ```
-
-
-
- Call **`balanceOf(address)`** (read-only).
-
-
- Smart contract ID, alias, or EVM address.
-
-
-
- Account to query: alias, Hedera account ID, or EVM address.
-
-
- **Example**
-
- ```sh
- hcli contract-erc20 balance-of --contract my-token --account 0.0.123456
- ```
-
-
-
- Call **`allowance(owner, spender)`** (read-only).
-
-
- Smart contract ID or local alias.
-
-
-
- Owner account: alias, account ID, or EVM address.
-
-
-
- Spender account: alias, account ID, or EVM address.
-
-
- **Example**
-
- ```sh
- hcli contract-erc20 allowance --contract my-token --owner alice --spender bob
- ```
-
-
-
- Call **`transfer(to, value)`**. Submits a contract call transaction (operator signs).
-
-
- Smart contract ID, alias, or EVM address.
-
-
-
- Recipient: alias, account ID, or EVM address.
-
-
-
- Amount passed to **`transfer`** as configured by the token (often smallest units—confirm against **`decimals`** for your contract).
-
-
-
- Gas for the contract call.
-
-
- **Example**
-
- ```sh
- hcli contract-erc20 transfer --contract my-token --to bob --value 1000000
- ```
-
-
-
- Call **`transferFrom(from, to, value)`**. Requires a sufficient allowance from **`from`** for the signing account (typically the operator). Submits a contract call transaction.
-
-
- Smart contract ID, alias, or EVM address.
-
-
-
- Source account: alias, account ID, or EVM address.
-
-
-
- Recipient: alias, account ID, or EVM address.
-
-
-
- Amount for **`transferFrom`**.
-
-
-
- Gas for the contract call.
-
-
- **Example**
-
- ```sh
- hcli contract-erc20 transfer-from --contract my-token --from alice --to bob --value 500000
- ```
-
-
-
- Call **`approve(spender, value)`**. Submits a contract call transaction.
-
-
- Smart contract ID, alias, or EVM address.
-
-
-
- Spender account: alias, account ID, or EVM address.
-
-
-
- Approved amount for **`approve`**.
-
-
-
- Gas for the contract call.
-
-
- **Example**
-
- ```sh
- hcli contract-erc20 approve --contract my-token --spender bob --value 1000000
- ```
-
-
-## Related
-
-NFT contract helpers are documented on the [Contract ERC-721 plugin](/hedera/open-source-solutions/hiero-cli/plugins/contract-erc721-plugin) page.
diff --git a/hedera/open-source-solutions/hiero-cli/plugins/contract-erc721-plugin.mdx b/hedera/open-source-solutions/hiero-cli/plugins/contract-erc721-plugin.mdx
deleted file mode 100644
index 5e0990e3..00000000
--- a/hedera/open-source-solutions/hiero-cli/plugins/contract-erc721-plugin.mdx
+++ /dev/null
@@ -1,294 +0,0 @@
----
-title: "Contract ERC-721 Plugin"
----
-
-The **Contract ERC-721** plugin calls standard **EIP-721** methods on an NFT collection contract deployed on Hedera. Deploy or import the contract first with the [Contract plugin](/hedera/open-source-solutions/hiero-cli/plugins/contract-plugin). For fungible (ERC-20) calls, see the [Contract ERC-20 plugin](/hedera/open-source-solutions/hiero-cli/plugins/contract-erc20-plugin).
-
-## Most Used Commands
-
-**Read collection metadata and token ownership**
-
-```sh
-hcli contract-erc721 name --contract my-nft
-hcli contract-erc721 owner-of --contract my-nft --token-id 1
-hcli contract-erc721 token-uri --contract my-nft --token-id 1
-```
-
-**Approve and transfer a specific token**
-
-```sh
-hcli contract-erc721 approve --contract my-nft --to bob --token-id 1
-hcli contract-erc721 safe-transfer-from --contract my-nft --from alice --to bob --token-id 1
-```
-
-## Full Command Reference
-
-Commands use the **`contract-erc721`** namespace (for example **`hcli contract-erc721 name`**). **`--contract` / `-c`** accepts a local alias, Hedera contract ID (`0.0.xxx`), or EVM address (`0x…`) where the manifest allows it.
-
-
- Call **`name()`** (read-only).
-
-
- Smart contract ID or local alias.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 name --contract my-nft
- ```
-
-
-
- Call **`symbol()`** (read-only).
-
-
- Smart contract ID or local alias.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 symbol --contract my-nft
- ```
-
-
-
- Call **`balanceOf(address)`** (read-only).
-
-
- Smart contract ID or local alias.
-
-
-
- Owner account: alias, account ID, or EVM address.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 balance-of --contract my-nft --owner alice
- ```
-
-
-
- Call **`ownerOf(uint256 tokenId)`** (read-only).
-
-
- Smart contract ID or local alias.
-
-
-
- Token ID (`uint256`).
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 owner-of --contract my-nft --token-id 1
- ```
-
-
-
- Call **`getApproved(uint256 tokenId)`** (read-only).
-
-
- Smart contract ID or local alias.
-
-
-
- Token ID to query.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 get-approved --contract my-nft --token-id 1
- ```
-
-
-
- Call **`isApprovedForAll(address owner, address operator)`** (read-only).
-
-
- Smart contract ID, alias, or EVM address.
-
-
-
- Owner account: alias, account ID, or EVM address.
-
-
-
- Operator account: alias, account ID, or EVM address.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 is-approved-for-all --contract my-nft --owner alice --operator bob
- ```
-
-
-
- Call **`tokenURI(uint256 tokenId)`** (read-only).
-
-
- Smart contract ID or local alias.
-
-
-
- Token ID to query.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 token-uri --contract my-nft --token-id 1
- ```
-
-
-
- Call **`approve(address to, uint256 tokenId)`**. State-changing (operator signs).
-
-
- Smart contract ID, alias, or EVM address.
-
-
-
- Address approved to transfer the token: alias, account ID, or EVM address.
-
-
-
- Token ID to approve.
-
-
-
- Gas for the contract call.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 approve --contract my-nft --to bob --token-id 1
- ```
-
-
-
- Call **`setApprovalForAll(address operator, bool approved)`**. State-changing.
-
-
- Smart contract ID, alias, or EVM address.
-
-
-
- Operator account: alias, account ID, or EVM address.
-
-
-
- Must be the string **`true`** or **`false`**.
-
-
-
- Gas for the contract call.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 set-approval-for-all --contract my-nft --operator bob --approved true
- ```
-
-
-
- Call **`safeTransferFrom`** (with or without the extra **`bytes`** argument). State-changing.
-
-
- Smart contract ID, alias, or EVM address.
-
-
-
- Current owner: alias, account ID, or EVM address.
-
-
-
- New owner: alias, account ID, or EVM address.
-
-
-
- Token ID to transfer.
-
-
-
- Gas for the contract call.
-
-
-
- Optional data payload for the 4-argument **`safeTransferFrom`** overload.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 safe-transfer-from --contract my-nft --from alice --to bob --token-id 1
- ```
-
-
-
- Call **`transferFrom(address from, address to, uint256 tokenId)`**. State-changing.
-
-
- Smart contract ID, alias, or EVM address.
-
-
-
- Current owner: alias, account ID, or EVM address.
-
-
-
- Recipient: alias, account ID, or EVM address.
-
-
-
- Token ID to transfer.
-
-
-
- Gas for the contract call.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 transfer-from --contract my-nft --from alice --to bob --token-id 1
- ```
-
-
-
- Calls a **custom** **`mint(address to, uint256 tokenId)`** style entry point (experimental). The manifest marks this command as experimental and assumes a contract that exposes a compatible **`mint`** used for testing.
-
-
- Smart contract ID, alias, or EVM address.
-
-
-
- Recipient of the minted token: alias, account ID, or EVM address.
-
-
-
- Token ID to mint.
-
-
-
- Gas for the contract call.
-
-
- **Example**
-
- ```sh
- hcli contract-erc721 mint --contract my-nft --to alice --token-id 42
- ```
-
-
-## Related
-
-Fungible token helpers: [Contract ERC-20 plugin](/hedera/open-source-solutions/hiero-cli/plugins/contract-erc20-plugin). Deploy and import: [Contract plugin](/hedera/open-source-solutions/hiero-cli/plugins/contract-plugin).
diff --git a/hedera/open-source-solutions/hiero-cli/plugins/contract-plugin.mdx b/hedera/open-source-solutions/hiero-cli/plugins/contract-plugin.mdx
deleted file mode 100644
index 0e160740..00000000
--- a/hedera/open-source-solutions/hiero-cli/plugins/contract-plugin.mdx
+++ /dev/null
@@ -1,187 +0,0 @@
----
-title: "Contract Plugin"
----
-
-## Most Used Commands
-
-**Deploy from a Solidity file**
-
-```sh
-hcli contract create \
- --name my-contract \
- --file ./MyContract.sol \
- --admin-key alice
-```
-
-**Import an existing on-chain contract into local state**
-
-```sh
-hcli contract import --contract 0.0.123456 --name my-alias
-```
-
-**List saved contracts**
-
-```sh
-hcli contract list
-```
-
-**Delete on Hedera (beneficiary required) or drop local state only**
-
-```sh
-hcli contract delete --contract my-alias --transfer-id 0.0.7890
-hcli contract delete --contract 0.0.123456 --state-only
-```
-
-
-#### **Create: `--file` vs `--default`**
-
-You must supply **`--file`** (path to a `.sol` file) **or** **`--default`** (`erc20` or `erc721` built-in template). They are mutually exclusive.
-
-
-## Full Command Reference
-
-
- Compile a Solidity source (or use a built-in template), deploy the contract to the current network, and run verification where the CLI supports it.
-
-
- Smart contract name or alias stored in CLI state.
-
-
-
- Path to a Solidity file (absolute or relative). Use with **`--base-path`** when imports need a root directory.
-
-
-
- Use a built-in template instead of **`--file`**. Mutually exclusive with **`--file`**.
-
-
-
- Base directory for resolving the Solidity file. Defaults to the current directory when using **`--file`** (see CLI README for **`--default`** behavior).
-
-
-
- Gas limit for contract creation.
-
-
-
- Admin key credential(s) for the new contract. Pass multiple times for **KeyList** / **ThresholdKey** style setups. See **`hcli contract create --help`** for accepted formats.
-
-
-
- M-of-N: how many of the **`--admin-key`** values must sign the create flow. Only applies when multiple **`--admin-key`** entries are provided.
-
-
-
- Contract memo.
-
-
-
- Solidity compiler version to use for compilation.
-
-
-
- Constructor argument values, in order. Repeat the flag once per argument.
-
-
-
- Key manager to use: `local` or `local_encrypted` (defaults to config setting).
-
-
-
- Initial HBAR balance for the contract. Examples: `100` (HBAR) or `100t` (tinybars).
-
-
-
- Auto-renew period: seconds as an integer, or with suffix `s`, `m`, `h`, or `d` (e.g. `500`, `500s`, `50m`, `2h`, `30d`).
-
-
-
- Account ID (`0.0.xxx`) that pays for contract auto-renewal.
-
-
-
- Maximum automatic token associations (`-1` for unlimited, `0` to disable).
-
-
-
- Account ID (`0.0.xxx`) to stake the contract to. Mutually exclusive with **`--staked-node-id`**.
-
-
-
- Node ID to stake the contract to. Mutually exclusive with **`--staked-account-id`**.
-
-
-
- Whether to decline staking rewards for this contract.
-
-
- **Examples**
-
- ```sh
- hcli contract create --name my-token --default erc20
- hcli contract create --name app --file ./App.sol --admin-key alice --gas 3000000
- ```
-
-
-
- List smart contracts stored in CLI state (including metadata such as network and verification flags where available).
-
- **Example**
-
- ```sh
- hcli contract list
- ```
-
-
-
- Import an existing contract from Hedera by **`0.0.xxx`** ID or **`0x…`** EVM address. The CLI reads contract info from the mirror node and stores admin key metadata in local state for later operations.
-
-
- Contract ID (`0.0.xxx`) or EVM address (`0x…`).
-
-
-
- Optional local alias for the imported contract.
-
-
-
-
- By default, submits a **`ContractDeleteTransaction`** on Hedera and then removes the contract from local state. With **`--state-only`**, only local state is cleared (no network transaction).
-
-
- Contract ID (`0.0.xxx`) or local alias.
-
-
-
- Remove from local CLI state only. No network delete.
-
-
-
- Account (ID or alias) that receives remaining HBAR after an on-chain delete. For a network delete, supply exactly one of **`--transfer-id`** or **`--transfer-contract-id`**. Do not combine with **`--state-only`**.
-
-
-
- Contract (ID or alias) that receives remaining HBAR. For a network delete, supply exactly one of **`--transfer-id`** or **`--transfer-contract-id`** (never both).
-
-
-
- Optional signing credential(s) for the network delete. Not allowed with **`--state-only`**. If omitted on a network delete, the CLI derives required admin keys from the mirror node and matches KMS keys (including M-of-N). Pass multiple times when several keys must sign.
-
-
-
- Key manager used when resolving **`--admin-key`** (defaults to config).
-
-
- **Examples**
-
- ```sh
- hcli contract delete --contract my-alias --transfer-id 0.0.5678
- hcli contract delete --contract 0.0.123456 --state-only
- ```
-
- This command uses **`requireConfirmation`**. In non-interactive environments, use the root **`--confirm`** flag (see [Overview](/hedera/open-source-solutions/hiero-cli/overview) → Global Flags) so the CLI does not block on the prompt.
-
-
-## Related plugins
-
-ERC-20 and ERC-721 helper plugins focus on **calling** deployed contracts. This page covers **compile**, **deploy**, **import**, **list**, and **delete** for Solidity sources and built-in **`erc20`** / **`erc721`** templates.
diff --git a/hedera/open-source-solutions/hiero-cli/plugins/schedule-plugin.mdx b/hedera/open-source-solutions/hiero-cli/plugins/schedule-plugin.mdx
deleted file mode 100644
index 3da4bd71..00000000
--- a/hedera/open-source-solutions/hiero-cli/plugins/schedule-plugin.mdx
+++ /dev/null
@@ -1,156 +0,0 @@
----
-title: "Schedule Plugin"
----
-
-## Most Used Commands
-
-**Register a schedule, submit a transfer as `ScheduleCreate`, then sign and verify**
-
-```sh
-hcli schedule create --name team-payout --admin-key alice --expiration "2026-12-31T23:59:59.000Z"
-
-hcli token transfer-ft \
- --token MYTOKEN \
- --from alice \
- --to bob \
- --amount 10 \
- --scheduled team-payout
-
-hcli schedule sign --schedule team-payout --key bob
-
-hcli schedule verify --name team-payout
-```
-
-
-#### **Batch vs schedule**
-
-The **Batch** plugin queues signed inner transactions for a later atomic **`batch execute`**. The **Schedule** plugin submits a **Hedera schedule** so execution depends on signatures and mirror-visible schedule state. See the [Batch plugin](/hedera/open-source-solutions/hiero-cli/plugins/batch-plugin) page for **`--batch` / `-B`**. Avoid combining flags in ways your command’s help does not describe.
-
-
-## Full Command Reference
-
-
- Register a **named** schedule in local CLI state (per network). That name is what you pass to **`--scheduled` / `-X`** on supported commands so the inner transaction is wrapped in a Hedera **`ScheduleCreateTransaction`** instead of executing immediately.
-
-
- Local name of the schedule record.
-
-
-
- Admin key for managing the schedule on chain (resolved to a key the CLI can use).
-
-
-
- Payer for the scheduled transaction. Must resolve to an account ID with a private key. Defaults to the operator.
-
-
-
- Public schedule memo (max 100 bytes).
-
-
-
- Expiration time in ISO 8601. Must be at most 62 days from now.
-
-
-
- When set, the schedule runs at expiration time instead of as soon as required signatures are collected.
-
-
-
- Key manager to use: `local` or `local_encrypted` (defaults to config setting).
-
-
- **Example**
-
- ```sh
- hcli schedule create --name my-schedule --admin-key alice --memo "Q1 payout"
- ```
-
-
-
- Submit a **`ScheduleSignTransaction`** to add a signature to an existing schedule. **`--schedule`** accepts either a **`0.0.x`** schedule entity ID or the local name from **`schedule create`**.
-
-
- Schedule ID (`0.0.x`) or local schedule name.
-
-
-
- Key material whose signature is added. Must resolve to a private key the CLI can sign with.
-
-
-
- Key manager to use: `local` or `local_encrypted` (defaults to config setting).
-
-
- **Example**
-
- ```sh
- hcli schedule sign --schedule my-schedule --key carol
- ```
-
-
-
- Remove the schedule on chain when applicable and align local state. An admin key is required on chain. If **`--admin-key`** is omitted, the CLI uses the admin key stored on the local schedule record when available.
-
-
- Schedule ID (`0.0.x`) or local schedule name.
-
-
-
- Admin key used to sign the delete. Optional if the stored record supplies one.
-
-
-
- Key manager to use: `local` or `local_encrypted` (defaults to config setting).
-
-
- **Example**
-
- ```sh
- hcli schedule delete --schedule my-schedule --admin-key alice
- ```
-
-
-
- Query the Mirror Node to see whether a schedule has executed and refresh local flags. Provide **either** a local **`--name`** **or** a **`--schedule-id`** (validation requires at least one).
-
-
- Local name of the schedule record.
-
-
-
- Schedule entity ID (`0.0.x`).
-
-
-
- Key manager to use: `local` or `local_encrypted` (defaults to config setting).
-
-
- **Examples**
-
- ```sh
- hcli schedule verify --name my-schedule
- hcli schedule verify --schedule-id 0.0.1234567
- ```
-
-
-## Scheduling inner transactions (`-X` / `--scheduled`)
-
-The Schedule plugin registers the **`scheduled`** hook. Commands that opt into this hook accept **`-X `** or **`--scheduled `**, where `` matches a record from **`schedule create`**. When set, the hook builds and submits a **`ScheduleCreateTransaction`** around the inner transaction, stores the returned schedule ID on the record, and stops the normal “execute immediately” path for that invocation.
-
-If **`--scheduled`** is omitted, the hook does nothing and the command behaves as usual.
-
-As of the current Hiero CLI manifests, the hook is registered on:
-
-- **Account:** `create`, `update`
-- **HBAR:** `transfer`
-- **Topic:** `create`, `submit-message`
-- **Token:** `burn-ft`, `burn-nft`, `mint-ft`, `mint-nft`, `transfer-ft`, `transfer-nft`, `cancel-airdrop`, `create-ft`, `create-nft`, `associate`, `create-ft-from-file`, `create-nft-from-file`, `freeze`, `unfreeze`
-
-Use **`hcli --help`** to confirm that **`--scheduled` / `-X`** appears for the command you are running.
-
-
-#### **Reuse and state**
-
-The hook rejects scheduling when the local record is already marked as having an on-chain schedule for that flow (`Transaction is already scheduled`). Plan names and cleanup (`schedule delete`, `schedule verify`) accordingly.
-
diff --git a/hedera/open-source-solutions/hiero-cli/plugins/swap-plugin.mdx b/hedera/open-source-solutions/hiero-cli/plugins/swap-plugin.mdx
deleted file mode 100644
index fa585f00..00000000
--- a/hedera/open-source-solutions/hiero-cli/plugins/swap-plugin.mdx
+++ /dev/null
@@ -1,218 +0,0 @@
----
-title: "Swap Plugin"
----
-
-Multi-party exchanges of **HBAR**, **fungible HTS tokens**, and **NFT serials**, composed step by step locally and executed as **one Hedera transfer transaction** (`CryptoTransfer`). If the submission fails (for example insufficient balance), the saved swap stays in CLI state unless you **`swap delete`** it.
-
-
- Swaps are **stateful**: nothing is submitted until **`hcli swap execute`**. Inspecting local drafts does not hit the network. Use **`swap list`**, **`swap view`**, and **`hcli swap --help`** on your installed build.
-
-
-## Typical workflow
-
-**Create a named swap, add each transfer you want, review, then execute**
-
-```sh
-hcli swap create -n exchange --memo "Alice ↔ Bob"
-
-hcli swap add-hbar -n exchange --from alice --to bob --amount 100
-hcli swap add-ft -n exchange --from bob --to alice --token my-token --amount 50
-
-hcli swap list
-hcli swap view -n exchange
-
-hcli swap execute -n exchange
-```
-
-**Drop a draft without submitting**
-
-```sh
-hcli swap delete -n exchange
-```
-
-## Limits and behaviour
-
-- **Transfer entry cap:** A single Hedera `TransferTransaction` supports at most **10** transfer entries. The CLI uses the same limit when you add steps.
-- **HBAR and FT:** Each `add-hbar` or `add-ft` step counts as **one** entry.
-- **NFTs:** Each **serial** in `add-nft --serials` counts as **one** entry when capacity is checked for that command.
-- **Atomicity:** All entries are applied in **one transaction** — they succeed or fail together.
-
-On **`swap execute`**, every distinct **source account** (`--from`, operator by default) must be able to sign. The CLI collects the required keys when signing before submission. After a **successful** execute, that swap name is removed from CLI state automatically.
-
-### State storage
-
-Draft swaps persist under your CLI state directory (see [Overview](/hedera/open-source-solutions/hiero-cli/overview#configuration-and-state)), typically **`~/.hiero-cli/state/swap-storage.json`**, **per network**.
-
-## Full command reference
-
-
- Create an empty swap with a memo stored for the eventual transaction (optional). No ledger transaction is sent.
-
-
- Name for this swap (used with all other `swap` subcommands).
-
-
-
- Optional memo on the **`swap execute`** transaction.
-
-
- **Example**
-
- ```sh
- hcli swap create -n my-swap --memo "Token exchange"
- ```
-
-
-
- Append an HBAR transfer from **`--from`** (default: operator) to **`--to`**.
-
-
- Swap name.
-
-
-
- Destination account (account ID or alias).
-
-
-
- Amount: plain value is in **HBAR** (for example `10`). The suffix **`t`** means **tinybars** (for example `1000t`).
-
-
-
- Source account: `accountId:privateKey`, alias, account ID, or key reference. Defaults to the operator.
-
-
-
- Key manager for resolving credentials (defaults to config).
-
-
- **Examples**
-
- ```sh
- hcli swap add-hbar -n my-swap --to alice --amount 10
- hcli swap add-hbar -n my-swap --to 0.0.123456 --amount 1000t --from bob
- ```
-
-
-
- Append a fungible HTS transfer. For display amounts (without **`t`**), decimals are resolved from the **mirror node** when you run the command.
-
-
- Swap name.
-
-
-
- Destination account.
-
-
-
- Fungible token ID or imported alias.
-
-
-
- Amount in **display units** unless you append **`t`** for **base units** (consistent with other token commands).
-
-
-
- Source account (defaults to operator).
-
-
-
- Key manager (defaults to config).
-
-
- **Examples**
-
- ```sh
- hcli swap add-ft -n my-swap --to alice --token my-token --amount 100
- hcli swap add-ft -n my-swap --to 0.0.123456 --token 0.0.8849743 --amount 50t --from bob
- ```
-
-
-
- Append one or more NFT serial transfers (**same token**, comma-separated serials).
-
-
- Swap name.
-
-
-
- Destination account.
-
-
-
- NFT token ID or imported alias.
-
-
-
- Comma-separated serial numbers (for example `1,2,3`).
-
-
-
- Source account (defaults to operator).
-
-
-
- Key manager (defaults to config).
-
-
- **Examples**
-
- ```sh
- hcli swap add-nft -n my-swap --to alice --token my-nft --serials 1,2,3
- hcli swap add-nft -n my-swap --to 0.0.123456 --token 0.0.8849743 --serials 5 --from bob
- ```
-
-
-
- Build the `TransferTransaction`, sign with every required **`from`** key, submit, and on success delete the swap from state.
-
-
- Swap to execute (must contain at least one transfer).
-
-
- **Example**
-
- ```sh
- hcli swap execute -n my-swap
- ```
-
-
-
- Summaries for all swaps stored for the **current network** (names, transfer counts, limits).
-
- **Example**
-
- ```sh
- hcli swap list
- ```
-
-
-
- Full detail for **one** named swap stored in CLI state: memo, transfers (type HBAR / FT / NFT), from/to, and counts versus the protocol limit (**10** entries per transaction).
-
- **Example**
-
- ```sh
- hcli swap view -n my-swap
- ```
-
-
-
- Remove the named swap from state **without** submitting a transaction.
-
-
- Swap to delete.
-
-
- **Example**
-
- ```sh
- hcli swap delete -n my-swap
- ```
-
-
-## Related
-
-- Hedera semantics for moving value between several accounts in one transaction match the topic covered under **[Atomic swaps](/hedera/sdks-and-apis/sdks/token-service/atomic-swaps)** in the SDK documentation.
-- The **[Batch plugin](/hedera/open-source-solutions/hiero-cli/plugins/batch-plugin)** queues **distinct** inner transactions for **HIP-551** atomic batch submission. **`swap`** assembles **one** `CryptoTransfer`. Use whichever matches your operational model.
diff --git a/hedera/tutorials/smart-contracts/foundry/how-to-fork-the-hedera-network-with-foundry-advanced-hts.mdx b/hedera/tutorials/smart-contracts/foundry/how-to-fork-the-hedera-network-with-foundry-advanced-hts.mdx
deleted file mode 100644
index f0fa5733..00000000
--- a/hedera/tutorials/smart-contracts/foundry/how-to-fork-the-hedera-network-with-foundry-advanced-hts.mdx
+++ /dev/null
@@ -1,900 +0,0 @@
----
-title: "How to Fork the Hedera Network with Foundry - Advanced HTS Contract (Part 2)"
----
-
-In this advanced tutorial, you'll learn how to interact with the Hedera Token Service (HTS) using System Contracts precompiles on a forked network with Foundry. This guide covers creating HTS tokens, querying token info, and testing ERC-20 level interactions using the [hedera-forking](https://github.com/hashgraph/hedera-forking) emulation layer.
-
-This guide shows how to:
-
-- Create HTS fungible tokens using System Contracts precompiles
-- Query HTS token info (getTokenInfo, getFungibleTokenInfo) on a forked network
-- Read HTS token properties via the ERC-20 interface (name, symbol, decimals, balanceOf)
-- Transfer HTS tokens using ERC-20 methods through the HIP-719 proxy pattern
-
-References:
-
-- Repo: [hashgraph/hedera-forking](https://github.com/hashgraph/hedera-forking)
-- HTS System Contracts: [hiero-contracts](https://github.com/hiero-ledger/hiero-contracts)
-- Supported methods: [README - Supported Methods](https://github.com/hashgraph/hedera-forking#hedera-token-service-supported-methods)
-
-
- For a deeper understanding of how Hedera forking works and its limitations,
- see [Forking Hedera Network for Local
- Testing](/hedera/core-concepts/smart-contracts/forking-hedera-network-for-local-testing).
-
-
-
- You can take a look at the complete code in the [**advanced-hts-fork-test-foundry
- repository**](https://github.com/hedera-dev/tutorial-hedera-fork-testing/tree/main/foundry/advanced-hts-fork-test-foundry).
-
-
----
-
-## Prerequisites
-
-- Completed [Part 1](/hedera/tutorials/smart-contracts/foundry/how-to-fork-the-hedera-network-with-foundry-basic-erc20) of this tutorial series
-- [Foundry](https://book.getfoundry.sh/getting-started/installation) installed
-- ECDSA account from the [Hedera Portal](https://portal.hedera.com/) with at least **20 HBAR** (15 HBAR for HTS token creation fee + gas)
-- Familiarity with Hedera System Contracts - more specifically [HTS System Contracts precompiles](https://github.com/hiero-ledger/hiero-contracts/tree/main/contracts/token-service)
-- A Hedera JSON-RPC endpoint:
- - mainnet: `https://mainnet.hashio.io/api`
- - testnet: `https://testnet.hashio.io/api`
-
----
-
-## Table of Contents
-
-1. [Step 1: Project Setup](#step-1-project-setup)
-2. [Step 2: Create the HTS Contract and Deploy to Testnet](#step-2-create-the-hts-contract-and-deploy-to-testnet)
-3. [Step 3: Write Tests for the Forked Network](#step-3-write-tests-for-the-forked-network)
-4. [Step 4: Run Tests on the Forked Network](#step-4-run-tests-on-the-forked-network)
-
----
-
-## Step 1: Project Setup
-
-### Initialize Project
-
-Create a new directory and initialize the Foundry project:
-
-```bash
-mkdir advanced-hts-fork-test-foundry
-cd advanced-hts-fork-test-foundry
-forge init
-```
-
-### Install Dependencies
-
-Install OpenZeppelin contracts and the Hedera forking library:
-
-```bash
-forge install OpenZeppelin/openzeppelin-contracts
-forge install hashgraph/hedera-forking
-```
-
-
- The `hedera-forking` library requires `forge-std >= v1.8.0`. If you're on an
- older project, update it first with `forge update lib/forge-std`.
-
-
-### Configure Remappings
-
-Create or update `remappings.txt` in your project root:
-
-```txt remappings.txt
-@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
-hedera-forking/=lib/hedera-forking/contracts/
-forge-std/=lib/forge-std/src/
-```
-
-
- Note that we are updating the `remappings.txt` in our root directory of the
- project and not in the `lib` directory where the dependencies are installed.
-
-
-### Set Environment Variables
-
-Create a `.env` file in your project root:
-
-```bash .env
-HEDERA_RPC_URL=https://testnet.hashio.io/api
-HEDERA_PRIVATE_KEY=0x-your-private-key
-```
-
-
- Replace the `0x-your-private-key` environment variable with the **HEX Encoded
- Private Key** for your **ECDSA** **account.** Note that this account **MUST**
- exist on **testnet** and have at least **20 HBAR** for the token creation fee and gas.
-
-
-Load the environment variables:
-
-```bash
-source .env
-```
-
-### Configure Foundry
-
-Update your `foundry.toml` file:
-
-```toml foundry.toml
-[profile.default]
-src = "src"
-out = "out"
-libs = ["lib"]
-ffi = true
-solc = "0.8.33"
-
-# Add this section for Hedera testnet
-[rpc_endpoints]
-testnet = "${HEDERA_RPC_URL}"
-```
-
-
- **Why `ffi = true`?** The `hedera-forking` emulation layer uses Foundry's FFI
- cheatcode to shell out to `curl` and query the Hedera Mirror Node for real
- token data (balances, metadata, associations). Without `ffi = true`, the
- emulation cannot fetch data and HTS calls will fail.
-
- **Security note:** `ffi = true` allows Foundry to execute shell commands. Only
- enable this in test profiles, never in production deployment scripts.
-
-
-Remove the default contracts that come with `forge init`:
-
-```bash
-rm -f script/Counter.s.sol src/Counter.sol test/Counter.t.sol
-```
-
----
-
-## Step 2: Create the HTS Contract and Deploy to Testnet
-
-### Create the HTS Interaction Contract
-
-Create a new file `src/HTSTokenManager.sol`:
-
-```solidity src/HTSTokenManager.sol
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.33;
-
-import {IHederaTokenService} from "hedera-forking/IHederaTokenService.sol";
-
-/// @title HTSTokenManager
-/// @notice Manages HTS fungible tokens via the Hedera Token Service precompile (0x167).
-/// @dev The HTS precompile at address(0x167) is a Hedera-native system contract.
-/// In fork testing, the hedera-forking library provides a Solidity emulation
-/// layer that responds to the same function signatures at the same address.
-contract HTSTokenManager {
- address constant HTS_PRECOMPILE = address(0x167);
- int32 constant SUCCESS = 22;
-
- address public tokenAddress;
-
- event ResponseCode(int256 responseCode);
- event CreatedToken(address tokenAddress);
- event MintedToken(int64 newTotalSupply, int64[] serialNumbers);
- event TransferToken(address tokenAddress, address receiver, int64 amount);
- event TokenInfo(IHederaTokenService.TokenInfo tokenInfo);
- event FungibleTokenInfo(IHederaTokenService.FungibleTokenInfo tokenInfo);
-
- receive() external payable {}
-
- /// @notice Creates an HTS fungible token with this contract as treasury.
- function createFungibleTokenPublic(
- string memory _name,
- string memory _symbol
- ) public payable {
- IHederaTokenService.HederaToken memory token;
- token.name = _name;
- token.symbol = _symbol;
- token.treasury = address(this);
- token.memo = "Created via HTSTokenManager";
-
- // Assign supply key and admin key to this contract
- IHederaTokenService.TokenKey[]
- memory keys = new IHederaTokenService.TokenKey[](2);
-
- keys[0] = IHederaTokenService.TokenKey({
- keyType: 0x10, // SUPPLY
- key: IHederaTokenService.KeyValue({
- inheritAccountKey: false,
- contractId: address(this),
- ed25519: bytes(""),
- ECDSA_secp256k1: bytes(""),
- delegatableContractId: address(0)
- })
- });
-
- keys[1] = IHederaTokenService.TokenKey({
- keyType: 0x01, // ADMIN
- key: IHederaTokenService.KeyValue({
- inheritAccountKey: false,
- contractId: address(this),
- ed25519: bytes(""),
- ECDSA_secp256k1: bytes(""),
- delegatableContractId: address(0)
- })
- });
-
- token.tokenKeys = keys;
-
- token.expiry = IHederaTokenService.Expiry({
- second: 0,
- autoRenewAccount: address(this),
- autoRenewPeriod: 7_776_000 // 90 days
- });
-
- (int256 responseCode, address createdToken) = IHederaTokenService(
- HTS_PRECOMPILE
- ).createFungibleToken{value: msg.value}(token, 0, 8);
-
- emit ResponseCode(responseCode);
- if (responseCode != SUCCESS) {
- revert("HTS: token creation failed");
- }
-
- tokenAddress = createdToken;
- emit CreatedToken(createdToken);
- }
-
- /// @notice Mints additional fungible tokens.
- function mintTokenPublic(
- address token,
- int64 amount
- )
- public
- returns (
- int256 responseCode,
- int64 newTotalSupply,
- int64[] memory serialNumbers
- )
- {
- bytes[] memory metadata;
- (responseCode, newTotalSupply, serialNumbers) = IHederaTokenService(
- HTS_PRECOMPILE
- ).mintToken(token, amount, metadata);
-
- emit ResponseCode(responseCode);
- if (responseCode != SUCCESS) {
- revert("HTS: mint failed");
- }
- emit MintedToken(newTotalSupply, serialNumbers);
- }
-
- /// @notice Transfers HTS tokens between accounts.
- function transferTokenPublic(
- address token,
- address sender,
- address receiver,
- int64 amount
- ) public returns (int256 responseCode) {
- responseCode = IHederaTokenService(HTS_PRECOMPILE).transferToken(
- token, sender, receiver, amount
- );
-
- emit ResponseCode(responseCode);
- if (responseCode != SUCCESS) {
- revert("HTS: transfer failed");
- }
- emit TransferToken(token, receiver, amount);
- }
-
- /// @notice Gets full token info for an HTS token.
- function getTokenInfoPublic(
- address token
- )
- public
- returns (
- int256 responseCode,
- IHederaTokenService.TokenInfo memory tokenInfo
- )
- {
- (responseCode, tokenInfo) = IHederaTokenService(HTS_PRECOMPILE)
- .getTokenInfo(token);
- emit ResponseCode(responseCode);
- emit TokenInfo(tokenInfo);
- }
-
- /// @notice Gets fungible-specific token info.
- function getFungibleTokenInfoPublic(
- address token
- )
- public
- returns (
- int256 responseCode,
- IHederaTokenService.FungibleTokenInfo memory tokenInfo
- )
- {
- (responseCode, tokenInfo) = IHederaTokenService(HTS_PRECOMPILE)
- .getFungibleTokenInfo(token);
- emit ResponseCode(responseCode);
- emit FungibleTokenInfo(tokenInfo);
- }
-}
-```
-
-**Key features of this contract:**
-
-- `createFungibleTokenPublic` - Creates new HTS fungible tokens via the precompile at `0x167`
-- `mintTokenPublic` - Mints additional tokens (requires supply key)
-- `transferTokenPublic` - Transfers HTS tokens between accounts
-- `getTokenInfoPublic` / `getFungibleTokenInfoPublic` - Query token information
-- The contract assigns itself as both the **treasury** and the **supply/admin key holder**
-
-### Compile the Contract
-
-```bash
-forge build
-```
-
-### Create Deployment Script
-
-Create a new file `script/DeployHTS.s.sol`:
-
-```solidity script/DeployHTS.s.sol
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.33;
-
-import {Script, console} from "forge-std/Script.sol";
-import {HTSTokenManager} from "../src/HTSTokenManager.sol";
-
-/// @title DeployHTSScript
-/// @notice Deploys HTSTokenManager to Hedera testnet.
-/// @dev This script ONLY deploys the contract. HTS token creation must be done
-/// separately using `cast send` because forge script simulates locally first,
-/// and the HTS precompile at 0x167 has no EVM bytecode to simulate against.
-contract DeployHTSScript is Script {
- function run() external {
- uint256 deployerPrivateKey = vm.envUint("HEDERA_PRIVATE_KEY");
- address deployer = vm.addr(deployerPrivateKey);
-
- console.log("=== HTSTokenManager Deployment ===");
- console.log("Deployer address:", deployer);
- console.log("Deployer balance:", deployer.balance / 1e18, "HBAR");
-
- vm.startBroadcast(deployerPrivateKey);
- HTSTokenManager manager = new HTSTokenManager();
- vm.stopBroadcast();
-
- console.log("");
- console.log("=== Deployment Successful ===");
- console.log("HTSTokenManager deployed to:", address(manager));
- console.log("Block number:", block.number);
- }
-}
-```
-
-### Deploy to Testnet
-
-Deployment is a two-step process. The reason is that `forge script` simulates all transactions locally before broadcasting them to the network. Since the HTS precompile at `0x167` has no EVM bytecode (it's a native Hedera system contract), the local simulation fails with `InvalidFEOpcode` when trying to call `createFungibleTokenPublic`. By splitting the deployment, Step 1 deploys using `forge script` (standard EVM deploy), and Step 2 uses `cast send` which sends the transaction directly to the RPC without local simulation.
-
-**Step 1:** Deploy the HTSTokenManager contract:
-
-```bash
-forge script script/DeployHTS.s.sol:DeployHTSScript --rpc-url $HEDERA_RPC_URL --broadcast -vvv
-```
-
-You should see output similar to:
-
-```bash
-=== Deployment Successful ===
-HTSTokenManager deployed to: 0x22723B710D0A1Bdc83706Dd8085414c0570FaB8b
-Block number: 33427480
-```
-
-Save the contract address - you'll need it for the next step.
-
-**Step 2:** Create the HTS token using `cast send`:
-
-```bash
-export CONTRACT_ADDRESS=0x22723B710D0A1Bdc83706Dd8085414c0570FaB8b
-```
-
-```bash
-cast send $CONTRACT_ADDRESS \
- 'createFungibleTokenPublic(string,string)' 'DemoHTS' 'DHTS' \
- --value 15ether \
- --rpc-url $HEDERA_RPC_URL \
- --private-key $HEDERA_PRIVATE_KEY
-```
-
-This sends the transaction directly to Hedera (bypassing local simulation), so the HTS precompile at `0x167` is handled natively by the consensus nodes.
-
-**Step 3:** Get the token address:
-
-```bash
-cast abi-decode 'tokenAddress()(address)' $(cast call $CONTRACT_ADDRESS 'tokenAddress()' --rpc-url $HEDERA_RPC_URL)
-```
-
-**Step 4:** Note the block number for fork testing:
-
-```bash
-cast block-number --rpc-url $HEDERA_RPC_URL
-```
-
-
- Save the deployed contract address, token address, and block number! You'll need
- these for your fork tests. The contract must exist at the block you're forking from.
-
-
-We have already deployed this HTS contract on testnet at [https://hashscan.io/testnet/contract/0x22723B710D0A1Bdc83706Dd8085414c0570FaB8b](https://hashscan.io/testnet/contract/0x22723B710D0A1Bdc83706Dd8085414c0570FaB8b) so we will be using this for the remainder of this exercise.
-
----
-
-## Step 3: Write Tests for the Forked Network
-
-Now we'll write tests that interact with the deployed HTS contract on the forked testnet. The key difference from the basic ERC-20 tutorial is the `htsSetup()` call - this activates the HTS emulation layer at address `0x167` so that HTS precompile calls work in the forked environment.
-
-Create a new file `test/HTSForkTest.t.sol`:
-
-
- Make sure to update the `DEPLOYED_HTS_CONTRACT` and `HTS_TOKEN` constants
- below with the values from your deployment.
-
-
-```solidity test/HTSForkTest.t.sol
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.33;
-
-import {Test, console} from "forge-std/Test.sol";
-import {htsSetup} from "hedera-forking/htsSetup.sol";
-import {IHederaTokenService} from "hedera-forking/IHederaTokenService.sol";
-import {IERC20} from "hedera-forking/IERC20.sol";
-import {HTSTokenManager} from "../src/HTSTokenManager.sol";
-
-contract HTSForkTest is Test {
- int32 constant SUCCESS = 22;
-
- // UPDATE THESE with your deployed addresses
- address payable constant DEPLOYED_HTS_CONTRACT =
- payable(0x22723B710D0A1Bdc83706Dd8085414c0570FaB8b);
- address constant HTS_TOKEN =
- 0x000000000000000000000000000000000080d4f4;
-
- HTSTokenManager public htsManager;
- IERC20 public token;
- address public alice;
- address public bob;
-
- function setUp() public {
- // CRITICAL: Initialize the HTS emulation layer FIRST.
- // This deploys the emulation contract at 0x167 so HTS calls work.
- // Without this, all HTS calls revert with InvalidFEOpcode.
- htsSetup();
-
- // Bind to deployed contracts on the fork
- htsManager = HTSTokenManager(DEPLOYED_HTS_CONTRACT);
- token = IERC20(HTS_TOKEN);
-
- // Create and fund test accounts
- alice = makeAddr("alice");
- bob = makeAddr("bob");
- vm.deal(alice, 100 ether);
- vm.deal(bob, 100 ether);
- vm.deal(DEPLOYED_HTS_CONTRACT, 100 ether);
- }
-
- /* =========================
- Token Info Tests
- ========================= */
-
- function test_GetTokenInfo() public {
- (int256 responseCode, IHederaTokenService.TokenInfo memory info) =
- htsManager.getTokenInfoPublic(HTS_TOKEN);
-
- assertEq(responseCode, int256(SUCCESS), "getTokenInfo should succeed");
- assertTrue(bytes(info.token.name).length > 0, "name not empty");
- assertTrue(bytes(info.token.symbol).length > 0, "symbol not empty");
-
- console.log("Token name:", info.token.name);
- console.log("Token symbol:", info.token.symbol);
- }
-
- function test_GetFungibleTokenInfo() public {
- (int256 responseCode, IHederaTokenService.FungibleTokenInfo memory info) =
- htsManager.getFungibleTokenInfoPublic(HTS_TOKEN);
-
- assertEq(responseCode, int256(SUCCESS), "getFungibleTokenInfo should succeed");
- console.log("Fungible token decimals:", info.decimals);
- }
-
- /* =========================
- ERC-20 Interface Tests
- ========================= */
-
- function test_ReadNameAndSymbol() public view {
- string memory name = token.name();
- string memory symbol = token.symbol();
- console.log("Token name:", name);
- console.log("Token symbol:", symbol);
- assertEq(name, "DemoHTS");
- assertEq(symbol, "DHTS");
- }
-
- function test_ReadDecimals() public view {
- uint8 decimals = token.decimals();
- console.log("Token decimals:", decimals);
- assertEq(decimals, 8);
- }
-
- function test_ReadTotalSupply() public view {
- uint256 totalSupply = token.totalSupply();
- console.log("Total supply:", totalSupply);
- assertGe(totalSupply, 0);
- }
-
- function test_ReadTreasuryBalance() public view {
- uint256 balance = token.balanceOf(DEPLOYED_HTS_CONTRACT);
- console.log("Treasury balance:", balance);
- assertGe(balance, 0);
- }
-
- /* =========================
- Transfer Tests
- ========================= */
-
- function test_DealAndTransfer() public {
- // Give alice tokens using Foundry's deal cheatcode
- uint256 amount = 1000;
- deal(HTS_TOKEN, alice, amount);
- assertEq(token.balanceOf(alice), amount);
-
- // Alice transfers to bob via ERC-20 interface
- vm.prank(alice);
- token.transfer(bob, 400);
-
- assertEq(token.balanceOf(alice), 600);
- assertEq(token.balanceOf(bob), 400);
- }
-
- function test_ApproveAndTransferFrom() public {
- deal(HTS_TOKEN, alice, 2000);
-
- vm.prank(alice);
- token.approve(bob, 1000);
-
- vm.prank(bob);
- token.transferFrom(alice, bob, 500);
-
- assertEq(token.balanceOf(alice), 1500);
- assertEq(token.balanceOf(bob), 500);
- }
-
- function test_TransferToMultipleRecipients() public {
- deal(HTS_TOKEN, alice, 5000);
-
- vm.prank(alice);
- token.transfer(bob, 2000);
-
- address charlie = makeAddr("charlie");
- vm.prank(alice);
- token.transfer(charlie, 1000);
-
- assertEq(token.balanceOf(alice), 2000);
- assertEq(token.balanceOf(bob), 2000);
- assertEq(token.balanceOf(charlie), 1000);
- }
-
- /* =========================
- Fork State Verification
- ========================= */
-
- function test_ConnectedToForkedNetwork() public view {
- uint256 blockNumber = block.number;
- console.log("Fork block number:", blockNumber);
- assertGt(blockNumber, 0);
- }
-
- function test_ContractHasBytecode() public view {
- uint256 codeSize;
- address contractAddr = DEPLOYED_HTS_CONTRACT;
- assembly { codeSize := extcodesize(contractAddr) }
- assertGt(codeSize, 0, "HTSTokenManager should have bytecode");
- }
-
- function test_HTSPrecompileHasEmulation() public view {
- uint256 htsCodeSize;
- address hts = address(0x167);
- assembly { htsCodeSize := extcodesize(hts) }
- assertGt(htsCodeSize, 0, "0x167 should have emulation bytecode");
- }
-
- function test_TokenHasBytecode() public view {
- uint256 tokenCodeSize;
- address tokenAddr = HTS_TOKEN;
- assembly { tokenCodeSize := extcodesize(tokenAddr) }
- assertGt(tokenCodeSize, 0, "HTS token should have proxy bytecode");
- }
-}
-```
-
-**Key points about these tests:**
-
-- **`htsSetup()` is critical** - Must be the first call in `setUp()` before any HTS interaction. It deploys the Solidity emulation layer at `0x167` so that HTS precompile calls work.
-- **ERC-20 interface** - HTS tokens expose standard ERC-20 methods (`name`, `symbol`, `decimals`, `balanceOf`, `transfer`, `approve`, `transferFrom`) through the HIP-719 proxy pattern. The emulation layer fetches real data from the Hedera Mirror Node via FFI.
-- **`deal()` for balances** - Foundry's `deal()` cheatcode sets token balances directly, which works with HTS tokens because the emulation layer maps storage slots correctly.
-- **`vm.prank` for impersonation** - Act as any account without their private key.
-- **Fork verification** - Tests confirm the fork is connected, contracts have bytecode, and the HTS emulation layer is active at `0x167`.
-
-
- **Foundry vs. Hardhat approach:** The Hardhat advanced tutorial tests
- `mintToken` and `transferToken` directly through the HTS precompile because
- the Hardhat plugin intercepts at the JSON-RPC level. In Foundry, the emulation
- layer excels at **read operations** and **ERC-20 level interactions**. For
- setting balances in tests, use Foundry's `deal()` cheatcode and standard
- ERC-20 methods (`transfer`, `approve`, `transferFrom`) which work through the
- HIP-719 proxy redirect pattern.
-
-
----
-
-## Step 4: Run Tests on the Forked Network
-
-Run your tests against the forked Hedera testnet:
-
-```bash
-forge test --fork-url $HEDERA_RPC_URL -vvv
-```
-
-Pin to a specific block for reproducible tests:
-
-```bash
-forge test --fork-url $HEDERA_RPC_URL --fork-block-number 33427481 -vvv
-```
-
-You should see output similar to:
-
-```bash
-Ran 13 tests for test/HTSForkTest.t.sol:HTSForkTest
-[PASS] test_ApproveAndTransferFrom() (gas: 1788900)
-[PASS] test_ConnectedToForkedNetwork() (gas: 3768)
-[PASS] test_ContractHasBytecode() (gas: 6379)
-[PASS] test_DealAndTransfer() (gas: 1688928)
-[PASS] test_GetFungibleTokenInfo() (gas: 1413178)
-[PASS] test_GetTokenInfo() (gas: 1403795)
-[PASS] test_HTSPrecompileHasEmulation() (gas: 6422)
-[PASS] test_ReadDecimals() (gas: 1204125)
-[PASS] test_ReadNameAndSymbol() (gas: 1216338)
-[PASS] test_ReadTotalSupply() (gas: 1204165)
-[PASS] test_ReadTreasuryBalance() (gas: 2055646)
-[PASS] test_TokenHasBytecode() (gas: 6425)
-[PASS] test_TransferToMultipleRecipients() (gas: 1853280)
-Suite result: ok. 13 passed; 0 failed; 0 skipped
-```
-
-### Pin to a Specific Block
-
-For reproducible tests, use `--fork-block-number` with a block where your contract exists. If you try to fork at a block before your contract was deployed, `setUp()` will fail because the contract doesn't exist yet at that block.
-
----
-
-## Best Practices for HTS Fork Testing with Foundry
-
-1. **Always call `htsSetup()` first** - It must be the very first call in `setUp()`, before any HTS interaction
-
-2. **Use `ffi = true` only in test profiles** - FFI allows arbitrary shell execution; never enable it in production deployment scripts
-
-3. **Pin your block number** - Use `--fork-block-number` for deterministic, reproducible tests in CI/CD
-
-4. **Use supported methods** - Stick to the [currently supported HTS methods](https://github.com/hashgraph/hedera-forking#hedera-token-service-supported-methods)
-
-5. **Always verify on real network** - Fork testing is for development speed; always test on testnet/mainnet before production
-
----
-
-## Bonus: Real-World SaucerSwap Mainnet Fork Test
-
-The tutorial repository includes a bonus test that demonstrates one of the most powerful use cases for fork testing: interacting with **production DeFi contracts** on Hedera mainnet without spending real HBAR.
-
-The `SaucerSwapForkTest.t.sol` file forks Hedera mainnet and executes a **real token swap** through [SaucerSwap V2](https://www.saucerswap.finance/) - swapping WHBAR for USDC at the current mainnet exchange rate, using real liquidity pools.
-
-### Run the SaucerSwap Tests
-
-```bash
-forge test --match-contract SaucerSwapForkTest \
- --fork-url https://mainnet.hashio.io/api \
- -vvv
-```
-
-
- These tests use **mainnet** (not testnet). No `.env` configuration is needed -
- fork tests don't require a private key because all balances are created locally
- with Foundry cheatcodes.
-
-
-### The Real Swap Test
-
-The headline test (`test_SwapWHBARForUSDCViaSaucerSwap`) executes a real swap through SaucerSwap V2's `exactInput` function:
-
-```solidity
-function test_SwapWHBARForUSDCViaSaucerSwap() public {
- // Give the trader 10 WHBAR using deal() - no real tokens needed
- uint256 whbarAmount = 10 * 1e8;
- deal(WHBAR, trader, whbarAmount);
-
- // Approve the SaucerSwap router
- vm.startPrank(trader);
- whbar.approve(SAUCERSWAP_ROUTER, whbarAmount);
-
- // Encode the swap path: WHBAR -> 0.15% fee tier -> USDC
- bytes memory path = abi.encodePacked(
- WHBAR,
- uint24(1500), // 0.15% fee tier for WHBAR/USDC pool
- USDC
- );
-
- // Execute the swap
- ExactInputParams memory params = ExactInputParams({
- path: path,
- recipient: trader,
- deadline: block.timestamp + 300,
- amountIn: whbarAmount,
- amountOutMinimum: 0
- });
-
- (bool success, bytes memory returnData) = SAUCERSWAP_ROUTER.call(
- abi.encodeWithSignature(
- "exactInput((bytes,address,uint256,uint256,uint256))",
- params
- )
- );
- require(success, "Swap failed");
- uint256 amountOut = abi.decode(returnData, (uint256));
- vm.stopPrank();
-
- // Trader received real USDC at mainnet exchange rate
- assertGt(amountOut, 0, "Should have received USDC from swap");
-}
-```
-
-### How It Works
-
-**Where does the WHBAR come from if the test account doesn't exist on mainnet?**
-
-Foundry's `deal(token, account, amount)` writes directly to the token's storage slots on the forked EVM. It sets the balance for the given account without any real transfer. The account doesn't need to exist on mainnet. Similarly, `vm.deal(account, amount)` sets native HBAR balances locally. Both cheatcodes only affect the fork - mainnet is never touched.
-
-**How does the swap execute against real liquidity?**
-
-The fork is a snapshot of mainnet state. The SaucerSwap V2 Router has real bytecode, and the WHBAR/USDC pool has real liquidity deposited by real LPs. When the test calls `exactInput`, the router reads real pool state (liquidity, tick, price), pulls WHBAR from the trader, swaps through the pool, and sends USDC to the trader - all at the real exchange rate. The entire execution happens locally on the fork.
-
-**Can I impersonate a real mainnet account instead?**
-
-Yes. `vm.prank(realMainnetAddress)` makes the next call appear to come from any address - no private key needed. You could impersonate a whale with millions in HBAR and use their real balances for testing:
-
-```solidity
-address whale = 0x...; // A real mainnet account
-vm.prank(whale);
-whbar.transfer(trader, 50000 * 1e8); // Uses the whale's real balance
-```
-
-**Why does this need `htsSetup()`?**
-
-Both WHBAR and USDC are HTS tokens. When the SaucerSwap router calls `transferFrom` on these tokens during the swap, the call goes through the HIP-719 proxy to `0x167`. Without `htsSetup()`, that address returns `0xfe` and the entire swap reverts.
-
-### Mainnet Addresses
-
-| Contract/Token | Hedera ID | EVM Address | Decimals |
-| -------------- | --------- | ----------- | -------- |
-| SaucerSwap V2 Router | `0.0.3949434` | `0x00000000000000000000000000000000003c437A` | - |
-| WHBAR | `0.0.1456986` | `0x0000000000000000000000000000000000163B5a` | 8 |
-| USDC (Native) | `0.0.456858` | `0x000000000000000000000000000000000006f89a` | 6 |
-
-> **Source:** [SaucerSwap Contract Deployments](https://docs.saucerswap.finance/developerx/contract-deployments)
-
----
-
-## Bonus: Bonzo Finance Mainnet Fork Test (Lending/Borrowing)
-
-The tutorial repository also includes a test that forks Hedera mainnet and interacts with [Bonzo Finance](https://bonzo.finance/) - an Aave V2 fork and the first lending/borrowing protocol on Hedera. The test deposits WHBAR as collateral and borrows USDC against it, using real contracts with ~7M USDC in real liquidity.
-
-### Run the Bonzo Tests
-
-```bash
-forge test --match-contract BonzoForkTest \
- --fork-url https://mainnet.hashio.io/api \
- -vvv
-```
-
-### What It Tests
-
-| Test | What It Does |
-| ---- | ------------ |
-| `test_DepositWHBAR` | Deposits 5000 WHBAR as collateral, receives aWHBAR tokens |
-| `test_DepositWHBARAndBorrowUSDC` | Full flow: deposit collateral, check account data, borrow 10 USDC, verify debt position |
-| `test_ReadBonzoUSDCLiquidity` | Reads real USDC liquidity in Bonzo (~7M USDC) |
-
-### How the Deposit + Borrow Works
-
-```
-deal(WHBAR, depositor, 5000e8) → Create 5000 WHBAR on the fork
-whbar.approve(LENDING_POOL, amount) → Approve LendingPool to pull WHBAR
-LendingPool.deposit(WHBAR, ...) → Deposit as collateral → receive aWHBAR
-LendingPool.getUserAccountData(...) → Check collateral, LTV (62.72%), borrow capacity
-LendingPool.borrow(USDC, 10e6, 2, ..) → Borrow 10 USDC at variable rate
- → Receive USDC + variable debt token minted
-```
-
-The LendingPool uses Bonzo's real oracle pricing to calculate collateral value, LTV ratios, and health factors - all against production state on the fork.
-
-**Why this matters:** If you're building on top of Bonzo (or any Aave V2 fork on Hedera), fork testing lets you test your integration against real protocol state, verify borrowing logic against real oracle prices, and simulate liquidation scenarios - without risking real funds.
-
-### Bonzo Mainnet Addresses
-
-| Contract | Address |
-| -------- | ------- |
-| LendingPool | `0x236897c518996163E7b313aD21D1C9fCC7BA1afc` |
-| aWHBAR | `0x6e96a607F2F5657b39bf58293d1A006f9415aF32` |
-| Variable Debt USDC | `0x8a90C2f80Fc266e204cb37387c69EA2ed42A3cc1` |
-
-> **Source:** [Bonzo Lend Contracts](https://docs.bonzo.finance/hub/developer/bonzo-lend/lend-contracts)
-
----
-
-## Understanding HTS Fork Testing with Foundry
-
-### Why Standard Fork Testing Breaks on Hedera
-
-On standard EVM chains, every contract is on-chain bytecode. When you fork and call any contract, the fork fetches its bytecode and executes it locally. Hedera's system contracts (HTS at `0x167`, Exchange Rate at `0x168`, PRNG at `0x169`) are native services implemented in the consensus node software - they have no EVM bytecode. When your fork tries to fetch code at `0x167`, the JSON-RPC relay returns `0xfe` (the INVALID opcode), and your test crashes with `InvalidFEOpcode`.
-
-### How `htsSetup()` Fixes It
-
-The `htsSetup()` function from the `hedera-forking` library:
-
-1. Deploys the `HtsSystemContractJson` emulation contract at `0x167` using `vm.etch`
-2. Creates a `MirrorNodeFFI` instance that queries the Hedera Mirror Node via curl
-3. Calls `vm.allowCheatcodes(0x167)` so the emulation can use `vm.store`, `vm.ffi`, and `vm.parseJson`
-
-After `htsSetup()`, HTS calls work because they hit a Solidity contract that fetches real token data from the Mirror Node.
-
-### How the HIP-719 Proxy Pattern Works
-
-Every HTS token address on Hedera contains identical proxy bytecode (defined by [HIP-719](https://hips.hedera.com/hip/hip-719)). When you call `token.balanceOf()`, the proxy delegates the call to `0x167` via `redirectForToken`. The emulation contract at `0x167` receives the call, fetches the real balance from the Mirror Node via FFI, and returns it.
-
-### Foundry vs. Hardhat Comparison for HTS Fork Testing
-
-| Aspect | Foundry | Hardhat |
-| ------ | ------- | ------- |
-| Emulation approach | Proactive: deploys Solidity emulation via `htsSetup()` | Reactive: worker thread intercepts JSON-RPC calls |
-| Data fetch mechanism | FFI + curl to Mirror Node | Node.js fetch to Mirror Node |
-| Required config | `ffi = true` in `foundry.toml` | `chainId` + `workerPort` in hardhat config |
-| HTS read operations | Fully supported via emulation | Fully supported via interception |
-| HTS write operations | Use `deal()` + ERC-20 methods | Direct precompile calls work |
-| Test language | Solidity | TypeScript |
-
-### Local vs. Remote State
-
-| Action | Affects Local Fork | Affects Testnet |
-| -------------------------- | ------------------ | --------------- |
-| Read balances | ✅ (cached) | ❌ (read-only) |
-| Transfer tokens (ERC-20) | ✅ | ❌ |
-| Query token info (HTS) | ✅ | ❌ |
-| `deal()` set balances | ✅ | ❌ |
-| Impersonate accounts | ✅ | ❌ |
-| Changes persist after test | ❌ (reset) | N/A |
-
----
-
-## Further Learning & Next Steps
-
-1. [**Forking Hedera Network for Local Testing**](/hedera/core-concepts/smart-contracts/forking-hedera-network-for-local-testing)\
- Deep dive into how Hedera forking works under the hood
-
-2. [**How to Fork Hedera with Foundry (Part 1)**](/hedera/tutorials/smart-contracts/foundry/how-to-fork-the-hedera-network-with-foundry-basic-erc20)\
- Start with basic ERC-20 fork testing
-
-3. [**How to Fork Hedera with Hardhat - Advanced HTS**](/hedera/tutorials/smart-contracts/how-to-fork-the-hedera-network-with-hardhat-advanced-hts)\
- Compare the Hardhat approach to HTS fork testing
-
-4. [**hedera-forking Repository**](https://github.com/hashgraph/hedera-forking)\
- Explore examples and documentation
-
-5. [**Hiero Contracts Repository**](https://github.com/hiero-ledger/hiero-contracts)\
- Explore HTS System Contracts interfaces
-
-
-
- [GitHub](https://github.com/kpachhai) |
- [LinkedIn](https://www.linkedin.com/in/kiranpachhai/)
-
-
diff --git a/images/networks/release-notes/services/0.72_performance-measurement-results.png b/images/networks/release-notes/services/0.72_performance-measurement-results.png
deleted file mode 100644
index 89e0feeea40fb81c1a5258ac52af2351e8bc24dc..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1285490
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