Closed github-actions[bot] closed 1 year ago
Comment from Optimism
Description: Gas grieffing attack while external calling
Reason: The reporter references that the SafeCall
library's call
function is vulnerable to a returndatabomb attack. However, the SafeCall
's call
function uses inline assembly to perform the call, which does not automatically copy the call's returndata to memory.
0xWeiss
medium
[M-01] Gas grieffing attack while external calling
Summary
In https://github.com/sherlock-audit/2023-01-optimism/blob/main/optimism/packages/contracts-bedrock/contracts/universal/StandardBridge.sol#L307
the external call:
it is vulnerable to a gas grieffing attack.
Vulnerability Detail
The attack can happen because the _to address is not always a trusted receiver. Case where it is vulnerable: The bridging functionality is used by whatever project/protocol. So, there is a intermediary. And they trigger the calls for the users in their platform passing the _to address as the user address that he inputs.
The address, is a smart contract that has a fallback function that loads lot of data in memory. So, the transaction will be much higher in gas cost for the intermediary.
Technical explanation: (bool success, ) is actually the same as writing (bool success, bytes memory data) which basically means that even though the data is omitted it doesn’t mean that the contract does not handle it. Actually, the way it works is the bytes data that was returned from the receiver will be copied to memory. Memory allocation becomes very costly if the payload is big, so this means that if a receiver implements a fallback function that returns a huge payload, then the msg.sender of the transaction, in our case the protocol/intermediary, will have to pay a huge amount of gas for copying this payload to memory.
Impact
Theft of gas/increase gas cost for protocols/intermediaries
Code Snippet
https://github.com/sherlock-audit/2023-01-optimism/blob/main/optimism/packages/contracts-bedrock/contracts/universal/StandardBridge.sol?plain=1#L307
Tool used
Manual Review
Recommendation
Use a low-level assembly call since it does not automatically copy return data to memory
bool success; assembly { success := call(3000, receiver, amount, 0, 0, 0) }