Skip to main content
Use the Multicall3From contract to batch multiple USDC transfers into one Arc transaction. This tutorial shows the full flow with viem, ethers.js, Python, and curl. You will configure a client, encode two ERC-20 transfer(...) subcalls, submit them through Multicall3From.aggregate3(...), and verify the resulting Transfer events. To learn how Multicall3From preserves your wallet as the sender, see Batched transactions.

Prerequisites

Before you begin, ensure that you’ve:
  • Installed Node.js v22+ for the TypeScript examples, or Python 3.10+ for the Python example.
  • Created an Arc Testnet wallet.
  • Funded the wallet with testnet USDC from the Circle Faucet.
  • Chosen two recipient addresses on Arc Testnet.

Step 1. Set up the project

Create a new project and install the dependencies for the client library you want to use:
Create an .env file:
Shell
Add your configuration:
.env
Replace YOUR_PRIVATE_KEY with the 0x-prefixed private key for the funded wallet. Replace each recipient value with an Arc Testnet address.

Step 2. Review the contract address and ABI

Arc Testnet uses the following predeployed contracts for this tutorial: For the full address list, see contract addresses. Create multicall3from-abi.json in your project:
multicall3from-abi.json
The script you build in the next steps loads this ABI file from the project root.

Step 3. Configure the client connection

Create the script file for your client library. The first chunk reads the wallet and recipient configuration from .env, sets the contract addresses, loads the Multicall3From ABI, and creates the clients that read chain state and submit transactions.
Create viem-batch.ts:
TypeScript
The public clients read chain state, the wallet or account objects sign transactions, and the contract interfaces encode the Multicall3From and ERC-20 calls.

Step 4. Encode the transfer calls

Add a chunk that sets the USDC amount and builds one ERC-20 transfer(...) subcall for each recipient. Each subcall targets the USDC contract, sets allowFailure to false, and includes the encoded transfer calldata.
TypeScript
1000000 is 1 USDC in base units because the USDC ERC-20 interface uses 6 decimals.

Step 5. Confirm Multicall3From is deployed

Before sending a transaction, check that the configured Multicall3From address has deployed bytecode.
TypeScript
If the bytecode check returns empty code, confirm that your RPC_URL points to Arc Testnet and that the address matches the table in Step 2.

Step 6. Simulate and send the batch

Simulate the aggregate3(...) call before sending the transaction. The simulation confirms that each encoded subcall can succeed from your wallet.
TypeScript
The receipt is reused in the next step to check the emitted USDC Transfer events.

Step 7. Verify the transfer events

Decode the USDC logs from the receipt and confirm that each expected transfer is present.
TypeScript
The from value in each expected Transfer event is your wallet address. That check confirms that the target USDC contract saw your wallet as the sender for each subcall.

Step 8. Run the script

Run the command for the script you created:
Successful output includes the transaction URL, block number, sender, and both recipient transfers:

Step 9. Check JSON-RPC directly with curl

Use curl for read-only JSON-RPC checks, such as verifying deployed bytecode or reading a transaction receipt. Use a client library such as viem, ethers.js, or web3.py to sign and submit the transaction itself.