Mock a function return value
Force any contract function on your Stagenet to return a fixed value, without changing the contract’s code or storage. Useful for pinning a price oracle to a known number, forcing a contract into a specific branch (paused() = true), or stubbing out a dependency you don’t want to seed.
The override sits at the EVM layer, so it applies to every call to the function — eth_call from outside, transactions, and inner calls from other contracts. The function body never runs; your fixed value is returned instead.
Prerequisites
- A Stagenet — create one in the dashboard if you don’t have one yet
- The contract.dev CLI installed and configured at your project root (only required for the CLI snippets below):
npm install contract.dev
npx contract.dev init --rpc-url=<YOUR_STAGENET_RPC_URL>Install an override
You need three things: the contract address, an ABI fragment for the function, and the return values you want.
From the CLI:
npx contract.dev function-override add 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 \
--abi 'function totalSupply() view returns (uint256)' \
--returns '["1000000000000"]'The command prints the override’s id — save it; you’ll need it later to update, disable, or remove the override.
From the SDK:
import { createStagenet } from "contract.dev";
const stagenet = createStagenet("<YOUR_STAGENET_RPC_URL>");
const override = await stagenet.addFunctionOverride({
contractAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
functionAbi: "function totalSupply() view returns (uint256)",
returnValues: ["1000000000000"], // 1M USDC, 6 decimals
});Every call to USDC.totalSupply() on your Stagenet now returns 1,000,000 — until you remove the override.
Pin a price feed
Pin a Chainlink-style latestAnswer() so the rest of your protocol can be exercised against a known price:
const ethUsdFeed = "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419";
await stagenet.addFunctionOverride({
contractAddress: ethUsdFeed,
functionAbi: "function latestAnswer() view returns (int256)",
returnValues: ["300000000000"], // $3,000 with 8 decimals
});Move the price by updating the override later:
await stagenet.updateFunctionOverride(override.id, ["250000000000"]); // $2,500Force a branch
Make a contract behave as if it’s in a particular state, even though no storage has been written:
npx contract.dev function-override add 0xVault... \
--abi 'function paused() view returns (bool)' \
--returns '["true"]'Every reader — including the contract’s own whenNotPaused modifier — sees paused() == true.
Scope an override to specific inputs
Pass --input-params (CLI) or inputParams (SDK) to make an override apply only when the call’s encoded inputs match exactly. The same selector can have many scoped overrides plus an optional wildcard.
# Wildcard: every call to balanceOf returns 1,000,000
npx contract.dev function-override add 0xA0b8...eB48 \
--abi 'function balanceOf(address) view returns (uint256)' \
--returns '["1000000000000"]'
# Scoped: only this holder reads as 500 USDC
npx contract.dev function-override add 0xA0b8...eB48 \
--abi 'function balanceOf(address) view returns (uint256)' \
--input-params '["0x1111111111111111111111111111111111111111"]' \
--returns '["500000000"]'await stagenet.addFunctionOverride({
contractAddress: usdc,
functionAbi: "function balanceOf(address) view returns (uint256)",
inputParams: ["0x1111111111111111111111111111111111111111"],
returnValues: ["500000000"],
});When both apply, the exact-input override wins.
Toggle during a test run
Disable an override without deleting it — handy for testing both branches:
const paused = await stagenet.addFunctionOverride({
contractAddress: vault,
functionAbi: "function paused() view returns (bool)",
returnValues: ["true"],
});
// run the "paused" path...
await stagenet.disableFunctionOverride(paused.id);
// run with the contract's real paused state...
await stagenet.enableFunctionOverride(paused.id);npx contract.dev function-override disable fov_abc123
npx contract.dev function-override enable fov_abc123A disabled override persists but isn’t applied — calls fall through to the real function.
List and remove
npx contract.dev function-override list # everything
npx contract.dev function-override list --contract 0xVault...
npx contract.dev function-override remove fov_abc123await stagenet.getFunctionOverrides();
await stagenet.getFunctionOverridesByContract(vault);
await stagenet.removeFunctionOverride(override.id);When to use a storage write instead
Function overrides intercept reads at the function boundary, so they’re great for view functions other contracts depend on. They are not the right tool when other functions need to observe a state change — e.g. an ERC20 balanceOf override won’t make transfer debit the right amount, because the underlying mapping hasn’t moved.
For state that other code paths must read consistently, set storage directly with storage overrides or use balance helpers.
Next steps
- Function overrides SDK reference — full method signatures and return shapes.
function-overrideCLI reference.- Override contract state — the storage/code/nonce path for changes that need to persist as real state.