{"id":"MIP-4","name":"Reserve Balance Introspection","status":"Proposed","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":"Pre-check if a transaction would fail before sending — apps can query spendable balance accounting for the 10 MON reserve. Design implications: show spendable vs total balance, disable send when amount exceeds spendable, pre-validate before wallet popup, explain reserve with clear tooltips. Design decisions: whether MAX subtracts reserve + gas automatically; how to surface pre-check failures without blocking power users.","officialUrl":"https://github.com/monad-crypto/MIPs/blob/main/MIPS/MIP-4.md","hasDetailedContent":true,"content":{"id":"MIP-4","summary":"MIP-4 adds a way to check if a transaction would fail BEFORE sending it. Specifically, it lets apps check if your account has enough \"spendable\" balance (accounting for the reserve requirement). Instead of sending a transaction and having it revert, wallets can pre-check and show \"Insufficient spendable balance\" before you waste time or gas.","applicability":{"whenToUse":["Your product addresses: transactions fail after user confirms.","Your product addresses: confusing when balance looks sufficient but tx fails.","The flow should deliver: check fails instantly before submission.","You are designing a pre-send validation experience with visible states and recovery paths."],"whenToAvoid":["Always subtract reserve for spendable amount.","MAX = balance, reserve, gas.","Clear tooltip: \"Reserved for async execution safety\"."]},"designerTakeaways":["You can design UI that delivers check fails instantly before submission.","You can shows \"Spendable: 90 MON\" (10 reserved for async execution safety) in the interface.","You can design UI that delivers light introspection without full simulation."],"problemsSolved":[{"problem":"Transactions fail after user confirms","oldWay":"Click send → wait → \"Transaction reverted: insufficient funds\"","newWay":"Check fails instantly before submission","impact":"high"},{"problem":"Confusing when balance looks sufficient but tx fails","oldWay":"\"I have 100 MON, why can't I send 100 MON?\"","newWay":"Shows \"Spendable: 90 MON\" (10 reserved for async execution safety)","impact":"high"},{"problem":"No way to pre-validate complex operations","oldWay":"Submit and pray, or use expensive simulation","newWay":"Light introspection without full simulation","impact":"medium"},{"problem":"Smart wallets can't predict failures accurately","oldWay":"UserOp submitted, bundler rejects, user confused","newWay":"Pre-check reserve before UserOp creation","impact":"medium"}],"uxPatterns":[{"name":"Pre-Send Validation","description":"Check if transaction would succeed before sending","mockup":"concept/gas-abstraction","userFlow":["User enters amount","App calls reserve introspection","Calculates spendable = balance - reserve","If amount > spendable: show error","Prevent submission of failing tx"]},{"name":"Smart MAX Button","description":"MAX accounts for reserve and gas","mockup":"concept/gas-abstraction","userFlow":["User clicks MAX","App queries total balance","Subtracts reserve (from MIP-4)","Subtracts estimated gas","Fills in maximum safe amount"]},{"name":"Transaction Pre-Check","description":"Validate before wallet popup","mockup":"generic/token-approval","userFlow":["User initiates swap","App runs pre-checks","Includes reserve balance check","Shows pass/fail for each","Only enable confirm if all pass"]}],"uiComponents":[{"name":"SpendableBalanceDisplay","description":"Shows spendable vs total balance with reserve","states":["loading","healthy","low","insufficient"],"props":["totalBalance","reserveAmount","spendable"]},{"name":"ReserveExplainer","description":"Tooltip explaining what reserve is for","states":["collapsed","expanded"],"props":["reserveAmount","reason"]},{"name":"PreTransactionCheck","description":"Checklist of validations before sending","states":["checking","passed","failed"],"props":["checks[]","onRetry"]},{"name":"SmartMaxButton","description":"Calculates max considering reserve and gas","states":["calculating","ready","zero"],"props":["balance","reserve","estimatedGas","onMax"]}],"antiPatterns":[{"pattern":"Using total balance for validation","why":"Ignores reserve, tx will fail","instead":"Always subtract reserve for spendable amount","severity":"critical"},{"pattern":"MAX button ignoring reserve","why":"User sends MAX → tx fails → frustration","instead":"MAX = balance - reserve - gas","severity":"critical"},{"pattern":"No explanation of reserve","why":"User confused why they can't spend their balance","instead":"Clear tooltip: \"Reserved for async execution safety\"","severity":"high"},{"pattern":"Only checking balance client-side","why":"Race conditions, stale data","instead":"Call introspection function for real-time check","severity":"medium"}],"onMonad":[{"aspect":"Reserve Introspection","ethereum":"No equivalent — balance is fully spendable","monad":"Can query exact reserve amount","designImplication":"Always show spendable vs total on Monad"},{"aspect":"Pre-validation","ethereum":"Simulate with eth_call (expensive)","monad":"Light introspection available","designImplication":"Pre-validate all transactions efficiently"},{"aspect":"Smart Wallet Integration","ethereum":"UserOps can drain to zero","monad":"Must account for reserve in UserOps","designImplication":"Paymaster logic needs reserve awareness"}],"keyTakeaways":["MIP-4 = pre-check if transaction would fail","On Monad, always show SPENDABLE balance, not total","MAX button must subtract reserve + gas","Pre-validate before showing wallet popup","Explain reserve with clear UI tooltips"],"technicalNotes":"MIP-4 adds an introspection method to query account reserve requirements. On Monad, EOAs must maintain a 10 MON minimum reserve to preserve safety under asynchronous execution — preventing race conditions where concurrent transactions drain an account. The introspection returns the current reserve amount, allowing apps to calculate spendable = balance - reserve. Undelegated accounts can bypass the reserve via a one-time \"emptying transaction\" per k-block period (k=3), but delegated accounts (EIP-7702) cannot."},"sources":[{"label":"Official specification","url":"https://github.com/monad-crypto/MIPs/blob/main/MIPS/MIP-4.md","type":"official-spec"}],"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"},"freshness":{"lastReviewed":"2026-04-05","lastUpdated":"2026-04-05"}}