Asset Hub Integration

Asset Hub is the primary parachain for token management on Kusama/Polkadot. This guide covers integrating ZK applications with Asset Hub.

What is Asset Hub?

Asset Hub (formerly Statemint/Statemine) is a system parachain that provides:

  • Fungible Tokens: Create and manage ERC20-like assets
  • NFTs: Non-fungible token support
  • Low Fees: Cheaper transactions than the relay chain
  • EVM Compatibility: Smart contract support via Frontier

Network Configuration

ParameterValue
Network NamePaseo Asset Hub
Chain ID420420422
RPC URLhttps://testnet-passet-hub-eth-rpc.polkadot.io
Block Explorerhttps://blockscout-passet-hub.parity-testnet.parity.io/
Faucethttps://faucet.polkadot.io/?parachain=1111
Native TokenPAS

Kusama Mainnet

ParameterValue
Network NameKusama Asset Hub
Chain ID(TBD)
RPC URLhttps://kusama-asset-hub-rpc.polkadot.io
Block Explorerhttps://blockscout.kusama.network/
Native TokenKSM

Getting PAS Tokens

1. Create a Wallet

cast wallet new

Output:

Successfully created new keypair.
Address:     0x7E68B2bf528c96e9b9D140211391d4e5FBce033e
Private key: 0xf07706918ef3fac8d5c1856010f470fecf15dca5b30a1ad1e5f8b3c022d8e997

2. Fund from Faucet

Visit: https://faucet.polkadot.io/?parachain=1111

Enter your address and request test tokens.

3. Check Balance

cast balance 0x7E68B2bf528c96e9b9D140211391d4e5FBce033e \
  --rpc-url https://testnet-passet-hub-eth-rpc.polkadot.io

Deploying Contracts

Using Remix

  1. Visit Remix for Polkadot
  2. Connect to Paseo Asset Hub network
  3. Write/paste your contract
  4. Deploy using your wallet

Using Foundry

# Create project
forge init my-zk-project
cd my-zk-project

# Add dependencies
forge install OpenZeppelin/openzeppelin-contracts

# Set RPC
export ETH_RPC_URL=https://testnet-passet-hub-eth-rpc.polkadot.io
export PRIVATE_KEY=your_private_key

# Deploy
forge create src/MyContract.sol:MyContract \
  --rpc-url $ETH_RPC_URL \
  --private-key $PRIVATE_KEY

Using Hardhat

// hardhat.config.js
module.exports = {
  networks: {
    paseo: {
      url: "https://testnet-passet-hub-eth-rpc.polkadot.io",
      accounts: [process.env.PRIVATE_KEY]
    }
  }
};

// Deploy script
async function main() {
  const Contract = await ethers.getContractFactory("MyContract");
  const contract = await Contract.deploy();
  await contract.waitForDeployment();
  console.log("Deployed to:", await contract.getAddress());
}

Example: ZK Verifier Deployment

1. Generate Verifier with snarkJS

# Export Solidity verifier
snarkjs zkey export verifierkey circuit_final.zkey verifier.sol

# Or export Groth16 verifier
snarkjs zkey export solidityverifier circuit_final.zkey verifier.sol

2. Deploy Verifier

# Deploy to Asset Hub
forge create src/verifier.sol:Groth16Verifier \
  --rpc-url https://testnet-passet-hub-eth-rpc.polkadot.io \
  --private-key $PRIVATE_KEY

3. Deploy Application Contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "./verifier.sol";

contract PolkadotDemo {
    IGroth16Verifier public immutable verifier;

    constructor() {
        verifier = IGroth16Verifier(0x00D124b363e7F278aEFF220398254EdE169D307c);
    }

    event DidSomething(bool myresult);

    function dosomething(
        uint256[2] calldata _pA,
        uint256[2][2] calldata _pB,
        uint256[2] calldata _pC,
        uint256[3] calldata _pubSignals
    ) external {
        require(
            verifier.verifyProof(_pA, _pB, _pC, _pubSignals),
            "Invalid proof"
        );
        emit DidSomething(true);
    }
}

Deploy:

forge create src/main.sol:PolkadotDemo \
  --rpc-url https://testnet-passet-hub-eth-rpc.polkadot.io \
  --private-key $PRIVATE_KEY

Testing Contracts

Using cast

# Call view function
cast call <CONTRACT_ADDRESS> \
  "myFunction(uint256):(uint256)" \
  "123" \
  --rpc-url https://testnet-passet-hub-eth-rpc.polkadot.io

# Send transaction
cast send <CONTRACT_ADDRESS> \
  "myFunction(uint256)" \
  "123" \
  --rpc-url https://testnet-passet-hub-eth-rpc.polkadot.io \
  --private-key $PRIVATE_KEY

Using Foundry Tests

// test/MyContract.t.sol
pragma solidity ^0.8.28;

import "forge-std/Test.sol";
import "../src/MyContract.sol";

contract MyContractTest is Test {
    MyContract public contract;

    function setUp() public {
        contract = new MyContract();
    }

    function testMyFunction() public {
        uint256 result = contract.myFunction(123);
        assertEq(result, 456);
    }
}

Run tests:

forge test

Asset Hub Specific Features

ERC20 Token Deployment

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {
    constructor() ERC20("My Token", "MTK") {
        _mint(msg.sender, 1000000 * 10 ** decimals());
    }
}

Cross-Chain Messages (XCM)

Asset Hub supports XCM for cross-parachain communication:

// Example: Send tokens to another parachain
function sendToParachain(
    uint32 paraId,
    address recipient,
    uint256 amount
) external {
    // XCM integration would go here
    // This is a simplified example
}

Gas Costs

OperationGas CostPAS Cost (approx)
Transfer21,0000.001
ERC20 Transfer65,0000.003
Contract Deployment500,000+0.02+
ZK Verification100,000-300,0000.005-0.015

Best Practices

1. Use Testnet First

Always test on Paseo before deploying to mainnet.

2. Verify Contracts

Use Blockscout for source verification:

forge verify-contract \
  <CONTRACT_ADDRESS> \
  src/MyContract.sol:MyContract \
  --chain-id 420420422 \
  --etherscan-api-key <KEY>

3. Monitor Gas

# Check gas price
cast gas-price --rpc-url https://testnet-passet-hub-eth-rpc.polkadot.io

4. Handle Reverts

try contract.myFunction(value) returns (uint256 result) {
    // Success
} catch Error(string memory reason) {
    // Handle revert message
} catch (bytes memory) {
    // Handle low-level error
}

Troubleshooting

"Insufficient funds"

Ensure your wallet has PAS tokens for gas.

"Contract creation failed"

Check:

  • Constructor arguments are correct
  • Gas limit is sufficient
  • No revert in constructor

"Transaction reverted"

Use cast logs to see events and debug:

cast logs --rpc-url https://testnet-passet-hub-eth-rpc.polkadot.io \
  --from-block latest

Resources


Previous: Poseidon Hash | Next: Shielded Pools