Blockchain security isn't optional.
Protect your smart contracts and DeFi protocols with Three Sigma, a trusted security partner in blockchain audits, smart contract vulnerability assessments, and Web3 security.
Get a Quote Today
Introduction
Glad to have you back for the second installment of the Foundry Cheatcodes Series. In Part 1 we compared Foundry to Hardhat and laid the foundation for faster, Solidity-native testing; today we zoom in on vm.prank
, the trick that lets your tests masquerade as any address to probe access-control edge cases.
Ever needed to test access control or simulate calls from different users? Foundry’s vm.prank
makes it dead simple to impersonate any address and validate your contract logic.
What Is vm.prank
and Why It Matters
The vm.prank(address)
cheatcode makes the next contract call appear to come from a different address (it sets msg.sender
). This is essential when testing logic that depends on the caller. For example, if only the owner can call a function, you can prank a non-owner and verify it fails. In Foundry’s forge-std
Test
contract, you simply do:

Here, vm.prank(0xBEEF)
forces the next call to c.privileged()
to originate from 0xBEEF
. Foundry then verifies the revert as expected. Behind the scenes Foundry invokes a special address 0x7109...DD12
to perform the cheat. Any time Solidity code calls that address, Forge’s custom EVM hooks it, decodes the calldata, and routes it to a native Rust handler that mutates the in-memory chain state. No contract is actually deployed, everything happens inside the test runner, so the bytecode stays lean and the cheatcodes disappear in production builds. If you ran the compiled test on mainnet the same call would simply revert, because nothing exists at 0x7109…DD12
outside Forge.
Simulating Multiple Calls with vm.startPrank
For multiple calls, use vm.startPrank(addr)
to persist the fake identity across subsequent calls, and end it with vm.stopPrank()
. For example:

Why Foundry Wins (and What’s Next)
Foundry’s speed, single-language test workflow, and built-in fuzz/invariant engines make it the first tool I reach for when security or deep protocol testing matters. Hardhat’s ecosystem is huge and its JS plugins are handy, but once teams feel the compile-and-test loop drop from seconds to milliseconds, and realise they can ditch TypeScript test harnesses entirely, the switch is hard to undo. Rust-level performance, Solidity-level ergonomics.
In the next installment we’ll keep the cheat-code deep dives rolling: Part 3 tackles the expect-based assertion trio, vm.expectRevert
, vm.expectEmit
, and vm.expectCall,
showing how to lock in reverts, events, and external calls before they happen. A new cheat-code post will land each day until we’ve worked through the full set.