Skip to main content
Batched transactions let an application submit multiple contract calls in a single Arc transaction. The predeployed Multicall3From contract (0x522fAf9A91c41c443c66765030741e4AaCe147D0) batches calls like common Multicall3 contracts. Unlike a common batching contract, it preserves the original externally owned account (EOA) wallet as msg.sender for each target call. To send batch USDC transfers end to end, see Send batch USDC transfers.

How a batch call works

Multicall3From routes each subcall through Arc’s CallFrom precompile. CallFrom executes calls on behalf of the original transaction sender. The transaction extension contracts use this precompile to keep the original EOA wallet as msg.sender for target calls. For a batch of USDC transfers:
  1. Your wallet calls Multicall3From.aggregate3(...).
  2. Multicall3From forwards each encoded USDC transfer(...) through CallFrom.
  3. The USDC contract sees your wallet as the sender for each transfer.
In a normal batching contract, the target contract usually sees the batching contract as msg.sender. The contract exposes the aggregate3(...) entry point:
struct Call3 {
    address target;
    bool allowFailure;
    bytes callData;
}

struct Result {
    bool success;
    bytes returnData;
}

function aggregate3(Call3[] calldata calls) external returns (Result[] memory);
target is the contract to call. allowFailure controls whether a failed subcall reverts the full batch. callData is the encoded calldata for the target contract.

Event verification

Multicall3From does not emit a batch-specific event. Verify the target contract events emitted by each subcall. For USDC transfers, a successful batch emits one USDC Transfer event per successful transfer.
EventFieldExpected value
TransferfromThe wallet that called Multicall3From.aggregate3(...), not Multicall3From.
TransfertoThe recipient for that subcall.
TransfervalueThe USDC amount in base units.
The from field is the key sender-preservation check. It confirms that the USDC contract saw your wallet as msg.sender for each subcall.

Unsupported patterns and guardrails

Multicall3From has explicit guardrails:
  • Submit aggregate3(...) from an EOA. Calls routed through an intermediary contract with a different msg.sender are rejected by CallFrom’s sender-spoofing constraint.
  • Do not use value-forwarding patterns. Multicall3From does not support aggregate3Value because CallFrom does not forward value on Arc.
  • Set allowFailure to false when every subcall must succeed. If a subcall fails with allowFailure: false, the whole batch reverts.
  • Set allowFailure to true only when your application explicitly handles failed subcalls.
Before you use batched transactions in production, test your exact call set and failure policy against Arc Testnet with the same wallet and indexing infrastructure you plan to use in your application.