{"id":"MIP-4","name":"Reserve Balance Introspection","status":"Final","chain":"monad","category":{"id":"transaction-friction","name":"Transaction Friction","description":"Reducing clicks, signatures, and mental overhead"},"journeyStages":[{"id":"asset-display","name":"Asset Discovery & Display","description":"Seeing tokens, NFTs, and balances"},{"id":"executing","name":"Executing Transactions","description":"Performing on-chain actions"},{"id":"gas","name":"Gas & Fees","description":"Paying for transactions"}],"uxImpact":"MIP-4 adds a precompile at 0x1001 with dippedIntoReserve(), which returns an ABI-encoded bool describing whether the current execution state has dipped into reserve across all accounts touched by the transaction. It is an in-execution contract check, not a reserve-amount query or a wallet preflight for an arbitrary unsigned transaction.","officialUrl":"https://github.com/monad-crypto/MIPs/blob/main/MIPs/MIP-4.md","discussionUrl":"https://forum.monad.xyz/t/mip-4-reserve-balance-introspection/363","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"MIP-4","sources":[{"label":"Canonical MIP-4 specification","url":"https://github.com/monad-crypto/MIPs/blob/7c95e69cb26d43d82e50d06199d4810067a3a2e0/MIPs/MIP-4.md","type":"official-spec"},{"label":"Monad Reserve Balance documentation","url":"https://docs.monad.xyz/developer-essentials/reserve-balance","type":"reference"},{"label":"Monad EIP-7702 documentation","url":"https://docs.monad.xyz/developer-essentials/eip-7702","type":"reference"}],"lastReviewed":"2026-09-18","specConstraints":[{"id":"call-only-precompile","constraint":"The reserve-balance precompile must be invoked with CALL; static and delegated call modes are not valid invocation paths.","appliesTo":"account-implementation","normativity":"normative","specQuote":"The precompile must be invoked via `CALL`.","specSection":"Specification","specUrl":"https://github.com/monad-crypto/MIPs/blob/main/MIPs/MIP-4.md#specification","designImplication":"Keep the reserve check in a deliberate CALL path and show implementation or simulation failures when a contract attempts a read-only or delegated call mode."},{"id":"delegation-target-rejection","constraint":"EIP-7702 delegations targeting the reserve precompile must revert.","appliesTo":"account-implementation","normativity":"normative","specQuote":"Invocations via [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) delegations targeting the precompile address must revert.","specSection":"Specification","specUrl":"https://github.com/monad-crypto/MIPs/blob/main/MIPs/MIP-4.md#specification","designImplication":"Keep delegation-target rejection visible in account implementation tests and do not offer a delegated-call path that appears to perform a reserve check."}],"lastUpdated":"2026-09-18","summary":"MIP-4 adds a precompile at 0x1001 with dippedIntoReserve(), which returns an ABI-encoded bool describing whether the current execution state has dipped into reserve across all accounts touched by the transaction. It is an in-execution contract check, not a reserve-amount query or a wallet preflight for an arbitrary unsigned transaction.","applicability":{"whenToUse":["Your contract, bundler, or account implementation needs to detect a reserve dip during its own execution path.","The flow can restore the balance, take an alternative path, or revert early with a useful error when the check returns true.","You are designing developer or power-user tooling that must explain the difference between an execution-time signal and wallet simulation.","A transaction flow needs an explicit state for a reserve check that is current to the executing transaction."],"whenToAvoid":["Treating MIP-4 as a wallet preflight for an arbitrary transaction before signing.","Using the bool result to infer an exact reserve amount or a universal spendable balance.","Calling the precompile with STATICCALL, DELEGATECALL, CALLCODE, nonzero value, or an invalid selector.","Showing a fixed 10 MON subtraction without checking balance, gas, delegation, inflight activity, and emptying eligibility."]},"designerTakeaways":["You can design a contract or bundler path that calls 0x1001 during execution and branches on the returned bool.","You can give a detected reserve dip a recovery, alternate-path, or early-revert state instead of waiting for a post-execution failure.","You can keep wallet preflight separate: estimate a transaction with current account, gas, delegation, recent-block, and emptying state rather than presenting MIP-4 as a spendable-balance API.","You can expose the call contract to developers: CALL only, 100 gas, exact selector, and all touched accounts are part of the integration."],"problemsSolved":[{"problem":"Contracts only learn about a reserve violation after their execution path finishes","oldWay":"Run the operation and discover the reserve-related revert after execution.","newWay":"Call dippedIntoReserve() during execution and choose whether to restore, reroute, or revert.","impact":"high"},{"problem":"A nested call can affect an account outside the immediate frame","oldWay":"Check only the account or frame that the current contract knows about.","newWay":"Use the precompile's bool, which evaluates the current state for all accounts touched by the transaction across call depth.","impact":"high"},{"problem":"Wallet and bundler authors confuse an execution signal with a sendable amount","oldWay":"Assume MIP-4 returns a reserve amount and calculate balance minus reserve before signing.","newWay":"Use reserve rules and transaction simulation for preflight, then use MIP-4 only inside an executing contract flow.","impact":"critical"},{"problem":"Reserve-aware integrations fail because the precompile call shape is wrong","oldWay":"Use a view call, send value, or pass extra calldata.","newWay":"Issue the exact selector through CALL with enough gas and handle specified reverts.","impact":"medium"}],"uxPatterns":[{"name":"Execution Reserve Check","description":"Show a contract or bundler's current execution check and its recovery path; this is not a wallet balance preflight.","userFlow":["A transaction enters the contract or account implementation.","The implementation calls 0x1001 with the dippedIntoReserve selector through CALL.","On success, the call consumes 100 gas and returns a bool for the current touched-account state.","If true, restore the relevant balance, choose an alternative path, or revert with a meaningful error.","Report the final execution result separately from the in-execution check."]},{"name":"Reserve-Aware Wallet Preflight","description":"Estimate a wallet action from reserve rules and simulation while clearly labeling the estimate; MIP-4 does not provide this preflight.","userFlow":["Read the current account state and the intended value and gas limits.","Check delegation, inflight and recent activity, and emptying-transaction eligibility.","Show an estimated sendable amount or an unavailable state with the reason.","Re-simulate or re-check immediately before signing when state may have changed.","Explain that the 0x1001 bool is an execution-time contract signal, not the amount used in the estimate."]},{"name":"Reserve Dip Recovery Notice","description":"Explain that an executing contract detected a reserve dip and what recovery or retry action is available.","userFlow":["Show the operation as reserve-checking or recovery in progress.","If the implementation restores or reroutes successfully, show the resulting execution state.","If it reverts, explain that the check is an execution signal and provide a transaction-specific next step.","Do not label the result as an exact reserve amount or promise that another transaction will be valid."]}],"uiComponents":[{"name":"ReserveExecutionStatus","description":"Shows the current contract-level reserve check without presenting it as a spendable balance.","states":["unknown","clear","dipped","recovering","reverted"],"props":["isDipped","checkScope","onRecovery"]},{"name":"ReserveAwarePreflight","description":"Shows a transaction-specific reserve estimate and the state used to produce it.","states":["loading","eligible","conditional","ineligible","stale"],"props":["estimatedSendable","gasLimit","delegationState","emptyingEligibility","onRecheck"]},{"name":"ReserveExplainer","description":"Explains the difference between the MIP-4 execution signal and the reserve rules used for wallet estimates.","states":["collapsed","expanded"],"props":["reserveParameter","eligibilityState","reason"]},{"name":"TransactionRecoveryNotice","description":"Communicates the recovery, alternate path, or revert selected after an execution-time reserve check.","states":["hidden","checking","recovered","failed"],"props":["operation","reason","onRetry"]}],"antiPatterns":[{"pattern":"Treating MIP-4 as a wallet preflight","why":"The precompile observes the current execution state; it does not inspect an arbitrary unsigned transaction before the user signs.","instead":"Use chain reserve rules and transaction simulation for wallet preflight, and reserve the precompile for an executing contract, bundler, or account path.","severity":"critical"},{"pattern":"Reading a reserve amount from the bool result","why":"dippedIntoReserve() returns only an ABI-encoded bool for the current state.","instead":"Model the transaction-specific amount from account state, gas, value, delegation, recent activity, and emptying eligibility.","severity":"critical"},{"pattern":"Calling the precompile as a view function","why":"MIP-4 requires CALL; STATICCALL, DELEGATECALL, and CALLCODE revert, as do invalid calldata and nonzero value.","instead":"Use the exact four-byte selector through CALL with at least the 100-gas call cost and handle failure states.","severity":"high"},{"pattern":"Ignoring a true result","why":"The contract may continue toward an execution that will fail the reserve check.","instead":"Restore the balance, take a safe alternative path, or revert early with a useful error.","severity":"high"},{"pattern":"Showing a universal 10 MON spendable formula","why":"The reserve parameter is not an amount that can be subtracted from every balance in every transaction.","instead":"Show a stateful estimate and disclose when the result depends on gas, delegation, inflight activity, or emptying eligibility.","severity":"high"}],"onMonad":[{"aspect":"Reserve signal","ethereum":"No MIP-4 precompile with this interface.","monad":"Monad exposes dippedIntoReserve() at 0x1001 as a bool for the current execution state.","designImplication":"Use it as a contract-level branch during execution, not as a wallet reserve-amount endpoint."},{"aspect":"Execution scope","ethereum":"Wallet and contract integrations use the chain's own simulation and failure semantics.","monad":"The MIP-4 check considers all accounts touched by the transaction, regardless of call depth.","designImplication":"Describe the check as transaction-scoped and keep nested-call effects visible in developer tooling."},{"aspect":"Invocation contract","ethereum":"No equivalent MIP-4 invocation contract.","monad":"The precompile requires CALL, consumes 100 gas on success, accepts only the exact selector, and rejects delegation targeting the precompile.","designImplication":"Make call shape and failure behavior part of implementation guidance and test cases."},{"aspect":"Wallet preflight","ethereum":"Use chain-specific balance and simulation rules.","monad":"Reserve-aware wallet estimates must use the Reserve Balance rules; MIP-4 itself does not calculate spendable balance.","designImplication":"Separate the wallet estimate, its freshness, and its eligibility reason from the contract's in-execution bool."}],"keyTakeaways":["MIP-4 is an execution-time bool at 0x1001, not a reserve-amount query.","dippedIntoReserve() checks the current state for all accounts touched by the transaction.","Invoke it through CALL with the exact selector and 100-gas call cost; other call modes and malformed inputs revert.","A contract can use true to recover, choose an alternative path, or revert early.","Wallet preflight remains a separate, stateful estimate based on reserve rules and simulation."],"technicalNotes":"MIP-4 specifies dippedIntoReserve() at 0x1001 with selector 0x3a61584e. The precompile must be called with CALL, rejects STATICCALL, DELEGATECALL, CALLCODE, EIP-7702 delegation targeting the precompile, nonzero value, and malformed calldata, and consumes 100 gas on success. It evaluates the current execution state for reserve violations across all accounts touched by the transaction, regardless of call depth, and returns an ABI-encoded bool. It does not return a reserve amount, calculate spendable balance, or preflight an arbitrary unsigned wallet transaction. Wallets should use the Reserve Balance rules and simulation for transaction-specific estimates, including gas, starting balance, delegation, inflight and recent k-block activity, and emptying eligibility.","relatedStandards":[{"id":"MONAD-RESERVE","relationship":"Wallet reserve rules and emptying-eligibility guidance"},{"id":"EIP-7702","relationship":"Delegation behavior that affects reserve checks"}]},"sources":[{"label":"Official specification","url":"https://github.com/monad-crypto/MIPs/blob/main/MIPs/MIP-4.md","type":"official-spec"},{"label":"Monad forum discussion","url":"https://forum.monad.xyz/t/mip-4-reserve-balance-introspection/363","type":"discussion"},{"label":"Canonical MIP-4 specification","url":"https://github.com/monad-crypto/MIPs/blob/7c95e69cb26d43d82e50d06199d4810067a3a2e0/MIPs/MIP-4.md","type":"official-spec"},{"label":"Monad Reserve Balance documentation","url":"https://docs.monad.xyz/developer-essentials/reserve-balance","type":"reference"},{"label":"Monad EIP-7702 documentation","url":"https://docs.monad.xyz/developer-essentials/eip-7702","type":"reference"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/MIP-4","markdown":"https://www.eipsfordesigners.com/standards/MIP-4/content.md","agent":"https://www.eipsfordesigners.com/standards/MIP-4/agent.md","api":"https://www.eipsfordesigners.com/api/standards/MIP-4","official":"https://github.com/monad-crypto/MIPs/blob/main/MIPs/MIP-4.md","discussion":"https://forum.monad.xyz/t/mip-4-reserve-balance-introspection/363"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}