Skip to main content
mip.watch
⌘K

MIP-4

Reserve Balance Introspection

Final Standards Track Core bundled in MONAD_NINE GitHub ↗ Forum ↗
Idea Draft Review Last Call Final Living

Add reserve balance precompile to query reserve balance violation state during transaction execution

Authors
Category Labs
Created
2026-01-08
Updated
Jul 14, 2026

Stakeholder Impact

What this MIP changes for each audience. Severity and action flags are model-derived with deterministic floors per MIP type/category.

TL;DR

This proposal introduces a new precompile that allows smart contracts to check if they are in a reserve balance violation during execution, enabling better error handling and state management. This is important because it helps contracts avoid unexpected reverts at the end of transactions.

What's Changing

  • New precompile at address 0x1001 - This allows contracts to check reserve balance violations mid-execution.
  • Method 'dippedIntoReserve' added - Contracts can now query if they are in a reserve violation state.
  • Gas cost set at 100 - This ensures that checking the reserve state is efficient and predictable.
  • Strict calldata requirements - Only specific inputs are accepted to prevent misuse and ensure reliability.
  • No impact on existing contracts - This addition does not alter the behavior of contracts that do not use the new precompile.

Developers

Smart contract & dapp builders, RPC consumers, tooling authors

The introduction of the new precompile at address 0x1001 with the method dippedIntoReserve requires developers to update their contracts to utilize this functionality for reserve balance introspection. Existing contracts will not be affected unless they choose to implement this new feature.

Medium

Users

Wallet users, EOA holders, dapp visitors

This change introduces a new precompile that allows smart contracts to check for reserve balance violations during execution, which may improve transaction handling for dapps. However, as an end user, you will not notice any direct changes to transaction fees, confirmation speeds, or wallet compatibility.

Low

Validators

Node operators, RPC operators, delegators

The introduction of the reserve balance precompile allows contracts to better manage reserve violations during execution, potentially reducing transaction reverts. However, this change does not directly impact validator revenue or operational requirements.

Medium

Foundation

Monad Foundation & Category Labs core devs

This proposal introduces a new precompile that requires coordination for its activation and integration across clients. It sets a precedent for future precompile introductions and necessitates clear documentation and communication with the ecosystem.

High action required

Generated Aug 7, 2026, 3:59 PM · model: gpt-4o-mini

Specification

Cite

## Abstract

Add a new precompile at address `0x1001` with a method `dippedIntoReserve` that returns whether the current execution state is in reserve balance violation.
This enables contracts to detect and recover from temporary reserve violations before transaction completion.

## Motivation

Monad's reserve balance mechanism (per the initial spec, Algorithm 3) reverts transactions that leave any touched account below its reserve threshold at execution end.
However, the check is performed post-execution: contracts have no way to know during execution whether they are in a violation state.

The reserve balance precompile allows contracts to query violation state mid-execution and adjust behavior accordingly—either by restoring balances, taking an alternative code path, or reverting early with a meaningful error.

## Specification

| Name                           | Value        |
| ------------------------------ | ------------ |
| `GAS_DIPPED_INTO_RESERVE`      | `100`        |
| `SELECTOR_DIPPED_INTO_RESERVE` | `0x3a61584e` |

The new precompile has address `0x1001`, and satisfies the following Solidity interface:

```solidity
interface IReserveBalance {
    function dippedIntoReserve() external returns (bool);
}
```

The Solidity selector for `dippedIntoReserve` is `SELECTOR_DIPPED_INTO_RESERVE (0x3a61584e)`.

The precompile must be invoked via `CALL`.
Invocations via `STATICCALL`, `DELEGATECALL`, or `CALLCODE` must revert.

Invocations via [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) delegations targeting the precompile address must revert.

Calldata must consist of exactly the 4-byte `SELECTOR_DIPPED_INTO_RESERVE`.
Any other calldata is invalid: if the calldata is shorter than 4 bytes or not equal to `SELECTOR_DIPPED_INTO_RESERVE` the precompile must revert with the error message "method not supported".
If extra calldata is appended beyond the selector, the precompile must revert with the error message "input is invalid".

The method `dippedIntoReserve()` is not payable and must revert with the error message "value is nonzero" when called with a nonzero value.

In case more than one revert condition is present, the revert error message must correspond with the conditions evaluated in the following order:

1. is not invoked via `CALL`
2. `gas < GAS_DIPPED_INTO_RESERVE`
3. `len(calldata) < 4`
4. `calldata[:4] != SELECTOR_DIPPED_INTO_RESERVE`
5. `value > 0`
6. `len(calldata) > 4`

Reverts consume all gas provided to the call frame.

On success, the method `dippedIntoReserve()` evaluates the condition that `DippedIntoReserve` (Algorithm 3 of the initial spec) would return, substituting the current state for the post-execution state.
The check considers all accounts touched in the transaction, regardless of call depth.
The call consumes `GAS_DIPPED_INTO_RESERVE` gas.

The return value is ABI-encoded as a Solidity `bool`—i.e., a 32-byte word in returndata.

## Rationale

### Address

Precompile address chosen follows the existing staking precompile at `0x1000`.

### Gas cost

Gas cost of `dippedIntoReserve()` is equivalent to the cost of one `tload`. 
Implementations should incrementally update their state to track violations of the reserve balance constraints, rather than iterating over the set of modified accounts in the current transaction on each call to the precompile.
Then `dippedIntoReserve()` should be a check of this violation state and therefore should have similar resource usage to a load from transient storage.

This was not benchmarked, but aligns with benchmarking and costing for the staking precompile's gas costs, which were calculated from the number of database loads and stores, events, and transfers.
The reserve balance check produces no events or transfers and is analagous to a load from transient storage instead of database storage and thus uses the cost for a `tload`.

Reverts consuming all gas is consistent with the behavior of Ethereum precompiles, which do not return remaining gas on failure, as opposed to Solidity functions which return unused gas on revert.

### Return value encoding

The return value is encoded consistently with standard Solidity ABI encoding.
This means callers can invoke the precompile via a normal contract call.

### Precompile vs. opcode

A previous design proposed adding a new opcode with similar semantics.
Since this introspection feature is intended for direct use by smart contract developers (e.g., in bundler entrypoint contracts), a precompile was chosen because it can be called immediately without requiring compiler or toolchain updates.

### Compatibility with other Monad precompiles

The semantics described above (strict calldata validation, ABI-encoded return values, rejecting calls with value, conventions around `*CALL` opcodes & EIP-7702, revert messages, and all-gas-consuming reverts) are chosen for explicit consistency with the existing Monad staking precompile.

The interface method `dippedIntoReserve()` is intentionally not declared `view`, so that a Solidity call site compiles to `CALL` rather than `STATICCALL`.

## Backwards Compatibility

This proposal adds a new precompile and does not modify existing behavior.
Contracts that do not use the precompile are unaffected.

## Security Considerations

The precompile is read-only and exposes information that is already implicitly available (the transaction will revert if violation persists).
No new attack surface is introduced.

## References

- [Monad Initial Specification](https://category-labs.github.io/category-research/monad-initial-spec-proposal.pdf)

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).

Forum discussion

8 posts · 11 likes · 6 months ago
Read more on forum ↗
  1. @Bruce Collie #1 Jan 8, 2026, 12:53 PM

    mips.monad.xyz Monad Improvement Proposals (MIPs) Add reserve balance precompile to query reserve balance violation state during transaction execution This MIP adds a new opcode that allows contracts on Monad to detect whether their local execution state is in violation of reserve balance and take action to avoid reverting.

  2. @Pdobacz #4 Jan 15, 2026, 1:10 PM

    Re gas cost Expected to be `O(N)` in the number of warm accounts (i.e., accounts with modified balances). Would it be feasible to: - Keep a cache of reserve balance check results per warm account address (with a count of failed checks for quick lookup) - Run the reserve balance check only on crossing boundaries where it actually might change. I think that is at transaction start (after auth processing) CALL with value!=0 and CREATE and SELFDESTRUCT and call frame reverting. - Run the check and update cache only for affected addresses (1 or 2 max per such op) - Have CHECKRESERVEBALANCE just return the cached result Then it would be possible to price CHECKRESERVEBALANCE at O(1) (and as cheap as an environment opcode)? The cost of checking and updating would be assumed to be included in the (expensive) ops from (2.). Cost of memory to hold the extra execution state included in co...

  3. @Bruce Collie #5 Jan 19, 2026, 11:02 AM

    I think that should be feasible to implement. We’ll try that method once we have our tests nailed down using the eager method as a reference.

  4. @ARitz Cracker #6 Jan 23, 2026, 11:17 PM

    Could the MIP link to the algorithm referenced? We will need to update our revm-based codebase to include this opcode.

  5. @Bruce Collie #7 Jan 26, 2026, 3:13 PM

    Yes, we’ll update the MIP to point to the algorithm in the current version of the Monad client - roughly speaking, the opcode will represent a call to dipped_into_reserve here .