{"id":"MONAD-RESERVE","name":"Reserve Balance Mechanism","status":"Active","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":"Every EOA must maintain a 10 MON reserve for async execution safety. Two-layer enforcement: consensus-time (inflight tx budget) and execution-time (revert if ending balance < reserve). Undelegated accounts get one emptying transaction per ~3 blocks that bypasses the reserve; delegated accounts (EIP-7702) cannot. Design implications: show spendable vs total balance, account for reserve in MAX buttons, detect delegation status for emptying tx eligibility, handle transactions that revert after block inclusion, warn when approaching reserve threshold. Design decisions: whether to surface emptying transaction option for sub-10-MON balances vs. simply prompting to add funds.","hasDetailedContent":true,"content":{"id":"MONAD-RESERVE","summary":"Monad requires every EOA to maintain a 10 MON reserve balance to preserve safety under asynchronous execution. During execution, transactions revert if the account's ending balance dips below the reserve — preventing race conditions where concurrent transactions drain an account. Undelegated accounts get one exception: an \"emptying transaction\" that can bypass the reserve once per k-block period (k=3 blocks). Delegated accounts (EIP-7702) cannot use this exception. Wallets must show \"spendable balance\" not just \"total balance\" so users understand what they can actually use.","applicability":{"whenToUse":["Your product addresses: async execution can cause concurrent balance drains.","Your users accidentally drain accounts completely.","The flow should deliver: reserve balance guarantees a gas budget even under concurrent execution.","You are designing a balance display with reserve experience with visible states and recovery paths."],"whenToAvoid":["Always show spendable as primary, total as secondary.","MAX = spendable, estimated gas.","Detect reverts, explain the cause, and offer retry with updated amounts.","The flow is a single low-risk transfer where batching adds confusion."]},"designerTakeaways":["You can design UI that delivers reserve balance guarantees a gas budget even under concurrent execution.","You can design UI that delivers can't spend below reserve (unless using emptying transaction).","You can design UI that delivers \"100 MON total, 90 MON spendable\" is explicit."],"problemsSolved":[{"problem":"Async execution can cause concurrent balance drains","oldWay":"Sequential execution prevents double-spend by ordering","newWay":"Reserve balance guarantees a gas budget even under concurrent execution","impact":"critical"},{"problem":"Users accidentally drain accounts completely","oldWay":"MAX button sends everything, account now useless","newWay":"Can't spend below reserve (unless using emptying transaction)","impact":"high"},{"problem":"New users confused by different balance types","oldWay":"\"I have 100 ETH\" (but actually 100 is fully spendable)","newWay":"\"100 MON total, 90 MON spendable\" is explicit","impact":"medium"},{"problem":"DeFi positions risk trapping users","oldWay":"Stake everything, can't afford gas to unstake","newWay":"Reserve prevents full lockup for most transactions","impact":"medium"}],"uxPatterns":[{"name":"Balance Display with Reserve","description":"Show both total and spendable balances","mockup":"concept/gas-abstraction","userFlow":["User opens wallet","App fetches total balance","Subtracts reserve amount","Displays both clearly","Tooltip explains reserve"]},{"name":"Reserve-Aware Send Form","description":"Prevent sending more than spendable","mockup":"concept/gas-abstraction","userFlow":["User opens send form","Shows spendable, not total","MAX calculates safely","Validates against spendable","Prevents invalid sends"]},{"name":"Low Balance Warning","description":"Alert when approaching reserve threshold","mockup":"generic/balance-display","userFlow":["App monitors spendable balance","When below threshold, show warning","Estimate remaining transactions","Offer easy add funds action","User can dismiss or act"]},{"name":"Emptying Transaction Flow","description":"Allow undelegated accounts to send their full balance once per k-block period","mockup":"generic/balance-display","userFlow":["User has balance below 10 MON reserve","App checks emptying tx eligibility (undelegated, no recent txs)","Shows explanation of emptying transaction rules","User sends full balance in single transaction","App shows cooldown notice: wait ~3 blocks before next tx"]},{"name":"Transaction Revert Notice","description":"Handle transactions that are included in a block but revert during execution","mockup":"concept/gas-abstraction","userFlow":["Transaction submitted and included in block","Execution reverts due to balance falling below reserve","App detects revert and shows clear explanation","Shows current spendable balance for context","Offers retry with updated amounts"]},{"name":"Reserve Explanation Modal","description":"Educate users on why reserve exists","mockup":"concept/gas-abstraction","userFlow":["User clicks \"?\" on reserve","Modal explains concept","Shows with/without comparison","User understands and dismisses"]}],"uiComponents":[{"name":"BalanceBreakdown","description":"Shows total, spendable, and reserved amounts","states":["loading","healthy","low","critical"],"props":["total","spendable","reserved","showDetails"]},{"name":"ReserveIndicator","description":"Visual indicator of reserved amount","states":["normal","highlighted","tooltip-open"],"props":["amount","onClick"]},{"name":"SpendableAmountInput","description":"Input that validates against spendable balance","states":["valid","exceeds-spendable","exceeds-total"],"props":["value","spendable","onChange","onMax"]},{"name":"LowBalanceAlert","description":"Warning banner for low spendable balance","states":["hidden","warning","critical"],"props":["spendable","threshold","onAddFunds","onDismiss"]},{"name":"ReserveExplainerModal","description":"Educational modal about reserve system","states":["closed","open"],"props":["reserveAmount","onClose"]},{"name":"EmptyingTxBanner","description":"Shows emptying transaction eligibility and rules for sub-reserve accounts","states":["eligible","ineligible-delegated","ineligible-cooldown","hidden"],"props":["balance","isDelegated","blocksSinceLastTx","kBlocks"]},{"name":"TransactionRevertNotice","description":"Explains why a transaction was included in a block but reverted during execution","states":["hidden","shown"],"props":["txHash","revertReason","currentSpendable","gasUsed","onRetry"]}],"antiPatterns":[{"pattern":"Showing only total balance","why":"Users think they can spend 100 MON when only 90 is spendable","instead":"Always show spendable as primary, total as secondary","severity":"critical"},{"pattern":"MAX button sending total balance","why":"Transaction will revert during execution, user loses gas fees","instead":"MAX = spendable - estimated gas","severity":"critical"},{"pattern":"Ignoring transaction reverts from concurrent execution","why":"Under async execution, balance can change between submission and execution — valid transactions can be included in a block but still revert","instead":"Detect reverts, explain the cause, and offer retry with updated amounts","severity":"high"},{"pattern":"No explanation of reserve","why":"Users confused why balance is \"locked\"","instead":"Clear info icon explaining reserve protects against async execution risks","severity":"high"},{"pattern":"Hiding the emptying transaction option","why":"Users with <10 MON think they can't transact at all","instead":"Show emptying transaction eligibility and cooldown for undelegated accounts","severity":"high"},{"pattern":"Treating delegated and undelegated accounts the same","why":"Delegated accounts (EIP-7702) cannot use emptying transactions — different rules apply","instead":"Check delegation status and show appropriate balance/send constraints","severity":"high"},{"pattern":"Using Ethereum wallet UX patterns unchanged","why":"Monad has different balance semantics and two-layer enforcement (consensus + execution)","instead":"Design specifically for reserve model","severity":"high"},{"pattern":"Letting users feel \"trapped\" by reserve","why":"Negative UX, feels like funds are inaccessible","instead":"Frame positively: \"Always able to transact\" and mention emptying tx escape hatch","severity":"medium"}],"onMonad":[{"aspect":"Balance Model","ethereum":"Balance is fully spendable","monad":"10 MON minimum reserve required per EOA","designImplication":"All balance UIs must show spendable vs total"},{"aspect":"Enforcement","ethereum":"Sequential execution prevents double-spend by ordering","monad":"Two-layer enforcement: consensus-time (inflight tx budget over k=3 blocks) and execution-time (revert if ending balance < reserve)","designImplication":"Transactions can be included in blocks but still revert — design for this edge case"},{"aspect":"Emptying Exception","ethereum":"No concept — balance fully spendable down to zero","monad":"Undelegated accounts get one emptying tx per k-block period that bypasses reserve","designImplication":"Show emptying tx eligibility for sub-10-MON accounts; explain cooldown period"},{"aspect":"MAX Calculations","ethereum":"MAX = balance - gas","monad":"MAX = balance - reserve - gas (or full balance via emptying tx if eligible)","designImplication":"MAX button logic must check delegation status and emptying tx eligibility"},{"aspect":"Smart Wallets (EIP-7702)","ethereum":"Can delegate entire balance","monad":"Delegated accounts cannot use emptying exception — reserve strictly enforced","designImplication":"Delegated accounts have stricter constraints; session keys can't bypass reserve"}],"keyTakeaways":["Monad requires 10 MON minimum reserve per EOA for async execution safety","ALWAYS show spendable balance, not just total","MAX button must account for reserve AND check emptying tx eligibility","Undelegated accounts can bypass reserve once per ~3 blocks (emptying transaction)","Delegated accounts (EIP-7702) cannot use the emptying exception","Transactions can be included in blocks but revert during execution — handle this gracefully","Frame reserve as benefit: \"Always able to transact\""],"technicalNotes":"Monad enforces a minimum balance reserve (10 MON per EOA) to preserve safety under asynchronous execution. Enforcement happens at two layers: (1) Consensus-time — validates that inflight transactions (included less than k=3 blocks ago) don't exceed a gas spend budget equal to the reserve balance or the account's lagged-state balance, whichever is lower. (2) Execution-time — transactions revert when the account's ending balance (before refunds) dips below the reserve, except for emptying transactions. Emptying transactions allow undelegated accounts to bypass the reserve once per k-block period, provided: the account has been undelegated for k blocks, has no pending delegation changes, and hasn't sent a transaction in the last k blocks. Delegated accounts (EIP-7702) cannot use the emptying exception and are strictly bound by the reserve. Note: valid transactions can be included in blocks but still revert during execution because consensus cannot access current state during validation."},"sources":[],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/MONAD-RESERVE","markdown":"https://www.eipsfordesigners.com/standards/MONAD-RESERVE/content.md","agent":"https://www.eipsfordesigners.com/standards/MONAD-RESERVE/agent.md","api":"https://www.eipsfordesigners.com/api/standards/MONAD-RESERVE"},"freshness":{"lastReviewed":"2026-04-05","lastUpdated":"2026-04-05"}}