Skip to main content
Every Virtual Environment exposes a precompile contract at 0xc100000000000000000000000000000000000000. Calling functions on this precompile from inside a transaction lets your contracts manipulate on-chain state directly, storage slots, balances, nonces, and event logs, without impersonating accounts or deploying helper proxies. These cheatcodes complement the Admin RPC methods. The Admin RPC methods manipulate state from outside a transaction (via JSON-RPC). The precompile manipulates state from inside a transaction (via Solidity call). Use the precompile when your setup needs to stay atomic, be replayable from a tx hash, or run in a loop over many slots.

Interface

Add this file to your project as IVnetPrecompile.sol:
IVnetPrecompile.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IVnetPrecompile {
    function setStorageAt(address target, bytes32 slot, bytes32 value) external returns (bool);
    function getStorageAt(address target, bytes32 slot) external view returns (bytes32);
    function setBalance(address target, uint256 balance) external returns (bool);
    function addBalance(address target, uint256 amount) external returns (bool);
    function setNonce(address target, uint256 value) external returns (bool);

    function emitEvent(address target, bytes calldata data) external returns (bool);
    function emitEvent(address target, bytes32 topic1) external returns (bool);
    function emitEvent(address target, bytes32 topic1, bytes calldata data) external returns (bool);
    function emitEvent(address target, bytes32 topic1, bytes32 topic2) external returns (bool);
    function emitEvent(address target, bytes32 topic1, bytes32 topic2, bytes calldata data) external returns (bool);
    function emitEvent(address target, bytes32 topic1, bytes32 topic2, bytes32 topic3) external returns (bool);
    function emitEvent(address target, bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes calldata data) external returns (bool);
    function emitEvent(address target, bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4) external returns (bool);
    function emitEvent(address target, bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes calldata data) external returns (bool);
}
Reference it in your contract at the fixed address:
IVnetPrecompile constant VNET = IVnetPrecompile(0xc100000000000000000000000000000000000000);

Functions

Storage

FunctionParametersReturnsDescription
setStorageAtaddress target, bytes32 slot, bytes32 valueboolWrites value to slot on target.
getStorageAtaddress target, bytes32 slotbytes32Reads the current value of slot on target.
VNET.setStorageAt(tokenContract, balanceSlot, bytes32(uint256(1000e18)));
bytes32 val = VNET.getStorageAt(tokenContract, balanceSlot);

Balance

FunctionParametersReturnsDescription
setBalanceaddress target, uint256 balanceboolSets the ETH balance of target to an exact value.
addBalanceaddress target, uint256 amountboolAdds amount to the current ETH balance of target.
VNET.setBalance(account, 10 ether);
VNET.addBalance(account, 2 ether);

Nonce

FunctionParametersReturnsDescription
setNonceaddress target, uint256 valueboolSets the transaction count of target.
VNET.setNonce(account, 42);

Events

emitEvent fires a log whose address field is target, not the calling contract. Downstream consumers (indexers, subgraphs, webhooks) treat the log as a real emission from target. Nine overloads cover zero to four indexed topics with an optional unindexed data payload:
OverloadTopicsData
emitEvent(target, data)0
emitEvent(target, t1)1,
emitEvent(target, t1, data)1
emitEvent(target, t1, t2)2,
emitEvent(target, t1, t2, data)2
emitEvent(target, t1, t2, t3)3,
emitEvent(target, t1, t2, t3, data)3
emitEvent(target, t1, t2, t3, t4)4,
emitEvent(target, t1, t2, t3, t4, data)4
topic1 is typically keccak256("EventName(type,type,...)"). Example, spoof a USDC Transfer:
VNET.emitEvent(
    USDC,
    keccak256("Transfer(address,address,uint256)"),
    bytes32(uint256(uint160(from))),
    bytes32(uint256(uint160(to))),
    abi.encode(amount)
);
The precompile also emits its own diagnostic logs (balance set, nonce set, storage written) with address = 0xc100000000000000000000000000000000000000. When inspecting a receipt for a spoofed log, filter logs[] by the target address to ignore the precompile’s own entries.

Known limitations

  • Arbitrum-based Virtual Environments. Cheatcode calls made through eth_call do not work because the precompile is not registered at the Nitro layer. Transactions, gas estimates, and simulations work as expected.

See also

  • Admin RPC, the equivalent JSON-RPC methods for state manipulation from outside a transaction.
  • Foundry cheatcode tutorial, end-to-end walkthrough deploying a reusable cheatcode playground.