Did you know that the Optimism chain has its own gas payment system for cross-chain messages?
There was a problem in the Olas protocol that could lead to double payment for its users.
In particular, from the code below, it seems that you need to pay for the cross-chain gas by sending ETH to the Optimism CrossDomainMessenger. This can be seen in how a cost amount of ETH is passed to the CrossDomainMessenger contract.
function _sendMessage(
address[] memory targets,
uint256[] memory stakingIncentives,
bytes memory bridgePayload,
uint256 transferAmount
) internal override returns (uint256 sequence) {
// Check for the bridge payload length
if (bridgePayload.length != BRIDGE_PAYLOAD_LENGTH) {
revert IncorrectDataLength(BRIDGE_PAYLOAD_LENGTH, bridgePayload.length);
}
// Check for the transferAmount > 0
if (transferAmount > 0) {
// Deposit OLAS
// Approve tokens for the predicate bridge contract
// Source: https://github.com/maticnetwork/pos-portal/blob/5fbd35ba9cdc8a07bf32d81d6d1f4ce745feabd6/flat/RootChainManager.sol#L2218
IToken(olas).approve(l1TokenRelayer, transferAmount);
// Transfer OLAS to L2 staking dispenser contract across the bridge
IBridge(l1TokenRelayer).depositERC20To(olas, olasL2, l2TargetDispenser, transferAmount,
uint32(TOKEN_GAS_LIMIT), "");
}
// Decode cost related data
(uint256 cost, uint256 gasLimitMessage) = abi.decode(bridgePayload, (uint256, uint256));
// Check for zero values
if (cost == 0 || gasLimitMessage == 0) {
revert ZeroValue();
}
// Check for the max message gas limit
if (gasLimitMessage > MESSAGE_GAS_LIMIT) {
revert Overflow(gasLimitMessage, MESSAGE_GAS_LIMIT);
}
// Check that provided msg.value is enough to cover the cost
if (cost > msg.value) {
revert LowerThan(msg.value, cost);
}
// Assemble data payload
bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(targets, stakingIncentives));
// Send message to L2
// Reference: https://docs.optimism.io/builders/app-developers/bridging/messaging#for-l1-to-l2-transactions-1
IBridge(l1MessageRelayer).sendMessage{value: cost}(l2TargetDispenser, data, uint32(gasLimitMessage));
// Since there is no returned message sequence, use the staking batch nonce
sequence = stakingBatchNonce;
}
This is incorrect, that is because instead, in Optimism, the cross-chain gas is paid by:
1. For L1 -> L2 transactions: the L1 gas is burnt in the Optimism bridge in Optimism's ResourceMetering to pay for the cross-chain gas in L2
2. For L2 -> L1 transactions: the user pays for the L1 gas by executing the functions proveWithdrawalTransaction and finalizeWithdrawalTransaction in OptimismPortal on the L1 to complete the cross-chain transactions
So in reality, there is no need to pass ETH to the CrossDomainMessenger to pay for the cross-chain gas.
Using the contracts as intended will cause unnecessary ETH to be sent and stuck in the OptimismDepositProcessorL1 and OptimismTargetDispenserL2, that is being misunderstood as the ETH being paid for the cross-chain gas.
Be carefull when using cross-chain messages.
Read the full report here:
#optimism
#crosschain
#bridge
Completely free courses
Learn more about the blockchain world
Free education videos
by RareSkills
by Jeiwan
by RareSkills
by RareSkills
by Andreas M. Antonopoulos, Gavin Wood
by Micah Dameron
Compare execution layer differences between chains
Dive deep into the storage of any contract