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

# Interact with Contracts

> Read and write smart contract data and handle events using Web3 libraries

export const Card = ({imgUrl, title, description, href, horizontal = false, newTab = false}) => {
  const [isHovered, setIsHovered] = useState(false);
  const handleClick = e => {
    e.preventDefault();
    if (newTab) {
      window.open(href, '_blank', 'noopener,noreferrer');
    } else {
      window.location.href = href;
    }
  };
  return <div className={`not-prose relative my-2 p-[1px] rounded-xl transition-all duration-300 ${isHovered ? 'bg-gradient-to-r from-[#FF4E00] to-[#874AE3]' : 'bg-gray-200'}`} onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)}>
      <a href={href} onClick={handleClick} className={`not-prose flex ${horizontal ? 'flex-row' : 'flex-col'} font-normal h-full bg-white overflow-hidden w-full cursor-pointer rounded-[11px] no-underline`}>
        {imgUrl && <div className={`relative overflow-hidden flex-shrink-0 ${horizontal ? 'w-[30%] rounded-l-[11px]' : 'w-full'}`} onClick={e => e.stopPropagation()}>
            <img src={imgUrl} alt={title} className="w-full h-full object-cover pointer-events-none select-none" draggable="false" />
            <div className="absolute inset-0 pointer-events-none" />
          </div>}
        <div className={`flex-grow px-6 py-5 ${horizontal ? 'w-[70%]' : 'w-full'} flex flex-col ${horizontal && imgUrl ? 'justify-center' : 'justify-start'}`}>
          {title && <h2 className="font-semibold text-base text-gray-800 m-0">{title}</h2>}
          {description && <div className={`font-normal text-gray-500 re leading-6 ${horizontal || !imgUrl ? 'mt-0' : 'mt-1'}`}>
              <p className="m-0 text-xs">{description}</p>
            </div>}
        </div>
      </a>
    </div>;
};

Read data from smart contracts and execute write operations using Para's wallet infrastructure.

## Prerequisites

You need Web3 libraries configured with Para authentication.

<Card title="Setup Web3 Libraries" description="Configure Ethers.js, Viem, or Wagmi with Para before proceeding" href="/v2/react/guides/web3-operations/evm/setup-libraries" />

<Tabs>
  <Tab title="Ethers.js">
    ## Read Contract Data

    ```typescript theme={null}
    import { ethers } from "ethers";

    const CONTRACT_ABI = [
      "function balanceOf(address owner) view returns (uint256)",
      "function totalSupply() view returns (uint256)",
      "function name() view returns (string)",
      "function symbol() view returns (string)",
      "function decimals() view returns (uint8)"
    ];

    async function readContractData(
      provider: ethers.Provider,
      contractAddress: string,
      userAddress: string
    ) {
      const contract = new ethers.Contract(
        contractAddress,
        CONTRACT_ABI,
        provider
      );

      const [balance, totalSupply, name, symbol, decimals] = await Promise.all([
        contract.balanceOf(userAddress),
        contract.totalSupply(),
        contract.name(),
        contract.symbol(),
        contract.decimals()
      ]);

      return {
        balance: ethers.formatUnits(balance, decimals),
        totalSupply: ethers.formatUnits(totalSupply, decimals),
        name,
        symbol,
        decimals
      };
    }
    ```

    ## Write Contract Data

    ```typescript theme={null}
    const STAKING_ABI = [
      "function stake(uint256 amount) payable",
      "function unstake(uint256 amount)",
      "function getStakedBalance(address user) view returns (uint256)",
      "event Staked(address indexed user, uint256 amount)",
      "event Unstaked(address indexed user, uint256 amount)"
    ];

    async function stakeTokens(
      signer: any,
      contractAddress: string,
      amount: string,
      decimals: number
    ) {
      const contract = new ethers.Contract(contractAddress, STAKING_ABI, signer);
      const parsedAmount = ethers.parseUnits(amount, decimals);

      const tx = await contract.stake(parsedAmount);
      await tx.wait();

      const newBalance = await contract.getStakedBalance(await signer.getAddress());

      return {
        hash: tx.hash,
        stakedAmount: ethers.formatUnits(newBalance, decimals)
      };
    }
    ```
  </Tab>

  <Tab title="Viem">
    ## Read Contract Data

    Read operations don't need mutation helpers -- use the Viem `publicClient` directly:

    ```typescript theme={null}
    import { createPublicClient, http, formatUnits } from "viem";
    import { sepolia } from "viem/chains";

    const CONTRACT_ABI = [
      {
        name: "balanceOf",
        type: "function",
        stateMutability: "view",
        inputs: [{ name: "owner", type: "address" }],
        outputs: [{ type: "uint256" }],
      },
      {
        name: "totalSupply",
        type: "function",
        stateMutability: "view",
        inputs: [],
        outputs: [{ type: "uint256" }],
      },
      {
        name: "name",
        type: "function",
        stateMutability: "view",
        inputs: [],
        outputs: [{ type: "string" }],
      },
      {
        name: "symbol",
        type: "function",
        stateMutability: "view",
        inputs: [],
        outputs: [{ type: "string" }],
      },
      {
        name: "decimals",
        type: "function",
        stateMutability: "view",
        inputs: [],
        outputs: [{ type: "uint8" }],
      },
    ] as const;

    const publicClient = createPublicClient({
      chain: sepolia,
      transport: http(),
    });

    async function readContractData(
      contractAddress: `0x${string}`,
      userAddress: `0x${string}`
    ) {
      const results = await publicClient.multicall({
        contracts: [
          {
            address: contractAddress,
            abi: CONTRACT_ABI,
            functionName: "balanceOf",
            args: [userAddress],
          },
          {
            address: contractAddress,
            abi: CONTRACT_ABI,
            functionName: "totalSupply",
          },
          {
            address: contractAddress,
            abi: CONTRACT_ABI,
            functionName: "name",
          },
          {
            address: contractAddress,
            abi: CONTRACT_ABI,
            functionName: "symbol",
          },
          {
            address: contractAddress,
            abi: CONTRACT_ABI,
            functionName: "decimals",
          },
        ],
      });

      const [balance, totalSupply, name, symbol, decimals] = results.map(
        (r) => r.result
      );

      return {
        balance: formatUnits(balance, decimals),
        totalSupply: formatUnits(totalSupply, decimals),
        name,
        symbol,
        decimals,
      };
    }
    ```

    ## Write Contract Data

    ```tsx theme={null}
    import { useParaViemClient, useParaViemWriteContract } from "@getpara/react-sdk";
    import { parseUnits, http } from "viem";
    import { sepolia } from "viem/chains";

    const STAKING_ABI = [
      {
        name: "stake",
        type: "function",
        stateMutability: "payable",
        inputs: [{ name: "amount", type: "uint256" }],
        outputs: [],
      },
    ] as const;

    function StakeTokens({
      contractAddress,
      decimals = 18,
    }: {
      contractAddress: `0x${string}`;
      decimals?: number;
    }) {
      const amount = "100";

      const { viemClient } = useParaViemClient({
        walletClientConfig: { chain: sepolia, transport: http() },
      });

      const {
        writeContractAsync,
        isPending,
        data: hash,
      } = useParaViemWriteContract(viemClient);

      return (
        <div>
          <button
            onClick={() =>
              writeContract({
                address: contractAddress,
                abi: STAKING_ABI,
                functionName: "stake",
                args: [parseUnits(amount, decimals)],
              })
            }
            disabled={isPending}
          >
            {isPending ? "Staking..." : `Stake ${amount} Tokens`}
          </button>
          {hash && <p>Transaction: {hash}</p>}
        </div>
      );
    }
    ```
  </Tab>

  <Tab title="Wagmi">
    ## Read Contract Data

    ```typescript theme={null}
    import { useReadContracts } from "@getpara/react-sdk/wagmi";
    import { formatUnits } from "viem";

    const CONTRACT_ABI = [
      {
        name: "balanceOf",
        type: "function",
        stateMutability: "view",
        inputs: [{ name: "owner", type: "address" }],
        outputs: [{ type: "uint256" }]
      },
      {
        name: "totalSupply",
        type: "function",
        stateMutability: "view",
        inputs: [],
        outputs: [{ type: "uint256" }]
      },
      {
        name: "name",
        type: "function",
        stateMutability: "view",
        inputs: [],
        outputs: [{ type: "string" }]
      },
      {
        name: "symbol",
        type: "function",
        stateMutability: "view",
        inputs: [],
        outputs: [{ type: "string" }]
      },
      {
        name: "decimals",
        type: "function",
        stateMutability: "view",
        inputs: [],
        outputs: [{ type: "uint8" }]
      }
    ] as const;

    function ContractData({
      contractAddress,
      userAddress
    }: {
      contractAddress: `0x${string}`;
      userAddress: `0x${string}`;
    }) {
      const { data, isPending } = useReadContracts({
        contracts: [
          {
            address: contractAddress,
            abi: CONTRACT_ABI,
            functionName: "balanceOf",
            args: [userAddress]
          },
          {
            address: contractAddress,
            abi: CONTRACT_ABI,
            functionName: "totalSupply"
          },
          {
            address: contractAddress,
            abi: CONTRACT_ABI,
            functionName: "name"
          },
          {
            address: contractAddress,
            abi: CONTRACT_ABI,
            functionName: "symbol"
          },
          {
            address: contractAddress,
            abi: CONTRACT_ABI,
            functionName: "decimals"
          }
        ]
      });

      if (isPending) return <div>Loading...</div>;

      const [balance, totalSupply, name, symbol, decimals] =
        data?.map(d => d.result) || [];

      return (
        <div>
          <p>Token: {name} ({symbol})</p>
          <p>Balance: {formatUnits(balance || 0n, decimals || 18)}</p>
          <p>Total Supply: {formatUnits(totalSupply || 0n, decimals || 18)}</p>
        </div>
      );
    }
    ```

    ## Write Contract Data

    ```typescript theme={null}
    import { useWriteContract, useWaitForTransactionReceipt, useReadContract } from "@getpara/react-sdk/wagmi";
    import { parseUnits, formatUnits } from "viem";

    const STAKING_ABI = [
      {
        name: "stake",
        type: "function",
        stateMutability: "payable",
        inputs: [{ name: "amount", type: "uint256" }],
        outputs: []
      },
      {
        name: "getStakedBalance",
        type: "function",
        stateMutability: "view",
        inputs: [{ name: "user", type: "address" }],
        outputs: [{ type: "uint256" }]
      }
    ] as const;

    function StakeTokens({
      contractAddress,
      userAddress,
      decimals = 18
    }: {
      contractAddress: `0x${string}`;
      userAddress: `0x${string}`;
      decimals?: number;
    }) {
      const amount = "100";

      const { data: hash, isPending, writeContract } = useWriteContract();

      const { isPending: isConfirming } = useWaitForTransactionReceipt({ hash });

      const { data: stakedBalance } = useReadContract({
        address: contractAddress,
        abi: STAKING_ABI,
        functionName: "getStakedBalance",
        args: [userAddress]
      });

      return (
        <div>
          <p>Staked: {formatUnits(stakedBalance || 0n, decimals)}</p>
          <button
            onClick={() => writeContract({
              address: contractAddress,
              abi: STAKING_ABI,
              functionName: "stake",
              args: [parseUnits(amount, decimals)]
            })}
            disabled={isPending || isConfirming}
          >
            {isPending ? "Staking..." : `Stake ${amount} Tokens`}
          </button>
          {hash && <p>Transaction: {hash}</p>}
        </div>
      );
    }
    ```
  </Tab>
</Tabs>

## Next Steps

<CardGroup cols={3}>
  <Card title="Watch Events" description="Subscribe to and filter contract events" href="/v2/react/guides/web3-operations/evm/watch-events" icon="eye" />

  <Card title="Manage Allowances" description="Handle token approvals and allowances" href="/v2/react/guides/web3-operations/evm/manage-allowances" icon="shield-check" />

  <Card title="Get Transaction Receipt" description="Parse transaction logs and events" href="/v2/react/guides/web3-operations/evm/get-transaction-receipt" icon="receipt" />
</CardGroup>
