diff --git a/pages/interop/_meta.json b/pages/interop/_meta.json index 8506dbcd9..003689cd5 100644 --- a/pages/interop/_meta.json +++ b/pages/interop/_meta.json @@ -13,6 +13,7 @@ "predeploy": "Superchain interop predeploys", "message-passing": "Superchain interop message passing", "message-expiration": "Message expiration", + "estimate-costs": "Cost of interop messages", "reading-logs": "Reading logs", "op-supervisor": "OP Supervisor", "superchain-eth-bridge": "Superchain ETH bridge", diff --git a/pages/interop/estimate-costs.mdx b/pages/interop/estimate-costs.mdx new file mode 100644 index 000000000..39aa11a6b --- /dev/null +++ b/pages/interop/estimate-costs.mdx @@ -0,0 +1,119 @@ +--- +title: Estimating the cost of interop messages +description: Estimate the gas cost of Superchain interop messages. +lang: en-US +content_type: guide +topic: interop-gas-estimate +personas: + - protocol-developer + - app-developer +categories: + - interoperability + - cross-chain-messaging + - superchain + - message-passing + - gas-cost +is_imported_content: 'false' +--- + +import { Callout } from 'nextra/components' +import { InteropCallout } from '@/components/WipCallout' + + + +# Estimating the cost of interop messages + + +As of May 2025, the cost of 100 interop messages is just a few cents. +Unless OP Stack transaction costs increase significantly, interop costs should not be a primary consideration in your implementation decisions. + +To see the current cost of gas, go to a [block explorer](https://optimism.blockscout.com/) and look at a recent transaction. + + +There are several factors that determine the cost of an [interop transaction](/interop/message-passing): + +* How you pass the message. + You can either use [`CrossL2Inbox`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol) directly, or use the cross domain messenger, [`L2ToL2CrossDomainMessenger`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol), which uses `CrossL2Inbox` internally. +* The transaction type. + Every interop message has two transactions, an [initiating message](/interop/message-passing#initiating-message) in a transaction to the source chain, and an [executing message](/interop/message-passing#executing-message) in the destination chain. + +## CrossL2Inbox + +This is the low level protocol used by all interop protocols, including `L2ToL2CrossDomainMessenger`. + +### Initiating message + +The initiating message is any log entry. +A log entry emitted by Solidity code contains 1-4 topics (t) and unlimited unstructured data bytes (n). +The gas cost is calculated as [375(t+1)+8n](https://www.evm.codes/?fork=cancun#a1). + +### Executing message + +The executing message cost has several components: + +1. The cost of posting the transaction. +2. The cost of hashing the message. +3. The cost of `CrossL2Inbox.validateMessage`. +4. The cost of using the message. + +The first and second components depend on the log entry. +`CrossL2Inbox.validateMessage` only requires a 32 byte hash of the log entry, but actually using it typically requires the information that has been hashed. + +Additionally, you must provide the `CrossL2Inbox` with the information needed to locate the log entry. +This information is encoded in a [five-member structure](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L7-L19) that requires 160 bytes (32 bytes × 5 members). +Lastly, you need to call a function which requires a 4-byte selector. + +Therefore, the total bytes required is: **164 + 32t + n** + +Where: +* `164` = base overhead (160 bytes for the structure + 4 bytes for the function selector) +* `t` = number of topics in the log entry +* `n` = number of data bytes in the log entry + +Every transaction posted costs at least *21,000* gas. +The hashing operation costs approximately [*30+0.2×\*](https://www.evm.codes/?fork=cancun#20), which is negligible by comparison. +We can usually ignore the [memory expansion cost](https://www.evm.codes/about#memoryexpansion), unless the validating contract uses a really large amount of memory. + +The cost of using the message is beyond the scope here, because it depends on your application. + +The main cost drivers are the 21,000 gas transaction cost plus the cost of posting a *164+32t+n* byte transaction. + +## Cross domain messenger + +This higher level protocol adds some expenses, mostly because replay protection requires storage, and [writing to storage](https://www.evm.codes/?fork=cancun#55) is a relatively expensive operation. + +### Initiating message + +The initiating message is sent by [`L2ToL2CrossDomainMessenger.sendMessage`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol#L128-L161). This function writes to storage twice. + +It writes to [specify that the hash has a sent message](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol#L157). +This would typically be written to previously empty storage, so the cost is *22,100* gas. + +Then it [increments the nonce value](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol#L158). +Overwriting previously used storage (which means storage where the present value is *not* zero) only costs *5,000* gas. + +Hence, the gas cost for creating an initiating message is approximately *27,100* gas, plus minor overhead for log emission and contract operations. +Note that this estimate excludes the 21,000 gas base transaction cost, which applies to all transactions. + +### Executing message + +If autorelay is turned on in a blockchain, then you don't care about the cost of the executing message. +The chain operator will bear the cost. + +If autorelay is not turned on, the executing message is a call to [`L2ToL2CrossDomainMessenger.relayMessage`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol#L197-L256). +The only storage operation here is [noting the hash has been used for a message already](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol#L241). +This is previously unwritten storage, so we can expect to pay the full *22,100* in gas. +Plus, of course, the *21,000* that any transaction costs. +All the other gas costs are negligible. + +## Conclusion + +Unless the message is *extremely* long, the cost of an interop message, taking both sides together, is unlikely to exceed *100,000* gas. +At the time of writing, each gas unit costs approximately `$3×10^-9`, so it would take about thirty messages to add up to a full cent. + +## Next steps + +* Build a [revolutionary app](/app-developers/get-started) that uses multiple blockchains within the Superchain +* Deploy a [SuperchainERC20](/interop/tutorials/deploy-superchain-erc20) to the Superchain +* Learn [how messages get from one chain to another chain](/interop/message-passing) +* Watch [this video](https://www.youtube.com/watch?v=FKc5RgjtGes), which gives an overview of Superchain interoperability. diff --git a/words.txt b/words.txt index f2d1ff61c..5dbe5bf14 100644 --- a/words.txt +++ b/words.txt @@ -85,7 +85,6 @@ counterfactually Crosschain crosschain Crossmint -custom-bridge Dapphub daserver DATACAP @@ -94,8 +93,8 @@ DATADIR datadir devdocs Devnet -Devnets devnet +Devnets devnets direnv DISABLETXPOOLGOSSIP