When contracts send messages from Ethereum to a rollup they need to pay for the execution of the message as a tx on the rollup. Arbitrum and Optimism have different approaches to this.
Makes the message sending function on their bridge payable, and expects the caller to send enough value to cover the cost of the L2 execution. The downside of this is that many existing contracts don’t provide the ability to make payable calls, and even if they did the value would potentially need to be passed from the user through all contracts in the path before reaching the payable function.
An example of this is the ERC721 standard. ERC721s provide a _checkOnERC721Received function that will be called after transferring to a contract. This could be used to transfer an ERC721 token to a contract and check that it has been received. However rollups that require a payable deposit function cant use this method, since _checkOnERC721Received doesn’t send any value with it. Instead, in order for a user to send value with the deposit they must split the deposit into 2 separate transactions:
- Approve a gateway contract to transfer the NFT
- Execute a transferfrom and send value to the rollup to pay for the L2 execution
To avoid enforcing a payable interface Optimism dont receive any funds for L2 execution of the messages. Instead they burn gas proportional to the L2 tx gas limit to prevent callers from being able to DOS the rollup nodes into processing arbitrary amounts of L2 gas for free. The downside of this is that the burning the gas takes up L1 block space, which is a valuable resource.
Below are two alternative proposals for new Ethereum opcodes that could accept funds without forcing changes on the public interfaces of calling contracts.
A new opcode (EXTRACTGAS) that extracts gas from the gas stipend of a transaction, converts it to value and sends it to the current address. The opcode increases gasUsed by gasExtracted and sends gasExtracted*tx.gasprice to the current address. Additionally when calculating the total amount of gas used in a block the total amount of gas extracted would need be subtracted from the gas used to ensure that the block gas limit wasn’t effected: blockGasUsed - blockGasExtracted < blockGasLimit.
A new transaction type that includes an additional value field called originValue, and a new opcode (PAYFROMORIGIN) that can take some funds from the originValue field and sends it to the currently executing contract. The originValue field isn’t strictly necessary, but may be nice in providing some protection to the transaction sender to prevent a contract from taking arbitrary amounts of value.
Edit: This problem could also be solved with 3074. A user could use a batch-capable invoker to first make the relevant contract call (which would internally call the bridge) without supplying a value, then call into the bridge contract after and pay for the previously deposited message. However this does has the overhead of having to make two extra calls.