Interact with your contract

Interact with your deployed contract using a script

Choose between using testnet or a local node.

Script setup

Choose between using Foundry, Hardhat with viem, or Hardhat with ethers.

  1. Create a new file in the script folder called InteractQuickstartToken.s.sol.
  2. Copy and paste the script below into InteractQuickstartToken.s.sol. This script will transfer 10 tokens to the recipient address and log some metadata for the token.
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.13;
    
    import {console2} from "forge-std/console2.sol";
    import {Script} from "forge-std/Script.sol";
    import {QuickstartToken} from "../src/QuickstartToken.sol";
    
    contract InteractQuickstartTokenScript is Script {
        uint256 internal constant TRANSFER_AMOUNT = 10 * 10 ** 18;
        address internal constant DEFAULT_RECIPIENT = 0x70997970C51812dc3A010C7d01b50e0d17dc79C8;
    
        function run() public {
            address contractAddress = vm.envAddress("CONTRACT_ADDRESS");
            address recipientAddress = vm.envOr("RECIPIENT_ADDRESS", DEFAULT_RECIPIENT);
            QuickstartToken quickstartToken = QuickstartToken(contractAddress);
            uint256 recipientBalanceBefore = quickstartToken.balanceOf(recipientAddress);
    
            vm.startBroadcast();
            quickstartToken.transfer(recipientAddress, TRANSFER_AMOUNT);
            vm.stopBroadcast();
    
            console2.log("Token name:", quickstartToken.name());
            console2.log("Token symbol:", quickstartToken.symbol());
            console2.log("Total supply:", quickstartToken.totalSupply() / 10 ** 18);
            console2.log("Transferred amount:", TRANSFER_AMOUNT / 10 ** 18);
            console2.log(
                "Recipient balance increase:", (quickstartToken.balanceOf(recipientAddress) - recipientBalanceBefore) / 10 ** 18
            );
            console2.log("Recipient balance:", quickstartToken.balanceOf(recipientAddress) / 10 ** 18);
        }
    }
    
  3. Set your deployed contract address and recipient address.
    export CONTRACT_ADDRESS="0x..."
    export RECIPIENT_ADDRESS="0x..."
    
  4. Run the interaction script.
    forge script script/InteractQuickstartToken.s.sol --rpc-url https://zksync-os-testnet-alpha.zksync.dev --skip-simulation --broadcast --private-key $TESTNET_PRIVATE_KEY
    

You should see the token name, symbol, transfer amount, and recipient balance in the logs.

  1. Create a new file in the scripts folder called interact.ts.
  2. Copy and paste the script below into scripts/interact.ts. This script will transfer 10 tokens to the recipient address and log some metadata for the token.
    import { network } from 'hardhat';
    import { defineChain, formatUnits, type Abi, type Address } from 'viem';
    
    const CONTRACT_ADDRESS: Address = '0x...';
    const RECIPIENT_ADDRESS: Address = '0x...';
    const TRANSFER_AMOUNT = 10n * 10n ** 18n;
    
    const zksyncOS = defineChain({
      id: 8022833,
      name: 'ZKsync OS',
      network: 'zksyncOS',
      nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
      rpcUrls: { default: { http: ['https://zksync-os-testnet-alpha.zksync.dev'] } },
    });
    
    const { viem } = await network.connect('zksyncOS');
    const publicClient = await viem.getPublicClient({ chain: zksyncOS });
    const [walletClient] = await viem.getWalletClients({ chain: zksyncOS });
    if (!walletClient) throw new Error('No wallet client. Set TESTNET_PRIVATE_KEY in the keystore.');
    
    const contract = await viem.getContractAt('QuickstartToken', CONTRACT_ADDRESS, {
      client: { public: publicClient, wallet: walletClient },
    });
    
    const [tokenName, tokenSymbol, totalSupply] = await Promise.all([
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'name',
      }),
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'symbol',
      }),
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'totalSupply',
      }),
    ]);
    
    const hash = await walletClient.writeContract({
      address: CONTRACT_ADDRESS,
      abi: contract.abi as Abi,
      functionName: 'transfer',
      args: [RECIPIENT_ADDRESS, TRANSFER_AMOUNT],
      account: walletClient.account,
    });
    await publicClient.waitForTransactionReceipt({ hash });
    
    const [senderBalance, recipientBalance] = await Promise.all([
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'balanceOf',
        args: [walletClient.account.address],
      }),
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'balanceOf',
        args: [RECIPIENT_ADDRESS],
      }),
    ]);
    
    console.log('Token name:', tokenName);
    console.log('Token symbol:', tokenSymbol);
    console.log('Total supply:', formatUnits(totalSupply as bigint, 18));
    console.log('Transferred amount:', formatUnits(TRANSFER_AMOUNT, 18));
    console.log('Recipient address:', RECIPIENT_ADDRESS);
    console.log('Recipient balance:', formatUnits(recipientBalance as bigint, 18));
    console.log('Sender balance:', formatUnits(senderBalance as bigint, 18));
    
  3. Set your deployed contract address and recipient address at the top of the script file.
  4. Run the script.
    npx hardhat run scripts/interact.ts
    

You should see the token name, symbol, transfer amount, recipient balance, and sender balance in the logs.

  1. Create a new file in the scripts folder called interact.ts.
  2. Copy and paste the script below into scripts/interact.ts. This script will transfer 10 tokens to the recipient address and log some metadata for the token.
    import { network } from 'hardhat';
    import { formatUnits, parseUnits } from 'ethers';
    
    const CONTRACT_ADDRESS = '0x...';
    const RECIPIENT_ADDRESS = '0x...';
    const TRANSFER_AMOUNT = parseUnits('10', 18);
    
    const { ethers } = await network.connect({
      network: 'zksyncOS',
      chainType: 'generic',
    });
    
    const [sender] = await ethers.getSigners();
    
    const contract = await ethers.getContractAt('QuickstartToken', CONTRACT_ADDRESS, sender);
    
    const tokenName = await contract.name();
    const tokenSymbol = await contract.symbol();
    const totalSupply = await contract.totalSupply();
    const transferTx = await contract.transfer(RECIPIENT_ADDRESS, TRANSFER_AMOUNT);
    await transferTx.wait();
    const senderBalance = await contract.balanceOf(sender.address);
    const recipientBalance = await contract.balanceOf(RECIPIENT_ADDRESS);
    
    console.log('Token name:', tokenName);
    console.log('Token symbol:', tokenSymbol);
    console.log('Total supply:', formatUnits(totalSupply, 18));
    console.log('Transferred amount:', formatUnits(TRANSFER_AMOUNT, 18));
    console.log('Recipient address:', RECIPIENT_ADDRESS);
    console.log('Recipient balance:', formatUnits(recipientBalance, 18));
    console.log('Sender balance:', formatUnits(senderBalance, 18));
    
  3. Set your deployed contract address and recipient address at the top of the script file.
  4. Run the script.
    npx hardhat run scripts/interact.ts
    

You should see the token name, symbol, transfer amount, recipient balance, and sender balance in the logs.

Script setup

Choose between using Foundry, Hardhat with viem, or Hardhat with ethers.

  1. Create a new file in the script folder called InteractQuickstartToken.s.sol.
  2. Copy and paste the script below into InteractQuickstartToken.s.sol. This script will transfer 10 tokens to the recipient address and log some metadata for the token.
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.13;
    
    import {console2} from "forge-std/console2.sol";
    import {Script} from "forge-std/Script.sol";
    import {QuickstartToken} from "../src/QuickstartToken.sol";
    
    contract InteractQuickstartTokenScript is Script {
        uint256 internal constant TRANSFER_AMOUNT = 10 * 10 ** 18;
        address internal constant DEFAULT_RECIPIENT = 0x70997970C51812dc3A010C7d01b50e0d17dc79C8;
    
        function run() public {
            address contractAddress = vm.envAddress("CONTRACT_ADDRESS");
            address recipientAddress = vm.envOr("RECIPIENT_ADDRESS", DEFAULT_RECIPIENT);
            QuickstartToken quickstartToken = QuickstartToken(contractAddress);
            uint256 recipientBalanceBefore = quickstartToken.balanceOf(recipientAddress);
    
            vm.startBroadcast();
            quickstartToken.transfer(recipientAddress, TRANSFER_AMOUNT);
            vm.stopBroadcast();
    
            console2.log("Token name:", quickstartToken.name());
            console2.log("Token symbol:", quickstartToken.symbol());
            console2.log("Total supply:", quickstartToken.totalSupply() / 10 ** 18);
            console2.log("Transferred amount:", TRANSFER_AMOUNT / 10 ** 18);
            console2.log(
                "Recipient balance increase:", (quickstartToken.balanceOf(recipientAddress) - recipientBalanceBefore) / 10 ** 18
            );
            console2.log("Recipient balance:", quickstartToken.balanceOf(recipientAddress) / 10 ** 18);
        }
    }
    
  3. Set your deployed contract address.
    export CONTRACT_ADDRESS="0x..."
    

    You may also change the recipient address. This example uses another anvil rich wallet as the recipient by default.
  4. Run the interaction script.
    forge script script/InteractQuickstartToken.s.sol --rpc-url http://localhost:8545 --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
    

You should see the token name, symbol, transfer amount, and recipient balance in the logs.

  1. Create a new file in the scripts folder called interact.ts.
  2. Copy and paste the script below into scripts/interact.ts. This script will transfer 10 tokens to the recipient address and log some metadata for the token.
    import { network } from 'hardhat';
    import { formatUnits, type Abi, type Address } from 'viem';
    
    const CONTRACT_ADDRESS: Address = (process.env.CONTRACT_ADDRESS as Address) || '0x...';
    const TRANSFER_AMOUNT = 10n * 10n ** 18n;
    const DEFAULT_RECIPIENT: Address = '0x70997970C51812dc3A010C7d01b50e0d17dc79C8';
    const recipientAddress = (process.env.RECIPIENT_ADDRESS as Address | undefined) || DEFAULT_RECIPIENT;
    
    const { viem } = await network.connect('anvil');
    const publicClient = await viem.getPublicClient();
    const [walletClient] = await viem.getWalletClients();
    if (!walletClient) throw new Error('No wallet client configured for the local node.');
    
    const contract = await viem.getContractAt('QuickstartToken', CONTRACT_ADDRESS, {
      client: { public: publicClient, wallet: walletClient },
    });
    
    const [tokenName, tokenSymbol, totalSupply, recipientBalanceBefore] = await Promise.all([
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'name',
      }),
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'symbol',
      }),
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'totalSupply',
      }),
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'balanceOf',
        args: [recipientAddress],
      }),
    ]);
    
    const hash = await walletClient.writeContract({
      address: CONTRACT_ADDRESS,
      abi: contract.abi as Abi,
      functionName: 'transfer',
      args: [recipientAddress, TRANSFER_AMOUNT],
      account: walletClient.account,
    });
    await publicClient.waitForTransactionReceipt({ hash });
    
    const [senderBalance, recipientBalance] = await Promise.all([
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'balanceOf',
        args: [walletClient.account.address],
      }),
      publicClient.readContract({
        address: CONTRACT_ADDRESS,
        abi: contract.abi as Abi,
        functionName: 'balanceOf',
        args: [recipientAddress],
      }),
    ]);
    const recipientBalanceIncrease = (recipientBalance as bigint) - (recipientBalanceBefore as bigint);
    
    console.log('Token name:', tokenName);
    console.log('Token symbol:', tokenSymbol);
    console.log('Total supply:', formatUnits(totalSupply as bigint, 18));
    console.log('Transferred amount:', formatUnits(TRANSFER_AMOUNT, 18));
    console.log('Recipient address:', recipientAddress);
    console.log('Recipient balance increase:', formatUnits(recipientBalanceIncrease, 18));
    console.log('Recipient balance:', formatUnits(recipientBalance as bigint, 18));
    console.log('Sender balance:', formatUnits(senderBalance as bigint, 18));
    
  3. Set your deployed contract address at the top of the script file.
    You may also change the recipient address. This example uses another anvil rich wallet as the recipient by default.
  4. Run the script.
    npx hardhat run scripts/interact.ts
    

You should see the token name, symbol, transfer amount, recipient balance, and sender balance in the logs.

  1. Create a new file in the scripts folder called interact.ts.
  2. Copy and paste the script below into scripts/interact.ts. This script will transfer 10 tokens to the recipient address and log some metadata for the token.
    import { network } from 'hardhat';
    import { formatUnits, parseUnits } from 'ethers';
    
    const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS || '0x...';
    const TRANSFER_AMOUNT = parseUnits('10', 18);
    const DEFAULT_RECIPIENT = '0x70997970C51812dc3A010C7d01b50e0d17dc79C8';
    const recipientAddress = process.env.RECIPIENT_ADDRESS || DEFAULT_RECIPIENT;
    
    const { ethers } = await network.connect('anvil');
    
    const [sender] = await ethers.getSigners();
    
    const contract = await ethers.getContractAt('QuickstartToken', CONTRACT_ADDRESS, sender);
    
    const tokenName = await contract.name();
    const tokenSymbol = await contract.symbol();
    const totalSupply = await contract.totalSupply();
    const recipientBalanceBefore = await contract.balanceOf(recipientAddress);
    const transferTx = await contract.transfer(recipientAddress, TRANSFER_AMOUNT);
    await transferTx.wait();
    const senderBalance = await contract.balanceOf(sender.address);
    const recipientBalance = await contract.balanceOf(recipientAddress);
    const recipientBalanceIncrease = recipientBalance - recipientBalanceBefore;
    
    console.log('Token name:', tokenName);
    console.log('Token symbol:', tokenSymbol);
    console.log('Total supply:', formatUnits(totalSupply, 18));
    console.log('Transferred amount:', formatUnits(TRANSFER_AMOUNT, 18));
    console.log('Recipient address:', recipientAddress);
    console.log('Recipient balance increase:', formatUnits(recipientBalanceIncrease, 18));
    console.log('Recipient balance:', formatUnits(recipientBalance, 18));
    console.log('Sender balance:', formatUnits(senderBalance, 18));
    
  3. Set your deployed contract address at the top of the script file.
    You may also change the recipient address. This example uses another anvil rich wallet as the recipient by default.
  4. Run the script.
    npx hardhat run scripts/interact.ts
    

You should see the token name, symbol, transfer amount, recipient balance, and sender balance in the logs.

Now that you've tested interacting with your contract onchain, in the next step we will build a frontend for transferring tokens with a browser wallet.


Made with ❤️ by the ZKsync Community