Skip to main content
This guide builds a 3-step simulation bundle that exercises the classic ERC-20 approval flow: mint tokens to a holder, approve a spender, then let the spender call transferFrom. Each step depends on state that the previous step creates, which is why a bundle is the right tool here.

Why a bundle?

Simulating each transaction in isolation breaks down:
  • Mint alone: you can verify the mint logic, but the holder address has no tokens on mainnet.
  • Approve alone: the simulation needs the holder to actually have a balance to approve from.
  • TransferFrom alone: requires both the balance and the approval to be in place.
A Sim Bundle runs all three in sequence, sharing the resulting state. Step 2 sees the minted balance from step 1. Step 3 sees the approval from step 2.

The three transactions

All three transactions target the DAI contract on Ethereum mainnet (0x6b175474e89094c44da98b954eedeac495271d0f).

Step 1: Mint 2 DAI

DAI’s mint function is guarded by a wards mapping: only addresses registered as wards can call it. The fake ward (0xe2e2...e2) is not a ward on mainnet. To make this step succeed, add a state override that sets the ward storage slot for that address to 1: The storage key is keccak256(abi.encode(wardAddress, 0)), the standard Solidity mapping slot for wards[fakeWardAddress] at storage position 0.

Step 2: Approve 1 DAI

The holder approves a spender to pull up to 1 DAI. This step works because step 1 already credited 2 DAI to the holder’s balance in the shared state stream.

Step 3: TransferFrom 0.03 DAI

The spender moves 0.03 DAI from the holder to a recipient. This works because step 2 granted the allowance, which is only visible inside the bundle’s state stream, not on-chain.

Run via the Simulator UI

1

Open the Sim Bundle Builder

Go to Simulator in the left navigation, then click New Simulation. The bundle builder opens with one empty step.
2

Configure the session strip

The session strip runs across the top. Set Network to Mainnet and leave Block as Pending.
3

Fill Step 1: Mint

Switch the step to Raw mode. Set:
  • From: 0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2
  • To: 0x6b175474e89094c44da98b954eedeac495271d0f
  • Calldata: 0x40c10f19000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce10000000000000000000000000000000000000000000000001bc16d674ec80000
Then expand State overrides, add the DAI contract, and enter the ward storage slot and value from the table above. Click Add storage override to commit the slot.
Step 1 mint transaction configured with state override

Step 1 with the mint calldata filled and the ward state override configured.

4

Add Step 2: Approve

Click + Add function call in the bundle rail. Switch the new step to Raw mode. Set:
  • From: 0xe58b9ee93700a616b50509c8292977fa7a0f8ce1
  • To: 0x6b175474e89094c44da98b954eedeac495271d0f
  • Calldata: 0x095ea7b3000000000000000000000000f7ddedc66b1d482e5c38e4730b3357d32411e5dd0000000000000000000000000000000000000000000000000de0b6b3a7640000
5

Add Step 3: TransferFrom

Add another step. Switch to Raw mode. Set:
  • From: 0xf7ddedc66b1d482e5c38e4730b3357d32411e5dd
  • To: 0x6b175474e89094c44da98b954eedeac495271d0f
  • Calldata: 0x23b872dd000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce1000000000000000000000000bd8daa414fda8a8a129f7035e7496759c5af8570000000000000000000000000000000000000000000000000006a94d74f430000
6

Run the bundle

Click Simulate (or press ⌘↵). All three steps execute in sequence. Click each step in the rail to inspect its decoded output, gas used, events, and token transfers.
Step 2 approve result showing the Approval event

The bundle after running: step 2 (approve) is focused, showing the Approval event and decoded output.

Step 3 transferFrom result showing the DAI transfer

Step 3 (transferFrom) succeeded. The 0.03 DAI transfer is visible in the ERC-20 transfers tab.

Run via the Simulation API

Use the simulate-bundle endpoint to run the same sequence programmatically. Replace {accountSlug} and {projectSlug} with your values.
The response is an array of three simulation results, one per step. Each entry contains status, gasUsed, decoded logs, a trace, assetChanges, and balanceChanges. A successful run shows "status": true for all three steps. If a step reverts (for example, because the state override is missing from step 1), the API returns all results up to and including the failing step, and subsequent steps are not run.

What to look for in the results

Next steps