{"id":"ERC-5164","name":"Cross-Chain Execution","status":"Last Call","chain":"both","category":{"id":"cross-chain","name":"Cross-Chain","description":"Moving assets and messages between chains"},"journeyStages":[{"id":"executing","name":"Executing Transactions","description":"Performing on-chain actions"},{"id":"status","name":"Status & Confirmation","description":"Waiting for and confirming outcomes"}],"uxImpact":"ERC-5164 standardizes message dispatch and destination execution interfaces for cross-chain applications. A bridge adapter can carry a dispatcher message to a destination executor, while bridge selection, timing, security, status, and recovery remain provider-specific.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-5164","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"ERC-5164","summary":"ERC-5164 standardizes message dispatch and destination execution interfaces for cross-chain applications. A bridge adapter can carry a dispatcher message to a destination executor, while bridge selection, timing, security, status, and recovery remain provider-specific.","partialDeployment":{"body":"ERC-5164 is Last Call. Treat cross-chain dispatch and execution as conditional on a selected bridge adapter, source and destination deployments, and available status and recovery data; verify bridge support before promising timing or recovery."},"applicability":{"whenToUse":["Your product addresses: each bridge has different interface.","Your product addresses: cross-chain UX is confusing.","The flow should deliver: a dispatcher message reaches a destination executor through a selected bridge adapter.","You are designing a cross-chain action experience with visible states and recovery paths."],"whenToAvoid":["The product never dispatches messages or state across chains.","The flow has no source/destination chain context to display.","The selected bridge/application provides no status or recovery data to surface.","The product only performs same-chain actions."]},"designerTakeaways":["Design around the dispatcher/executor interface for providers that implement it, while disclosing the selected bridge's behavior.","Use source/destination chain and message identifiers to keep the journey legible; do not imply universal timing or recovery.","Show dispatchMessage as a request that reaches remote execution only when the selected bridge/application delivers it and the destination executor invokes the target."],"problemsSolved":[{"problem":"Each bridge has different interface","oldWay":"Learn Arbitrum bridge API, then Optimism, then Polygon...","newWay":"A common dispatcher/executor interface can be used across adapters that implement it; bridge support still needs verification.","impact":"critical"},{"problem":"Cross-chain UX is confusing","oldWay":"Different UI patterns for each chain","newWay":"The UI can keep source, destination, and message stages consistent while provider-specific timing and status remain separate.","impact":"critical"},{"problem":"Can't execute contracts across chains easily","oldWay":"Manual bridging, then manual execution","newWay":"MessageDispatcher sends a message to a destination MessageExecutor, which invokes the target call","impact":"high"},{"problem":"Hard to track cross-chain transactions","oldWay":"Check source chain, then destination, manually","newWay":"The application can correlate dispatcher/executor observations with its bridge-specific tracking data","impact":"high"},{"problem":"Bridge-specific lock-in","oldWay":"App only works with one bridge","newWay":"Swap bridge adapters without changing the application message interface","impact":"medium"}],"uxPatterns":[{"name":"Cross-Chain Action","description":"Execute action on another chain","mockup":"concept/bridge","userFlow":["User wants to stake on different chain","Sees current chain and destination","Views action journey (steps)","Sees time and fee estimates","Signs transaction on source chain","Message bridged to destination","Destination MessageExecutor invokes the target when the selected bridge/application delivers it"]},{"name":"Cross-Chain Transaction Tracker","description":"Track message as it crosses chains","userFlow":["User initiates cross-chain action","Sees progress through each stage","Source chain confirmed first","Bridge/application transit status is shown when available","Destination execution is confirmed from the executor or provider","Links to explorers for verification"]},{"name":"Bridge Selector","description":"Choose which bridge to use","userFlow":["User needs to cross chains","Views bridge options supplied by the application/provider","Compares time, cost, security","Selects preferred bridge","Proceeds with cross-chain action"]},{"name":"Cross-Chain Error Handling","description":"Show when cross-chain action fails","userFlow":["Cross-chain action fails on destination","User sees where failure occurred","Clear error explanation","Explains whether the selected bridge/application offers recovery; message failure alone does not refund assets","Shows only recovery options the provider actually supports"]},{"name":"Governance Cross-Chain","description":"DAO votes execute on multiple chains","userFlow":["DAO proposal passes","Execution begins on all chains","User sees status per chain","Each chain updates as executed","New parameters active when complete"]}],"uiComponents":[{"name":"CrossChainProgress","description":"Multi-step progress for cross-chain tx","states":["source-pending","bridging","destination-pending","complete","failed"],"props":["sourceChain","destChain","bridge","currentStep","timeRemaining"]},{"name":"BridgePicker","description":"Select from available bridges","states":["loading","ready","selected"],"props":["bridges[]","selectedBridge","onSelect"]},{"name":"ChainPairIndicator","description":"Visual showing source → destination","states":["connecting","connected","error"],"props":["sourceChain","destChain","status"]},{"name":"MessageTracker","description":"Track cross-chain message by ID","states":["searching","found","in-transit","delivered","failed"],"props":["messageId","sourceChain","destChain","status"]},{"name":"CrossChainError","description":"Display cross-chain failure with recovery","states":["source-failed","bridge-failed","dest-failed"],"props":["error","failedStep","recoveryOptions[]"]}],"antiPatterns":[{"pattern":"Promising a universal ETA","why":"ERC-5164 does not define timing or a status feed.","instead":"Show a provider-sourced estimate when available and provide pending/unknown states otherwise.","severity":"high"},{"pattern":"Hiding source and destination chain","why":"A message can be delivered or fail across distinct environments.","instead":"Show chain context and the selected provider at every confirmation and status step.","severity":"critical"},{"pattern":"Claiming real-time progress without provider data","why":"The interface exposes message calls and identifiers, not a universal progress stream.","instead":"Display only observed dispatcher, bridge, and executor events.","severity":"high"},{"pattern":"Treating remote execution failure as automatic refund","why":"Timing, security, and recovery remain bridge/application-specific.","instead":"Show the failed stage and only provider-supported recovery actions.","severity":"critical"},{"pattern":"Hiding bridge selection and tradeoffs","why":"Route, security, cost, and recovery vary by provider.","instead":"Name the selected bridge/application and label each estimate or guarantee source.","severity":"medium"}],"keyTakeaways":["ERC-5164 standardizes dispatcher and executor calls for compatible cross-chain applications.","Show source, destination, message ID, and provider data separately.","Provide timing and progress only when the selected bridge/application exposes them, with pending/unknown states.","Treat recovery, ordering, security, and refunds as provider/application behavior."],"specConstraints":[{"id":"erc-5164-dispatcher-executor-pair","constraint":"A compatible implementation includes both a Message Dispatcher on the calling side and a Message Executor on the receiving side.","appliesTo":"application","normativity":"normative","specQuote":"The specification defines two components: the \"Message Dispatcher\" and the \"Message Executor\". The Message Dispatcher lives on the calling side, and the executor lives on the receiving side. When a message is sent, a Message Dispatcher will move the message through a transport layer to a Message Executor, where they are executed. Implementations of this specification must implement both components.","specSection":"Abstract","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#abstract","designImplication":"Only present a cross-chain action as ERC-5164-backed when the selected source and destination deployments expose the corresponding dispatcher and executor; keep bridge transport behavior separately labeled."},{"id":"erc-5164-unique-message-id","constraint":"Each message or batch has a messageId unique across chains and dispatchers.","appliesTo":"application","normativity":"normative","specQuote":"A unique `messageId` MUST be generated for each message or message batch. The message identifier MUST be unique across chains and dispatchers.","specSection":"Specification — MessageDispatcher","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#messagedispatcher","designImplication":"Use the messageId as the stable cross-chain correlation key, while showing source chain and dispatcher so users can distinguish otherwise similar messages."},{"id":"erc-5164-destination-routing","constraint":"A MessageDispatcher rejects unsupported destination chains and forwards supported messages to a MessageExecutor on the requested chain.","appliesTo":"application","normativity":"normative","specQuote":"`MessageDispatcher`s MUST revert if `toChainId` is not supported.\n\n`MessageDispatcher`s MUST forward the message to a `MessageExecutor` on the `toChainId`.","specSection":"Specification — MessageDispatcher — MessageDispatcher Methods","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#messagedispatcher-methods","designImplication":"Validate destination support before signing and make an unsupported-chain failure explicit; do not show a remote execution step until the selected route actually supports it."},{"id":"erc-5164-dispatch-tracking","constraint":"Dispatch returns the unique messageId and emits MessageDispatched so the sender can track the message.","appliesTo":"application","normativity":"normative","specQuote":"`MessageDispatcher`s MUST return the `messageId` to allow the message sender to track the message.","specSection":"Specification — MessageDispatcher — MessageDispatcher Methods","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#messagedispatcher-methods","designImplication":"Persist the returned identifier in the confirmation and tracker; if an adapter does not expose it, label cross-chain tracking as unavailable rather than inventing a substitute."},{"id":"erc-5164-dispatched-event","constraint":"A MessageDispatcher emits MessageDispatched for each individual message.","appliesTo":"infrastructure","normativity":"normative","specQuote":"The `MessageDispatched` event MUST be emitted by the `MessageDispatcher` when an individual message is dispatched.","specSection":"Specification — MessageDispatcher — MessageDispatcher Events","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#messagedispatcher-events","designImplication":"Use the observed dispatch event as the source-backed start of a cross-chain timeline, and distinguish it from bridge transit or destination execution."},{"id":"erc-5164-transport-verification","constraint":"A MessageExecutor should verify message data with the bridge transport layer before executing it.","appliesTo":"infrastructure","normativity":"normative","specQuote":"`MessageExecutor`s SHOULD verify all message data with the bridge transport layer.","specSection":"Specification — MessageExecutor — Execution","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#execution","designImplication":"Show the selected bridge or transport verification source in an advanced trust view; do not imply that the generic dispatcher interface alone authenticates a message."},{"id":"erc-5164-no-duplicate-execution","constraint":"A MessageExecutor must not successfully execute a message more than once.","appliesTo":"infrastructure","normativity":"normative","specQuote":"`MessageExecutor`s MUST NOT successfully execute a message more than once.","specSection":"Specification — MessageExecutor — Execution","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#execution","designImplication":"Represent duplicate delivery as an already-executed terminal state, not as a second successful user action."},{"id":"erc-5164-retry-failed-message","constraint":"A failed message execution reverts its transaction so the message can be retried later.","appliesTo":"application","normativity":"normative","specQuote":"`MessageExecutor`s MUST revert the transaction when a message fails to be executed allowing the message to be retried at a later time.","specSection":"Specification — MessageExecutor — Execution","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#execution","designImplication":"Show destination failure and retry eligibility as separate states; never imply that a reverted destination execution automatically refunds or reverses bridge-side effects."},{"id":"erc-5164-cross-chain-provenance","constraint":"Destination calldata includes messageId, fromChainId, and from so the receiver can verify the cross-chain sender and origin chain.","appliesTo":"infrastructure","normativity":"normative","specQuote":"`MessageExecutor`s MUST append the ABI-packed (`messageId`, `fromChainId`, `from`) to the calldata for each message being executed. This allows the receiver of the message to verify the cross-chain sender and the chain that the message is coming from.","specSection":"Specification — MessageExecutor — Execution — Calldata","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#calldata","designImplication":"When displaying remote call provenance, show the source chain and sender supplied by the executor; do not reduce a cross-chain call to an unqualified destination address."},{"id":"erc-5164-executed-event","constraint":"MessageIdExecuted is emitted once a message or batch has executed.","appliesTo":"application","normativity":"normative","specQuote":"`MessageIdExecuted` MUST be emitted once a message or message batch has been executed.","specSection":"Specification — MessageExecutor — MessageExecutor Events","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#messageexecutor-events","designImplication":"Use the destination execution event as the completion signal only after confirming its source chain and messageId."},{"id":"erc-5164-duplicate-error","constraint":"An executor reverts an already executed message and should identify that duplicate with MessageIdAlreadyExecuted.","appliesTo":"application","normativity":"normative","specQuote":"`MessageExecutor`s MUST revert if a messageId has already been executed and SHOULD emit a `MessageIdAlreadyExecuted` custom error.","specSection":"Specification — MessageExecutor — MessageExecutor Errors","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#messageexecutor-errors","designImplication":"Explain duplicate-delivery errors as idempotency protection and keep retry controls disabled when the message already executed."},{"id":"erc-5164-failure-error","constraint":"An executor reverts an individually failing message and should emit MessageFailure.","appliesTo":"application","normativity":"normative","specQuote":"`MessageExecutor`s MUST revert if an individual message fails and SHOULD emit a `MessageFailure` custom error.","specSection":"Specification — MessageExecutor — MessageExecutor Errors","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#messageexecutor-errors","designImplication":"Keep the failure reason and failed stage visible, while presenting recovery only when the selected bridge or application provides it."},{"id":"erc-5164-bridge-trust-profile","constraint":"Bridge security varies by implementation, so users must understand the selected bridge's trust profile.","appliesTo":"application","normativity":"security-considerations","specQuote":"Bridge trust profiles are variable, so users must understand that bridge security depends on the implementation.","specSection":"Security Considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#security-considerations","designImplication":"Name the bridge or transport and disclose its security, timing, and recovery properties at the decision point; the ERC-5164 interface is not a universal trust guarantee."},{"id":"erc-5164-dispatch-payment-option","constraint":"A MessageDispatcher MAY require payment to dispatch a cross-chain message.","appliesTo":"infrastructure","normativity":"normative","specQuote":"`MessageDispatcher`s MAY require payment.","specSection":"Specification — MessageDispatcher — MessageDispatcher Methods","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#messagedispatcher-methods","designImplication":"Disclose any dispatcher or bridge payment before confirmation and treat its presence as route-specific rather than assuming every cross-chain message has the same fee model."},{"id":"erc-5164-execution-order-not-guaranteed","constraint":"A MessageExecutor MAY execute message IDs in any order; ERC-5164 provides no ordering guarantee across messages or batches.","appliesTo":"infrastructure","normativity":"normative","specQuote":"The `MessageExecutor` will execute a messageId only once, but may execute messageIds in any order. This specification makes no ordering guarantees, because messages and message batches may travel non-sequentially through the transport layer.","specSection":"Specification — MessageExecutor","specUrl":"https://ercs.ethereum.org/ERCS/erc-5164#messageexecutor","designImplication":"Track each message independently and avoid presenting cross-chain batches as ordered progress unless the selected bridge or application supplies that guarantee."}],"technicalNotes":"ERC-5164 defines MessageDispatcher.dispatchMessage(uint256 toChainId, address to, bytes data) and a destination MessageExecutor. The executor appends messageId, fromChainId, and from to the destination calldata before invoking the target. It does not define a CrossChainReceiver.processMessage interface, bridge discovery, universal ordering, asset escrow, or refunds; timing, security, tracking, and recovery remain bridge/application-specific.","lastUpdated":"2026-09-18","sources":[{"label":"ERC-5164 official specification","url":"https://ercs.ethereum.org/ERCS/erc-5164","type":"official-spec"}],"lastReviewed":"2026-09-18"},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-5164","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=ERC-5164","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-5164","markdown":"https://www.eipsfordesigners.com/standards/ERC-5164/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-5164/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-5164","official":"https://ercs.ethereum.org/ERCS/erc-5164","discussion":"https://ethereum-magicians.org/search?q=ERC-5164"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}