{"id":"ERC-223","name":"Token with Transaction Handling","status":"Final","chain":"both","category":{"id":"transaction-friction","name":"Transaction Friction","description":"Reducing clicks, signatures, and mental overhead"},"journeyStages":[{"id":"executing","name":"Executing Transactions","description":"Performing on-chain actions"}],"uxImpact":"Tokens notify receiving contracts and revert if handler missing — prevents tokens being permanently lost to incompatible contracts. Design implications: show 'safe transfer' indicators, remove 'tokens may be lost' warnings for 223 tokens, simplify deposit flows since callback handles everything. Design decisions: low adoption limits usefulness — must handle mixed token standards gracefully, decide whether to surface the safety difference to users or abstract it away, consider that 223 transfers to EOAs work normally. Addresses Sending to Wrong Address pain point (Critical severity) — users sending tokens to contracts that can't handle them is a permanent-loss scenario. ERC-223 addresses the contract-send case specifically (tokens bounce back), complementing ENS/address-book solutions which address the human-error case.","hasDetailedContent":true,"content":{"id":"ERC-223","summary":"ERC-223 prevents tokens from being permanently lost by adding a safety mechanism: contracts must explicitly accept tokens or the transfer reverts. Unlike ERC-20 where sending tokens to a contract that doesn't handle them means they're gone forever, ERC-223 tokens bounce back if the recipient can't process them. It also combines approve+transferFrom into a single transfer with data, reducing steps.","applicability":{"whenToUse":["Your product addresses: tokens sent to wrong contracts are lost forever.","Your product addresses: transfer to contracts requires approve + transferFrom.","The flow should deliver: transfer reverts if contract doesn't implement receiver.","You are designing a safe transfer with callback experience with visible states and recovery paths."],"whenToAvoid":["Clear message: \"Contract can't receive these tokens, yours are safe\".","Highlight \"One-step deposit\" when interacting with contracts.","Badge indicating \"Protected transfer\" for ERC-223.","The flow is a single low-risk transfer where batching adds confusion."]},"designerTakeaways":["You can design UI that delivers transfer reverts if contract doesn't implement receiver.","You can design UI that delivers single transfer() with data parameter triggers action.","You can design UI that delivers tokenReceived() callback lets contract process immediately."],"problemsSolved":[{"problem":"Tokens sent to wrong contracts are lost forever","oldWay":"Send ERC-20 to contract without handler = permanent loss","newWay":"Transfer reverts if contract doesn't implement receiver","impact":"critical"},{"problem":"Transfer to contracts requires approve + transferFrom","oldWay":"Two transactions: approve contract, then call contract","newWay":"Single transfer() with data parameter triggers action","impact":"high"},{"problem":"No way for contracts to react to incoming tokens","oldWay":"Contract has no idea tokens arrived, must be notified separately","newWay":"tokenReceived() callback lets contract process immediately","impact":"high"},{"problem":"Users accidentally send tokens to token contract itself","oldWay":"Common mistake: send USDC to USDC contract address = lost","newWay":"Token contract can reject or return accidental sends","impact":"medium"},{"problem":"Deposit flows are fragmented across transactions","oldWay":"Approve → Deposit → Contract pulls tokens (3 interactions)","newWay":"Transfer to contract triggers deposit in one action","impact":"medium"}],"uxPatterns":[{"name":"Safe Transfer with Callback","description":"One-step deposit that triggers action","mockup":"generic/token-approval","userFlow":["User enters deposit amount","UI shows this is a one-step process","User clicks deposit","Transfer with data triggers vault deposit","Vault credits user automatically"]},{"name":"Protected Address Warning","description":"Prevent sending to incompatible addresses","mockup":"generic/token-transfer","userFlow":["User enters contract address","UI detects it's a contract (not EOA)","Shows warning but explains safety","ERC-223 protection reassures user","Transaction reverts if incompatible"]},{"name":"Transfer Revert Explanation","description":"When transfer fails due to incompatible recipient","mockup":"concept/tx-status","userFlow":["Transfer to incompatible contract","Transaction reverts (tokens safe)","UI explains what happened positively","Shows balance unchanged","Suggests alternatives"]},{"name":"Token Transfer with Payload","description":"Attach data to trigger specific actions","mockup":"concept/nft-gallery","userFlow":["User clicks buy on NFT","UI shows payment will include data","Explains atomic nature","Transfer triggers NFT delivery","Both happen in one transaction"]}],"uiComponents":[{"name":"ContractCompatibilityCheck","description":"Verify if recipient handles ERC-223","states":["checking","compatible","incompatible","unknown"],"props":["address","tokenAddress","onResult"]},{"name":"TransferWithData","description":"Transfer input with optional data payload","states":["simple","with-data","encoding","ready"],"props":["amount","recipient","data","onTransfer"]},{"name":"SafetyIndicator","description":"Badge showing ERC-223 protection status","states":["protected","unprotected","unknown"],"props":["tokenStandard","recipient"]},{"name":"RevertExplainer","description":"Friendly explanation when transfer reverts","states":["displaying","dismissed"],"props":["reason","tokenName","alternatives"]}],"antiPatterns":[{"pattern":"Not explaining why transfers can fail","why":"Users confused when transaction reverts","instead":"Clear message: \"Contract can't receive these tokens, yours are safe\"","severity":"high"},{"pattern":"Hiding the callback/data functionality","why":"Users miss the one-transaction benefit","instead":"Highlight \"One-step deposit\" when interacting with contracts","severity":"high"},{"pattern":"Showing ERC-223 transfers same as ERC-20","why":"Users don't understand the safety difference","instead":"Badge indicating \"Protected transfer\" for ERC-223","severity":"medium"},{"pattern":"Not pre-checking contract compatibility","why":"Users waste gas on doomed transfers","instead":"Simulate transfer, warn if it would revert","severity":"medium"},{"pattern":"Complex data encoding exposed to users","why":"Technical details confuse users","instead":"UI constructs data payload, shows human-readable summary","severity":"medium"}],"onMonad":[{"aspect":"Callback Execution","ethereum":"tokenReceived callback may be gas-heavy","monad":"Cheap gas makes callbacks practical for complex logic","designImplication":"Can offer richer callback-triggered actions"},{"aspect":"Revert Speed","ethereum":"Failed transfer still takes time to confirm failure","monad":"Sub-second feedback on incompatible transfers","designImplication":"Instant \"tokens safe\" confirmation on revert"},{"aspect":"Simulation","ethereum":"Pre-checking compatibility requires RPC calls","monad":"Fast simulation for compatibility checking","designImplication":"Real-time compatibility indicator as user types address"},{"aspect":"Atomic Operations","ethereum":"Transfer+action atomic but slow confirmation","monad":"Atomic operations with instant finality","designImplication":"Buy NFT flow completes visibly in under 1 second"}],"keyTakeaways":["ERC-223 = tokens that can't be lost to incompatible contracts","Always explain the safety benefit vs ERC-20","Use positive messaging when transfers revert (\"tokens safe!\")","Highlight one-step contract interactions","On Monad: instant feedback on both successful and failed transfers"],"technicalNotes":"ERC-223 adds a transfer(address, uint256, bytes) function that calls tokenReceived(address, uint256, bytes) on the recipient if it's a contract. If the recipient doesn't implement this interface, the transfer reverts. This prevents tokens from being stuck in contracts that don't handle them. The data parameter allows passing arbitrary info to trigger actions."},"sources":[{"label":"Official specification","url":"https://eips.ethereum.org/EIPS/eip-223","type":"official-spec"},{"label":"Discussion","url":"https://ethereum-magicians.org/search?q=ERC-223","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-223","markdown":"https://www.eipsfordesigners.com/standards/ERC-223/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-223/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-223","official":"https://eips.ethereum.org/EIPS/eip-223","discussion":"https://ethereum-magicians.org/search?q=ERC-223"},"freshness":{"lastReviewed":"2026-04-05","lastUpdated":"2026-04-05"}}