{"id":"ERC-1363","name":"Payable Token","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"},{"id":"gas","name":"Gas & Fees","description":"Paying for transactions"}],"uxImpact":"ERC-1363 defines transferAndCall and approveAndCall receiver interfaces for tokens and compatible contracts. When both sides implement the relevant callback, one transaction can transfer tokens and invoke a contract action; callback success does not by itself guarantee the business service outcome.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-1363","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"ERC-1363","summary":"ERC-1363 defines transferAndCall and approveAndCall receiver interfaces for tokens and compatible contracts. When both sides implement the relevant callback, one transaction can transfer tokens and invoke a contract action; callback success does not by itself guarantee the business service outcome.","applicability":{"whenToUse":["The selected token and recipient can combine payment and callback handling in one transaction.","The product can explain the difference between approveAndCall and transferAndCall.","The selected token and recipient implement the callback path and the product can explain its success and failure states.","You are designing a purchase or service flow with visible callback, business-state, and recovery states."],"whenToAvoid":["The token or recipient does not implement the ERC-1363 callback interface needed for this flow.","The receiving contract cannot validate that msg.sender is the expected token contract or handle callback failure safely.","The product needs universal ERC-20 compatibility or a separate approve-and-call flow is clearer."]},"designerTakeaways":["Explain that a compatible token and recipient can transfer tokens and invoke a callback in one transaction.","Show the callback action and its data in the review step before signing.","Handle unsupported callbacks, callback reverts, and successful transfers whose business action still needs confirmation.","Validate that the callback caller is the expected token contract and keep callback logic bounded."],"problemsSolved":[{"problem":"Payment and service delivery require two steps","oldWay":"User sends tokens, then separately triggers service (two transactions)","newWay":"A compatible token and recipient can invoke a callback during the transfer transaction","impact":"critical"},{"problem":"Approve + transferFrom requires two transactions","oldWay":"Approve contract to spend tokens, then call contract to pull tokens","newWay":"transferAndCall can combine token transfer and callback invocation when the token and recipient support it","impact":"high"},{"problem":"Payment contracts need complex state tracking","oldWay":"Track who approved, pull payments on demand, handle edge cases","newWay":"The callback receives transfer data that the recipient can validate and process according to its own rules","impact":"high"},{"problem":"Users can approve but never complete purchase","oldWay":"Approval sits unused, confusing for users and contracts","newWay":"A callback revert can revert the transaction, but a successful callback is not proof that the external service fulfilled its promise","impact":"medium"},{"problem":"Can't include payment context with transfer","oldWay":"Transfer tokens, then separately communicate what it's for","newWay":"Include data parameter with transfer for context","impact":"medium"}],"uxPatterns":[{"name":"One-Click Purchase","description":"Use one token transfer and callback when the selected token, receiver, and business action support it","userFlow":["User views item for sale","Clicks \"Buy Now\"","Wallet prompts to send 500 GAME","User confirms","Callback reports the selected contract action","Show transfer confirmation separately from the external item or service outcome"]},{"name":"Subscription Activation","description":"Attempt payment and callback activation in one transaction when the integration supports it","userFlow":["User selects subscription tier","Clicks \"Pay & Activate\"","Token transfer includes subscription data","Contract receives tokens + callback","Callback reports its activation result","Show service access only after the product verifies its own service state"]},{"name":"Crowdfund Contribution","description":"Send a contribution with callback data when the recipient supports the reward action","userFlow":["User enters contribution amount","UI shows reward tier earned","User clicks Contribute","Tokens transferred with backer data","Callback reports its reward or recording result","Show the token transfer and reward state separately when the product can verify both"]},{"name":"Token-Gated Access","description":"Send an entry payment and callback request when the recipient supports both","userFlow":["User views community details","Clicks \"Pay & Get Access\"","Token transfer includes user address","Contract receives payment","Callback reports its access result","Show access only after the product verifies its own authorization state"]}],"uiComponents":[{"name":"PayableTokenButton","description":"Single-click payment button using transferAndCall","states":["ready","confirming","processing","success","error"],"props":["amount","token","recipient","callData","onSuccess"]},{"name":"AtomicPurchaseCard","description":"Product card with one-click purchase","states":["available","purchasing","owned","sold-out"],"props":["item","price","tokenSymbol","onPurchase"]},{"name":"TransferWithDataForm","description":"Form for transfers with attached data","states":["editing","reviewing","sending","complete"],"props":["recipient","amount","dataFields[]","onSubmit"]},{"name":"CallbackStatusIndicator","description":"Shows if transfer callback succeeded","states":["pending","callback-executing","success","callback-failed"],"props":["transferHash","callbackResult","error"]},{"name":"InstantActivationBadge","description":"Indicates that a callback may request a service action in the same transaction","states":["default","highlighted"],"props":["featureName","tooltip"]}],"antiPatterns":[{"pattern":"Still requiring approve + action for ERC-1363 tokens","why":"Defeats the purpose, users still need two transactions","instead":"Use transferAndCall or approveAndCall for single-tx flow","severity":"critical"},{"pattern":"Not handling callback failure gracefully","why":"Transfer succeeds but callback fails = confusing state","instead":"Define callback failure behavior explicitly and show when a successful callback still needs service-state verification","severity":"critical"},{"pattern":"Not explaining the one-click benefit","why":"Users don't know they're getting better UX","instead":"Show \"No approval needed for this supported path\" and state that callback and service outcomes may need separate confirmation","severity":"medium"},{"pattern":"Using transferAndCall without validating caller","why":"Anyone can call your callback with arbitrary data","instead":"Check msg.sender is the token contract in onTransferReceived","severity":"critical"},{"pattern":"Complex callback logic that might fail","why":"Failed callback means lost funds or stuck state","instead":"Keep callbacks simple, validate inputs, handle edge cases","severity":"high"},{"pattern":"Not showing what callback will do","why":"Users don't understand what happens after transfer","instead":"Explain \"Pay and receive [item]\" or \"Pay and activate [service]\"","severity":"medium"}],"keyTakeaways":["ERC-1363 lets compatible token and recipient contracts combine transfer or approval with a callback","Use it for purchases, subscriptions, or access flows only when the selected integration implements the callback path","Show the one-transaction path without claiming that the external service completed","Validate token caller in callbacks for security","Keep callbacks simple to prevent failed transactions"],"technicalNotes":"ERC-1363 extends ERC-20 with transferAndCall, transferFromAndCall, approveAndCall. Receivers implement IERC1363Receiver with onTransferReceived(operator, from, value, data). Spenders implement IERC1363Spender with onApprovalReceived(owner, value, data). Must return magic bytes4 to confirm callback handled successfully.","lastUpdated":"2026-09-18","specConstraints":[{"id":"transfer-callback-recipient","constraint":"A contract accepting `transferAndCall` or `transferFromAndCall` must implement the receiver interface.","appliesTo":"application","normativity":"normative","specQuote":"A contract that wants to accept token payments via `transferAndCall` or `transferFromAndCall` **MUST** implement the following interface:","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-1363#specification","designImplication":"Detect callback support before presenting a one-transaction token payment and show a fallback when the recipient cannot handle it."},{"id":"transfer-callback-acceptance","constraint":"A transfer callback must return the required magic value or the call fails.","appliesTo":"application","normativity":"normative","specQuote":"* transfer. Return of other than the magic value MUST result in the\n* transaction being reverted.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-1363#specification","designImplication":"Show callback rejection separately from token balance failure and keep the payment retryable."},{"id":"approval-callback-recipient","constraint":"A contract accepting `approveAndCall` must implement the approval receiver interface.","appliesTo":"application","normativity":"normative","specQuote":"A contract that wants to accept token payments via `approveAndCall` **MUST** implement the following interface:","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-1363#specification","designImplication":"Explain that approval and follow-up action are coupled in this path and identify the recipient contract before confirmation."},{"id":"approval-callback-acceptance","constraint":"An approval callback must return the required magic value or the call fails.","appliesTo":"application","normativity":"normative","specQuote":"* approval. Return of other than the magic value MUST result in the\n* transaction being reverted.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-1363#specification","designImplication":"Keep an explicit callback-rejected state and do not show the allowance action as completed without the return value."},{"id":"erc20-callback-compatibility","constraint":"The extension preserves ERC-20 transfer and transferFrom methods while adding callback methods.","appliesTo":"application","normativity":"backwards-compatibility","specQuote":"## Backwards Compatibility\nThis proposal has been inspired also by [ERC-223](https://github.com/ethereum/EIPs/issues/223) and [ERC-677](https://github.com/ethereum/EIPs/issues/677) but it uses the [ERC-721](./eip-721.md) approach, so it doesn't override the [ERC-20](./eip-20.md) `transfer` and `transferFrom` methods and defines the interfaces IDs to be implemented maintaining the [ERC-20](./eip-20.md) backwards compatibility.","specSection":"Backwards Compatibility","specUrl":"https://ercs.ethereum.org/ERCS/erc-1363#backwards-compatibility","designImplication":"Keep ordinary ERC-20 sends available and label callback-enabled payments as a separate path."},{"id":"approval-callback-race","constraint":"Changing an allowance with approve-and-call has the same transaction-ordering race as ERC-20 approval.","appliesTo":"application","normativity":"security-considerations","specQuote":"Changing an allowance with the `approveAndCall` methods brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering.","specSection":"Security Considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-1363#security-considerations","designImplication":"Show the spender and replacement amount clearly and use a zero-first allowance update when the product needs to reduce this race."}],"sources":[{"label":"ERC-1363 official specification","url":"https://ercs.ethereum.org/ERCS/erc-1363","type":"official-spec"}],"lastReviewed":"2026-09-18"},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-1363","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=ERC-1363","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-1363","markdown":"https://www.eipsfordesigners.com/standards/ERC-1363/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-1363/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-1363","official":"https://ercs.ethereum.org/ERCS/erc-1363","discussion":"https://ethereum-magicians.org/search?q=ERC-1363"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}